VDP

From MegaDrive Wiki
Revision as of 21:42, 19 January 2013 by Tristanseifert (talk | contribs) (Notes: Fixed RefList template — capitalisation matters, apparently.)
Jump to: navigation, search
The VDP in a Model 1 Mega Drive.The VRAM is visible near the bottom left, and the cartridge slot near the top.

The VDP, also known as Video Display Processor, handles all video output on the Mega Drive. The VDP is often known as the YM7101, which is derived from the Sega Master System VDP for backwards compatibility. The Master System VDP is in turn derived from the Texas Instruments TMS9918A. In all Model 1 Mega Drives, the VDP is a dedicated large chip on the main motherboard, as shown on the right, whereas on later models it is integrated into one big chip with the I/O controllers.

It has 64 KB of VRAM, which can be used to store patterns (also known as art or tiles) plane and sprite name tables, as well as horizontal scroll data. The benefit of storing name tables and H-Scroll in VRAM is that you can decide where this data is stored, but leaves less room for art. The VDP has 64 9-bit entries of CRAM, totalling 64 words, to store palettes. This special area of the VDP is known as CRAM, or Colour RAM.

The VDP has the capability of displaying up to 80 sprites on-screen, as well as the A and B planes, and the Window plane. The window plane can be used as a replacement for the A plane in some circumstances. It can also support 64 on-screen colours at any time, as well as scrolling the entire screen or specific parts of it horizontally and vertically. There is also multiple registers that control how the VDP is configured, which are written to the control word as 16-bit words. The TMSS in late model 1 and all model 2 and 3 consoles disables the VDP if the ASCII "SEGA" isn't written to a specific area of I/O memory. See this howto article for details.

Using the VDP

VDP I/O Layout

To access the VDP, you must use a special area of I/O memory. Below is a map of the VDP's IO memory, starting at $C00000:

Address
$C00000 Data Port
$C00002 Data Port (Mirror)
$C00004 Control Port
$C00006 Control Port (Mirror)
$C00008 H/V Counter
$C0000A H/V Counter (Mirror)
$C0000C H/V Counter (Mirror)
$C0000E H/V Counter (Mirror)
$C00011 SN76489 PSG
$C00013 SN76489 PSG (Mirror)
$C00015 SN76489 PSG (Mirror)
$C00017 SN76489 PSG (Mirror)
$C0001C "Disable"/Debug register
$C0001E "Disable"/Debug register (Mirror)

Most of the time, it is not required to use any memory addresses besides the control and data ports. Note that the data and control ports are really only a word wide, but they are mirrored. Due to the way how the 16 bit 68000 does longword accesses (write high word, increment address, write low word,) this allows for more efficient longword writes, than two word writes to the same address. The H/V counter is usually not used for any significant purposes outside of randomisation and light guns. To use the H/V counter, it must be enabled in Register 0. Followed after the H/V counter is the PSG register, which can only be accessed as a byte on the odd addresses. It can also be accessed by the Z80, so accesses between the PSG register must be coordinated if both the Z80 and 68000 are going to be accessing it. Lastly, there is a 'debug register' which was presumably used during VDP development to test various features and verify functionality. Not much is known about it, besides what is noted below.

Due to the way the Mega Drive was designed, the 64 KB of VRAM were not mapped to M68k address space, which opens up lots of more space for I/O peripherals and other devices but can create an inconvenience in programming the VDP.

VDP Registers

The VDP has 25 registers, of which you can program 24 through code. Some registers do not seem to do anything and are not documented anywhere, but that doesn't mean you should be afraid to try. The last register isn't a register that is written, but you read back the VDP control to a CPU register or work RAM, you can get various information about the current state of the VDP. Many registers are also programmed as bitfields - meaning you should be able to set individual bits, and then write the final hex number to the VDP control port.

All register values are written to the control port as a word - the first byte being the register number added to $80, and the second byte being the value.

In the tables below, any bits shown as 0 will always be 0, and any values shown as 1 will always be 1. Bits that change something have a letter assigned to them that is explained below the table.

$00 - Mode Register 1

Register 00 - Mode Register 01
128 64 32 16 8 4 2 1
0 0 L IE1 0 1 HV DE
  • When L is set, the leftmost 8 pixels are blanked.
  • The state of the bit IE1 decides whether the VDP will generate a horizontal interrupt for every nth scanline, or not. This is a level 4 interrupt for the M68k. A 1 means it is enabled, while 0 means it is disabled.
  • The state of HV lets you 'latch' the contents of the H/V counter. If it is set to 1, the VDP will stop modifying the counter so you can read it and calculate things, while when set to 0, the VDP will actively update the counter.
  • DE tells the VDP if the display is enabled or not. Mode Register 02 also has this flag and this one is usually 0. When set to 1, it can be used to overlay an input from the CSync pin onto the video.

$01 - Mode Register 2

