4 * Megadrive's VDP C++ module
6 * A useful resource for the Genesis VDP:
7 * http://cgfm2.emuviews.com/txt/genvdp.txt
8 * Thanks to Charles MacDonald for writing these docs.
26 memset(mem
, 0, sizeof(mem
));
28 memset(dirt
, 0xff, 0x35); // mark everything as changed
29 memset(highpal
, 0, sizeof(highpal
));
30 memset(sprite_order
, 0, sizeof(sprite_order
));
31 memset(sprite_mask
, 0xff, sizeof(sprite_mask
));
34 masking_sprite_index_cache
= -1;
36 sprite_overflow_line
= INT_MIN
;
44 * @param md The md instance this VDP belongs to.
46 md_vdp::md_vdp(md
& md
): belongs(md
)
48 vram
= (mem
+ 0x00000);
49 cram
= (mem
+ 0x10000);
50 vsram
= (mem
+ 0x10080);
51 dirt
= (mem
+ 0x10100); // VRAM/CRAM/Reg dirty buffer bitfield
52 // Also in 0x34 are global dirt flags (inclduing VSRAM this time)
62 vram
= cram
= vsram
= NULL
;
65 /** Calculate the DMA length. */
67 { return (reg
[0x14]<<8)+reg
[0x13]; }
69 /** Calculate DMA start address. */
70 int md_vdp::dma_addr()
73 addr
=(reg
[0x17]&0x7f)<<17;
82 * DMA can read from anywhere.
84 * @param addr Address where to read from.
85 * @return Byte read at "addr".
87 unsigned char md_vdp::dma_mem_read(int addr
)
89 return belongs
.misc_readbyte(addr
);
94 * Must go through these calls to update the dirty flags.
96 * @param addr Address to write to.
97 * @param d Byte to write.
100 int md_vdp::poke_vram(int addr
,unsigned char d
)
105 // Store dirty information down to 256 byte level in bits
107 byt
=addr
>>8; bit
=byt
&7; byt
>>=3; byt
&=0x1f;
108 dirt
[0x00+byt
]|=(1<<bit
); dirt
[0x34]|=1;
117 * @param addr Address to write to.
118 * @param d Byte to write.
121 int md_vdp::poke_cram(int addr
,unsigned char d
)
126 // Store dirty information down to 1byte level in bits
128 byt
=addr
; bit
=byt
&7; byt
>>=3; byt
&=0x0f;
129 dirt
[0x20+byt
]|=(1<<bit
); dirt
[0x34]|=2;
137 * Set value in VSRAM.
139 * @param addr Address to write to.
140 * @param d Byte to write.
143 int md_vdp::poke_vsram(int addr
,unsigned char d
)
148 { dirt
[0x34]|=4; vsram
[addr
]=d
; }
153 * Write a word to memory and update dirty flags.
155 * @param d 16-bit data to write.
158 int md_vdp::putword(unsigned short d
)
160 // Called by dma or a straight write
164 if (rw_addr
& 0x0001) {
165 poke_vram((rw_addr
+ 0), (d
& 0xff));
166 poke_vram((rw_addr
+ 1), (d
>> 8));
169 poke_vram((rw_addr
+ 0), (d
>> 8));
170 poke_vram((rw_addr
+ 1), (d
& 0xff));
174 poke_cram((rw_addr
+ 0), (d
>> 8));
175 poke_cram((rw_addr
+ 1), (d
& 0xff));
178 poke_vsram((rw_addr
+ 0), (d
>> 8));
179 poke_vsram((rw_addr
+ 1), (d
& 0xff));
187 * Write a byte to memory and update dirty flags.
189 * @param d 8-bit data to write.
192 int md_vdp::putbyte(unsigned char d
)
194 // Called by dma or a straight write
197 case 0x04: poke_vram (rw_addr
,d
); break;
198 case 0x0c: poke_cram (rw_addr
,d
); break;
199 case 0x14: poke_vsram(rw_addr
,d
); break;
208 * Read a word from memory.
212 unsigned short md_vdp::readword()
214 // Called by a straight read only
215 unsigned short result
=0x0000;
218 case 0x00: result
=( vram
[(rw_addr
+0)&0xffff]<<8)+
219 vram
[(rw_addr
+1)&0xffff]; break;
220 case 0x20: result
=( cram
[(rw_addr
+0)&0x007f]<<8)+
221 cram
[(rw_addr
+1)&0x007f]; break;
222 case 0x10: result
=(vsram
[(rw_addr
+0)&0x007f]<<8)+
223 vsram
[(rw_addr
+1)&0x007f]; break;
230 * Read a byte from memory.
234 unsigned char md_vdp::readbyte()
236 // Called by a straight read only
237 unsigned char result
=0x00;
240 case 0x00: result
= vram
[(rw_addr
+0)&0xffff]; break;
241 case 0x20: result
= cram
[(rw_addr
+0)&0x007f]; break;
242 case 0x10: result
=vsram
[(rw_addr
+0)&0x007f]; break;
251 * A VDP command is 32-bits in length written into the control port
252 * as two 16-bit words. The VDP maintains a pending flag so that it knows
253 * what to expect next.
255 * CD1 CD0 A13 A12 A11 A10 A09 A08 (D31-D24)
256 * A07 A06 A05 A04 A03 A02 A01 A00 (D23-D16)
257 * ? ? ? ? ? ? ? ? (D15-D8)
258 * CD5 CD4 CD3 CD2 ? ? A15 A14 (D7-D0)
260 * Where CD* indicates which ram is read or written in subsequent
261 * data port read/writes. A* is an address.
263 * Note that the command is not cached, but rather, the lower 14 address bits
264 * are commited as soon as the first half of the command arrives. Then when
265 * the second word arrives, the remaining two address bits are commited.
267 * It is possible to cancel (but not roll back) a pending command by:
268 * - reading or writing to the data port.
269 * - reading the control port.
271 * In these cases the pending flag is cleared, and the first half of
272 * the command remains comitted.
276 int md_vdp::command(uint16_t cmd
)
278 if (cmd_pending
) // If this is the second word of a command
280 uint16_t A14_15
= (cmd
& 0x0003) << 14;
281 rw_addr
= (rw_addr
& 0xffff3fff) | A14_15
;
283 // Copy rw_addr to mirror register
284 rw_addr
= (rw_addr
& 0x0000ffff) | (rw_addr
<< 16);
287 uint16_t CD4_2
= (cmd
& 0x0070);
291 rw_dma
= ((cmd
& 0x80) == 0x80);
295 else // This is the first word of a command
297 // masking away command bits CD1 CD0
298 uint16_t A00_13
= cmd
& 0x3fff;
299 rw_addr
= (rw_addr
& 0xffffc000) | A00_13
;
301 // Copy rw_addr to mirror register
302 rw_addr
= (rw_addr
& 0x0000ffff) | (rw_addr
<< 16);
305 uint16_t CD0_1
= (cmd
& 0xc000) >> 12;
309 // we will expect the second half of the command next
315 // if it's a dma request do it straight away
318 int mode
=(reg
[0x17]>>6)&3;
319 int s
=0,d
=0,i
=0,len
=0;
320 s
=dma_addr(); d
=rw_addr
; len
=dma_len();
328 val
= dma_mem_read(s
++); val
<<=8;
329 val
|=dma_mem_read(s
++); putword(val
);
333 // Done later on (VRAM fill I believe)
339 val
= vram
[(s
++)&0xffff]; val
<<=8;
340 val
|=vram
[(s
++)&0xffff]; putword(val
);
350 * Write a word to the VDP.
352 * @param d 16-bit data to write.
355 int md_vdp::writeword(unsigned short d
)
359 // This is the 'done later on' bit for words
360 // Do a dma fill if it's set up:
361 if (((reg
[0x17]>>6)&3)==2)
379 * Write a byte to the VDP.
381 * @param d 8-bit data to write.
384 int md_vdp::writebyte(unsigned char d
)
388 // This is the 'done later on' bit for bytes
389 // Do a dma fill if it's set up:
390 if (((reg
[0x17]>>6)&3)==2)
409 * Write away a VDP register.
411 * @param addr Address of register.
412 * @param data 8-bit data to write.
414 void md_vdp::write_reg(uint8_t addr
, uint8_t data
)
418 // store dirty information down to 1 byte level in bits
419 if (reg
[addr
] != data
) {
424 dirt
[(0x30 + byt
)] |= (1 << bit
);
428 // "Writing to a VDP register will clear the code register."