Video Interface

Introduction
The Video Interface Registers provide a lot of flexibility, the exact same chips and registers are used to support NTSC, PAL and M-PAL. Below each register will be explained using sample data to clarify how it should be used. All registers are 32-bits in length and should always be written a full word (32-bits) at a time.

Video Standards
The video standards send more than just pixel data both on each line and with additional lines at the top and bottom of a frame.

Hardware
Most of the Video Interface is implemented inside the RCP (Reality CoProcessor), although there is a Video DAC (Digital Analog Converter) on the mainboard, and another encoder IC (ENC-NUS) which which appears to manage some of the signal differences between Composite and S-Video Output.

Base Address - 0x0440'0000
N64 Addressing can be complicated, so to keep it simple use the following conventions:


 * Use 0xA in the leading zero position (0xA440'0000) to write directly to the memory location.

When using the VI Interface this should be all you need. For other Interfaces there are some situations that it should be accessed with a different technique, so they will be covered in more depth where it's relevant.

0x0440 0004 - VI_DRAM_ADDR_REG - R/(W default)
This is the address of the FrameBuffer that should be sent to the TV, it's nice that the buffer doesn't have to be copied and can be sent directly to the TV. If you are using double or triple buffered screens this is the value that you will be changing to display the next screen.

0x0440 0008 - VI_H_WIDTH_REG - R/(W default)
This is the width in pixels of the framebuffer if you draw to the framebuffer based on a different width than what is given here the image will drift with each line to the left or right. The common values are 320 and 640, the maximum value is 640. The minimum value depends on the TV set, 160 would probably be a safe minimum but no guarantee. The same value would also be used on drawing commands for clipping or scissors.

0x0440 000C - VI_V_INTR_REG - R/(W default)
This is the Vertical Interrupt configuration register, when the VI is sending lines to the TV when it reaches this line it will trigger a VI Interrupt. The line number entered here is usually the last one that has pixel data. This is the ideal time to swap the frame buffer, because you want to do this while the non-pixel data is being sent.

0x0440 0010 - VI_V_CURRENT_LINE_REG - RO (Read Only/Writes ignored)
This is the line that the VI is currently sending to the TV

0x0440 0014 - VI_BURST_REG - R/(W default)
This register holds 4 related values:


 * [7:0] horizontal sync width in pixels
 * [15:8] color burst width in pixels
 * [19:16] vertical sync width in half lines
 * [29:20] start of color burst in pixels from h-sync

An example value for NTSC @ any resolution is 0x03e52239 or 00 00'0011'1110 0101 0010'0010 0011'1001 in binary.


 * horizontal sync width in pixels: 57 (decimal)
 * color burst width in pixels: 34 (decimal)
 * vertical sync width in half lines: 5 (decimal)
 * start of color burst in pixels from h-sync: 62 (decimal)

An example value for PAL @ any resolution is 0x0404233a or 00 00'0100'0000 0100 0010'0011 0011'1010 in binary


 * horizontal sync width in pixels: 58 (decimal)
 * color burst width in pixels: 35 (decimal)
 * vertical sync width in half lines: 4 (decimal)
 * start of color burst in pixels from h-sync: 64 (decimal)

0x0440 0018 - VI_V_SYNC_REG - R/(W default)
This is the total number of lines both visible and non-visible that must be sent to the TV (based on the the standard for NTSC/PAL)

NTSC: 0x20D = 525

PAL: 0x271 = 625

0x0440 001C - VI_H_SYNC_REG

 * [11:0] total duration of a line in 1/4 pixel units
 * [20:16] a 5-bit leap pattern used for PAL only (h_sync_period)

NTSC: 1/4 pixel width = 0xC15 = 3093

PAL: 0x00150c69 = 10101 0000 1100'0110'1001


 * 1/4 pixel width = 3177
 * pattern = 10101 = 21

0x0440 0020 - VI_H_SYNC_LEAP_REG

 * [11:0] identical to h_sync_period
 * [27:16] identical to h_sync_period

NTSC: 0x0c150c15


 * h_sync_period: 0x0c15 = 3093
 * h_sync_period: 0x0c15 = 3093

PAL: 0x0c6f0c6e


 * h_sync_period: 0x0c6e = 3182
 * h_sync_period: 0x0c6f = 3183

0x0440 0024 - VI_H_START_REG

 * [9:0] end of active video in screen pixels
 * [25:16] start of active video in screen pixels

NTSC: 0x006c02ec = 0000'00 00'0110'1100 0000'00 10'1110'1100


 * end of visible pixels on a line: 748 pixels
 * start of visible pixels on a line: 108 pixels

PAL: 0x00800300 = 0000'00 00'1000'0000 0000'00 11'0000'0000


 * end of visible pixels on a line: 768 pixels
 * start of visible pixels on a line: 128 pixels

0x0440 0028 - VI_V_START_REG

 * [9:0] end of active video in screen half-lines
 * [25:16] start of active video in screen half-lines

NTSC: 0x002501ff = 0000'00 00'0010'0101 0000'00 01'1111'1111


 * end of active video in screen half-lines: 511
 * start of active video in screen half-lines 37

PAL: 0x005f0239 = 0000'00 00'0101'1111 0000'00 10'0011'1001


 * end of active video in screen half-lines: 569
 * start of active video in screen half-lines 95

0x0440 002C - VI_V_BURST_REG

 * [9:0] end of color burst enable in half-lines
 * [25:16] start of color burst enable in half-lines

NTSC: 0x000e0204 = 0000'00 00'0000'1110 0000'00 10'0000'0100


 * end of color burst enable in half-lines: 516
 * start of color burst enable in half-lines: 14

PAL: 0x0009026b = 0000'00 00'0000'1001 000000 10'0110'1011


 * end of color burst enable in half-lines: 619
 * start of color burst enable in half-lines: 9

0x0440 0030 - VI_X_SCALE_REG

 * [11:0] 1/horizontal scale up factor (2.10 format)
 * [27:16] horizontal subpixel offset (2.10 format)

NTSC: 0x00000334


 * 1/horizontal scale up factor (2.10 format)
 * horizontal subpixel offset (2.10 format)

PAL: 0x0000019A


 * 1/horizontal scale up factor (2.10 format)
 * horizontal subpixel offset (2.10 format)

0x0440 0034 - VI_Y_SCALE_REG

 * [11:0] 1/vertical scale up factor (2.10 format)
 * [27:16] vertical subpixel offset (2.10 format)

NTSC: 0x00000400 = 0100'0000'0000


 * 1/vertical scale up factor: 1.0
 * vertical subpixel offset: 0.0

PAL: 0x02000800 = 0000 0010'0000'0000 0000 1000'0000'0000


 * 1/vertical scale up factor: 1000'0000'0000 = 2.0
 * vertical subpixel offset: 0010'0000'0000 = 0.5