Sega Mega Drive/VDP general usage

From Sega Retro

The VDP (Video Display Processor) is the main graphics processor in the Sega Mega Drive. It is capable of displaying two graphics planes - a foreground (plane A) and background (plane B) - which can be moved independently, as well as a static window plane, and up to 80 sprites (no more than 20 per scanline) on screen.

It contains 64kB of VRAM, used to store graphics data, nametable data for the three planes, horizontal scroll data for the foreground and background planes, and the sprite table. It also has 128 bytes of CRAM, used to store 64 colours (4 palettes of 16 colours). In practice, this equates to 61 usable colours since the first colour in each palette is transparent, and one of those is used as the "background" colour. Finally, VSRAM stores the vertical scroll data.

Ports

Features of the VDP such as VRAM are not directly accessible by the 68k. Instead, all instructions and data must be sent through the control and data ports.

68k Address Length Description
$C00000 B/W/L Data port
$C00002 B/W Data port (mirror)
$C00004 B/W/L Control port
$C00006 B/W Control port (mirror)
$C00008 B/W H/V counter (read-only)
$C0000A B/W H/V counter (read-only, mirror)
$C0000C B/W H/V counter (read-only, mirror)
$C0000E B/W H/V counter (read-only, mirror)
$C00011 B SN76489 PSG (write-only)
$C00013 B SN76489 PSG (write-only, mirror)
$C00015 B SN76489 PSG (write-only, mirror)
$C00017 B SN76489 PSG (write-only, mirror)
$C0001C W Debug register
$C0001E W Debug register (mirror)

Control port

Reading

Reading the control port always returns the status register, which contains information about what the VDP is currently doing.

move.w ($c00004).l,d0

Writing

Writing to the control port will modify one of 24 write-only registers, which are used to change various settings, or to set an address for doing read/write operations on the VRAM/CRAM/VSRAM.

7
6
5
4
3
2
1
0

1
0
0
RS4-RS0
7
6
5
4
3
2
1
0

D7-D0
  • RS4-RS0: Register number.
  • D7-D0: Data to write to register.

To modify a register, write a word (1 byte for the register number, 1 byte for the modification) to the control port:

move.w #$8004,($c00004).l ; set register 0 to $04

Because the control port is mirrored at $c00006, it is possible to send two words at the same time:

move.l #$80048134,($C00004).l ; set register 0 to $04 and register 1 to $34

Data port