Address Mapping
Addresses are not mapped to VRAM physical addresses in the most straightforward fashion. This doesn't matter for emulators or folks writing games/demos, but may be of interest to others that want to snoop on the VRAM bus. The lists below show the mapping between logical address bits and physical row and column address bits.
Row:
- A2
- A3
- A4
- A5
- A6
- A7
- A8
- A9
- A0
- A1
- A10
- A11
- A12
- A13
- A14
- A15
General RAM Access Info
The Genesis uses a dual port DRAM for its video RAM. This dual port RAM has both a random access port which allows (slow) random access to arbitrary bytes and (fast) sequential access to bytes within a single row. Setting up the serial access port requires using the same address and control lines as the parallel access port (this is called a read transfer operation), but once that is done you can use the ports independently until you need to switch to a different row on the serial access port. The Genesis VDP doesn't take advantage of this though. It uses the serial port almost exclusively and only uses the random access port for 68K initiated access (either through data port read/writes or DMA operations).
The VDP always reads data from the serial port in 4 byte chunks and all memory operations (even random access and refresh cycles) take 4 cycles of SC (the serial port clock). Please note that during a serial port access, the data for the 4 bytes being addressed in the memory operation are actually on the data bus during the next memory operation.
In 32-cell mode SC appears to run at approximately 10.74MHz, which gives 684 cycles and 171 memory operations per line. Of these 171 operations, 4 will be refresh cycles (CAS before RAS refresh), 16 random access (for the 68K whether it uses them or not), 1 will be used to read the horizontal scroll values for Planes A and B, 16 will be used to read the second half of sprite attribute table entries (i.e. the part that specifies horizontal position and which tile to use), 34 will be used to read name table entries for planes A and B and the remainder will be used to read tiles. The order of these operations is in the following section.
Access Order and Timing
For a good portion of rendering (the part that involves the background planes), memory operations are bundled in groups of 4. Since there are only a few variations on what's in those groups I'll define them ahead of time to allow for a more compact representation of the information:
Group A_stile:
Name Table Plane A
Sprite Tile Row(previous line)
Plane A Tile Row
Plane A Tile Row
Group A_68k:
Name Table Plane A
68K Access Slot
Plane A Tile Row
Plane A Tile Row
Group A_refresh:
Name Table Plane A
Refresh
Plane A Tile Row
Plane A Tile Row
Group B_stile:
Name Table Plane B
Sprite Tile Row (previous line)
Plane B Tile Row
Plane B Tile Row
Group B_sat:
Name Table Plane B
Sprite Attribute Table entry (well, half of one)
Plane B Tile Row
Plane B Tile Row
The order of memory operations for an active display line is as follows:
!HSYNC low
7X Sprite Tile Row (previous line)
68K Access Slot
Horizontal Scroll Data
4X Sprite Tile Row (previous line)
!HSYNC high
A_stile
B_stile
A_68k
B_sat
A_68k
B_sat
A_68k
B_sat
A_refresh
B_sat
A_68k
B_sat
A_68k
B_sat
A_68k
B_sat
A_refresh
B_sat
A_68k
B_sat
A_68k
B_sat
A_68k
B_sat
A_refresh
B_sat
A_68k
B_sat
A_68k
B_sat
A_68k
B_sat
A_refresh
B_sat
2X 68K Slot
14X Sprite Tile Row
68K Slot
5X Sprite Tile Row
!HSYNC Low
7X Sprite Tile Row
68K Slot
Horizontal Scroll Data (next line)
4X Sprite Tile Row
!HSYNC High
Notes
From this it's clear why doing CRAM DMA during HBlank still causes display noise: there's only one 68K slot during HBlank. Turning off the display frees up some slots at the expense of some of the sprite data, but you can't use the entirety of HBlank because the horizontal scroll value is read early.
Unused 68K access slots will perform a read of whatever address was used in the previous memory operation.
Next Steps
40 cell mode
More details on sprite rendering access
Timing of read of the other half of the Sprite Attribute Table entries
Refresh timing during VBlank/Display off
Hopefully at least some of this information is new and useful. I had fun figuring it out at least.