Sega Virtua Processor Research

Discussion in 'Discussion & Q&A' started by Novedicus, Nov 12, 2018.

  1. Novedicus

    Novedicus Well-Known Member Member

    Joined:
    Aug 26, 2013
    Messages:
    857
    Hello, as some of you may know, I have been reverse engineering Virtua Racing to see how the SVP works myself. It is currently known that it's an SSP1601 chip running a custom ROM that generates Mega Drive tile data from model data and that the 68000 can directly access the SVP's DRAM (which is mapped at $300000 on the 68000 side). The chip's XST register can also be directly written to at $A15000.

    However, I wanted to see how this specific ROM worked. Here are my current findings:

    $300000-$305FFF - Tile buffer #1
    $306000-$30BFFF - Tile buffer #2
    $30EC00-$30FBFF - Model/camera data
    $30FC00-$30FDFF - Sprite data
    $30FE00 - Screen mirror flag
    $30FE02 - Command finished flag
    $30FE04 - Tile buffer address
    $30FE06 - Command sent flag
    $30FE08 - Command ID
    $30FE10 - SEGA sequence value

    The SVP is initialized by clearing DRAM and setting the XST to the string "OH" and disabling the chip's so called "halt flag" (referenced from the current SVP documentation as of November 2018).

    A command is handled by setting the "sent flag" to a nonzero value and then setting the command ID and then checking the "finished flag" to see if it's nonzero.

    Here are the command I have documented:

    0 - Invalid
    1 - Communication test
    2 - Render models and sprites (with camera, used by Virtua Racing mode and Free Run mode in Virtua Racing)
    3 - Render models and sprites (with camera, used by during Virtua Racing mode when the goal is reached or a game over has happened)
    4 - Renders models and sprites (with camera and split screen, used by the 2P VS. mode in Virtua Racing)
    5 - Render SEGA sequence (Used by the SEGA screen in Virtua Racing)
    6 - Render models (with camera, used by the title screen in Virtua Racing)
    7 - Unknown (causes a glitchy mess afaik)
    8 - Render models and sprites (with camera and course ranking table taking up the first 6 sprite slots, used by the title screen in Virtua Racing)
    9 - Render models (Has smaller position range, but more precision, used by the mode select screen in Virtua Racing)
    $A - Render models and sprites (with camera, used by the instant replay in Virtua Racing)
    $B - Render models and sprites (with a fixed camera, used by the instant replay in Virtua Racing)
    $C - Render models (with camera, has smaller position range, but more precision)
    $D - Invalid
    $E - Invalid
    $F - Invalid

    When a command is sent and completed, a DMA transfer can be done directly from DRAM to VRAM. Virtua Racing uses double buffering using the tile buffers as seen above so after each transfer, it swaps the buffer to use. The buffer is not cleared by the SVP, so it must be done manually by the 68000.

    As for model data, in commands 4 and 6, the first model slot is generally the main camera and can also render the main map. Commands 5 treats the first slot like any other model.

    Command 5 is special, as the placement of the SEGA models are done by the SVP itself and where they are is determined by $30FE10, which gets constantly incremented every frame. In command 5, the only other movement that can be applied is Z axis rotation.

    For each model, it uses $40 bytes of DRAM for its variables, and this is what I have found so far (it also applies to the camera):
    $00 - Visible flag
    $02 - X position
    $04 - Y position
    $06 - Z position
    $08 - X angle
    $0A - Y angle
    $0C - Z angle
    $26 - Model data pointer (which is divided by 2 because the SVP handles things by words instead of bytes, and typically OR'd with $8000000 to handle autoincrement on the SVP's side)

    For each sprite, it uses $10 bytes of DRAM for its variables, and this is what I have documented:
    $00 - Visible flag
    $04 - X and Y position (00YY YYXX XXXY YYYX in binary, note X position is divided by 4 here)
    $06 - Sprite data pointer (same format as a model data pointer)

    The model format is very simple. The first word is just the poly count minus 1, and what follows is the actual poly data. The first 2 bytes for each poly are a set of flags. The high byte handles the colors of the poly. A poly can have up to 2 colors, which are dithered together. Each nibble is a palette index. The low byte is a set of flags with the following bitfield:

    0CDS0000

    S - Shape (0 = square, 1 = triangle)
    D - Dithering pattern (0 = vertical line, 1 = checkerboard)
    C = Backface culling flag (0 = off, 1 = on)

    Then for each vertex, it's just its X position, Y position, and Z position, all being signed word values. 4 vertices for a square poly and 3 for a triangle poly.

    For sprites, its format is also rather simple. The first word is the width of the sprite divided by 4 minus 1. The second word is the height of the sprite minus 1. This means sprites can only have widths that are multiples of 4. The rest is the actual pixel data, which is generally formatted like a bitmap, while also still using the same pixel format as the Genesis (meaning that each byte still represents 2 pixels with each nibble being a palette index).

    The way I formatted the ROM to make this run was to change the header up a little and implement the DSP ROM and debugging functions. I changed the local and international names to be like in Virtua Racing and put "53 56 00 00 20 00 04 00" at $1C8 in the header as well. I then ripped the DSP ROM and debugging functions (located at $800 and ends at $1FFFF in Virtua Racing) and padded from the end of the header to $800 and put the data at $800.

    And that's all I have for now. I think it's generally enough to get something working at least, but there's still work to do.
     
    Last edited: Nov 12, 2018
  2. Novedicus

    Novedicus Well-Known Member Member

    Joined:
    Aug 26, 2013
    Messages:
    857
    So, command 2 is pretty much command 6, except it can render sprites!

    See updated OP for more information.