SEGA Genesis: Video Display Processor

VDP chip

The graphics of the SEGA Genesis is handled by the Video Display Processor (VDP) chip. It has it's own 64 KB of dedicated Video RAM (VRAM), containing all graphics data including tiles, sprites, color palettes, and scrolling tables. This memory is separate from the 64 KB of main memory directly accessible from the Motorola 68000 CPU.

The VDP is controlled through memory-mapped I/O, specifically these addresses:

$C00004 VDP Control Port
$C00000 VDP Data Port

All access to the VDP is provided through writing to these addresses.
In this post, I will explain how to set the VDP registers and write data to VRAM.

In the following, we'll use these constants instead of the raw addresses:

vdp_control = $C00004
vdp_data = $C00000

Now, this post is going to be pretty dry, but hey, at least there are a few Golden Axe screenshots.

VDP Registers

VDP Registers in Golden Axe title

The VDP has a set of registers which, along with the contents of VRAM, determine its behaviour. The VDP registers are set up by writing a control word to the VDP Control Port ($C00004).

Let's try an example:

Set the address of Plane A (tilemap) to the VRAM address $C000.

This is done by setting VDP register $02, 'Plane A Name Table Location' to $C000.

We're not writing to color palette RAM or vertical scroll RAM, so we'll pick the normal 'VRAM write': 000001. We distribute it according to the pattern shown earlier:

[01.. .... .... .... .... .... 0000 ....]

We then take our address $C000, which in binary is 1100000000000000, and, distribute it according to the bit pattern:

[0100 0000 0000 0000 .... .... 0000 ..11]

And fill up with zeroes according to the pattern:

[0100 0000 0000 0000 0000 0000 0000 0011]

We're done with the command word. In hexadecimal it's:

[0100 0000 0000 0000 0000 0000 0000 0011]
4 0 0 0 0 0 0 3

We can now write it to the VDP Control Port to set up our VRAM write:

move.l #$40000003,vdp_control ; Set up VRAM write to address $C000

Now that the VRAM write operation is set up, we can write our data to the VDP Data Port:

move.w #$0007,vdp_data ; Write 7 to $C000

Auto-increment

Ax=Battler with an axe that he will never use

To be able to write a loop that copies a sequence of data to VRAM, we can set up the auto-increment register in the VDP. When writing to the VRAM Data Port, the address written to is automatically incremented with this value. Thus, a single VRAM write command written to the VDP Control Port can be followed by several VDP Data Port writes.

Let's make a VDP register set command for setting the auto-increment register $0F: