Import Debian changes 1.23-11
[debian-dgen.git] / vdp.cpp
blobfcb9bb598baad896d045dcc68a31f403cb127a7b
1 // DGen v1.13+
2 // Megadrive's VDP C++ module
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "md.h"
9 int md_vdp::get_screen_info(struct dgen_sinfo *si)
11 // Release the pointers to vdp Data to an external function
12 si->vram=vram; si->cram=cram; si->vsram=vsram;
13 si->vdp_reg=reg;
14 // NB - if you change anything, remember to set 'dirt' accordingly
15 return 0;
18 int md_vdp::reset()
20 if (!ok) return 1;
22 rw_mode=0x00; rw_addr=0; rw_dma=0;
23 memset(mem,0,0x10100);
24 memset(reg,0,0x20);
25 memset(dirt,0xff,0x35); // mark everything as changed
26 return 0;
29 md_vdp::md_vdp()
31 ok=0;
32 belongs=0; // Don't know which megadrive vdp belongs to yet
34 mem=vram=cram=vsram=NULL;
35 mem=new unsigned char[0x10100+0x35]; //0x20+0x10+0x4+1 for dirt
36 if (mem==0) return;
37 vram=mem+0x00000; cram=mem+0x10000; vsram=mem+0x10080;
38 dirt=mem+0x10100; // VRAM/CRAM/Reg dirty buffer bitfield
39 // Also in 0x34 are global dirt flags (inclduing VSRAM this time)
41 highpal=new unsigned int[64]; if (highpal==0) return;
43 Bpp = Bpp_times8 = 0;
45 ok=1;
46 reset();
50 md_vdp::~md_vdp()
52 free(mem);
53 mem=vram=cram=vsram=NULL;
54 ok=0;
57 int md_vdp::dma_len()
58 { return (reg[0x14]<<8)+reg[0x13]; }
60 int md_vdp::dma_addr()
62 int addr=0;
63 addr=(reg[0x17]&0x7f)<<17;
64 addr+=reg[0x16]<<9;
65 addr+=reg[0x15]<<1;
66 return addr;
70 // DMA can read from anywhere
71 unsigned char md_vdp::dma_mem_read(int addr)
73 return belongs->misc_readbyte(addr);
76 // Must go through these calls to update the dirty flags
77 int md_vdp::poke_vram(int addr,unsigned char d)
79 // Keeping GCC happy over unused vars. [PKH]
80 // int diff=0;
81 addr&=0xffff;
82 if (vram[addr]!=d)
84 // Store dirty information down to 256 byte level in bits
85 int byt,bit;
86 byt=addr>>8; bit=byt&7; byt>>=3; byt&=0x1f;
87 dirt[0x00+byt]|=(1<<bit); dirt[0x34]|=1;
88 vram[addr]=d;
90 return 0;
92 int md_vdp::poke_cram(int addr,unsigned char d)
94 // int diff=0;
95 addr&=0x007f;
96 if (cram[addr]!=d)
98 // Store dirty information down to 1byte level in bits
99 int byt,bit;
100 byt=addr; bit=byt&7; byt>>=3; byt&=0x0f;
101 dirt[0x20+byt]|=(1<<bit); dirt[0x34]|=2;
102 cram[addr]=d;
105 return 0;
107 int md_vdp::poke_vsram(int addr,unsigned char d)
109 // int diff=0;
110 addr&=0x007f;
111 if (vsram[addr]!=d)
112 { dirt[0x34]|=4; vsram[addr]=d; }
113 return 0;
116 int md_vdp::putword(unsigned short d)
118 // int diff=0;
119 // Called by dma or a straight write
120 switch(rw_mode)
122 case 0x04: poke_vram (rw_addr+0,d>>8); poke_vram (rw_addr+1,d&0xff); break;
123 case 0x0c: poke_cram (rw_addr+0,d>>8); poke_cram (rw_addr+1,d&0xff); break;
124 case 0x14: poke_vsram(rw_addr+0,d>>8); poke_vsram(rw_addr+1,d&0xff); break;
126 rw_addr+=reg[15];
127 return 0;
130 int md_vdp::putbyte(unsigned char d)
132 // int diff=0;
133 // Called by dma or a straight write
134 switch(rw_mode)
136 case 0x04: poke_vram (rw_addr,d>>8); break;
137 case 0x0c: poke_cram (rw_addr,d>>8); break;
138 case 0x14: poke_vsram(rw_addr,d>>8); break;
140 rw_addr+=reg[15];
141 return 0;
144 #undef MAYCHANGE
146 unsigned short md_vdp::readword()
148 // Called by a straight read only
149 unsigned short result=0x0000;
150 switch(rw_mode)
152 case 0x00: result=( vram[(rw_addr+0)&0xffff]<<8)+
153 vram[(rw_addr+1)&0xffff]; break;
154 case 0x20: result=( cram[(rw_addr+0)&0x007f]<<8)+
155 cram[(rw_addr+1)&0x007f]; break;
156 case 0x10: result=(vsram[(rw_addr+0)&0x007f]<<8)+
157 vsram[(rw_addr+1)&0x007f]; break;
159 rw_addr+=reg[15];
160 return result;
163 unsigned char md_vdp::readbyte()
165 // Called by a straight read only
166 unsigned char result=0x00;
167 switch(rw_mode)
169 case 0x00: result= vram[(rw_addr+0)&0xffff]; break;
170 case 0x20: result= cram[(rw_addr+0)&0x007f]; break;
171 case 0x10: result=vsram[(rw_addr+0)&0x007f]; break;
173 rw_addr+=reg[15];
174 return result;
178 int md_vdp::command(unsigned int cmd)
180 // Decode 32-bit VDP command
181 rw_dma=((cmd&0x80)==0x80);
182 rw_mode= cmd&0x00000070;
183 rw_mode|=(cmd&0xc0000000)>>28;
184 // mode writes: 04=VRAM 0C=CRAM 14=VSRAM
185 // mode reads: 00=VRAM 20=CRAM 10=VSRAM
186 rw_addr= (cmd&0x00000003)<<14;
187 rw_addr|=(cmd&0x3fff0000)>>16;
188 // If not dma (or we need a fill),
189 // we are set up to write any data sent to vdp data reg
191 // if it's a dma request do it straight away
192 if (rw_dma)
194 int mode=(reg[0x17]>>6)&3;
195 int s=0,d=0,i=0,len=0;
196 s=dma_addr(); d=rw_addr; len=dma_len();
197 switch (mode)
199 case 0: case 1:
200 for (i=0;i<len;i++)
202 unsigned short val;
203 val= dma_mem_read(s++); val<<=8;
204 val|=dma_mem_read(s++); putword(val);
206 break;
207 case 2:
208 // Done later on
209 break;
210 case 3:
211 for (i=0;i<len;i++)
213 unsigned short val;
214 val= vram[(s++)&0xffff]; val<<=8;
215 val|=vram[(s++)&0xffff]; putword(val);
217 break;
221 return 0;
224 int md_vdp::writeword(unsigned short d)
226 if (rw_dma)
228 // This is the 'done later on' bit for words
229 // Do a dma fill if it's set up:
230 if (((reg[0x17]>>6)&3)==2)
232 int i,len;
233 len=dma_len();
234 for (i=0;i<len;i++)
235 putword(d);
236 return 0;
239 else
241 putword(d);
242 return 0;
244 return 0;
247 int md_vdp::writebyte(unsigned char d)
249 if (rw_dma)
251 // This is the 'done later on' bit for bytes
252 // Do a dma fill if it's set up:
253 if (((reg[0x17]>>6)&3)==2)
255 int i,len;
256 len=dma_len();
257 for (i=0;i<len;i++)
258 putbyte(d);
259 return 0;
262 else
264 putbyte(d);
265 return 0;
268 return 0;