VDP odds and ends
Posted: Sat Mar 09, 2013 6:09 am
Doing some experiments, may add some test programs later.
Mode 4 CRAM access
You must set the auto-increment value to $00 to sequentially write to CRAM addresses. Each word written has the following format:
---- ---- ---bb ggrr : How word is interpreted in mode 4
---- bbb- --gg grrr : How word is interpreted in mode 5
Notice that when loading a palette in mode 4 you just put the 6-bit value in the LSB of the word written as before. But bits 11-9 are latched too, and if you load a palette in mode 4 and switch to mode 5 the values are re-interpreted as shown.
This applies in the other direction too, e.g. writing $0EEE in mode 5 becomes $0E3F when you switch to mode 4, though only bits $003F matter.
Mode 4 VRAM access
In mode 4 VRAM is addressed differently. You have to use an auto-increment value of $01. The mapping of address register bits (as written by a %10xxxxxxxxxxxxxx command) to physical VRAM address bits is as follows:
Address register bit 0 = Specifies to byte-swap word written
Address register bit 1 = VRAM address bit 2
Address register bit 2 = VRAM address bit 3
Address register bit 3 = VRAM address bit 4
Address register bit 4 = VRAM address bit 5
Address register bit 5 = VRAM address bit 6
Address register bit 6 = VRAM address bit 7
Address register bit 7 = VRAM address bit 8
Address register bit 8 = VRAM address bit 9
Address register bit 9 = VRAM address bit 1
Address register bit 10 = VRAM address bit 10
Address register bit 11 = VRAM address bit 11
Address register bit 12 = VRAM address bit 12
Address register bit 13 = VRAM address bit 13
VRAM address bit 14 = 0
VRAM address bit 15 = 0
Since the address counter is 14 bits, it wraps after writing a word to address $3FFE to $0000. When in mode 4 only the first 16K is used, and the latter 48K of VRAM is free to store Mode 5 specific data.
In this mode it is helpful to consider that the VDP takes the upper 13 bits of the 14-bit register and treats that as a word offset into VRAM, such that an auto-increment of 1 is adding 1 to the word offset after each write.
Because the VRAM addressing changes depending on what mode you are in, you have to take care when accessing data intended for when mode when in the other. The easy method is to just switch to mode 4 when accessing the first 16K and mode 5 for the latter. But if you were going to load a tile set in mode 5 that was intended for mode 4, the tile data would need to be preprocessed and have the data byte locations moved around to accommodate the different addressing expected in mode 4.
Other Mode 4 issues
Remember that you have to be in mode 5 to change register $8F to set the auto-increment, so you'll do a lot of switching in and out of mode 5 as you load VRAM and CRAM data.
If the width is set to 320 pixels the sync is a little off and there's junk in the rightmost 8 columns, that mostly relates to sprite data. If you keep it set to 256 pixels then there's much less distortion when switching between mode 4 and 5.
Both interlace modes work in mode 4, but the positioning of even and odd frames is off by a large amount (like 32 lines?) so it is unusable. Even if you blanked out the top and the bottom and put data in the middle such that it would display correctly, the half-line offset between frames isn't quite right either so you don't really get a full 525 scanlines across two frames, some of them overlap instead of appearing below one another.
In mode 4 the 128K addressing feature is disabled. This bit is the 4K/16K DRAM size for the TMS9918, which does nothing on the SMS though some software may set or clear it. For compatibility with those games, bit 7 of VDP register 1 has no effect in mode 4.
Speaking of mode 4 there's already some older documentation here about it:
http://cgfm2.emuviews.com/txt/msvdp.txt
It mentions some of the specifics about how Mode 4 in the Genesis VDP operates differently to that in the SMS and SMS 2.
Read codes
Using that DTACK generator circuit I posted about earlier:
viewtopic.php?p=17678
I tried mapping out the code value for reads by running through all possible combinations. Here are the results:
00 : Normal VRAM read
04 : Normal VSRAM read
08 : Normal CRAM read
0C : 8-bit VRAM read
20 : Normal VRAM read
24 : Normal VSRAM read
28 : Normal CRAM read
2C : 8-bit VRAM read
01-03 : Return VRAM read buffer on each read
05-07 : Return VRAM read buffer on each read
09-0B : Return VRAM read buffer on each read
0D-0F : Return VRAM read buffer on each read
21-23 : Return VRAM read buffer on each read
25-27 : Return VRAM read buffer on each read
29-2B : Return VRAM read buffer on each read
2D-2F : Return VRAM read buffer on each read
10-1F : Return VRAM read buffer on each read
30-3F : Return VRAM read buffer on each read
For the 8-bit VRAM read, the LSB works like normal and the MSB of the value returned is fixed to the byte at VRAM offset $C000. I wonder why that location specifically?
More fun with $C0001E
When you set bit 8 of this register, color 0 of a palette is visible instead of them all mapping to the same one. So you can get 64 colors instead of 60.
Mode 4 CRAM access
You must set the auto-increment value to $00 to sequentially write to CRAM addresses. Each word written has the following format:
---- ---- ---bb ggrr : How word is interpreted in mode 4
---- bbb- --gg grrr : How word is interpreted in mode 5
Notice that when loading a palette in mode 4 you just put the 6-bit value in the LSB of the word written as before. But bits 11-9 are latched too, and if you load a palette in mode 4 and switch to mode 5 the values are re-interpreted as shown.
This applies in the other direction too, e.g. writing $0EEE in mode 5 becomes $0E3F when you switch to mode 4, though only bits $003F matter.
Mode 4 VRAM access
In mode 4 VRAM is addressed differently. You have to use an auto-increment value of $01. The mapping of address register bits (as written by a %10xxxxxxxxxxxxxx command) to physical VRAM address bits is as follows:
Address register bit 0 = Specifies to byte-swap word written
Address register bit 1 = VRAM address bit 2
Address register bit 2 = VRAM address bit 3
Address register bit 3 = VRAM address bit 4
Address register bit 4 = VRAM address bit 5
Address register bit 5 = VRAM address bit 6
Address register bit 6 = VRAM address bit 7
Address register bit 7 = VRAM address bit 8
Address register bit 8 = VRAM address bit 9
Address register bit 9 = VRAM address bit 1
Address register bit 10 = VRAM address bit 10
Address register bit 11 = VRAM address bit 11
Address register bit 12 = VRAM address bit 12
Address register bit 13 = VRAM address bit 13
VRAM address bit 14 = 0
VRAM address bit 15 = 0
Since the address counter is 14 bits, it wraps after writing a word to address $3FFE to $0000. When in mode 4 only the first 16K is used, and the latter 48K of VRAM is free to store Mode 5 specific data.
In this mode it is helpful to consider that the VDP takes the upper 13 bits of the 14-bit register and treats that as a word offset into VRAM, such that an auto-increment of 1 is adding 1 to the word offset after each write.
Because the VRAM addressing changes depending on what mode you are in, you have to take care when accessing data intended for when mode when in the other. The easy method is to just switch to mode 4 when accessing the first 16K and mode 5 for the latter. But if you were going to load a tile set in mode 5 that was intended for mode 4, the tile data would need to be preprocessed and have the data byte locations moved around to accommodate the different addressing expected in mode 4.
Other Mode 4 issues
Remember that you have to be in mode 5 to change register $8F to set the auto-increment, so you'll do a lot of switching in and out of mode 5 as you load VRAM and CRAM data.
If the width is set to 320 pixels the sync is a little off and there's junk in the rightmost 8 columns, that mostly relates to sprite data. If you keep it set to 256 pixels then there's much less distortion when switching between mode 4 and 5.
Both interlace modes work in mode 4, but the positioning of even and odd frames is off by a large amount (like 32 lines?) so it is unusable. Even if you blanked out the top and the bottom and put data in the middle such that it would display correctly, the half-line offset between frames isn't quite right either so you don't really get a full 525 scanlines across two frames, some of them overlap instead of appearing below one another.
In mode 4 the 128K addressing feature is disabled. This bit is the 4K/16K DRAM size for the TMS9918, which does nothing on the SMS though some software may set or clear it. For compatibility with those games, bit 7 of VDP register 1 has no effect in mode 4.
Speaking of mode 4 there's already some older documentation here about it:
http://cgfm2.emuviews.com/txt/msvdp.txt
It mentions some of the specifics about how Mode 4 in the Genesis VDP operates differently to that in the SMS and SMS 2.
Read codes
Using that DTACK generator circuit I posted about earlier:
viewtopic.php?p=17678
I tried mapping out the code value for reads by running through all possible combinations. Here are the results:
00 : Normal VRAM read
04 : Normal VSRAM read
08 : Normal CRAM read
0C : 8-bit VRAM read
20 : Normal VRAM read
24 : Normal VSRAM read
28 : Normal CRAM read
2C : 8-bit VRAM read
01-03 : Return VRAM read buffer on each read
05-07 : Return VRAM read buffer on each read
09-0B : Return VRAM read buffer on each read
0D-0F : Return VRAM read buffer on each read
21-23 : Return VRAM read buffer on each read
25-27 : Return VRAM read buffer on each read
29-2B : Return VRAM read buffer on each read
2D-2F : Return VRAM read buffer on each read
10-1F : Return VRAM read buffer on each read
30-3F : Return VRAM read buffer on each read
For the 8-bit VRAM read, the LSB works like normal and the MSB of the value returned is fixed to the byte at VRAM offset $C000. I wonder why that location specifically?
More fun with $C0001E
When you set bit 8 of this register, color 0 of a palette is visible instead of them all mapping to the same one. So you can get 64 colors instead of 60.