When V30 is used on NTSC hardware, the picture is unstable and will roll upwards.
Register 01 - Mode Register 02
128 64 32 16 8 4 2 1
T DE IE0 X Y SMS 0 0
  • T switches between TMS9918A and Mega Drive display select. Should be 0.
  • DE decides if the display is enabled (1) or disabled (0). This is useful to perform quick art loading.
  • IE0 enables the vertical blank interrupt, or VBI. This is a Level 6 interrupt to the M68k.
  • X allows DMA to be performed when set, while it disables any sort of DMA when it is not set.
  • Y sets the vertical display mode/resolution. When set to 1, 30 cell (240 pixel) mode is enabled, which is exclusive to PAL. When set to 0, 28 cell (224 pixel) mode is enabled, which is always the case on NTSC. Enabling 30 cell mode on an NTSC Mega Drive will cause the image to roll upwards and be unstable.
  • SMS selects between Master System and Mega Drive mode. Should be 1.

$02 - Plane A Name Table Location

Register 02 - Plane A Name Table Location
128 64 32 16 8 4 2 1
0 0 X X X 0 0 0
  • XXX is the VRAM location of the name table for Plane A divided by $400. This means that your Plane A name table has to be located at a VRAM address that's a multiple of $400. If you want your plane A name table to be located at $C000 in VRAM, divide that by $400, giving you the result to write to the VDP register, $30.

$03 - Window Name Table Location

Register 03 - Window Name Table Location
128 64 32 16 8 4 2 1
0 0 X X X 0 0 0
  • XXX is the VRAM location of the name table for the Window Plane divided by $400. This means that your Window Plane name table has to be located at a VRAM address that's a multiple of $400. If you want your window plane name table to be located at $F000 in VRAM, divide that by $400, which gives you $3C, which is what you'd write to this register.

$04 - Plane B Name Table Location

Register 04 - Plane B Name Table Location
128 64 32 16 8 4 2 1
0 0 0 0 0 X X X
  • XXX is the VRAM location of the name table for Plane B divided by $2000. This means that your Plane B name table has to be located at a VRAM address that's a multiple of $2000. If you want the plane B name table to be stored at $E000 in VRAM, divide that by $2000, which gives you $07, which is the value you'd write to this register.

$05 - Sprite Table Location

Register 05 - Sprite Attribute Table Location
128 64 32 16 8 4 2 1
0 X X X X X X X
  • XXXXXXX is the VRAM location of the sprite attribute table divided by $200. This means that your sprite attribute table has to be located at a VRAM address that's a multiple of $200. The lower limit of the location multiple means you can squish between unused space for mappings, and so on. Say you want your sprite attribute table to be located at $D800 in VRAM, divide this by $200 and write $6C to this register.

$06 - Unused

Register 06 - Unused/Unknown
128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 0

This is one of these odd unused registers that aren't documented anywhere to our knowledge. Many, if not all games don't touch these registers. Don't hesitate to inform us if you have info about one of these, though.

$07 - Background Colour

Register 07 - Background Colour
128 64 32 16 8 4 2 1
0 0 X X Y Y Y Y
  • XX is the palette line from where the background colour is to be retrieved from, while YYYY is the entry in that palette to use. Do note that the colour you declared as the transparent colour can be displayed. For example, if you want to use colour 2 of palette line 2, you'll write $11 to this register.

$08 - Unused

Register 08 - Unused/Unknown
128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 0

This is one of these odd unused registers that aren't documented anywhere to our knowledge. Many, if not all games don't touch these registers. Don't hesitate to inform us if you have info about one of these, though.

$09 - Unused

Register 09 - Unused/Unknown
128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 0

This is one of these odd unused registers that aren't documented anywhere to our knowledge. Many, if not all games don't touch these registers. Don't hesitate to inform us if you have info about one of these, though.

$0A - Horizontal Interrupt Counter

Register 10 - Horizontal Interrupt
128 64 32 16 8 4 2 1
H H H H H H H H
  • HHHHHHHH is after how many scanlines you want your horizontal interrupt to be called on. For this to take any effect, make sure you enabled horizontal interrupts in register 0's IE1, and that you are not blocking interrupts on the M68k side.

Note that this counter is reloaded at the top of the screen, or when a horizontal interrupt is fired, no other times.

$0B - Mode Register 3

Register 11 - Mode Register 3
128 64 32 16 8 4 2 1
0 0 0 0 IE2 VS HS1 HS2
  • IE2 controls external interrupts that are raised by the TH pin on one of the three IO ports. This is how almost all light guns function. When the trigger is depressed, they pull TH high which causes the game's external interrupt routine to run. This is a Level 2 interrupt on the M68k side.
  • VS controls vertical scrolling. When set to 0, the entire screen is scrolled by one longword in VSRAM. When set to 1, every word in VSRAM vertically scrolls two cells, or tiles of art.
  • HS1 and HS2 both control horizontal scrolling. When set to 00, the entire screen is scrolled at once by one longword in the horizontal scroll table. Setting 01 is prohibited, and may cause undefined behaviour. When set to 10, every long scrolls 8 pixels, and when set to 11, every longword scrolls one scanline.

$0C - Mode Register 4

Sonic the Hedgehog 2's multiplayer mode uses Interlace Mode 2.
Register 12 - Mode Register 4
128 64 32 16 8 4 2 1
RS0 VSY HSY SPR SHI LSM1 LSM0 RS1
  • RS0 and RS1 should be set to the same value, seeing as they control the same thing. When set to 0, the VDP is using horizontal 32 tile mode. When set to 1, the VDP will use a 40 tile wide display.
  • SHI enables shadow/highlight mode, a special mode to allow for more colours on-screen when set.
  • LSM1 and LSM0 control interlace settings: 00 sets no interlace, 01 enables interlace, 10 is prohibited, and 11 interlaces at double resolution. Sonic 2 and some other games use the latter interlace mode for their dual-player split screen.
  • SPR enables the external pixel bus to allow external hardware to generate colour data.
  • HSY appears to do something relating to the horizontal sync, which seems to freeze it.
  • VSY replaces the VSync signal with a pixel clock signal when set.

$0D - Horizontal Scroll Data Location

Register 13 - HScroll Data Location
128 64 32 16 8 4 2 1
0 0 X X X X X X
  • XXXXXX controls where the HScroll data, if at all, is stored. This location has to be a multiple of 400h. For example, if your HScroll data is located at $DC00, you will divide that by $400 to get 37h.

$0E - Unused

Register 14 - Unused/Unknown
128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 0

This is one of these odd unused registers that aren't documented anywhere to our knowledge. Many, if not all games don't touch these registers. Don't hesitate to inform us if you have info about one of these, though.

$0F - Auto-Increment Value

Register 15 - Auto-Increment Value
128 64 32 16 8 4 2 1
X X X X X X X X
  • XXXXXXXX sets the 8-bit value to add after a VRAM access. This is incredibly useful for writing art to the VDP control port, as you can write a word, and the VDP will automatically increase the VRAM pointer for you. Many games set this to 2.

$10 - Plane Size

Register 16 - Plane Size
128 64 32 16 8 4 2 1
0 0 X X 0 0 Y Y
  • XX sets the size of the vertical size of both the A and B planes. When set to 00, you will get a 32 tile vertical size, 01 sets 64 tile vertical, and 11 sets 128 vertical tile size. Setting 10 is prohibited and may cause undefined behaviour.
  • YY sets the size of the horizontal size of both the A and B planes. When set to 00, you will get a 32 tile horizontal size, 01 sets 64 tile horizontal, and 11 sets 128 horizontal tile size. Setting 10 is prohibited and may cause undefined behaviour.

It is important to know that a name table can never exceed 8192 bytes. While a 64x64 or 128x32 name table is valid, a 128x128 or 64x128 name table is not valid.

$11 - Window Plane Horizontal Position

Register 17 - Window Plane Horizontal Position
128 64 32 16 8 4 2 1
D 0 0 X X X X X
  • D sets the direction in which to move the window plane horizontally - 0 means to the left, while 1 means to the right.
  • XXXXX sets how many cells to move the window plane horizontally in the direction specified by D.

$12 - Window Plane Vertical Position

Register 18 - Window Plane Vertical Position
128 64 32 16 8 4 2 1
D 0 0 X X X X X
  • D sets the direction in which to move the window plane vertically - 0 means up, while 1 means down.
  • XXXXX sets how many cells to move the window plane vertically in the direction specified by D.

An important feature to know about the window plane is that it masks plane A, even transparent pixels. This makes it unsuitable for use in many circumstances, but some games use it as a HUD.

$13 and $14 - DMA Length

Registers 19 and 20 - DMA Length
128 64 32 16 8 4 2 1 Register 20 128 64 32 16 8 4 2 1
X X X X X X X X Y Y Y Y Y Y Y Y
  • XXXXXXXX is the low byte of the DMA length.
  • YYYYYYYY is the high byte of the DMA length.

If the DMA length is set to 0, the VDP will treat it as $FFFF, which will cause lots of issues.

$15 to $17 - DMA Source

Registers 21, 22 and 23 - DMA Source
128 64 32 16 8 4 2 1 Register 22 128 64 32 16 8 4 2 1 Register 23 128 64 32 16 8 4 2 1
X X X X X X X X Y Y Y Y Y Y Y Y M1 M2 Z Z Z Z Z Z
  • XXXXXXXX is the low byte of the DMA source address.
  • YYYYYYYY is the middle byte of the DMA source address.
  • ZZZZZZ is the high byte of the DMA source address.
  • M1 and M2 tell the VDP what type of DMA shall be coming up - 00 means that whatever is referenced in these 3 registers is copied to the VRAM. 01 means VRAM fill, and 11 means VRAM copy. 10 is not documented anywhere and seems to be prohibited. More about these DMA modes can be found here.

Status Register

To retrieve some information about the VDP's internal state, the control port, $C00004 or $C00006 can be read as a word to get the status register.

