VDP1
The VDP1 (Video Display Processor 1) is one of the two graphics processors for the Sega Saturn. Its used for drawing sprites, polygons, and lines. Priority and most other effects are actually handled via the VDP2.
Memory Map
VDP1 VRAM | 0x25c00000 | 512 kilobytes |
VDP1 Frame buffer | 0x25c80000 | 256 kilobytes |
VDP1 I/O register address | 0x25d00000 |
Abbrev. | Description | Address | Access |
---|---|---|---|
TVMR | TV mode selection. | 0x25d00000 | Write only |
FBCR | Controls the frame buffer. bit 0: Unused when bit 1 is set to 0, but when bit 1 is set to 1, it tells the VDP1 to erase(if this bit is 0) or change(if this bit is set to 1) at the next v-sync. bit 1: Toggles between auto erase/change and manual. | 0x25d00002 | Write only |
PTMR | Plot trigger. | 0x25d00004 | Write only |
EWDR | Erase/write color | 0x25d00006 | Write only |
EWLR | Erase/write upper-left position. | 0x25d00008 | Write only |
EWRR | Erase/write lower-right position. | 0x25d0000a | Write only |
ENDR | Force draw end. | 0x25d0000c | Write only |
EDSR | Transfer end status | 0x25d0000e | Read only |
LOPR | Return the last command table processed | 0x25d00010 | Read only |
COPR | Return the current command table processed | 0x25d00012 | Read only |
MODR | Mode status | 0x25d00014 | Read only |
Initializing the VDP1
In order to initialize the VDP1, the VDP2 display must be enabled before anything can be displayed. The code below should initialize the VDP1 properly:
void Init_VDP1(void) { /* Interrupts should be disabled. */ TVMR = 0; PTMR = 2; /* Immediately start drawing. */ FBCR = 0; EWDR = 0; /* Set the frame buffer to black. */ /* Erase the entire screen using a rectangle ranging from (0,0) to (320,224) */ EWLR = 0; EWRR = ((320 >> 3) << 9) | 224; /* Enable interrupts. */ }
Frame buffer
The VDP1 contains two frame buffers, both of which are 2 Mbit each. At any given time one frame buffer is designated as front(and displayed on the screen) and the other is designated as back(gets mapped to the 0x25C80000 area for rendering). Any time anything is drawn from the command tables, it always is drawn to the back frame buffer. When doing automatic and manual erase, it's always the front frame buffer that gets erased. When manually changing the buffers, it appears to take approximately 256 hblank's worth of time before the new back buffer can be accessed, regardless of when it's done.
Command tables
In order to display something onto the frame buffer, a 32 byte command table should be set up and written to the VDP1 VRAM. The command is set up like so:
typedef struct VDP1_CommandTable { unsigned short cmdctrl; unsigned short cmdlink; unsigned short cmdpmod; unsigned short cmdcolr; unsigned short cmdsrca; unsigned short cmdsize; signed short cmdxa; signed short cmdya; signed short cmdxb; signed short cmdyb; signed short cmdxc; signed short cmdyc; signed short cmdxd; signed short cmdyd; unsigned short cmdgrda; unsigned short dummy; } VDP1_CommandTable;
The VDP1 supports the following command tables:
Command Table | Description | Command ID |
---|---|---|
Draw normal sprite | Draws a regular unscaled, unrotated sprite | 0x0 |
Draw scaled sprite | Draws a scaled sprite | 0x1 |
Draw distorted sprite | Draws a sprite with any four corner coordinates creating a distorted looking sprite | 0x2 |
Draw Polygon | Draws a regular untextured quad | 0x4 |
Draw Polylines | Draws four lines | 0x5 |
Draw Line | Draws a single line | 0x6 |
User clipping | An adjustable clipping rectangle. You can adjust this multiple times per frame | 0x8 |
System clipping | The main clipping rectangle for all future drawing to the screen. | 0x9 |
Local coordinates | Offsets all future draw commands' coordinates | 0xA |
Draw End | Causes VDP1 to stop parsing command tables and ends drawing | 0xC, 0xD, 0xE, 0xF |