From Yabause
Jump to: navigation, search

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