VDP Status Register
128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
0 0 1 1 0 1 F1 F2 VIP SO SC OF VB HB DMA PAL
  • F1 and F2 indicate the status of the FIFO - when F1 is set, the FIFO is empty. When F2 is set, the FIFO is full. The FIFO can hold 4 16-bit words for the VDP to process. If the M68k attempts to write one more word once full is raised, it will be frozen until the first word can be delivered. If the FIFO has items in it, both bits will be clear.
  • VIP indicates that a vertical interrupt occurs, approximately at line $E0. It seems to be cleared at the end of the frame.
  • SO is set when there are too many sprites on the current scanline. The 17th sprite in 32 cell mode and the 21st sprite on one scanline in 40 cell mode will cause this.
  • SC is set when any sprites have non-transparent pixels overlapping. This is likely cleared at the end of the frame.
  • OF is set if the display is interlaced, and if the display is currently in the odd frame.
  • VB returns the real-time status of the V-Blank signal. It is presumably set on line $E0 and unset at $FF.
  • HB returns the real-time status of the H-Blank signal.
  • DMA is set for the duration of a DMA operation. This is only useful for fills and copies, since the M68k is frozen during M68k to VRAM transfers.
  • PAL seems to be set when the system's display is PAL, and possibly reflects the state of having 240 line display enabled. The same information can be obtained from the version register.

Calculating VRAM Addresses

To access the VRAM, you need to tell the VDP where exactly you want to write to. VRAM is not mapped directly into address space, so therefore a command must be written to the VDP's control port ($C00004) to tell it which of it's memories you wish to access, and how.

Calculate a VRAM Address
Byte 4 128 64 32 16 8 4 2 1 Byte 3 128 64 32 16 8 4 2 1
M1 M0 A13 A12 A11 A10 A09 A08 A07 A06 A05 A04 A03 A02 A01 A00
Byte 2 128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 0 M5 M4 M3 M2 0 0 A15 A14

For now, ignore any bits that are set to 0 in the table above. First, let's start off by figuring out what value to put for the A's. If you wanted to write to the VRAM address $AC80, you would first convert this into bits, which would leave you with the following:


128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0

The M's will control the mode of where you will write to or read from. They work as following:

  • If M0 through M5 are 0, then VRAM read mode is set.
  • If M1 through M5 are 0, but M0 is 1, then VRAM write mode is set.
  • If M0, M1, M2, M4 and M5 are 0, but M3 is 1, then CRAM read mode is set.
  • If M2 through M5 are 0, but M0 and M1 are 1, then CRAM write mode is set.
  • If M0, M1, M3, M4 and M5 are 0, but M2 is 1, then VSRAM read mode is set.
  • If M1, M3, M4 and M5 are 0, but M0 and M2 are 1, then VSRAM write mode is set.

Now, if we continue with the example above of writing to $AC80, your final value will leave you with something like this:

VRAM Write to $AC80
Byte 4 128 64 32 16 8 4 2 1 Byte 3 128 64 32 16 8 4 2 1
0 1 1 0 1 1 0 0 1 0 0 0 0 0 0 0
Byte 2 128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

Now, simply convert this to hexadecimal to get the final value of $6C800002. Writing and reading to the various areas of the VDP's memory space is now a piece of cake. To write to CRAM, an easy trick is to remember $C0000000, where the C stands for Colour or CRAM.

VDP Features

Palettes

The VDP has an internal memory called CRAM, or colour RAM, which is 64 words of 9 bits each. This is divided up into 4 palette lines, while one palette line is divided into 16 different palette entries, with the first entry always being transparent (but is able to be displayed as the display background colour.) and the remaining 15 entries being able to be used regularly. Tiles reference into a palette with each nybble, and mappings tell them which one of the 4 palette lines it shall use. The format of a CRAM entry is as follows:

128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
0 0 0 0 B B B 0 G G G 0 R R R 0

The CRAM can be accessed at any time during the display period, with one access 'slot' every 32 pixels during active display, and any time during inactive display. If the CRAM is attempted to be read or written during active display, the value that was being read or written to the CRAM at that location will appear on-screen due to a bug on the hardware. This effect is called "CRAM Dots." Therefore, it is common practice to update the CRAM during blanking through the use of DMA.

VRAM

The VDP comes with 64 KB of VRAM that is used to store many things, save for vertical scrolling info and colours. The VDP could theoretically be modified to use 128 KB of VRAM by replacing the DRAM chips, as there is enough address bits to accommodate 512 rows in the DRAM instead of 256. Access to the VRAM is severely limited during active display and is done through a 4 level FIFO that stores the address and data to write to it. The status register indicates the status of it, and should it become full, the 68k is halted until the FIFO clears. Therefore, it's recommended practice to turn the display off or transfer data using DMA during blanking to access the VRAM.

Interrupts

The VDP is responsible for providing interrupts for the 68k. These interrupts are either of levels 2, 4 or 6.

Vertical Interrupt

The Vertical Interrupt, or VBlank, is fired when the electron beam in the television has finished drawing the last scanline and will start moving back to the top to draw the next frame again. It's commonly used to fire off DMA queues, palette buffers, read controllers and so on. It's interrupt level is 6, meaning it has the lowest priority.

Horizontal Interrupt

The horizontal interrupt is fired once the VDP has completed outputting the scanline specified by the Register 10. The VDP's internal scanline counter is loaded with the value from this register at the top of the screen, and once it hits 0, the interrupt will be fired and the register re-loaded with the value. For example, if the register were to be set to $10, the interrupt would be fired every 16 scanlines. It's interrupt level is 4, meaning it can interrupt a VBlank.

Due to how the VDP is designed, there is a delay before the new value set in Register 10 becomes effective. The counter for the horizontal interrupt must first expire with the previous value before the new one takes effect. For example, when it it is set to $10, and after the first interrupt on line $10 it is set to $08, the next interrupt will still happen after $10 scanlines, at which point the new value will take effect. This is caused because the VDP's internal scanline counter for horizontal interrupts is only reloaded with the value of register 10 once it reaches 0, not when the register is written to.

External Interrupt

Controller ports can be configured so that when the /TH port is changed, the VDP will latch the HV counter's value, and generate a level 2 interrupt on the Motorola 68000. This facility is used by light guns to interrupt the game when the trigger is pressed, at which point the game will use various techniques to determine if the gun was aimed at the object at the position specified by the HV counter. Note that programatically changing /TH does not cause an interrupt.

DMA

The VDP has an interesting little feature called DMA, or Direct Memory Access. This is nothing new - many computers and other devices have this as well to move data faster without requiring the CPU to do it. As explained in the registers section above, the VDP has the capability of doing 3 different DMA types - M68k to VRAM, VRAM Fill and VRAM copy. Something important to note is that during M68k to VRAM transfers, as the VDP will have the bus, the M68k will be frozen by the VDP for the duration of the DMA transfer. Thankfully, the speed advantage of DMA over manually writing art in a loop is worth the lost execution time, as long as the DMA is done during VBlank or when the display is enabled. During HBlank, the speed of DMA is about the same as the speed of a art loading loop running on the M68k. Do note that the Z80 will keep running during DMA, unless it attempts to access the bus, at which point it will also be frozen for the duration of the DMA transfer.

To set up a DMA, you must set the DMA registers (19-23). For DMA to work, you will need to enable DMA in register 1, as well as set the auto-increment register (15) to a meaningful value — usually this is 2, to transfer art, but other values can be used to optimise things, and even creating a bitmapped display. The VDP will then halt the 68k, transfer the data specified at the fastest speed possible to it's memory, and then resume the M68k.

A VRAM Fill will 'fill' will fill another VRAM address with data from an even VRAM address. I have no idea what this could be used for, but for some reason this mode exists. This applies to only VRAM, not CRAM or VSRAM. The last DMA mode is VRAM Copy - it will copy from the source address to the destination address, for as many bytes as the length register indicates. I'm not sure why this mode exists, either. These two modes don't freeze the M68k, but it is important that you only read the VDP status register, H/V counter, and write to the PSG registers. Doing otherwise may corrupt VRAM and VDP registers.

Often times, games will create a DMA queue that will hold a specific number of entries to DMA on the next vertical blank interrupt, where it will be processed. See the howto article on this to learn about making one.

DMA Bandwidth

All numbers in the tables indicating transfer capacity are in bytes, not words. Active display indicates the total number of bytes transferrable during the time of active display, including HBlank intervals. Disabled display indicates the amount of bytes of data transferrable during the VBlank.

68k to VRAM

The table below indicates the available bandwidth when doing a DMA from the 68k address space to the VDP.

Resolution Disabled Display Active Display Total
60 Hz 256 x 224 6118 3584 9702
320 x 224 7524 4032 11556
50 Hz 256 x 224 14329 3584 17913
320 x 224 17622 4032 21654
256 x 240 11753 3840 15593
320 x 240 14454 4320 18774
VRAM Fill

The table below indicates the available bandwidth when doing a VRAM fill DMA.

Resolution Disabled Display Active Display Total
60 Hz 256 x 224 6308 3360 9668
320 x 224 7752 3808 11560
50 Hz 256 x 224 14774 3360 18134
320 x 224 18156 3360 18134
256 x 240 12118 3600 15718
320 x 240 14892 4080 18972
VRAM Copy

The table below indicates the available bandwidth when doing a VRAM copy from one area in VRAM to another.

Resolution Disabled Display Active Display Total
60 Hz 256 x 224 3154 1792 4946
320 x 224 3876 2016 5892
50 Hz 256 x 224 7387 1792 9179
320 x 224 9078 2016 11094
256 x 240 6059 1920 7979
320 x 240 7446 2160 9606
DMA Limitations

Because the VDP acquires bus mastership during a DMA transfer, it is not possible for any other hardware to access the MD bus. This can pose a problem for the Z80, as most of the time it is used as part of the sound driver, which often needs to read from ROM. The Z80 may continue running during a DMA transfer, but if it attempts to access 68k access space, it will be halted for the remainder of the DMA transfer. It's common for games to stop the Z80 during the length of a DMA transfer, but the reason for this is currently unknown. It is possible that this may be done to circumvent a bug in the I/O controller or VDP itself on certain hardware.

Due to limitations in the VDP, all data transferred through DMA must not cross a 128KB boundary, possibly due to the DMA counter being only 17 bits. If data crosses this 128 KB boundary, random data from elsewhere in the 68k address space will be read. For example, if art that was 64 kilobytes in size was located in a ROM at $1E0000, it would be able to be transferred without problems, as it does not exceed $1FFFFF, the next boundary. If however, this same piece of art was located at $1F2000, and a DMA was attempted, parts of the art after $1FFFFF would not be transferred correctly.

A similar issue occurs if the second word of the DMA address is written to the mirror of the VDP port (at $C00006) which may cause the first word of the DMA transfer to not be transferred. This can be circumvented easily by writing the second word of the transfer address to the first control port, not the mirror of it. A similar problem can occur when performing a DMA transfer from the Mega CD Word RAM, due to a timing problem with the DRAM that prevents the address from getting latched into the memory, although all following words that will be transferred correctly. To circumvent this problem, set the DMA source and destination as one word less than needed, and length one more than is needed. This may corrupt the word in VRAM before, but ensure all data will be transferred correctly.

There is significantly less DMA bandwidth available on NTSC-60 hardware than there is on PAL-50 hardware, due to the fact that NTSC hardware has a higher output framerate.

Patterns

Patterns are little 8x8 pieces of art that can be displayed in any of the 4 available palettes. Each pattern is 20h bytes in length, and is stored anywhere in VRAM. They are mapped to the display through the use of the plane maps, which can also set the palette line for them to use, as well as the high priority flag. Many games store their patterns compressed in their ROMs for a number of reasons, mainly the fact to save ROM space. Some games will decompress them to RAM and DMA from there, while others will simply just write to the VDP. While the first is faster, it might not be the right option if it has the possibility of corrupting RAM.

Name Tables

Name Tables will tell the VDP what to draw, and where to draw it. Essentially, they map patterns to the different planes you can have on-screen at any given time. As mentioned before, these name tables can never exceed 8KBytes in size. Some games will compress these, but in some cases, for example, if scrolling credits are needed and so is tile reloading, compression can often be a hassle unless it is able to decompress only a specific range of bytes. RLE compression often works very well for compressing name tables. If you scroll past the end of a name table, it will wrap again. Some games will use this to have scrolling credits.

An entry in a name table is 16 bits, and works as follows:

128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
Priority Palette Vertical Flip Horizontal Flip Tile Index

When the priority bit is set, the tile will be displayed above low priority tiles on the same plane, or planes 'below' it in the priority ordering. Horizontal and Vertical flip will flip the tile either horizontally or vertically. The palette bits allow displaying the tile with one of the four palette lines. It is worth noting that when Interlace mode 2 is selected, the LSB of the tile index will be ignored, as tiles are now 8x16 in size.

Priority

The VDP has a complex system of priorities that can be used to achieve several complex effects. The priority order goes like follows, with the least priority being the first item in the list:

  1. Backdrop Colour
  2. Plane B with priority bit clear
  3. Plane A with priority bit clear
  4. Sprites with priority bit clear
  5. Window Plane with priority bit clear
  6. Plane B with priority bit set
  7. Plane A with priority bit set
  8. Sprites with priority bit set
  9. Window Plane with priority bit set

Sprites

An example of a 2x2 cell sprite from Sonic the Hedgehog, with the palette below it.

Sprites are objects with a size of up to 4x4 (cells) that can be arbitrarily positioned on-screen.

Sprites can only appear in the active display area, unless some programming trick is employed. The sprites with the highest priority will be the ones that will get drawn if there are more than the maximum sprites on a single scanline. When a sprite's X position is set to 0, it can be used to mask all other sprites on that same scanline, so long as they have low priority. The range X values is 0 through 551, but the displayable X values begins at 128, up to 383 or 447, depending on horizontal mode. The sprite's Y position values are from 0 through 551, but the displayable values start at 128 and go up to 351 or 367 depending on vertical mode. When interlace mode 2 is enabled (to double vertical resolution) the sprite's Y position range doubles, with the displayable area starting at 256 to 703 or 735 depending on vertical mode.

Sprite Attribute Table

All sprites are specified in the VRAM in the Sprite Attribute table, pointed to by Register $05. Each entry takes up 8 bytes, with the following format:

128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
Unused Vertical Position
128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
Unused Horizontal Size Vertical Size Unused Link Data
128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
Priority Palette Palette Vertical Flip Horizontal Flip Pattern to use
128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
Unused Horizontal Position

Sprite Sizes

The numbers inside boxes represent their link entry, a yellow box represents a sprite with the priority bit set. The blue rectangle is the window plane, whereas the red and green are the BG and FG, respectively. No planes have the priority set on any tile.

Using two bits for vertical and horizontal sizes, 16 different sprite sizes are possible, up to 4x4 cells. Sizes are defined in cells (8x8 patterns, or 8x16 in Interlace 2) going down the row before the column.

Vert
Horiz
0 1 2 3
0
0
0
1
0
1
2
0
1
2
3
1
0 1
0 2
1 3
0 3
1 4
2 5
0 4
1 5
2 6
3 7
2
0 1 2
0 2 4
1 3 5
0 3 6
1 4 7
2 5 8
0 4 8
1 5 9
2 6 A
3 7 B
3
0 1 2 3
0 2 4 6
1 3 5 7
0 3 6 9
1 4 7 A
2 5 8 B
0 4 8 C
1 5 9 D
2 6 A E
3 7 B F

Linking and Priority

Each sprite entry has a link field, which indicates the next sprite entry to draw. This ID can be acquired by taking the VRAM absolute address of the sprite entry, subtracting the sprite table base address from it and dividing it by 8. The VDP will begin drawing the first sprite, and then draw the next one indicated by the link. Sprites that come later in the link list can be considered of having a higher priority - they will be drawn above any other sprites that may be drawn at their coordinates. However, the priority flag in the sprite table entry can be used to enhance this.

At the end of a sprite table, the last sprite must have it's link field set to 0, otherwise the results are undefined.

Limitations

The VDP imposes some limitations as for how many sprites may be displayed on one line (If more sprites are to be displayed, they will simply not be drawn):

  • In 32 cell horizontal mode, the VDP will display up to 64 sprites per frame, and a maximum of 16 sprites on a single scanline.
  • In 40 cell horizontal mode, the VDP will display up to 80 sprites per frame, and a maximum of 20 sprites on a single scanline.

Usually one would expect to be able to change the data in the sprite table mid-frame to create effects - however, this is not possible by simply changing the values of the sprite table as the VDP contains an internal sprite table buffer in which the sprites are pre-calculated prior to displaying them. This cache is re-calculated every frame, or if the sprite table location register is changed. This register can be changed mid-frame, but the side effects of doing this are unknown and undefined.

Shadow/Highlight

An example of Shadow/Highlight on the Mega Drive. The highlighted states are done using sprites.
An example of the Shadow/Highlight effect with sprites being used for a sort of 'Lens Flare' effect in Vectorman.

Shadow/Highlight is a special VDP mode that allows for more colours to be displayed on-screen at once, about 3 times as much as the normal 512. To use this mode, special colours and the priority system are used. Even though there wasn't very many Mega Drive games that took advantage of this mode, a notable example of this mode is the game Vectorman, where it is used extensively.

An entry in a name table is by default shadowed with the priority bit cleared. When it is set, it will be displayed at regular intensity. If a tile in Plane B has the priority bit set, any other tiles on other planes that pass over that tile will also be highlighted. Sprites with special colours can be used to either add shadow or highlight a colour:

  • Sprites with colour 14 of palette 3 will highlight the underlying pixels - if the underlying pixel is shadowed, it will be displayed normally. If it's already normal, it will be highlighted.
  • Sprites with colour 15 of palette 3 will shadow the underlying pixels - if the underlying pixel is normal, it will be shadowed. If it is shadowed, nothing will occur. If it's highlighted, it will be displayed normally.

It is possible to mix these colours with other colours from the same palette line to create effects. Sprites are also displayed differently depending on their priority setting, identically how it works with name tables.

Note that colours 14 of any palette behave abnormally in Shadow/Highlight mode. This is most likely due to a bug in the VDP implementation. There may be other colours that don't function as expected.

Emulators calculate shadow colours by dividing regular colours by two, and highlight colours by multiplying by two. Hardware appears to follow this behaviour to some extent, although it can't be known for certain as it's very hard to get undistorted colour values from the hardware.

Horizontal Scrolling

An example illustrating how horizontal and vertical scrolling work. The numbers indicate the scroll value for the columns/rows adjacent/below them. The red illustrates where the patterns would loop.

The VDP can scroll the A and B plane horizontally in a number of ways - the entire plane, every row of tiles, or every scanline. This is controlled by Register 11 as well as Register 13. The HScroll data is located in VRAM - so you will need to give up some title space to have this feature.

  • If you have entire plane scrolling enabled, the VDP high word will scroll the FG plane, and the low plane will scroll the BG plane. Note that the plane will wrap once it reaches the edge of the plane's size.
  • When you enable per-row horizontal scrolling, every longword in your HScroll table will tell the VDP how much to scroll every 8-pixel row on-screen. The format is still the same as before - first word scrolls the FG, and the second scrolls the BG. This will obviously take up more space in VRAM.
  • Lastly is per-scanline horizontal scrolling. This mode allows you to scroll all 224 on-screen scanlines (240 in PAL mode) individually. This can be used to create visually appealing effects such as water wobbles, and so on. Each long in your HScroll table will tell the VDP how to scroll each scanline. As previously, you will have the first word controlling the FG, and the second controlling the BG. This mode also takes up the most space in VRAM, with 960 bytes.

It's best to have an in-RAM buffer for the last two modes as writing to the VDP isn't exactly fast. The buffer can then be transferred using DMA every VBlank.

Vertical Scrolling

Like Horizontal Scrolling, Vertical Scrolling allows you to scroll the content on the VDP's 2 planes, but vertically. The setup of VScroll is decided by Register 11. You can either scroll both planes as a whole vertically, or scroll a 2 tile wide column of your name tables at once. Vertical Scrolling data is located in RAM on the VDP itself. It is also written like regular VRAM, but it is not exactly fast either, so a buffer should be applied here too.

  • The first mode of vertical scrolling is much like the first mode of horizontal scrolling - the entire screen is scrolled vertically by the first long in VSRAM. The first word scrolls the FG, and the second scrolls the BG.
  • To have more precise effects, you can scroll individual columns that are 2 tiles (or 16 pixels) wide individually. Every column is scrolled by a long in VSRAM - the first word scrolls the FG, while the second word scrolls the BG. Combined with horizontal scrolling of various accuracies, it is possible to create very interesting effects, such as rotations, and more.

H/V Counter

The H/V counter contains the current location of the electron beam in the television, or the currently drawn pixel. By pulling the /TH line low on controllers, a game may latch the HV counter as well as cause a 68k interrupt. This technique is often used for light guns. It can be read from $C00008.

The format of the counter in regular non-interlace mode is as follows:

128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
V7-V0 H8-H1

However, due to the fact that interlace mode doubles the screen resolution, another bit is needed for resolution. To get around that, the LSB is dropped from the vertical component to allow adding of another bit.

128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
V7 V6 V5 V4 V3 V2 V1 V8 H8-H1
  • The vertical counter will count to 224 pixels in 28 vertical cell mode, and count to 240 pixels in 30 vertical cell mode.
  • The horizontal counter will count to 256 pixels in 32 horizontal cell mode, and 320 pixels in 40 vertical cell mode.
  • During HBlank in 32 horizontal cell mode, when the counter reaches 264, it will increment. It will then increment normally until 296 and then jump to a value of -46 indicating the beam is restarting on a new line.
  • During HBlank in 40 horizontal cell mode, when the counter reaches 328, it will increment. It will then increment normally until 360 and then jump to a value of -46 indicating the beam is restarting on a new line.
  • During VBlank in 28 vertical cell mode the counter will continue to increment normally from 224 to 234. It will reset to 229, indicating the beam will re-start on the top of the display. It will then increment until active display.
  • During VBlank in 30 vertical cell mode the counter will continue to increment normally from 240 to 10. It will reset to 210, indicating the beam will re-start on the top of the display. It will then increment until active display.

PSG

The PSG chip is integrated into the VDP die. See this article for more information.

Undocumented Features

Debug Register

The VDP contains a register at $C0001C in memory space that will disable various parts of the VDP and cause it to perform other 'test' modes. This register is not supported on any emulator, ad it is mirrored at $C0001E.

128 64 32 16 8 4 2 1 Byte 1 128 64 32 16 8 4 2 1
 ? SHDE2 SHDE1 SHDE0 CLICK CLICK PSGEN BGHDE SDBG DISP CORR1  ? KILL1  ?  ?  ?
  • SHDE0 to SHDE2: These bits hide all sprites on screen, but some bits may do other functions when combined with others.
  • CLICK: When the bit is toggled, a click can be heard in the audio.
  • PSGEN: When set, the PSG will be disabled.
  • BGHDE: When set, the BG layer is hidden, dots appear at top of screen as well as a line line at the right right and sprites are hidden.
  • SDBG: When set, the VDP draws black box around sprites, like a debug mode.
  • DISP: When set, display can be disabled (Overrides Register $01)
  • CORR1: When set, corrupt data is displayed, and it appears to corrupt the internal VDP state
  • KILL1: When set, causes streaks down screen as if there was a continuous 68k -> CRAM DMA

No games appear to use this register, nor is it documented anywhere. A ROM to test this behaviour (real hardware only) can be downloaded here.

Pinout

The VDP is a 128 pin QFP chip on the main board of the Mega Drive. On Model 2 and 3 Mega Drives, it is no longer a discrete chip because it is integrated with the other hardware in a single chip, to save space and manufacturing costs.

315-5313 pinout.png

Unused External Buses

The VDP has multiple busses that are not connected to anything, but still broken out to pins. These buses are:

  • Pixel bus (120-127) outputs palette index, palette line, Shadow/Highlight state, if enabled. Used for external colour RAMs.
  • VRAM 2 Control (9, 14) Control signals for the second VRAM bank: /SE1 and /WE1
  • VRAM 2 data/address (18-25) Data and address lines for second VRAM bank

The VDP can use 128 KB of VRAM, which is supported by nearly everything but tile indices. The serial data access bus appears to be shared between both memories.

Test Programme

The first page of the programme.

This programme gives examples of various effects the VDP is capable of displaying. To change pages, hold the Start button, and then press the left or right buttons. Pressing Start and up at the same time will open the table of contents.

Download.png Download VDP Test Programme
File: InteractiveVDPDocs.zip (37 KB) (info)

Current version: 1.0

References

Notes