VB Sacred Tech Scroll - Virtual Boy Specifications

Virtual Boy Hadrware Specifications
Cartridges & ROM Format
CPU Memory Map
Virtual Image Processor (VIP)
Virtual Sound Unit (VSU)
Hardware Control Registers
CPU V810 Family Microprocessor
System Reset
About VB Sacred Tech Scroll

Cartridges & ROM Format

Cartridges on Virtual Boy contain memory circuits for both ROM and WRAM, which get mapped directly onto the system bus. The ROM data contains information pertinent to running the program as well as some additional information about the game provided by Nintendo.

Cartridge Memory

The CPU address space allows for up to 16 MB of both ROM and RAM on the cartridge, for a maximum total of 32 MB of memory. Additionally, address space is allocated for another 16 MB of cartridge expansion memory, though it was never used in any commercial game.

ROM images must be at the very least no fewer than 1024 bytes in size, and the number of bytes must be an integral power of 2. The implication is that in the binary representation of the number of bytes in the image, only one bit will be set and the rest will be zero. The addresses in the ROM memory range are masked with (rom_size - 1), effectively mirroring/duplicating the contents of ROM across the entire 16 MB memory range. The same occurs for cartridge RAM.

Editor's Note: There is no information in the ROM image describing the capacity of the RAM chip, though it is assumed the mirroring works the same way. Emulators should support however much RAM games attempt to access, at least until a de facto ROM file format standard with a header can be drafted up.

RAM on Virtual Boy cartridges (if present) may be battery backed (SRAM).

ROM Format

Virtual Boy ROM images are directly used by the CPU as per the V810 family specification. After all ROM mirroring and system address masking occurs, the effective ROM data starting at address 0xFFFFFDE0 contains significant information. In other words, the significant data inside a ROM file is located at (rom_size - 544).

Virtual Boy ROM Header
  0xFFFFFDE0-0xFFFFFDF3   Game Title, Shift-JIS
  0xFFFFFDF4-0xFFFFFDF8   (Reserved, zero)
  0xFFFFFDF9-0xFFFFFDFA   Maker code, ASCII
  0xFFFFFDFB-0xFFFFFDFE   Game code, ASCII
  0xFFFFFDFF              Game version, 1.<value>
V810 Family Exception/Interrupt Handlers
  0xFFFFFE00-0xFFFFFE0F   Program code of Game Pad interrupt handler
  0xFFFFFE10-0xFFFFFE1F   Program code of Timer Zero interrupt handler
  0xFFFFFE20-0xFFFFFE2F   Program code of Cartridge interrupt handler
  0xFFFFFE30-0xFFFFFE3F   Program code of Link interrupt handler
  0xFFFFFE40-0xFFFFFE4F   Program code of VIP interrupt handler
  0xFFFFFE50-0xFFFFFF5F   (Not used)
  0xFFFFFF60-0xFFFFFF7F   Program code of floating-point exception handler
  0xFFFFFF80-0xFFFFFF8F   Program code of zero division exception handler
  0xFFFFFF90-0xFFFFFF9F   Program code of invalid opcode exception handler
  0xFFFFFFA0-0xFFFFFFAF   Program code of handler for lower 16 TRAP vectors
  0xFFFFFFB0-0xFFFFFFBF   Program code of handler for upper 16 TRAP vectors
  0xFFFFFFC0-0xFFFFFFCF   Program code of address trap handler
  0xFFFFFFD0-0xFFFFFFEF   Program code of duplexed exception/MNI handler
  0xFFFFFFF0-0xFFFFFFFF   Program code of reset interrupt handler
For more information on the exception and interrupt handlers, refer to the CPU Exceptions & Interrupts section.

As the CPU's program counter is initialized to 0xFFFFFFF0 on system reset, the entry point in a Virtual Boy ROM file is effectively the sixteenth-to-last byte in the file.

CPU Memory Map

The CPU memory bus of the Virtual Boy is 27 bits wide and is divided into 8, 16 MB segments. The upper 5 bits are masked out and produce mirrors of the entire memory map according to the lower 27 bits.

CPU Memory Map
0x00000000-0x00FFFFFF   VIP Memory and Control Registers
0x01000000-0x01FFFFFF   VSU Control Registers
0x02000000-0x02FFFFFF   Hardware Control Registers
0x03000000-0x03FFFFFF   Not Used
0x04000000-0x04FFFFFF   Cartridge Expansion
0x05000000-0x05FFFFFF   System WRAM
0x06000000-0x06FFFFFF   Cartridge RAM
0x07000000-0x07FFFFFF   Cartridge ROM
0x08000000-0xFFFFFFFF   Mirroring of CPU Memory Map
Cartridge Expansion

No commercial cartridges use this area. For all intents and purposes, it is a general-purpose address range that passes through the cartridge.

An interrupt exists that can be raised by the expansion area. Cartridge interrupts have an exception code of 0xFE20 and branch CPU execution to address 0xFFFFFE20.

System WRAM

The Virtual Boy has 64 KB of system RAM mapped to 0x05000000-0x0500FFFF. This is the scratch memory for programs running on the CPU. The upper 8 bits are masked out to produce mirrors of the entire RAM space according to the lower 16 bits.

Cartridge RAM and Cartridge ROM

Cartridges can contain RAM chips of their own, and always contain ROM chips. Cartridge RAM and ROM sizes must be some exponent of 2 bytes in size (but need not be the same size), up to 16 MB each. Any bits above the range of the chips are masked out and produce mirrors of the entire address space according to the lower bits.

Virtual Image Processor (VIP)

Overview
VIP Overview
VIP Memory Map
VIP Display Procedure

Memory
VIP Frame Buffers
VIP Characters
VIP Background Segments
VIP Objects
VIP Windows
VIP Column Table

Registers
VIP Interrupts
VIP Display Registers
VIP Brightness and Palettes
VIP Drawing Registers
VIP Miscellaneous Registers

VIP Overview

The Virtual Boy contains two LED screens manufactured by Reflection Technologies, Inc. The screens each consist of a single column of LEDs and a mirror that oscillates at 50.0 hz. The LEDs activate and deactivate with such timing that by the time the light reflects off of the mirror and towards the user's eye, it gives the illusion of a 2D matrix of pixels with varying brightness. Each screen's mirror vibrates opposite the other to maintain balance and optimize power consumption.

Virtual Boy's displays are 384x224 pixels in size, and the frame rate is 50.0 hz. Editor's Note: Old documentation stated that the Virtual Boy has a display period of 50.2 hz, but this is incorrect. The servo controller that drives the displays monitors the mirrors, adjusting if necessary to maintain a constant display period of 50.0 hz at all times.

Image Composition

Images on Virtual Boy can be composed from objects in video memory and/or by directly manipulating the frame buffers. In the case of the former, the VIP will read attributes and pixel data to produce images very quickly. Images are rendered into frame buffer memory before being displayed. Each display has two frame buffers, making both displays double buffered.

Graphical elements are arranged into Windows, known in some circles as "worlds", which themselves are arranged on the screen and can overlap with one another. The contents of Windows consist of the other types of graphical elements and various effects like clipping regions (analagous to "scrolling" on other systems) and affine transformations are available.

Image Elements

The atomic unit of the Virtual Boy's graphics is the Character, also known as a tile. Characters represent 8x8 patterns of pixel data and are used by the other types of graphical elements. Characters cannot be used on the screen on their own, but must be contained within a Window.

Individual Characters can be used directly via an Object, also called a sprite. Objects consist of one entire Character and can be placed at any arbitrary location in, partially in, or entirely out of the bounds of their parent Windows. Objects also support horizontal and vertical flipping of pixel data.

Characters can be arranged into 64x64 cell canvases or grids called Background Segments, for a total of 512x512 pixels each. Multiple Background Segments can be arranged within Windows--forming a construct not unlike the canvas of Characters that the Segment represents--which can then be shifted around inside the window to produce a scrolling effect. This assembled construct is referred to as the Background of the Window.

Direct Rendering

In addition to the windowing functionality of the graphical subsystem, the program can directly access the frame buffers for each screen and write pixel data into them in whatever way is desired. The trade-off is that CPU time must be used to process images (whereas the VIP operates independently from the CPU) and images are drawn more slowly than by the VIP. In either case, it is still the responsibility of the VIP to transfer completed images to the LED displays.

VIP Memory Map

The VIP memory map is 19 bits wide. The upper 5 bits are masked out and produce mirrors of the entire memory map according to the lower 19 bits.

VIP Memory Map
0x00000000-0x00005FFF   Left Frame Buffer 0
0x00006000-0x00007FFF   CHR RAM Pattern Table 0
0x00008000-0x0000DFFF   Left Frame Buffer 1
0x0000E000-0x0000FFFF   CHR RAM Pattern Table 1
0x00010000-0x00015FFF   Right Frame Buffer 0
0x00016000-0x00017FFF   CHR RAM Pattern Table 2
0x00018000-0x0001DFFF   Right Frame Buffer 1
0x0001E000-0x0001FFFF   CHR RAM Pattern Table 3
0x00020000-0x0003D7FF   Background Segments and Window Parameter Table
0x0003D800-0x0003DBFF   Window Attributes
0x0003DC00-0x0003DFFF   Column Table
0x0003E000-0x0003FFFF   Object Attribute Memory (OAM)
0x00040000-0x0005DFFF   Mirroring of VIP Control Registers
0x0005E000-0x0005FFFF   VIP Control Registers (See below)
0x00060000-0x00077FFF   Not Used
0x00078000-0x00079FFF   Mirroring of CHR RAM Pattern Table 0
0x0007A000-0x0007BFFF   Mirroring of CHR RAM Pattern Table 1
0x0007C000-0x0007DFFF   Mirroring of CHR RAM Pattern Table 2
0x0007E000-0x0007FFFF   Mirroring of CHR RAM Pattern Table 3
0x00080000-0x00FFFFFF   Mirroring of VIP Memory Map
VIP Control Registers
0x0005F800 - Interrupt Pending
0x0005F802 - Interrupt Enable
0x0005F804 - Interrupt Clear
0x0005F820 - Display Status
0x0005F822 - Display Control
0x0005F824 - LED Brightness 1
0x0005F826 - LED Brightness 2
0x0005F828 - LED Brightness 3
0x0005F82A - LED Brightness Idle
0x0005F82E - Frame Repeat
0x0005F830 - Column Table Address
0x0005F840 - Drawing Status
0x0005F842 - Drawing Control
0x0005F844 - Version
0x0005F848 - OBJ Group 0 Pointer
0x0005F84A - OBJ Group 1 Pointer
0x0005F84C - OBJ Group 2 Pointer
0x0005F84E - OBJ Group 3 Pointer
0x0005F860 - BG Palette 0
0x0005F862 - BG Palette 1
0x0005F864 - BG Palette 2
0x0005F866 - BG Palette 3
0x0005F868 - OBJ Palette 0
0x0005F86A - OBJ Palette 1
0x0005F86C - OBJ Palette 2
0x0005F86E - OBJ Palette 3
0x0005F870 - Clear Color
The VIP Control Registers must be accessed as halfwords (16 bits). Byte access does not work, and any addresses except those listed above cannot be accessed. Editor's Note: Not that it would be recommended, but will word access work?

VIP Display Procedure

The VIP display procedure occurs at 50.0hz, or at a 20 millisecond interval. Activities occur during the procedure in the following order:

• The Start of Frame Processing status is set.
• Depending on the value of the Frame Repeat register, the drawing procedure (see below) may occur. However, if the previous frame's drawing procedure is still working, the Drawing Exceeds Frame Period status will be set instead.
• At this point, depending on how much time is left, the CPU can further manipulate the frame buffers prior to display.
• The left frame buffer is displayed. When this completes, it will set the Left Display Finished status.
• The right frame buffer is displayed. When this completes, it will set the Right Display Finished status.

Drawing Procedure

According to the number of display frames specified by the Frame Repeat register, the drawing procedure will be performed. Activities occur during the procedure in the following order:

• The Start of Drawing status is set.
• The first frame buffer used for each display is buffer 0. The next drawing frame uses buffer 1, and it alternates in this manner every other drawing frame.
• Frame buffers are processed 8 pixels at a time, starting at the top-left corner of the image and working down. When rendering reaches the bottom of the image, it continues from the top of the next column to the right. The Drawing Y Position Match status can be configured for this time.
• Before any Window data is drawn, the pixels are populated with the clear color.
• All 32 Windows are processed, starting with Window 31 and working back to Window 0. Windows with lesser indexes are drawn in front of Windows with greater indexes.
• Windows of mode Normal, Line Shift and Affine are drawn according to their attributes and optional parameters. Windows of mode Object are drawn using the process described in the VIP Window Mode: Object section.
• The Window Stop attribute can be used to cause the VIP to stop drawing Windows immediately.
• The Drawing Finished status will be set.

Various VIP interrupts can be configured when various display statuses become set.

Editor's Note: What is the exact timing of each stage of the display procedure? Is it 10ms between Start of Frame Processing and the time the left frame buffer is transmitted, and each display is 5ms? How many pixels of each Window type can the VIP draw before Drawing Exceeds Frame Period?

VIP Frame Buffers

When the VIP sends images to the LED displays, it loads them from the active frame buffer for each display. Both displays have two frame buffers. The VIP will use one frame buffer for one display frame, then the other frame buffer for the next display frame. The active frame buffer will alternate in this manner every other frame, starting with frame buffer 0.
0x00000000-0x00005FFF   Left Frame Buffer 0
0x00008000-0x0000DFFF   Left Frame Buffer 1
0x00010000-0x00015FFF   Right Frame Buffer 0
0x00018000-0x0001DFFF   Right Frame Buffer 1
The format of all four frame buffers is the same: there are 0x6000 bytes representing a 384x256 pixel image at 2 bits per pixel. Pixels are stored in column-major order (top to bottom first, then left to right) starting with the least significant bits of the first byte. Only the first 224 pixels within each column will be output to the display.

The VIP will compose images from graphical elements and store the results in the frame buffers. The program may then further manipulate the frame buffers. Afterward, the VIP will read from the frame buffers to send image data to the LED displays. For more information, refer to the VIP Drawing Procedure section.

VIP Characters

The VIP contains enough Character memory for 2048 Characters. They are all indexed sequentially from 0 to 2047, but their memory regions are not contiguous. The reason for this likely comes from a design consideration where Character memory fills in the otherwise unused regions in between frame buffer memory.
0x00006000-0x00007FFF   CHR RAM Pattern Table 0
0x0000E000-0x0000FFFF   CHR RAM Pattern Table 1
0x00016000-0x00017FFF   CHR RAM Pattern Table 2
0x0001E000-0x0001FFFF   CHR RAM Pattern Table 3
In addition to these four memory ranges, Character memory is mirrored linearly from 0x00078000 to 0x0007FFFF, which is a contiguous region. The region of addresses from 0x00060000 to 0x0007FFFF is otherwise unused, save for the virtual mapping of Character memory addresses.
0x00078000-0x00079FFF   Mirroring of CHR RAM Pattern Table 0
0x0007A000-0x0007BFFF   Mirroring of CHR RAM Pattern Table 1
0x0007C000-0x0007DFFF   Mirroring of CHR RAM Pattern Table 2
0x0007E000-0x0007FFFF   Mirroring of CHR RAM Pattern Table 3
The format of Characters is 16 bytes, representing an 8x8 pixel square with 2 bits per pixel. The lowest bits of the first byte represent the top-left pixel, the highest bits of the second byte represent the top-right pixel, and so on for all pixels within the Character.

VIP Background Segments

A Background Segment represents a 64x64 grid of Characters, with optional effects such as flip and Palette selection.
0x00020000-0x0003D7FF   Background Segments and Window Parameter Table
Background Segments occupy 8 KB of memory (0x2000 bytes), and there is enough room in the memory region for 14 Segments (0x00020000-0x0003BFFF). There is an additional 0x1800 bytes at the end of the region that cannot be used as Segment memory, but can be used as Window parameter memory.

The boundary between Background Segments and Window parameters varies depending on context; both types of data share the same memory. Editor's Note: Is it possible to interleave Window parameters in between Segments? Is it possible to store parameter data in memory that belongs to a Segment already in use?

Background Segments are 64x64 grids of cells, where the first entry specifies the upper-left cell, the 64th entry specifies the upper-right cell, and so on for all 4096 entries. Entries are 16 bits in size and have the following format:
    15 14 13 12 11 10         0
   +-----+--+--+--+------------+
   | Pal |HF|VF|0 | Character  |
   +-----+--+--+--+------------+
Bits: 2   1  1  1       11
Character - The index of the Character in CHR memory (0 to 2047) to display in this cell.
VF - Vertical Flip - If set, the Character will be flipped vertically.
HF - Horizontal Flip - If set, the Character will be flipped horizontally.
Pal - Palette - The Palette index (0 to 3) for this Character. Specified by the BG Palette registers.

The effect of using both the horizontal and vertical flip attributes is that the Character will be rotated 180 degrees.

VIP Objects

Objects, also known as sprites, are graphical elements that can be used to display Characters at arbitrary locations. This contrasts with the Background, which can only display Characters at a fixed, 8-pixel interval. The trade-off is that Objects require more memory per Character, and take longer to draw.
0x0003E000-0x0003FFFF   Object Attribute Memory (OAM)
Object entries consist of 8 bytes each, and there is enough room in OAM for 1024 Object definitions. Not all Objects need to be used. Object definitions are organized as 4 halfwords and have the following format:
   15 14                    0
  +--------------------------+
0 |            X             |
  +--+--+--------------------+
1 |L |R |      Parallax      |
  +--+--+--------------------+
2 |            Y             |
  +-----+--+--+--+-----------+
3 | Pal |HF|VF|0 | Character |
  +-----+--+--+--+-----------+
   15 14 13 12 11 10        0
X - Signed X coordinate, in pixels, of the top-left pixel of the Object within the parent Window. 0 is on the left.
Parallax - The signed, X horizontal bias for parallax effects. Subtract from X for the left display, and add to X for the right display.
L - Left - When set, Object will be drawn on the left display.
R - Right - When set, Object will be drawn on the right display.
Y - Signed Y coordinate, in pixels, of the top-left pixel of the Object within the parent Window. 0 is on the top.
Character - The index of the Character in CHR memory (0 to 2047) to display in this Object.
VF - Vertical Flip - If set, the Character will be flipped vertically.
HF - Horizontal Flip - If set, the Character will be flipped horizontally.
Pal - Palette - The Palette index (0 to 3) for this Object. Specified by the OBJ Palette registers.

The Left and Right fields operate independently from the corresponding fields in the Window definition. A Window can be drawn to both displays, yet Objects within it might not be.

The fourth halfword of the Object definition has the same format as the halfword of the Background entry definition.

The effect of using both the horizontal and vertical flip attributes is that the Character will be rotated 180 degrees.

VIP Windows

VIP Window Attributes
VIP Window Backgrounds
VIP Window Mode: Normal
VIP Window Mode: Line Shift
VIP Window Mode: Affine
VIP Window Mode: Object

VIP Window Attributes

Windows are the root construct from which all graphics are drawn by the VIP. They can specify either Backgrounds or groups of Objects, both of which specify pixel data from Characters. Their position, size and contents can be configured.
0x0003D800-0x0003DBFF   Window Attributes
Window entries consist of 32 bytes each, and there is enough room in memory for 32 Windows. Not all Windows need to be used.

Window definitions are organized as 16 halfwords and have the following format:
    15 14 13 12 11 10 9 8  7   6   5 4 3     0
   +--+--+-----+-----+---+---+----+---+-------+
 0 |L |R |Mode | BGW |BGH|OoB|Stop|0 0|BaseSeg|
   +--+--+-----+-----+---+---+----+---+-------+
 1 |                    X                     |
   +------------------------------------------+
 2 |                 Parallax                 |
   +------------------------------------------+
 3 |                    Y                     |
   +------------------------------------------+
 4 |                   BG X                   |
   +------------------------------------------+
 5 |               BG Parallax                |
   +------------------------------------------+
 6 |                   BG Y                   |
   +------------------------------------------+
 7 |                  Width                   |
   +------------------------------------------+
 8 |                  Height                  |
   +------------------------------------------+
 9 |            Parameter Address             |
   +------------------------------------------+
10 |          Out of Bounds Character         |
   +------------------------------------------+
11 |                                          |
12 |                                          |
13 |             VIP Scratch Area             |
14 |                                          |
15 |                                          |
   +------------------------------------------+
BaseSeg - Base Background Segment - The index of the first Background Segment (0 to 13) of the Window's background.
Stop - Stop Drawing Windows - If set, then this Window and all Windows with lesser indexes will not be drawn.
OoB - Out of Bounds - Determines what is drawn when the Window's Background is scrolled beyond the bounds of the Background itself:
• 0 = The entire background will repeat as if tessellated.
• 1 = The Out of Bounds Character will be drawn in all cells beyond the bounds of the Background.
BGH - BG Height - Raising 2 to the power of this field will yield the height of the Window's background, in Background Segments.
BGW - BG Width - Raising 2 to the power of this field will yield the width of the Window's background, in Background Segments.
Mode - Indicates how the Window will draw its contents:
• 0 = Normal
• 1 = Line Shift
• 2 = Affine
• 3 = Object
L - Left - When set, Window will be drawn on the left display.
R - Right - When set, Window will be drawn on the right display.
X - Signed X coordinate, in pixels, of the top-left pixel of the Window within the display. 0 is on the left.
Parallax - The signed, X horizontal bias for parallax effects. Subtract from X for the left display, and add to X for the right display.
Y - Signed Y coordinate, in pixels, of the top-left pixel of the Window within the display. 0 is on the top.
BG X - Signed X coordinate of the pixel within the Background to be displayed as the top-left pixel of the Window. 0 is the left edge of the Background.
BG Parallax - The signed, X horizontal bias for Background parallax effects. Subtract from BG X for the left display, and add to BG X for the right display.
BG Y - Signed Y coordinate of the pixel within the Background to be displayed as the top-left pixel of the Window. 0 is the top edge of the Background.
Width - The unsigned width of the Window, in pixels. Add 1 to this value for the actual width.
Height - The unsigned height of the Window, in pixels. Add 1 to this value for the actual height.
Parameter Address - Offset into BG Segment/Window Params memory where any parameters for this Window are stored. To resolve the actual address, multiply this value by 2, then add 0x00020000.
Out of Bounds Character - If specified, references the Background cell entry index relative to Base Background Segment. This Character will be drawn when the Window's Background is scrolled beyond the bounds of the Background itself.
VIP Scratch Area - The VIP uses this memory as working variables during the drawing process. The CPU is not allowed to write to this area. Editor's Note: Can the CPU read from this area?

Base Background Segment must be in the range of 0 to 13.

Window widths must be in the range of 1 to 384 pixels. Window heights must be in the range of 8 to 224 pixels for all Window modes except Affine, and 1 to 224 for Affine mode Windows.

The lowest 4 bits of Parameter Address must be 0. That is to say, the parameter address must be divisible by 16.

Editor's Note: Can the OoB Char be taken from a Segment that isn't part of the Window's Background?

For information regarding how the VIP processes window data, refer to the VIP Drawing Procedure section.

VIP Window Backgrounds

For all Window modes except Object, the Window's Background is constructed with Background Segments. The Segments used are always sequential, starting with the Segment specified by the Window's Base Background Segment attribute.

Backgrounds must consist of 1, 2, 4 or 8 Segments, and any combination of BG Width and BG Height that satisfies that requirement is vaild. The value of the Window's Base Background Segment field must be divisible by the number of Segments in the Background, and there must be enough Segment memory from that point to accommodate every Segment in the Background. For example, a 4-Segment Background may begin with Segments 0, 4 or 8. It cannot begin with Segment 12, however, because there is only memory for 14 Segments and 12 + 4 > 14.

The top-left Segment is the first Segment, and is the one specified by the Window's Base Background Segment attribute. Segment indexes then increment by 1 in row-major order. For example, a Background that is 4 Segments wide, 2 Segments tall, and a Base Background Segment of 0: the top-left Segment is 0; the top-right Segment is 3; the bottom-left Segment is 4; and the bottom-right Segment is 7.

VIP Window Mode: Normal

For Normal mode Windows, no additional information is necessary: all of the applicable fields are specified in VIP Window Attributes.

• The Windows' Backgrounds are selected as specified.
• Windows are drawn on the specified displays.
• Windows are drawn with the given widths, heights and Y coordinates.
• The Windows' X positions are calculated as X - Parallax for the left display and X + Parallax for the right display.
• The left edge of the visible clipping regions within the Windows' Backgrounds are calculated as BG X - BG Parallax for the left display and BG X + BG Parallax for the right display.
• The top edge of the visible clipping regions within the Windows' Backgrounds are given by BG Y.
• The width and height of the visible clipping regions within the Windows' Backgrounds are the same as the Windows' width and height.
• If pixels past the bounds of the Background are visible in the Window, it will either repeat the Background or the Out of Bounds Character (according to configuration).

The Parameter Address field is not used for Windows with mode Normal.

VIP Window Mode: Line Shift

Windows of mode Line Shift consist of all of the functionality of mode Normal, with additional processing of the source X coordinate within the Window's Background. Each row of pixels within the Window can specify horizontal shifts for each display independently, further modifying the BG X attribute.

The Parameter Address field specifies the address within the BG Segment/Window Parameter memory to use for Line Shift parameters:
0x00020000-0x0003D7FF   Background Segments and Window Parameter Table
The memory used for Line Shift parameters must contain enough entries to account for every row of pixels in the Window. That is to say, the number of Line Shift entries should be at least the height of the Window. Line Shift entries are 4 bytes, organized into two halfwords and with the following format:
 15             0
+----------------+
|   Left Shift   |
+----------------+
|  Right Shift   |
+----------------+
Left Shift - The signed shift amount for the corresponding line in the left display. This is added to the source X coordinate within the Background. The final Background source X coordinate is calculated as BG X - BG Parallax + Left Shift
Right Shift - The signed shift amount for the corresponding line in the right display. This is added to the source X coordinate within the Background. The final Background source X coordinate is calculated as BG X + BG Parallax + Right Shift

The first Line Shift entry applies to the top row of pixels in the Window, and each additional entry proceeds towards the bottom.

Line Shift values must be in the range of -511 to 511.

VIP Window Mode: Affine

The Affine Window mode on Virtual Boy features similar functionality to the famous "Mode 7" screen mode of the Super NES. With it, various effects can be applied to Window Backgrounds, including scaling, rotation and perspective projection. In contrast to the SNES, the Virtual Boy can provide these transformations to any number of Windows individually.

Windows of mode Affine consist of all of the functionality of mode Normal, with the exception that the source X and Y coordinates within the Window's Background are calculated differently. The BG X, BG Parallax and BG Y attributes are not used in Affine mode.

The Parameter Address attribute specifies the address within the BG Segment/Window Parameter memory to use for Affine parameters:
0x00020000-0x0003D7FF   Background Segments and Window Parameter Table
The memory used for Affine parameters must contain enough entries to account for every row of pixels in the Window. That is to say, the number of Affine entries should be at least the height of the Window. Affine entries are 16 bytes, organized into eight halfwords and with the following format:
   15             0
  +----------------+
0 |      BG X      |
  +----------------+
1 |  BG Parallax   |
  +----------------+
2 |      BG Y      |
  +----------------+
3 | BG X Increment |
  +----------------+
4 | BG Y Increment |
  +----------------+
5 |                |
6 |  VIP Scratch   |
7 |                |
  +----------------+
BG X - Signed X coordinate of the pixel within the Background to be displayed as the top-left pixel of the Window. 0 is the left edge of the Background. This value is stored as 13.3 fixed point.
BG Parallax - The signed, X horizontal bias for Background parallax effects. This is a 16-bit integer. See below for how this value is used.
BG Y - Signed Y coordinate of the pixel within the Background to be displayed as the top-left pixel of the Window. 0 is the top edge of the Background. This value is stored as 13.3 fixed point.
BG X Increment - For every pixel along the corresponding row of output pixels in the Window, add this value to the Background source X coordinate, starting at BG X. This value is stored as 7.9 fixed point.
BG Y Increment - For every pixel along the corresponding row of output pixels in the Window, add this value to the Background source Y coordinate, starting at BG Y. This value is stored as 7.9 fixed point.
VIP Scratch - The VIP uses this memory as working variables during the drawing process. The CPU is not allowed to write to this area. Editor's Note: Can the CPU read from this area?

The BG X and BG Y parameters are stored as fixed-point fields, where the upper 13 bits represent the integer and the lower 3 bits represent the fraction (halves, quarters and eighths).

The BG X Increment and BG Y Increment parameters are stored as fixed-point fields, where the upper 7 bits represent the integer and the lower 9 bits represent the fraction (halves, quarters, eighths, etc.).

Affine Parallax

The parallax calculations for Affine Windows works differently than it does for Normal, Line Shift and Object:

• If BG Parallax is negative, it is added to the Window X coordinate index prior to fetching the pixel from the Background for the left display. The right display is not affected.
• If BG Parallax is non-negative, it is added to the Window X coordinate index prior to fetching the pixel from the Background for the right display. The left display is not affected.

For any given pixel within a row of pixels in a Window, denoted by Window_X and starting at 0, the output pixels for the left and right displays can be determined with the following algorithm:
X1 = BG_X + BG_X_Increment *  Window_X
Y1 = BG_Y + BG_Y_Increment *  Window_X
X2 = BG_X + BG_X_Increment * (Window_X + BG_Parallax)
Y2 = BG_Y + BG_Y_Increment * (Window_X + BG_Parallax)

If BG_Parallax < 0 Then
    Output_Left  = Background.Pixel(X2, Y2)
    Output_Right = Background.Pixel(X1, Y1)
Else
    Output_Left  = Background.Pixel(X1, Y1)
    Output_Right = Background.Pixel(X2, Y2)
End If
The values of the source X and Y coordinates to fetch from the Background must be in the range of -4096 to 4096. Editor's Note: What happens if they go out of bounds?

VIP Window Mode: Object

Up to four Windows can be specified as type Object. Objects are organized into four groups, by index, and entire groups are drawn by specifying Object Windows.

No Background information is used in Object Windows. All attributes that do not pertain to Background information still apply.

Like the Windows themselves, the VIP will draw Objects in reverse order, starting with the highest specified index and counting down. Objects with lesser indexes will be drawin in front of Objects with greater indexes. The exact indexes to start and stop at are specified by the OBJ Group registers.

0x0005F848 - OBJ Group 0 Pointer (R/W)
0x0005F84A - OBJ Group 1 Pointer (R/W)
0x0005F84C - OBJ Group 2 Pointer (R/W)
0x0005F84E - OBJ Group 3 Pointer (R/W)

Bits 15-10   Not used
Bits  9-0    Object Index
For each display frame, the VIP keeps track of which Object groups have been drawn. The first time an Object Window is drawn, it will contain Object group 3. The second time, it will contain Object group 2. This continues for groups 1 and 0.

The first Object drawn from a group in an Object Window is specified by the OBJ Group register that corresponds with that Object group. For example, OBJ Group 2 Pointer corresponds with Object group 2, and the register itself contains the index of the first Object to draw in group 2. Object indexes range from 0 to 1023.

The VIP will continue to draw Objects, decreasing the index by 1 each time, for as long as the current Object index is greater than the index specified by the next OBJ Group register. For example, if OBJ Group 2 Pointer is set to 123 and OBJ Group 1 Pointer is set to 45, then Object group 2 will consist of all Objects with indexes in the range of 46 to 123.

If the next OBJ Group register has a value greater than or equal to the current OBJ Group register, or if the current Object group being drawn is group 0, then all remaining Objects through index 0 will be drawn. Having said that, additional Object Windows can still be used, because the VIP starts drawing Objects at the values specified in the OBJ Group registers each time.

Object Windows used after Object group 0 has been drawn during one display frame will not have any effect. Editor's Note: Is this correct?

VIP Column Table

In order to produce a 2-dimensional matrix of pixels on a display consisting of 1 column of LEDs, the Virtual Boy uses two oscillating mirrors and times the emission of light from the LEDs accordingly. This physically works due to the afterimage properties of the human retina. However, this means that the amount of time each column of pixels should be displayed varies as the angle of the mirror relative to the LEDs changes. To correct for this movement, the column table was implemented.
0x0003DC00-0x0003DFFF   Column Table
The column table is divided into halves: 0x0003DC00 to 0x0003DDFF represent the table vaules for the left display, and 0x0003DE00 to 0x0003DFFF represent the table values for the right display. Table values are 16 bits in size, and there is enough room for 512 entries total.

The format of a column table entry is as follows:
 15     8 7      0
+--------+--------+
| Repeat |  Time  |
+--------+--------+
Time - The amount of time, in units of 200 nanoseconds, to display the corresponding four columns. Add 1 to this value. Must be 0x2C <= Time <= 0xFE
Repeat - The number of times to repeat the LED emission for each of the corresponding four columns. Add 1 to this value.

The column table contains 96 significant timing values, each corresponding with 4 columns of display for a total of 384 columns. Additional column entries are provided to stabilize the display when beyond the bounds of the display frame. The amount of time a column remains active must be greater than the total time spent emitting light on that column.

The number of times light is emitted on a column is a brightness multiplier for that column. By using low values in the LED Brightness registers, the Repeat field in the column table can be used for varying levels of brightness horizontally along the display.

Editor's Note: For all intents and purposes, the maximum brightness of a column as specified by the Brightness registers, times the number of repetitions, should not be greater than 127.

The column table entries at 0x0003DCA4 and 0x0003DEA4 represent the width of the 4 right-most columns of the left and right displays, respectively. Likewise, the entries at 0x0003DD62 and 0x0003DF62 represent the 4 left-most columns of the left and right displays, respectively.

0x0005F830 - Column Table Address (R)
Bit 15-8  Right Table Address
Bit  7-0  Left Table Address
Set by the VIP while outputting to the displays. Counts down for each display, 96 times during each display frame. The values in this register, multiplied by 2, result in the addresses relative to 0x0003DC00 (left) and 0x0003DE00 (right) to be read by the VIP.

Nintendo supplies a default column table for developers. In normal situations, this will never need to be changed, with the possible exception of the Repeat values:
0000   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
0010   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
0020   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
0030   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
0040   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
0050   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
0060   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
0070   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 E0 00 BC 00
0080   A6 00 96 00 8A 00 82 00  7A 00 74 00 6E 00 6A 00
0090   66 00 62 00 60 00 5C 00  5A 00 58 00 56 00 54 00
00A0   52 00 50 00 50 00 4E 00  4C 00 4C 00 4A 00 4A 00
00B0   48 00 48 00 46 00 46 00  46 00 44 00 44 00 44 00
00C0   42 00 42 00 42 00 40 00  40 00 40 00 40 00 40 00
00D0   3E 00 3E 00 3E 00 3E 00  3E 00 3E 00 3E 00 3C 00
00E0   3C 00 3C 00 3C 00 3C 00  3C 00 3C 00 3C 00 3C 00
00F0   3C 00 3C 00 3C 00 3C 00  3C 00 3C 00 3C 00 3C 00
0100   3C 00 3C 00 3C 00 3C 00  3C 00 3C 00 3C 00 3C 00
0110   3C 00 3C 00 3C 00 3C 00  3C 00 3C 00 3C 00 3C 00
0120   3C 00 3E 00 3E 00 3E 00  3E 00 3E 00 3E 00 3E 00
0130   40 00 40 00 40 00 40 00  40 00 42 00 42 00 42 00
0140   44 00 44 00 44 00 46 00  46 00 46 00 48 00 48 00
0150   4A 00 4A 00 4C 00 4C 00  4E 00 50 00 50 00 52 00
0160   54 00 56 00 58 00 5A 00  5C 00 60 00 62 00 66 00
0170   6A 00 6E 00 74 00 7A 00  82 00 8A 00 96 00 A6 00
0180   BC 00 E0 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
0190   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
01A0   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
01B0   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
01C0   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
01D0   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
01E0   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
01F0   FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
These values should be written to both 0x0003DC00 and 0x0003DE00. The list can be compacted: the high bytes are always 0x00, and the bottom half is radially symetrical to the top. It can be stored as 128 bytes, where values are written to the low addresses and counting up, as well as to the high addresses and counting down.

VIP Interrupts

The VIP has three registers for managing interrupt, and they all have the same format:

0x0005F800 - Interrupt Pending (R)
0x0005F802 - Interrupt Enable (R/W)
0x0005F804 - Interrupt Clear (W)

Bit  15     Drawing Exceeds Frame Period
Bit  14     Drawing Finished
Bit  13     Drawing Y Position Match
Bits 12-5   Not used
Bit   4     Start of Frame Processing
Bit   3     Start of Drawing
Bit   2     Right Display Finished
Bit   1     Left Display Finished
Bit   0     Display Not Ready
Interrupt Pending bits are set when their corresponding situations occur. These bits will still become set even if not selected by Interrupt Enable

Interrupt Enable selects which situations can raise VIP interrupts.

Interrupt Clear resets and acknowledges bits. To clear all pending interrupts, write to this register the same value read from Interrupt Pending.

When any enabled interrupt condition is met, a VIP interrupt is raised. VIP interrupts have an exception code of 0xFE40 and branch CPU execution to address 0xFFFFFE40.

For information on exactly when VIP interrupts occur relative to one another, refer to the VIP Display Procedure section.

The Display Exceeds Frame Period condition occurs when the VIP takes too much time drawing Window graphics, causing the rendering to spill over into the time when the left frame buffer is to be displayed.

The Drawing Finished condition occurs when all Window graphics have completed rendering to the frame buffers. Depending on how much Window data was processed, there may be enough time for the CPU to further manipulate the frame buffers prior to being displayed. Otherwise, this condition is useful as an analog to "VBlank", where it is safe to modify Window data without affecting display output.

Drawing Y Position Match occurs when the Y Position fields of the Drawing Status and Drawing Control registers match. This can happen once per column of pixels.

Start of Frame Processing occurs when the entire display procedure begins for each frame.

Start of Drawing occurs at the same time as Start of Frame Processing, but may not occur according to the Frame Repeat register.

Right Display Finished and Left Display Finished occur when the right and left displays (respectively) have completed LED emission and the corresponding frame buffers are no longer in use.

Display Not Ready occurs when display components are out of sync. The internal display controller will eventually correct itself.

VIP Display Registers

0x0005F820 - Display Status (R)
Bits 15-11   Not used
Bit  10      Column Table Address Locked
Bit   9      Display Sync Signals Enabled
Bit   8      VIP Memory is Refreshing
Bit   7      Display Procedure Beginning
Bit   6      Display is Ready
Bit   5      Right FB1 Being Displayed
Bit   4      Left FB1 Being Displayed
Bit   3      Right FB0 Being Displayed
Bit   2      Left FB0 Being Displayed
Bit   1      Display is Enabled
Bit   0      Not used
Display Procedure is Beginning will be set to 1 at the beginning of the Display Procedure.

Bits 5-2 can be read as a single value to determine whether the display is currently busy. If none of the frame buffers are being displayed, meaning the 4-bit value is zero, then it is safe to modify them.

0x0005F822 - Display Control (W)
Bits 15-11   Not used
Bit  10      Lock Column Table Address
Bit   9      Enable Display Sync Signals
Bit   8      Refresh VIP Memory
Bit   7-2    Not used
Bit   1      Enable Display
Bit   0      Reset Display
Lock Column Table Address prevents the VIP from reading new values from the column table, instead re-using the previously read value.

Enable Display Sync Signals is required to transfer frame buffer data to the LEDs. Editor's Note: Will other VIP interrupts still occur, just without any LED emissions?

Writing 1 to Refresh VIP Memory will initiate a memory-refresh cycle on VIP memory. Writing 0 has no effect. It is only used to perform the refresh operation.

Setting Enable Display to 1 enables the display, and setting it to 0 turns the display off.

Writing 1 to Reset Display sends a reset signal to the VIP. The VIP will idle until the start of the next display frame. It will also clear the following interrupts in the Interrupt Pending register:

• Drawing Exceeds Frame Period
• Start of Frame Processing
• Start of Drawing
• Right Display Finished
• Left Display Finished
• Display Not Ready

Writing 0 to Reset Display has no effect. It is only used to perform the reset operation.

VIP Brightness and Palettes

0x0005F824 - LED Brightness 1 (W)
0x0005F826 - LED Brightness 2 (W)
0x0005F828 - LED Brightness 3 (W)
0x0005F82A - LED Brightness Idle (W)

Bits 15-8   Not used
Bits  7-0   Brightness
The values specified in the Brightness registers indicate how long, in units of 50 nanoseconds, LEDs should emit light for the corresponding color values. The longer light is emitted for a single pixel, the brighter that pixel will appear.

Brightness settings 1 and 2 are used directly. Brightness setting 3, however, is actually the sum of the LED Brightness 1, 2 and 3 registers. For this reason, if LED Brightness 1 is set to some number X, Brightness 2 to 2X, and Brightness 3 to 0, the net brightness of Brightness 3 is actually X + 2X + 0 = 3X.

The emission period for a single pixel is equal to the time specified by the corresponding Brightness register, plus the time specified by the Brightness Idle register, plus five inactive clocks (250 nanoseconds). This emission period is repeated for each pixel according to the configuration in the column table. The number of repetitions is effectively a brightness multiplier: 2 repetitions is twice as bright, 3 repetitions is three times as bright, etc.

The product of the emission period times the number of repetitions must be less than the total display period for the column of pixels in question.

The LED Brightness Idle register does not represent the brightness timing for any color value. It is, however, added to the end of all columns' emission periods, but without emitting any light.

Editor's Note: The calculations don't seem to match up with observations during bench testing. Testing shows that the maximum effective brightness is 128, or slightly less than that. This might be due to the actual maximum physical brightness of the LEDs, however.

0x0005F860 - BG Palette 0 (R/W)
0x0005F862 - BG Palette 1 (R/W)
0x0005F864 - BG Palette 2 (R/W)
0x0005F866 - BG Palette 3 (R/W)
0x0005F868 - OBJ Palette 0 (R/W)
0x0005F86A - OBJ Palette 1 (R/W)
0x0005F86C - OBJ Palette 2 (R/W)
0x0005F86E - OBJ Palette 3 (R/W)

Bits 15-8   Not used
Bits  7-6   Color for Pixel Value 3
Bits  5-4   Color for Pixel Value 2
Bits  3-2   Color for Pixel Value 1
Bits  1-0   Not used
When a pixel is fetched from a Character, it is passed through one of these Palettes. The exact Palette to use is specified in the Background entry or Object referencing the Character. The values in the Palette for each pixel value correspond with the brightness registers of the same index.

For example, let's say a Character pixel is read, and its value is 2. Let's also say that the Character was used in a Background, and the specified Palette was 1. Lastly, let's say that the value in BG Palette 1 is 0x00B8. Pixel value 2 corresponds with bits 5-4, which in 0x00B8 come out to 3. Therefore, the Brightness 3 register is used as the color for this pixel.

As there is no Brightness register for color 0, specifying a Palette value of 0 will be unconditionally black.

A transparent pixel will occur if the pixel value in the Character is 0.

0x0005F870 - Clear Color (R/W)
Bits 15-2   Not used
Bits  1-0   Clear Color
When the VIP begins rending using Window data, it first resets the entire frame buffer to the value specified in this register. Upon display, the Brightness register of the same index will be used to generate the color.

As there is no Brightness register for color 0, specifying a clear color of 0 will be unconditionally black.

VIP Drawing Registers

0x0005F840 - Drawing Status (R)
Bit  15      Drawing at Y Position
Bits 14-13   Not used
Bits 12-8    Current Y Position
Bit   4      Drawing Exceeds Frame Period
Bit   3      Writing to Frame Buffer 0
Bit   2      Writing to Frame Buffer 1
Bit   1      Drawing is Enabled
Bit   0      Not used
Drawing at Y Position will be set when Current Y Position matches the Y Position field in the Drawing Control register.

The Display Exceeds Frame Period condition occurs when the VIP takes too much time drawing Window graphics, causing the rendering to spill over into the time when the left frame buffer is to be displayed.

VIP interrupts can be rased for the above status conditions. For more information, refer to Display Procedure.

Current Y Position indicates which pixels are being rendered by the VIP within the current column of pixels. Pixels are processed in units of 8, so multiply this value by 8 for the actual vertical coordinate within the frame buffer.

Writing to Frame Buffer 0 and Writing to Frame Buffer 1 indicate which frame buffer is being rendered to for this frame. They will not both be set in a single read.

0x0005F842 - Drawing Control (W)
Bits 15-13   Not used
Bits 12-8    Y Position
Bit   1      Enable Drawing
Bit   0      Reset Drawing
Y Position is used in conjunction with the Current Y Position field of Drawing Status, and the Drawing Y Position Match field of Interrupt Enable to configure an interrupt to occur at a particular Y position for each column of pixels being rendered. Multiply this value by 8 for the actual Y position within the iamge.

Setting Enable Drawing to 1 enables rendering of Window data to the frame buffers, and setting it to 0 turns drawing off.

Writing 1 to Reset Drawing sends a drawing reset signal to the VIP. Drawing will stop, but one of the Writing to Frame Buffer flags will become set in Drawing Status. Do not access any Object Group, Palette, or the Version register until both flags are cleared.

Reset Drawing will also clear the following interrupts in the Interrupt Pending register:

• Drawing Exceeds Frame Period
• Drawing Finished
• Display Not Ready

Writing 0 to Reset Drawing has no effect. It is only used to perform the reset operation.

VIP Miscellaneous Registers

0x0005F82E - Frame Repeat (W)
Bits 15-4   Not used
Bits  3-0   Repeat Count
This register controls how many display frames elapse before the VIP Drawing Procedure occurs. Add 1 to this value to specify the number of display frames.

To suspend drawing indefinitely, simply disable it in Drawing Control.

0x0005F844 - Version (R)
Bits 15-5   Not used
Bits  4-0   Version
Indicates the hardware version of the VIP, which can be used to determine what features are available. There was only ever one model of the Virtual Boy produced, and its version is 2.

Virtual Sound Unit (VSU)

Overview
VSU Overview
VSU Memory Map
VSU Generation Procedure
VSU Master Control

Channel Features
VSU PCM Waveforms
VSU Play Control
VSU Volume
VSU Frequency
VSU Envelope
VSU Sweep & Modulation
VSU Noise Generator

VSU Overview

The Virtual Boy's sound unit has 5 wave channels and a noise channel. The system has two built-in stereo speakers, a volume wheel, and a headphone jack.

Channels 1 through 4 are standard wave channels. Channel 5 contains all of the functionality of the standard wave channels, as well as support for frequency sweep and modulation. The sixth channel is a noise generator.

Wave generation is performed by writing 32 PCM samples to VSU memory and those samples are used to produce the output waves.

Audio output is 10-bit stereo at 41700 hz.

VSU Memory Map

Editor's Note: Is the VSU memory range mirrored at all?

VSU Memory Map
0x01000000-0x0100007F   PCM Wave Table 0
0x01000080-0x010000FF   PCM Wave Table 1
0x01000100-0x0100017F   PCM Wave Table 2
0x01000180-0x010001FF   PCM Wave Table 3
0x01000200-0x0100027F   PCM Wave Table 4
0x01000280-0x010002FF   Modulation Table
0x01000400-0x010005FF   VSU Control Registers (See below)
VSU Control Registers
0x01000400 - Channel 1 Play Control
0x01000404 - Channel 1 Volume
0x01000408 - Channel 1 Frequency Low
0x0100040C - Channel 1 Frequency High
0x01000410 - Channel 1 Envelope Data
0x01000414 - Channel 1 Envelope Control
0x01000418 - Channel 1 PCM Wave

0x01000440 - Channel 2 Play Control
0x01000444 - Channel 2 Volume
0x01000448 - Channel 2 Frequency Low
0x0100044C - Channel 2 Frequency High
0x01000450 - Channel 2 Envelope Data
0x01000454 - Channel 2 Envelope Control
0x01000458 - Channel 2 PCM Wave

0x01000480 - Channel 3 Play Control
0x01000484 - Channel 3 Volume
0x01000488 - Channel 3 Frequency Low
0x0100048C - Channel 3 Frequency High
0x01000490 - Channel 3 Envelope Data
0x01000494 - Channel 3 Envelope Control
0x01000498 - Channel 3 PCM Wave

0x010004C0 - Channel 4 Play Control
0x010004C4 - Channel 4 Volume
0x010004C8 - Channel 4 Frequency Low
0x010004CC - Channel 4 Frequency High
0x010004D0 - Channel 4 Envelope Data
0x010004D4 - Channel 4 Envelope Control
0x010004D8 - Channel 4 PCM Wave

0x01000500 - Channel 5 Play Control
0x01000504 - Channel 5 Volume
0x01000508 - Channel 5 Frequency Low
0x0100050C - Channel 5 Frequency High
0x01000510 - Channel 5 Envelope Data
0x01000514 - Channel 5 Envelope/Sweep/Modulation Control
0x01000518 - Channel 5 PCM Wave
0x0100051C - Channel 5 Sweep/Modulation Data

0x01000540 - Noise Channel Play Control
0x01000544 - Noise Channel Volume
0x01000548 - Noise Channel Frequency Low
0x0100054C - Noise Channel Frequency High
0x01000550 - Noise Channel Envelope Data
0x01000554 - Noise Channel Envelope/Noise Control

0x01000580 - Sound Disable
All VSU control registers are 8 bits wide and should be accessed by byte.

VSU Generation Procedure

The procedure for producing audio on the Virtual Boy is as follows. This section describes the operations of the hardware and it is not necessary that this exact algorithm be used to produce sound. It is documented here for the sake of completeness.

Volume Generation

Volume levels are generated for each sound channel, as well as for each of the left and right stereo output channels. The volume generation for one output channel (left/right) for one sound channel is as follows:

• The 4-bit volume value is multiplied by the current 4-bit envelope value.
• Of the resulting 8 bits, only the upper 5 bits are used as the output volume.
• If the output volume is not 0, 1 is added to it.

Sample Generation

A sample, either from the PCM waveforms or from the noise generator, is read in as a 6-bit value according to the sweep, modulation and noise specifications. It is then processed as follows, for each of the left and right output channels independently:

• The 6-bit sample is multiplied by the 5-bit volume value calculated in the Volume Generation procedure.
• Of the resulting 11 bits, only the upper 10 are used.
• The 10-bit values for all samples are added together.
• Of the resulting 13-bit value, only the upper 10 are used as output.

The output sample rate is 41700 hz before being converted to an analog signal.

VSU Master Control

0x01000580 - Sound Disable (W)
Bits 7-1   Not used
Bit  0     Stop Sound
Setting Stop Sound to 1 will stop any sound channels currently generating sound. Editor's Note: Is this an action bit, or does it need to be set to 0 again before sounds can be used?

VSU PCM Waveforms

Wave generation on the VSU is performed by reading samples from PCM wave memory. There are five wave tables, each with 32 samples.
0x01000000-0x0100007F   PCM Wave Table 0
0x01000080-0x010000FF   PCM Wave Table 1
0x01000100-0x0100017F   PCM Wave Table 2
0x01000180-0x010001FF   PCM Wave Table 3
0x01000200-0x0100027F   PCM Wave Table 4
Samples are accessed on word boundaries, but only the 6 least significant bits are used. Samples are unsigned: 0 is the minimum value and 63 is the maximum value.

All 32 samples of a PCM wave table represent one cycle of the wave. To sample all 32 samples n times per second is to produce an n hz wave.

PCM wave table memory can only be written while all sound channels are inactive.

Editor's Note: Is PCM wave memory read/write or write-only?

0x01000418 - Channel 1 PCM Wave (W)
0x01000458 - Channel 2 PCM Wave (W)
0x01000498 - Channel 3 PCM Wave (W)
0x010004D8 - Channel 4 PCM Wave (W)
0x01000518 - Channel 5 PCM Wave (W)

Bits 7-3   Not used
Bits 2-0   Wave Index
The Wave Index field specifies which PCM wave table (0-4) to use on this sound channel. Editor's Note: What happens if you specify 5 or 6?

VSU Play Control

0x01000400 - Channel 1 Play Control (W)
0x01000440 - Channel 2 Play Control (W)
0x01000480 - Channel 3 Play Control (W)
0x010004C0 - Channel 4 Play Control (W)
0x01000500 - Channel 5 Play Control (W)
0x01000540 - Noise Channel Play Control (W)

Bit  7     Enable Channel
Bit  6     Not used
Bit  5     Use Duration
Bits 4-0   Duration
Setting Enable Channel to 1 will activate the sound channel and begin generating sound. Setting it to 0 will immediately stop sound generation on the channel.

Setting Use Duration to 1 will cause the channel to automatically deactivate after the specified duration has elapsed. Setting this bit to 0 will cause the channel to generate sound indefinitely until deactivated by some other means.

Duration specifies how long the channel should generate sound before automatically shutting itself off, in units of 260.4 Hz (≈ 38.402 milliseconds). Add 1 to this value for the actual duration specifier.

Editor's Note: This whole business with duration is being interpreted correctly, right?

VSU Volume

Sound channel levels can be adjusted individually for both the left and right output channels.

0x01000404 - Channel 1 Volume (W)
0x01000444 - Channel 2 Volume (W)
0x01000484 - Channel 3 Volume (W)
0x010004C4 - Channel 4 Volume (W)
0x01000504 - Channel 5 Volume (W)
0x01000544 - Noise Channel Volume (W)

Bits 7-4   Left Volume
Bits 3-0   Right Volume
Left Volume controls the channel for the left output channel, and Right Volume controls the right channel. The minimum value is 0, which specifies silence, and the maximum value is 15.

VSU Frequency

The input sample rate for all sound channels is variable. All frequency values are 11 bits in size.

0x01000408 - Channel 1 Frequency Low (W)
0x01000448 - Channel 2 Frequency Low (W)
0x01000488 - Channel 3 Frequency Low (W)
0x010004C8 - Channel 4 Frequency Low (W)
0x01000508 - Channel 5 Frequency Low (W)
0x01000548 - Noise Channel Frequency Low (W)

Bits 7-0   Data
0x0100040C - Channel 1 Frequency High (W)
0x0100044C - Channel 2 Frequency High (W)
0x0100048C - Channel 3 Frequency High (W)
0x010004CC - Channel 4 Frequency High (W)
0x0100050C - Channel 5 Frequency High (W)
0x0100054C - Noise Channel Frequency High (W)

Bits 7-3   Not used
Bits 2-0   Data
The Frequency registers modify the sound channel's input sampling rate. Samples read from PCM waveforms or from the noise generator are produced at the specified frequency, which allows different tones to be generated.

PCM Waveform Sample Rate

When PCM waveforms are sampled, the value of the Frequency registers is used to calculate the sampling rate with the following formula:

PCM_Rate = 5,000,000 hz / ((2,048 - Frequency) * 32)

The minimum Frequency value for PCM waveforms is 0 (≈ 76.29 hz), and the maximum value is 2,040 (≈ 19,531.25 hz). Editor's Note: What happens if you specify a higher frequency? Specifying even 2047 gives the astronomically high frequency of 156,250.0 hz, so perhaps the hardware won't accept them.

Noise Sample Rate

When noise is sampled, the value of the Frequency registers is used to calculate the sampling rate with the following formula:

Noise_Rate = 500,000 hz / (2,048 - Frequency)

The minimum Frequency value for noise is 0 (≈ 244.14 hz) and the maximum value is 2,047 (= 500,000.00 hz).

VSU Envelope

The envelope function of sound channels allows their volume to decay over time.

0x01000414 - Channel 1 Envelope Control (W)
0x01000454 - Channel 2 Envelope Control (W)
0x01000494 - Channel 3 Envelope Control (W)
0x010004D4 - Channel 4 Envelope Control (W)
0x01000514 - Channel 5 Envelope/Sweep/Modulation Control* (W)
0x01000554 - Noise Channel Envelope/Noise Control* (W)

Bits 7-2   Not used*
Bit  1     Repeat Envelope
Bit  0     Enable Envelope
* - The Channel 5 and Noise registers have additional bits not pertinent to envelope control. For more information, see VSU Sweep & Modulation and VSU Noise Generator.

When Repeat Envelope is set to 1, and the envelope reaches 0, the envelope will be reset to its Reload Value and the cycle will repeat. When Repeat Envelope is set to 0, the envelope will remain at 0 once it reaches it.

Setting Enable Envelope to 1 will activate the envelope function, even while the channel is currently generating sound. Setting this bit to 0 will disable the envelope.

0x01000410 - Channel 1 Envelope Data (W)
0x01000450 - Channel 2 Envelope Data (W)
0x01000490 - Channel 3 Envelope Data (W)
0x010004D0 - Channel 4 Envelope Data (W)
0x01000510 - Channel 5 Envelope Data (W)
0x01000550 - Noise Channel Envelope Data (W)

Bits 7-4   Reload Value
Bit  3     Direction
Bits 2-0   Step Interval
Reload Value specifies the initial envelope value as well as the value it loads when repeating. When set, the envelope is immediately set to this value. 0 represents silence and 15 represents full volume.

Direction specifies the direction in which the envelope moves:

0 - Envelope will decrease (decay) over time.
1 - Envelope will increase (grow) over time.

In both cases, the envelope period ends when the envelope value reaches 0. For a growth period, this happens the next step after the value becomes 15.

Step Interval specifies how long each envelope value will last, in units of 65.1 hz (≈ 15.361 milliseconds). Add 1 to this value for the actual duration amount.

VSU Sweep & Modulation

Channel 5 has, in addition to all of the features of Channels 1-4, support for frequency sweep and modulation functions. Frequency modifications are made directly to the frequency registers.

0x01000514 - Channel 5 Envelope/Sweep/Modulation Control (W)
Bit  7     Not used
Bit  6     Enable Sweep/Modulation
Bit  5     Repeat Modulation
Bit  4     Function
Bits 3-0   Not used*
* - This register has additional bits not pertinent to sweep or modulation. For more information, see VSU Envelope.

Setting Enable Sweep/Modulation to 1 will activate the frequency modification feature of the channel. Setting this bit to 0 will deactivate the feature.

When Repeat Modulation is set to 1, the modulation samples will be read from the Modulation Table repeatedly. When this bit is 0, the modulation samples will be read once and the channel will continue with the last-read frequency.

Function specifies which frequency modification function to use:

0 - Sweep
1 - Modulation

0x0100051C - Channel 5 Sweep/Modulation Data (W)
Bit  7     Modification Base Interval
Bits 6-4   Modification Interval
Bit  3     Sweep Direction
Bits 2-0   Sweep Amount
The Modification Base Interval specifies the base frequency used by frequency modification functions:

0 - 1041.6 hz (≈ 0.96 milliseconds)
1 - 130.2 hz (≈ 7.68 milliseconds)

The integer value in Modification Interval is multiplied by the specified Modification Base Interval frequency to resolve the actual interval between frequency modifications.

If Modification Interval is 0, then frequency modification will not be performed.

For either frequency modificaiton function, if the frequency drops below 0 or rises above 2040, sound generation on channel 5 will be stopped.

Sweep

When using the sweep function, the frequency of sound channel 5 is modified over time algorithmically.

Sweep Direction specifies whether the frequency will change in an upward or downward direction:

0 - Sweep Amount is subtracted from the channel frequency
1 - Sweep Amount is added to the channel frequency

At the interval specified by Modification Base Interval and Modification Interval, sound channel 5's Frequency registers will be modified by +/- Sweep Amount, depending on the value of Sweep Direction.

Modulation

In addition to the values in the Channel 5 Sweep/Modulation Data register, sample memory exists for reading modulation data:
0x01000280-0x010002FF   Modulation Table
Like the PCM waveforms, the modulation samples are accessed as words, and there are 32 of them. Modulation samples have a different binary format, however: modulation samples are 8 bits, and signed (two's complement).

At the interval specified by Modification Base Interval and Modification Interval, sound channel 5's Frequency registers will be modified by the next modulation sample, according to the setting of Repeat Modulation.

Modulation table memory can only be written while all sound channels are inactive.

VSU Noise Generator

The Virtual Boy noise generator is a 15-bit linear feedback shift register with a configurable tap location. Output is binary: noise is only either high or low.

0x01000554 - Noise Channel Envelope/Noise Control (W)
Bit  7     Not used
Bits 6-4   Tap Location
Bits 3-0   Not used*
* - This register has additional bits not pertinent to noise generation. For more information, see VSU Envelope.

Tap Location specifies the bit within the shift register to use as the feedback source in noise generation. Different bits will produce pseudorandom bit sequences of different lengths before the sequences repeat. The bit positions were selected by the hardware designer and sorted in descending order of sequence length:

0 - Bit 14 - Sequence length of 32767
1 - Bit 10 - Sequence length of 1953
2 - Bit 13 - Sequence length of 254
3 - Bit 4 - Sequence length of 217
4 - Bit 8 - Sequence length of 73
5 - Bit 6 - Sequence length of 63
6 - Bit 9 - Sequence length of 42
7 - Bit 11 - Sequence length of 28

At the interval specified in the Frequency registers, a single bit is produced by the noise generator. The bit is then scaled to 6 bits to be the same size as the samples of the other sound channels. That is to say, if a 0 is generated, the sample is 0; and if a 1 is generated, the sample is 63.

Algorithm

The shift register is 15 bits wide and is initialized to all 1s. When a bit is produced as noise, two bits from the shift register are XORed together. One of the bits is bit 7, and the other bit is the bit specified by Tap Location. The inverse of the result (0 becomes 1 and vice/versa) is used as the output. The entire register is then shifted to the left one bit, and the result of the earlier XOR operation (not inverted) becomes the new bit 0.

Editor's Note: When is the shift register seeded to all 1s? When the Noise Control register is written?

Hardware Control Registers

Hardware Control Registers
Hardware Control Memory Map
Hardware Link Port
Hardware Game Pad
Hardware Timer
Hardware Wait Controller

Hardware Control Memory Map

All hardware control registers are 8 bits wide and should be accessed by byte.

Editor's Note: Is the hardware control memory range mirrored at all?

Hardware Control Memory Map
0x02000000 - Link Control Register
0x02000004 - Auxiliary Link Register
0x02000008 - Link Transmit Data
0x0200000C - Link Receive Data
0x02000010 - Game Pad Input Low
0x02000014 - Game Pad Input High
0x02000018 - Timer Counter/Reload Low
0x0200001C - Timer Counter/Reload High
0x02000020 - Timer Control Register
0x02000024 - Wait Control Register
0x02000028 - Game Pad Input Control Register
Addresses from 0x02000000 through 0x02FFFFFF other than the ones listed above do not have any behavior associated with them.

Hardware Link Port

The link port on the Virtual Boy is used for communications between two systems. No link cable was ever manufactured for Virtual Boy, and no commercial games are known to support communications.

The link port contains 8 pins and is keyed. The following diagram depicts the link port, looking into the socket from the bottom of the Virtual Boy unit:
  ____________
 /            \
|  1  2  3  4  |
| ============ |
|  5  6  7  8  |
'--------------'
Editor's Note: The following description of pin connections may not be 100% accurate.

When linking pins with a link cable, the following connections need to be made:

Pin 1 -> Pin 1
Pin 2 -- Not connected
Pin 3 -> Pin 3
Pin 4 -> Pin 8
Pin 5 -- Not connected
Pin 6 -> Pin 6
Pin 7 -> Pin 7
Pin 8 -> Pin 4

0x02000000 - Link Control Register (R/W, with exceptions)
Bit  7     R/W   Disable Link Interrupt
Bits 6-5   ---   Not used
Bit  4     R/W   Clock Select
Bit  3     ---   Not used
Bit  2      W    Transmit/Receive
Bit  1      R    Communication Status
Bit  0     ---   Not used
Setting Disable Link interrupt to 1 will prevent Link interrupt from being raised. When enabled, Link interrupts occur after a communication completes. Link interrupts have an exception code of 0xFE30 and branch CPU execution to address 0xFFFFFE30.

Clock Select is used to determine the clock source for communications. One Virtual Boy system must be configured as a master, and the other as slave. The master will transmit the clock signal, and the slave will listen for it.

• 0 - Internal clock (master)
• 1 - External clock (slave)

Setting Transmit/Receive to 1 will initiate a communication between Virtual Boy systems. Both systems must set this bit in order for communication to occur. Additionally, both systems will transmit and receive data simultaneously. Setting this bit to 0 has no effect; it is only used to perform the communication operation.

Communication Status will be set to 1 during communication, and 0 when the link is idle.

0x02000008 - Link Transmit Data (W/R)
0x0200000C - Link Receive Data (R)

Bits 7-0   Data
These 8-bit registers are used to store and retrieve data to be sent and received during a link communication, respectively. Link Transmit Data must be set prior to transmission, and Link Receive Data should not be read before communication completes. Communication status can be determined with the Link Control Register.

0x02000004 - Auxiliary Link Register (R/W, with exceptions)
Bit  7     R/W   Disable Link Interrupt
Bits 6-5   ---   Not used
Bit  4     R/W   Interrupt Compare
Bit  3     R/W   Aux Transmit Data
Bit  2      R    Aux Receive Data
Bit  1     R/W   Enable Aux Link
Bit  0      R    Aux Link Status
Editor's Note: This register is not well understood. Information in this section may not be 100% accurate.

The Auxiliary Link optionally sends 1 bit of information between Virtual Boy systems upon completion of a data communication as performed with the Link Control Register. The value of the Aux bit can be automatically checked against the configuration of this register to raise a Link interrupt. As with the Link Control Register, Link intererupts raised by the Auxiliary Link Register also have an exception code of 0xFE30 and branch CPU execution to address 0xFFFFFE30.

Setting Disable Link Interrupt to 1 will prevent Link interrupts from being raised by the Auxiliary Link.

Interrupt Compare stores the value to check received Aux data against to determine whether to raise a Link interrupt. If Aux Receive Data matches Interrupt Compare, and Aux Link interrupts are enabled, a Link interrupt will be raised.

Aux Transmit Data contains the value to send on the Aux Link when a normal Link communication completes.

Aux Receive Data contains the value received on the Aux Link when a normal Link communication comletes.

Editor's Note: The function and significance of Aux Link Status is not apparent at this time. Perhaps it's set when the 1 Aux bit is being transmitted?

Hardware Game Pad

The Virtual Boy has an 8-direction, 6-buton game pad that also supplies power to the system. It was manufactured with a battery pack that accepted 6 AA batteries, and an A/C Adapter was also manufactured and sold separately.

0x02000028 - Game Pad Input Control Register (R/W, with exceptions)
Bit 7   R/W   Game Pad Interrupt Disable
Bit 6   ---   Not used
Bit 5   R/W   Latch Game Pad Signal
Bit 4   R/W   Software Input Clock Signal
Bit 3   ---   Not used
Bit 2    W    Initiate Hardware Read
Bit 1    R    Hardware Input in Progress
Bit 0   R/W   Abort Hardware Read
Setting Game Pad Interrupt Disable to 1 will prevent Game Pad interrupt from being raised. It must also be set in the interrupt handler to acknowledge the interrupt. Game Pad interrupts have an exception code of 0xFE00 and branch CPU execution to address 0xFFFFFE00.

The Latch Game Pad Signal primes the game pad for software input reads. This bit must be set to 1 before any input is read by software, and set to 0 during software or hardware input reads.

Software Input Clock Signal sends read signals to the game pad. The bits actually sent to the game pad are the opposite of the bits written to this register:

0 - Sends a 1 to the game pad
1 - Sends a 0 to the game pad

To perform a software read, bits need to be sent to the game pad in the order of 0 followed by 1. This needs to occur 16 times: one for each bit in the Game Pad Input registers (for a total of 32 writes). The first bit sent to the game pad must be a 0, and must be sent after the Latch Game Pad signal. If the Game Pad Input registers are read before all 16 bits of input have been processed, the data will be junk and may not reflect the actual state of the game pad buttons.

Initiate Hardware Read will perform the latch and clock operations automatically by the hardware. A single input read will be performed. The rate at which the hardware reads game pad input is slower than can be done with a software read. However, if enabled, a Game Pad interrupt can be raised. If enabled, a Game Pad interrupt will be raised if any bit in the Game Pad Input registers is read as a 1, with the exception of the following:

• A button
• B button
• The "always 1" bit from the standard controller

If all other bits are 0, a Game Pad interrupt will not be raised. Setting Initiate Hardware Read to 0 has no effect; it is only used to initiate the hardware game pad input read process.

Hardware Input in Progress will be set to 1 while a hardware read is being performed, and 0 when no hardware game pad input read is in progress. If the Game Pad Input registers are read while this bit is set, the data will be junk and may not reflect the actual state of the game pad buttons.

Abort Hardware Read will abort any hardware game pad input reading currently in progress, and no interrupt will be raised. If Initiate Hardware Read is specified in the same write as Abort Hardware Read, no hardware game pad input read will occur.

0x02000010 - Game Pad Input Low (R)
Bit 7   Right D-Pad Right
Bit 6   Right D-Pad Up
Bit 5   L Button
Bit 4   R Button
Bit 3   B Button
Bit 2   A Button
Bit 1   Always 1
Bit 0   Low Battery
0x02000014 - Game Pad Input High (R)
Bit 7   Right D-Pad Down
Bit 6   Right D-Pad Left
Bit 5   Select Button
Bit 4   Start Button
Bit 3   Left D-Pad Up
Bit 2   Left D-Pad Down
Bit 1   Left D-Pad Left
Bit 0   Left D-Pad Right
The game pad will transmit input status to these two registers during a game pad input read. When a button is pressed (or the battery voltage is low), the corresponding bit will be 1. Otherwise, the bit will be 0.

Neither of these registers should be accessed before all 16 bits of input have been read from the game pad.

Hardware Timer

A high-frequency hardware timer exists in the Virtual Boy that can be used by programs to perform accurate timing of activities. The timer is a 16-bit value that counts down by 1 each tick, and reloads a preset value once it reaches 0.

0x02000020 - Timer Control Register (R/W, with exceptions)
Bits 7-5   ---   Not used
Bit  4     R/W   Tick Interval
Bit  3     R/W   Enable Timer Zero Interrupt
Bit  2      W    Clear Timer Zero Status
Bit  1      R    Timer Zero Status
Bit  0     R/W   Enable Timer
Tick Interval configures the amount of time between timer ticks:

• 0 - 100 microseconds per tick
• 1 - 20 microseconds per tick

A microsecond is one millionth of a second. This bit can be updated while Enable Timer is set. Editor's Note: One source discourages changing the tick interval while the timer is enabled, but testing has shown that it works.

Setting Enable Timer Zero Interrupt to 1 will allow Timer Zero interrupt to be raised when Timer Zero Status becomes set. Timer Zero interrupts have an exception code of 0xFE10 and branch CPU execution to 0xFFFFFE10. Editor's Note: Will the interrupt be raised only when the timer counts down from 1, or whenever the timer is zero?

Setting Clear Timer Zero Status to 1 resets the Timer Zero Status bit and acknowledges Timer Zero interrupts. The Timer Zero interrupt handler must first set Enable Timer Zero Interrupt to 0, then set Clear Timer Zero to 1 in order to acknowledge the interrupt. Due to this, the Timer Zero interrupt handler must re-enable the timer in order for future interrupts to be raised. Setting this bit to 0 will have no effect; its only purpose is to clear the Timer Zero Status bit.

Timer Zero Status will be set to 1 when the timer reaches 0. This must be cleared by setting Clear Timer Zero Status to 1 while the timer is disabled. Editor's Note: If this flag is not cleared, will the timer remain at 0?

Setting Enable Timer to 1 will activate the timer and it will begin to count down from its most recent count value. Setting this bit to 0 will stop the timer.

0x02000018 - Timer Counter/Reload Low (R/W)
0x0200001C - Timer Counter/Reload High (R/W)

Bits 7-0   Timer Counter (R)/Timer Reload Value (W)
Reading from these registers will return the current counter value. Take care when reading these registers while the timer is active, as it's possible to construct an improper result due to timer operations between reads.

Writing to these registers will specify a new value for the timer to reload after it reaches 0. Writing to either of these registers will load all 16 bits of the timer's reload value to the timer's current count.

Hardware Wait Controller

0x02000024 - Wait Control Register (R/W)
Bits 7-2   Not used
Bit  1     Cartridge Expansion Waits
Bit  0     Cartridge ROM Waits
Both bits of this register have the same configuration values:

• 0 - 2 waits
• 1 - 1 wait

The internal wait controller will generate bus waits for hardware components. Cartridge waits can be configured if high-speed cartridge hardware is available. Commercial games set Cartridge ROM Waits to 1 wait, and no commercial game uses the Cartridge Expansion addresses.

CPU V810 Family Microprocessor

The Virtual Boy uses a modified NEC V810 CPU called the NVC that operates at 20.0 MHz. A handful of instructions were added by Nintendo.

Overview
CPU Registers and Flags
CPU Data Types and Conventions
CPU Exceptions & Interrupts
CPU Cache Dump & Restore
CPU List of Exceptions

Instruction Set
CPU Instruction Formats
CPU Memory and Register Transfers
CPU Arithmetic/Bitwise Operations
CPU Jump and Control Instructions
CPU Floating-Point Instructions
CPU Bit String Instructions
CPU Miscellaneous Instructions
CPU Nintendo Instructions

Other Info
CPU List of Instructions by Opcode
CPU List of Instructions by Mnemonic
CPU List of Instructions by Format

CPU Registers and Flags

The NEC V810 family contains 32 general-purpose program registers, ten system registers and a program counter. All registers are 32 bits wide.

Program Registers

The program registerscan be used for any purpose by the program and will not be modified by the system except under specific circumstances initiated by the program. There are 32 program registers, called r0 through r31. While most of them are only used by the program for storage and data processing, a few of them do have special significance:
PC - Program Counter

The program counter (PC) represents the address of the current instruction being executed. Its lowest bit is fixed to 0, meaning it can only reference addresses on a halfword boundary (only even addresses).

PC is normally incremented by the CPU by the number of bytes in the instruction after execution, but can be set by the program by using a jump instruction. When used with a relative jump instruction, a displacement value of 0 refers to the jump instruction itself: incrementation does not occur prior to execution, or after a jump instruction. Bit string instructions will only increment PC after they have finished, but can be "saved" and paused by system interrupts.

PC cannot be read by the program, though by definition it would change as soon as it was read anyway. If the value in this register is required for whatever reason, use the JAL instruction with a displacement value of 4 and then use the contents of r31.

System Registers

There are 10 system registers, with the following names and symbols:
  PSW    Program Status Word
  EIPC   Exception/Interrupt PC
  EIPSW  Exception/Interrup PSW
  FEPC   "Fatal" (Duplexed) Exception PC
  FEPSW  Duplexed Exception PSW
  ECR    Exception Cause Register
  ADTRE  ADdress Trap Register for Execution
  CHCW   CacHe Control Word
  TKCW   TasK Control Word
  PIR    Processor ID Register
The values of the system registers can be read by the program using the STSR instruction and, with exception, written using the LDSR instruction.

PSW - Program Status Word

The Program Status Word (PSW) register contains various fields that indicate the current state of operations as well as ancillary results of instructions after they are executed.

The format of PSW is as follows:
   31        20 19 16 15 14 13 12 11 10  9   8   7   6   5   4   3  2 1 0
  +------------+-----+--+--+--+--+-----+---+---+---+---+---+---+--+--+-+-+
  |    RFU     | Int |NP|EP|AE|ID| RFU |FRO|FIV|FZD|FOV|FUD|FPR|CY|OV|S|Z|
  +------------+-----+--+--+--+--+-----+---+---+---+---+---+---+--+--+-+-+
  Bits: 12        4    1  1  1  1   2    1   1   1   1   1   1   1  1 1 1
Z - Zero - Set when the result of an operation is zero, cleared otherwise.

S - Sign - A copy of the most significant bit of the result of an operation. For signed operations, this indicates a negative number.

OV - Overflow - Set when an operation exceeds the range of a signed integer and corrupts the sign bit, cleared otherwise. This can indicate, as an example, a negative result when adding two positive numbers.

CY - Carry - Set when an operation exceeds the range of an unsigned integer, cleared otherwise. This can occur, as an example, when subtracting a value from a lesser value.

FPR - Floating-Point Precision Degradation - Set when the result of a floating-point operation loses precision due to some information not being contained within the significant digits. This flag is never cleared by floating-point instructions.

FUD - Floating-Point Underflow - Set when the result of a floating-point operation is a denormal number and not zero. This flag is never cleared by floating-point instructions.

FOV - Floating-Point Overflow - Set when the result of a floating-point operation is above the maximum normalized value that can be expressed by the data type. This flag is never cleared by floating-point instructions.

FZD - Floating-Point Zero Division - Set when attempting to divide by zero in a floating-point operation if the numerator is not also zero. This flag is never cleared by floating-point instructions.

FIV - Floating-Point Invalid Operation - Set when attempting to divide 0 / 0 or convert a value to an integer that cannot be represented with 32 bits. This flag is never cleared by floating-point instructions.

FRO - Floating-Point Reserved Operand - Set when one or both operands of a floating-point operation is/are any of the following: a denormal number, NaN, infinity or negative infinity. This flag is never cleared by floating-point instructions.

RFU - Reserved for Future Use

ID - Interrupt Disable - Set this when maskable interrupts should be ignored.

AE - Address Trap Enable - Set this to enable the hardware breakpoint debugging function.

EP - Exception Pending - Indicates if exception/interrupt handling is in progress.

NP - NMI Pending - Indicates if non-maskable interrupt handling is in progress.

Int - Interrupt Mask Level - Formally I3-I0, sets the minimum interrupt level at which maskable interrupts are to be processed.

RFU - Reserved for Future Use

Manipulation of PSW can be done via the LDSR/STSR and CLI/SEI instructions.

The conditions pertinent to the Bcond and SETF instructions check for specific combinations of flags in PSW.

EIPC, EIPSW, FEPC and FEPSW - Exception/Interrupt Status Saving Registers

When an exception or interrupt occurs, the contents of PC and PSW are stored into these status saving registers so that program flow can continue after the exception or interrupt is handled.

Under normal circumstances, only EIPC and EIPSW are needed. If an exception is already being processed when another exception occurs (which, under normal circumstances, should only happen because of an interrupt), a duplexed exception occurs and is processed like a non-maskable interrupt. In this case, FEPC and FEPSW are used as well to allow returning to the handler of the first exception.

If a non-maskable interrupt occurs on its own--outside of the context of a duplexed exception--then only FEPC and FEPSW are used and they will return to the program.

In either case, returning from and acknowledging exceptions/interrupts is done with the RETI instruction. Since the corresponding *PSW register contains the status of PSW prior to the occurrence of the exception/interrupt in question, RETI will implicitly clear the pending flags.

ECR - Exception Cause Register

During exception/interrupt processing, the source of the exception can be resolved, as the name implies, by examining the Exception Cause Register (ECR).

The format of ECR is as follows:
   31            16 15             0
  +----------------+----------------+
  |      FECC      |      EICC      |
  +----------------+----------------+
EICC - The exception code of the first exception that occurs.

FECC - For duplexed exceptions, the exception code of the second exception that occurred.

Exception codes are 16-bit, and the source of the exception is stored into ECR.EICC. In the event of a duplexed exception, the code for the second exception that occurred is transferred into ECR.FECC. Duplexed exceptions can be detected by the NMI handler by checking whether the EP flag is set in PSW. This can be accomplished via the STSR instruction.

ECR cannot be written to by the program and therefore cannot be changed with the LDSR instruction. However, it is not truly read-only, so the CPU is still able to modify it.

ADTRE - Address Trap Register for Execution

The Address Trap Register for Execution (ADTRE) is used to provide hardware breakpoint functionality for debugging. If PSW.AE is set, and the value of PC matches the value of ADTRE, then an exception is triggered instead of executing the instruction at that address.

CHCW - Cache Control Word

The Cache Control Word (CHCW) register is used by programs to configure the state of the V810 family processors' internal instruction cache. The cache contains 128 entries at 8 bytes each for a total of 1 KB cachable memory, which is used to accelerate reads and writes between the CPU and system memory.

Editor's Note: The exact behavior of the cache--how it populates entries and its replacement policy--is not specified in the V810 family documentation. Since it has no bearing on emulation (except in the unlikely event the program manipulates dumped cache data for whatever reason), cache functionality really doesn't need to be implemented in an emulator.

Commands for cache control are issued when CHCW is written to by the LDSR instruction. Only one of four commands may be issued to the cache during a single LDSR operation. All cache operations complete before the next instruction is fetched, and any interrupts that occur are held until the cache operation completes. (In all cases, interrupts will be processed after the execution of the instruction they coincide with, and before the next instruction.)

CHCW has the following format:
   31        20 19         8 7 6  5   4  3 2  1   0
  +------------,------------+---+---+---+---+---+---+
  |    CEN    (SA)   CEC    |RFU|ICR|ICD|RFU|ICE|ICC|
  +------------'------------+---+---+---+---+---+---+
  Bits: 12    (24)    12      2   1   1   2   1   1
ICC - Instruction Cache Clear - Set this to 1 to clear cache entries. When doing so, also set CEN to the index of the first entry to clear and CEC to the number of entries to clear. Clearing cache entries will always stop after the last entry, which has significance in situations where CEN + CEC > 128. This value is always read (via the STSR instruction) as 0.

ICE - Instruction Cache Enable - Set this to 1 to enable the instruction cache, and to 0 to disable it. This is the only value that can be read back as 1 via the STSR instruction.

RFU - Reserved for Future Use - Always read as 0.

ICD - Instruction Cache Dump - Set to 1 to perform a dump of the cache. When doing so, also set SA to the upper 24 bits of the dump/restore area. This value is always read as 0.

ICR - Instruction Cache Restore - Set to 1 to perform a restore of the cache. When doing so, also set SA to the upper 24 bits of the dump/restore area. This value is always read as 0.

RFU - Reserved for Future Use - Always read as 0.

SA, CEN and CEC share the same 24 bits of the CHCW register. Their use depends on the context in which they are used.

SA - Spill-Out Base Address - The upper 24 bits of the memory location to use as the cache dump/restore area during dump and restore operations. The contents of the cache are written to this address during a dump and read during a restore. This value is always read as 0.

CEC - Clear Entry Count - The number of cache entries to clear during a clear operation. If CEC > 128, then 128 will be used as the count. In the event CEN + CEC > 128, then 128 - CEN entries are cleared instead. This value is always read as 0.

CEN - Cache Entry Number - The index of the starting cache entry to clear (0-127) during a clear operation. If CEN >= 128, nothing happens. This value is always read as 0.

No more than one of ICC, ICE, ICD and ICR should be set in a single write via the LDSR instruction. If more than one is set, operation is not guaranteed. Editor's Note: But what exactly would happen?

After the cache is dumped, all entries must be cleared before the cache is enabled again. Editor's Note: And what if they aren't?

TKCW - Task Control Word

The Task Control Word (TKCW) register is fixed and read-only on the V810 family, and therefore is of little interest to the programmer. It is documented here for the sake of completeness.

As it pertains to the STSR instruction, TKCW has a value of 0x000000E0.

TKCW controls the specifics of floating-point operations. It has the following format:
   31                    9  8   7   6   5   4   3   2  1 0
  +-----------------------+---+---+---+---+---+---+---+---+
  |          RFU          |OTM|FIT|FZT|FVT|FUT|FPT|RDI|RD |
  +-----------------------+---+---+---+---+---+---+---+---+
  Bits:      23             1   1   1   1   1   1   1   2
RD - Rounding Control - Specifies the direction of rounding. This is fixed to 00: toward nearest.

RDI - Rounding Control Bit for Integer Conversion - Specifies how to round when converting to integer. This is fixed to 0: use the same direction as RD. This causes the CVT.SW instruction to operate differently than the TRNC.SW instruction.

FPT - Precision Trap Enable - Specifies if FPR (floating-point precision degradation) exceptions can occur. This is fixed to 0: precision degradation exceptions cannot occur.

FUT - Underflow Trap Enable - Specifies if FUD (floating-point underflow) exceptions can occur. This is fixed to 0: underflow exceptions cannot occur.

FVT - Overflow Trap Enable - Specifies if FOV (floating-point overflow) exceptions can occur. This is fixed to 1: overflow exceptions can occur.

FZT - Zero Divide Trap Enable - Specifies if FZD (floating-point zero divide) exceptions can occur. This is fixed to 1: zero divide exceptions can occur.

FIT - Invalid Operation Trap Enable - Specifies if FIV (floating-point invalid operatin) exceptions can occur. This is fixed to 1: invalid operation exceptions can occur.

OTM - Operand Trap Mask - Specifies if FRO (floating-point reserved operand) exceptions are masked. This is fixed to 0: reserved operand exceptions can occur (are not masked).

RFU - Reserved for Future Use

PIR - Processor ID Register

The Processor ID Register (PIR) contains a unique code identifying which processor is present so that software can decide how to operate. It has a fixed value and is read-only.

As it pertains to the STSR instruction, PIR has a value of 0x00005346 on Virtual Boy.

The Virtual Boy NVC is a non-standard V810 processor. For the sake of completeness, PIR has the following format on ordinary V810 family processors:
   31            16 15          4 3   0
  +----------------+-------------+-----+
  |      RFU       |     PT      |NECRV|
  +----------------+-------------+-----+
  Bits:   16             12         4
NECRV - NEC Reserved - Treat this as undefined.

PT - Processor Type - Set to 0x810 for the V810 family.

RFU - Reserved for Future Use - Fixed to zero.

CPU Data Types and Conventions

The V810 family of processors can work with a small number of different data types, which are referred to by specific names. In general, the CPU can work with integers, floating-point numbers and strings of bits.

Byte Order

For all data types on V810 family CPUs, bytes are stored and read with the low (least significant) byte first. In other words, the system byte order is little-endian.

Integer Data Types

Integer data types can be read and stored in units of 8, 16 or 32 bits, but processing only occurs with 32-bit integers. The different data sizes are referred to by the following names on the V810 family:

• 8-bit - Byte
• 16-bit - Halfword
• 32-bit - Word

When accessing memory or port addresses for transferring data of a given type, the address itself must fall on a multiple of the size of that data type. For example, when loading a word from RAM, the address in memory must be divisible by 4--it must fall on a word boundary.

Values read as immediate parameters in instructions may be sign extended when converting to 32 bits, but also may not. Sign extension means that the extra bits prepended to the value match the most significant bit of the value itself. Contrast with zero extension, which always uses 0 for the extra bits. Typically, arithmetic and address displacement values are sign-extended, while bitwise values are zero-extended. Refer to the documentation for individual instructions to determine what form of extension is to be used.

Integers can be processed as both signed and unsigned, depending on the instruction used an/or the condition to check for. The nature of two's complement storage means the same mathematical procedures can be performed for both.

Floating-Point Data Type

The floating-point format used by the V810 family is IEEE-754 32-bit Single, referred to as "floating short" in the documentation. The data type has the following format:

31 30    23 22                    0
+-+--------+-----------------------+
|S|  Exp.  |      Significand      |
+-+--------+-----------------------+
Significand - Represents the portion of a binary fractional value after the point (halves, quarters, eighths, etc.). For normalized values, there is an implicit 1 on the integer side of the point, whereas for denormal values there is an implicit 0. The word "mantissa" is a common name for this value, but IEEE stresses "significand" to avoid ambiguity with the use of mantissa in regards to logarithms, which is not the same type of value.
Exp. - Exponent - An exponent to raise 2 to the power of when constructing the number represented by the data. The value packed into these 8 bits is biased: subtract 127 from their value to resolve the true exponent.
S - Sign - The sign bit. If clear, the number is positive. If set, the number is negative.

The Exponent and Significand fields are examined to determine what kind of number is being represented:

• Infinity - Exponent is all 1s and Significand is all 0s.
• NaN (not a number) - Exponent is all 1s and Significand is not all 0s.
• Normalized number - Exponent is a mixture of 1s and 0s. The significand has a leading 1 before the point.
• Denormalized number - Exponent is all 0s. The significand has a leading 0 before the point.
•Zero - Exponent is all 0s and Significand is all 0s. Technically a denormal number.

All types of numbers are signed, meaning there can be such things as negative zero and negative infinity.

Construction of the represented number is done with the following formulas:

• Normalized = (-1 ^ Sign) * (2 ^ (Exponent - 127)) * 1.Significand
• Denormalized = (-1 ^ Sign) * 0.Significand
• Infinity and NaN = Cannot be calculated.

On the V810 family, only normalized numbers and the special-case denormal value zero are accepted as valid operands in the Floating-Point instructions. If an indefinite, non-number or non-zero denormal number is used (called "reserved operands"), it will raise an exception.

The following cases are detected during processing:

• Use of a reserved operand is prohibited.
• An attempt to divide zero by zero results in an invalid operation.
• An attempt to divide a non-zero number by zero results in a zero division error.
• If the exponent of the result of a floating-point operation is greater than 127, an overflow occurs.
• If the exponent of the result of a floating-point operation is less than -126 (a denormal number) and not zero, an underflow occurs.
• If the significand of the result of a floating-point operation has significance beyond 23 bits, precision degradation occurs.

Bit String

In addition to the data types that can be processed by register operations, the V810 family also supports strings of data of arbitrary length--precise on the bit level--called bit strings. The bit string operations provide a convenience for, and hardware acceleration of, bulk processing of data in system memory.

Bit strings are defined by three properties:

• Starting Word Address - The address in memory of the word that contains the first bit of the string. Must fall on a word boundary.
• Starting Bit Offset - The index (0-31) of the first bit of the string within the starting word, relative to the lowest bit.
• Length - The size of the string, in bits. This is a 32-bit unsigned value, meaning strings can be as large as (232 - 1) bits, or 512 MB minus one bit.

Bit string operations work on two bit strings--a source and a destination--both of the same length. For more information on bit strings, refer to the CPU Bit String Instructions section.

Assembly Conventions

The official notation of assembly instructions on the V810 family is as follows:

• Mnemonics (instruction names) are all-uppercase.
• Registers are specified with the lowercase letter r followed by the number of the register, expressed in decimal.
• Source operands are listed on the left, and destination operands on the right.* Immediate values are always listed first.
• Load/store instructions list the displacement value immediately followed by the register name in [] brackets.
• The Bcond instruction is never used by name, but rather the conditions themselves are used as the mnemonic following the capital letter B.
• The LDSR/STSR instructions specify the system register by name rather than by numeric ID.
• The SETF instruction specifies the condition by name rather than by numeric ID.
• The destination register of the JMP instruction has [] brackets around it.

* - Some instructions will have reversed operand order compared to other instructions of the same format. For example, this applies to store instructions and LDSR among others.

Example instructions:
HALT
JMP   [r12]
ANDI  7FFFh, r1, r2
LD.W  4[r1], r3
BNE   -12
LDSR  r4, PSW
SETF  NE
A few considerations:

• Numeric representaiton for immediate and displacement values is determined by the assembler/disassembler. Typical representations include signed decimal, or unsigned hexadecimal followed by the lowercase letter h (as in 7FFFh).
• Comment specification is determined by the assembler, but is typically indicated by the ; semicolon. C/C++ style comments /* */ and // may also be used in some cases.
• Existing program code may use all-lowercase mnemonics for instructions, different numeric representations, different notation of registers and/or other differences from the V810 family documentation.

Calling Convention

Programs written for Virtual Boy using the Nintendo-supplied C compiler follow a particular calling convention for functions and stack manipulation.

The program registers have the following significance in the Virtual Boy calling convention:

• r0 - Fixed value of 0.
• r1 - Not used by the compiler, but is used in hand-coded and template assembly for construction of 32-bit immediate values and for calculating effective addresses.
• r2 - Not used by the compiler. The V810 family specifies this register as the stack pointer for exception handlers. Exceptions on Virtual Boy use r3 instead.
• r3 - The stack pointer. Commercial games initialize this to 0x0500FFFC.
• r4 - Data pointer. Global and static variables are referenced relative to the address in this register. Commercial games initialize this to 0x05008000.
• r5 - Not used by the compiler. The V810 family specifies this register as the text pointer, but text data on Virtual Boy is always at 0x07000000.
• r6-r9 - Reserved for function arguments. r6 receives the first argument and r9 receives the fourth argument.
• r10-r19 - Local function data. None of these registers are guaranteed to be preserved after a function returns.
• r20-r29 - Not used by the compiler.
• r30 - Reserved for CPU operation. In particular, integer multiply and divide instructions modify this register.
• r31 - Link pointer. This must be set to the return address upon entering a function body. This register is set automatially by the JAL instruction.

When pushing data to the stack, first decrease the value in r3, then write the data to the new address.

When calling a function, 16 bytes are always allocated on the stack. These bytes are defined for use with the stdarg and varargs calling conventions to add the first four function arguments to the stack. Even when the standard calling convention is used, these bytes are always present for all function calls.

The first four arguments in function calls are passed in registers r6 through r9, respectively. Additional arguments are pushed to the stack (appearing after the aforementioned 16 bytes), where arguments of lower order are stored to lower addresses. Upon entering a function body, the address of the fifth argument is 10h[r3], the address of the sixth argument is 14h[r3], and so-on.

The return value from a function, if any, is stored in r10.

r31 is populated with the return address when returning from a function. The compiler always uses the instruction "JMP [r31]" to return from functions.

CPU Exceptions & Interrupts

An exception on the V810 family processors is an event that triggers special CPU behavior. In particular, the current PC and PSW are saved in the status saving registers, and execution is redirected to a predefined address, called an exception handler.

An interrupt is an event raised by hardware activity, such as by the VIP or game pad. Interrupts are a subset of exceptions.

Exception Handlers

All exceptions have an exception code, which represents the type of exception that was raised. Exception codes are 16 bits and match the low 16 bits of the addresses of the corresponding exception handlers. During the initial exception processing, the exception code is copied into the ECR register.

Every exception code has a corresponding address that gets stored to PC when the exception occurs. These handlers are located at the very end of the CPU's address space, in the 0xFFFFFE00 - 0xFFFFFFFF range. Bytes within this region represent the actual instructions for the CPU to execute.

All handlers begin on a 16-byte boundary (the lowest 4 bits are zeroes), meaning each type of exception has only 16 bytes available for handler code; a maximum of 8 instructions. However, this is enough space to initialize and execute a JMP instruction.

For a full list of handler addresses on Virtual Boy, refer to CPU List of Exceptions.

Restore PC

The return address for an exception is stored into the appropriate status saving register, though exactly what that is in relation to PC depends on the type of exception that was triggered.

The address Current PC is the address of the instruction that raised the exception, if the exception is the result of an invalid operation of some sort. These same instructions can be aborted by interrupts, in which case Current PC is still used.

The address Next PC is the address of the instruction following the instruction currently being executed. Normally, Next PC is used for interrupts, but if an instruction is aborted by the interrupt, Current PC is used instead. Except for instructions that can be aborted by an interrupt, all instructions will complete execution before the interrupt is processed.

The TRAP instruction's behavior is not invalid--its purpose is to raise an exception--so it consequently uses Next PC as the Restore PC.

The following instructions can be aborted by interrupts and/or raise exceptions: DIV/DIVU, floating-point instructions and bit string instructions.

Additionally, any illegal opcode (an opcode without a corresponding instruction), including sub-opcodes of bit string and floating-point instructions, will raise an exception.

Masking Interrupts

If an interrupt is masked, it will not be processed. Masking can occur in two ways: by disabling interrupts via the ID flag of the PSW register, or if the interrupt's interrupt level is less than the minimum Interrupt Mask Level specified in PSW.

Interrupts can be disabled entirely by setting the ID flag in the PSW register. This can be done with the LDSR and SEI instructions. While the ID flag is set, all maskable interrupts are ignored regardless of their interrupt level. To enable interrupts, clear the flag with LDSR or CLI.

While interrupts are enabled, they can still be ignored if their interrupt level is less than the minimum Interrupt Mask Level specified in the PSW register. The interrupt level of any given interrupt is hardware-defined, so system designers should assign lower interrupt levels to less important interrupts.

Interrupts are always ignored if the NP or EP flags of the PSW register are set, meaning an interrupt cannot be processed while another interrupt is already being processed.

The Reset and non-maskable interrupts (NMI) cannot be disabled and will always be processed. The NMI is not used on the Virtual Boy.

Duplexed Exceptions

A duplexed exception occurs if an exception occurs while another exception is already being processed. Both exception codes are stored in the ECR register and the duplexed exception is processed like an NMI. For more information on what happens when a duplexed exception occurs, refer to Exception Processing.

The NMI handler code can detect a duplexed exception by checking the EP flag of the PSW register.

Fatal Exceptions

If an exception occurs while an NMI (either by the hardware or as a duplexed exception) is being processed, a machine fault/fatal exception occurs.

For more information on what happens when a fatal exception occurs, refer to Exception Processing.

Note that maskable interrupts cannot cause a fatal exception because they are ignored when the NP or EP flag is set in the PSW register. Since the Virtual Boy does not use the NMI, the only possible way for a machine fault to occur is if the NMI handler itself raises an exception.

Exception Priority

If multiple exceptions/interrupts occur simultaneously, the order in which they are processed depends on their priority.

Exception priority is as follows, ordered highest to lowest:

• Reset*
• NMI / Duplexed Exception
VIP interrupt**
Link interrupt**
Cartridge interrupt**
Timer Zero interrupt**
Game Pad interrupt**
• Address Trap
TRAP instruction
• Illegal Opcode
• Zero Division (DIV/DIVU instructions)
Floating-Point Reserved Operand***
• Floating-Point Invalid Operation***
• Floating-Point Zero Division***
• Floating-Point Overflow***

* - Reset does not behave like other interrupts, since it forcefully initializes the hardware. For more information on what happens during Reset, refer to the System Reset section.

** - Note that only the interrupt with the highest priority of simultaneous interrupts will be processed because interrupts are explicitly ignored during exception processing.

*** - Only one floating-point exception can occur for a single instruction. If a given instruction qualifies for more than one (such as dividing NaN by zero), only the one with the highest priority will be caught and processed. This includes the setting of the corresponding status flag in PSW.

Floating-point underflow and precision degredation have defined exception codes and handler addresses, but cannot actually occur on V810 because of the configuration of TKCW.

Exception Processing

When a maskable interrupt occurs:

if ( (NP or EP or ID) = 1 ) or (interrupt_level < Int) then -- Interrupt is masked
ignore interrupt
else -- Interrupt is accepted
EIPC = PC
EIPSW = PSW

if interrupt_level < 15 then
Int = interrupt_level + 1
else
Int = 15
end if

accept interrupt
end if

When an exception or accepted interrupt occurs:

if NP = 1 then -- Fatal exception
word ptr [0x00000000] = 0xFFFF0000 or exception_code
word ptr [0x00000004] = PC
word ptr [0x00000008] = PSW
halt until Reset
else if EP = 1 then -- Duplexed exception
FEPC = PC
FEPSW = PSW
ECR.FECC = exception_code
NP = 1
ID = 1
AE = 0
PC = 0xFFFFFFD0
else -- Normal exception/interrupt
EIPC = PC -- Already handled for interrupts
EIPSW = PSW -- Already handled for interrupts
ECR.EICC = exception_code
EP = 1
ID = 1
AE = 0
PC = handler_address
end if

Returning from Exceptions

When handling has been completed for an exception, interrupt or trap, control is returned to the program by the RETI instruction. The exact behavior of RETI depends on the status of the NP flag in the PSW register:

NP = 1 - If an NMI or duplexed exception is being processed, the PC and PSW registers are loaded from the FEPC and FEPSW registers, respectively.

NP = 0 - If an NMI or duplexed exception is not being processed, the PC and PSW registers are loaded from the EIPC and EIPSW registers, respectively. Note that this is true even if the EP flag is cleared.

Address Trap

An address trap is a special debugging exception in the V810 family processors. It can be used to configure a hardware breakpoint on a particular address, which can then cause an exception on execution at that address.

If the AE flag in PSW is set and PC becomes equal to ADTRE when it prepares to execute an instruction, an address trap occurs and the corresponding exception is processed.

Address traps have an exception code of 0xFFC0 and branch CPU execution to address 0xFFFFFFC0.

 CPU Cache Dump & Restore

The V810 family processors provide up to 1 KB of CPU instruction cache, the contents of which can be dumped to and restored from system memory. For information on how to use the cache functions, refer to CHCW - Cache Control Word. This section documents the format of the data in the dump/restore area.

Cache dump and restore functions specify the upper 24 bits of the address to dump to/restore from. The data itself occupies 1536 bytes, which doesn't technically require a full 12 bits of addressing. Two kinds of data are written to the dump/restore area:

Block - The 8 bytes representing the cache data for one cache entry. These are stored in the same order they appear within CPU memory.

Entry - A bit-packed word representing one cache entry. This element has the following format:
  31 28 27 23 22 21                  0
  +----+-----+-+----------------------+
  | 0  |NECRV|V|         TAG          |
  +----+-----+-+----------------------+
TAG - Bits 31-10 of the cache entry tag, which represent the high 22 bits of the address that the cache entry represents.

V - Valid Bit - Indicates if this entry is currently valid (not cleared)

NECRV - NEC Reserved - Consider this undefined.

At the location specified by the SA field in CHCW:
  SA + 0x00000000   128 Block elements, starting with cache entry 0
  SA + 0x00000400   128 Entry elements, starting with cache entry 0
  SA + 0x00000600   (This is the first byte after the dump data)
Note that the cache tags are only precise to a 1 KB boundary.

CPU List of Exceptions

The following chart lists the exceptions that can occur on Virtual Boy:

Name Exception Code Handler Address Restore PC
Game Pad 0xFE00 0xFFFFFE00 Next PC*
Timer Zero 0xFE10 0xFFFFFE10 Next PC*
Cartridge 0xFE20 0xFFFFFE20 Next PC*
Link 0xFE30 0xFFFFFE30 Next PC*
VIP 0xFE40 0xFFFFFE40 Next PC*
Floating-Point Reserved Operand 0xFF60 0xFFFFFF60 Current PC
Floating-Point Overflow 0xFF64 0xFFFFFF60 Current PC
Floating-Point Zero Division 0xFF68 0xFFFFFF60 Current PC
Floating-Point Invalid Operation 0xFF70 0xFFFFFF60 Current PC
Zero Division 0xFF80 0xFFFFFF80 Current PC
Illegal Opcode 0xFF90 0xFFFFFF90 Current PC
TRAP (vector < 16) 0xFFA0 + vector 0xFFFFFFA0 Next PC
TRAP (vector >= 16) 0xFFA0 + vector 0xFFFFFFB0 Next PC
Address Trap 0xFFC0 0xFFFFFFC0 Current PC
Duplexed Exception 0xFFD0 0xFFFFFFD0 Current PC
Reset 0xFFF0 0xFFFFFFF0 --

* - These interrupts will use Current PC if they cause an instruction to abort. For more information, refer to Restore PC.

Game Pad, Timer Zero, Cartridge, Link and VIP are all maskable interrupts. Their interrupt levels are equal to the second-least-significant nibble of their exception codes. For example, VIP has an exception code of 0xFE40, so its interrupt level is 4.

All floating-point exceptions, including Invalid Operation, have the same handler address: 0xFFFFFF60.

The NMI is not used on the Virtual Boy, but if it was, it would have the same exception code and handler address as Duplexed Exception, and have the same Restore PC policy as the other interrupts.

CPU Instruction Formats

Instructions on the V810 family processors can be 16- or 32-bit, depending on the opcode. Instructions are packed into bits using seven different formats, depending on the type of instruction and which addressing mode it uses. NEC refers to these formats simply as Format I through Format VII, and they are defined below.

Instructions are read in 16-bit halfwords, where the low byte of each halfword comes first. The opcode begins at the highest bit of the second byte, meaning bit 15 and downward within the first halfword. For 32-bit instructions, a second halfword is read, and the first halfword is treated as the upper 16 bits of a 32-bit data unit.

Format I - Register-to-register
Instruction size: 16 bits
Field layout:
   15  10 9   5 4   0
  +------+-----+-----+
  |  op  |reg2 |reg1 |
  +------+-----+-----+
op
- The instruction's opcode.
reg2
- The 5-bit index (0-31) of the destination register.
reg1
- The 5-bit index (0-31) of the source register.

Example assembly notation: MOV r1, r2

Format II - Immediate-to-register
Instruction size: 16 bits
Field layout:
   15  10 9   5 4   0
  +------+-----+-----+
  |  op  |reg2 |imm5 |
  +------+-----+-----+
op
- The instruction's opcode.
reg2
- The 5-bit index (0-31) of the destination register.
imm5
- The 5-bit value used as the instruction's source operand.*

* - Depending on the instruction, the immediate value may be sign- or zero-extended, or used as a 5-bit value. For bit string instructions, this field is used as a sub-opcode field.

Example assembly notation: ADD 5, r2

Format III - Conditional branch
Instruction size: 16 bits
Field layout:
 15 13 12 9 8        0
  +---+----+----------+
  |op |cond|  disp9   |
  +---+----+----------+
op
- The instruction's opcode.*
cond
- The 4-bit condition identifier specifying which branch instruction this is.**
disp9
- A 9-bit, sign-extended displacement value specifying the relative target address if the branch is taken.

* - All of the conditional branch instructions have 100 as their opcode bits, and no other instruction begins with those three bits.
** - For a list of condition identifiers, refer to the CPU Jump and Control Instructions section.

Example assembly notation: BNZ 1Eh -- Usually specifies a label or the destination address

Format IV - Middle-distance jump
Instruction size: 32 bits
Field layout:
   15  10 9        0 31           16
  +------+--------------------------+
  |  op  |         disp26           |
  +------+--------------------------+
op
- The instruction's opcode.
disp26
- A 26-bit, sign-extended displacement value specifying the relative target address of the jump.

Example assembly notation: JR -46519 -- Usually specifies a label or the destination address

Format V - 3-operand
Instruction size: 32 bits
Field layout:
   15  10 9   5 4   0 31            16
  +------+-----+-----+----------------+
  |  op  |reg2 |reg1 |     imm16      |
  +------+-----+-----+----------------+
op
- The instruction's opcode.
reg2
- The 5-bit index (0-31) of the destination register.
reg1
- The 5-bit index (0-31) of the source register.
imm16
- The 16-bit value used as another source operand.*

* - Depending on the instruction, the immediate value may be sign- or zero-extended, or used as a 16-bit value.

Example assembly notation: ORI 3F20h, r1, r2

Format VI - Load/store
Instruction size: 32 bits
Field layout:
   15  10 9   5 4   0 31            16
  +------+-----+-----+----------------+
  |  op  |reg2 |reg1 |     disp16     |
  +------+-----+-----+----------------+
op
- The instruction's opcode.
reg2
- The 5-bit index (0-31) of the register to be used as the destination for loading data or as the source for storing data.
reg1
- The 5-bit index (0-31) of the register containing the base value of the address to load from/store to.
disp16
- A 16-bit, sign-extended displacement value specifying the final address, relative to the base address specified by reg1.

Example assembly notation: LD.W -16[r1], r2

Format VII - Extended instruction
Instruction size: 32 bits
Field layout:
   15  10 9   5 4   0 31  26 25      16
  +------+-----+-----+------+----------+
  |  op  |reg2 |reg1 |subop |   RFU    |
  +------+-----+-----+------+----------+
op
- The instruction's opcode.
reg2
- The 5-bit index (0-31) of the destination register.
reg1
- The 5-bit index (0-31) of the source register.
subop
- The extended opcode for this instruction.
RFU
- Reserved for future use.

Example assembly notation: MULF.S r1, r2

CPU Memory and Register Transfers

Register/Immediate to Register Transfer
  010000  ----  II  1  MOV     Move Immediate      reg2 = sign extend imm5
  000000  ----   I  1  MOV     Move Register       reg2 = reg1
  101000  ----   V  1  MOVEA   Add Immediate       reg2 = reg1 + (sign extend imm16)
  101111  ----   V  1  MOVHI   Add High Halfword   reg2 = reg1 + (imm16 << 16)
The MOVHI and MOVEA instructions are provided for populating registers with 32 bits of immediate data. Bear in mind that they perform arithmetic addition, but do not affect the status flags.

Load and Input Register
  111000  ----  VI  3  IN.B   Input Byte       reg2 = zero extend (byte ptr [reg1 + disp16])
  111001  ----  VI  *  IN.H   Input Halfword   reg2 = zero extend (halfword ptr [reg1 + disp16])
  111011  ----  VI  *  IN.W   Input Word       reg2 = word ptr [reg1 + disp16]
  110000  ----  VI  *  LD.B   Load Byte        reg2 = sign extend (byte ptr [reg1 + disp16])
  110001  ----  VI  *  LD.H   Load Halfword    reg2 = sign extend (halfword ptr [reg1 + disp16])
  110011  ----  VI  *  LD.W   Load Word        reg2 = word ptr [reg1 + disp16]
Note that *.H masks the lower bit of the address to 0, and *.W masks the lower two bits to 0. This forces data to be read on a boundary of the same size as the data being read.

The input instructions operate on CPU memory. The Virtual Boy does not have an I/O bus. They operate similarly to the load instructions, but they will zero-extend the values read rather than sign-extend them.

The number of cycles requred to complete a load or input instruction (except for IN.B) depends on the context in which the instruction is used.

The situations and cycle counts for load instructions are as follows:
1 cycle - When used after an instruction that takes many cycles and does not conflict with the load instruction. Editor's Note: How many is "many"?
2 cycles - When following another load instruction on a 32-bit bus*
3 cycles - When used by itself on a 32-bit bus*
4 cycles - When following another load instruction on a 16-bit bus
5 cycles - When used by itself on a 16-bit bus

The situations and cycle counts for input instructions are as follows:
3 cycles - When used on a 32-bit bus*
5 cycles - When used on a 16-bit bus

* - Note that Virtual Boy always uses a 16-bit bus, so the 32-bit cycle counts are only provided for the sake of completeness.

Store and Output Register
  111100  ----  VI  *  OUT.B   Output Byte       byte ptr [reg1 + disp16] = reg2 and 0xFF
  111101  ----  VI  *  OUT.H   Output Halfword   halfword ptr [reg1 + disp16] = reg2 and 0xFFFF
  111111  ----  VI  *  OUT.W   Output Word       word ptr [reg1 + disp16] = reg2
  110100  ----  VI  *  ST.B    Store Byte        byte ptr [reg1 + disp16] = reg2 and 0xFF
  110101  ----  VI  *  ST.H    Store Halfword    halfword ptr [reg1 + disp16] = reg2 and 0xFFFF
  110111  ----  VI  *  ST.W    Store Word        word ptr [reg1 + disp16] = reg2
Note that *.H masks the lower bit of the address to 0, and *.W masks the lower two bits to 0. This forces data to be written on a boundary of the same size as the data being written.

The output instructions operate on CPU memory. The Virtual Boy does not have an I/O bus. They operate in identical fashion to the store instructions.

The number of cycles requred to complete a store or output instruction depends on the context in which the instruction is used.

The situations and cycle counts are as follows (applies to both ST and OUT):
1 cycle - The first two consecutive executions of the instruction
2 cycles - Subsequent executions of the instruction on a 32-bit bus*
4 cycles - Subsequent executions of the instruction on a 16-bit bus

* - Note that Virtual Boy always uses a 16-bit bus, so the 32-bit cycle count is only provided for the sake of completeness.

CPU Arithmetic/Bitwise Operations

Arithmetic Operations
  010001  cvsz  II   1  ADD    Add Immediate       reg2 = reg2 + (sign extend imm5)
  000001  cvsz   I   1  ADD    Add Register        reg2 = reg2 + reg1
  101001  cvsz   V   1  ADDI   Add Immediate       reg2 = reg1 + (sign extend imm16)
  010011  cvsz  II   1  CMP    Compare Immediate   result = reg2 - (sign extend imm5)
  000011  cvsz   I   1  CMP    Compare Register    result = reg2 - reg1
  001001  -vsz   I  38  DIV    Divide Signed       r30 = reg2 mod reg1, reg2 = reg2 / reg1
  001011  -0sz   I  36  DIVU   Divide Unsigned     r30 = reg2 mod reg1, reg2 = reg2 / reg1
  001000  -vsz   I  13  MUL    Multipy Signed      result = reg2 * reg1, r30 = result high 32, reg2 = result low 32
  001010  -vsz   I  13  MULU   Multipy Unsigned    result = reg2 * reg1, r30 = result high 32, reg2 = result low 32
  000010  cvsz   I   1  SUB    Subtract            reg2 = reg2 - reg1
There is no subtraction instruction that uses immediate data. If you need one, use ADD or ADDI with a negative number.

The CMP instructions discard their output. Their only use is to modify the status flags for the purpose of conditional execution.

The remainder of division operations is stored in register r30, as are the upper 32 bits of multiplication operations. In both cases, the data is written to r30 prior to the storage of the result in reg2.

Overflow for DIV can only occur if the maximum negative value (0x80000000) is divided by -1 (0xFFFFFFFF). Should this occur, the result will also be the maximum negative value, r30 will become zero, and the Overflow flag will be 1. Otherwise, the Overflow flag will be 0.

Overflow for MUL and MULU will occur if the entire 64-bit result is not equal to the sign- or zero-extended (respectively) lower 32 bits of the result. Otherwise, the Overflow flag will be 0.

The DIV and DIVU instructions can raise the Zero Division exception.

Bitwise Operations
  001101  -0sz   I  1  AND    And Register                       reg2 = reg2 and reg1
  101101  -00z   V  1  ANDI   And Immediate                      reg2 = reg1 and (zero extend imm16)
  001111  -0sz   I  1  NOT    Not                                reg2 = not reg1
  001100  -0sz   I  1  OR     Or Register                        reg2 = reg2 or reg1
  101100  -0sz   V  1  ORI    OR Immediate                       reg2 = reg1 or (zero extended imm16)
  010111  c0sz  II  1  SAR    Shift Arithmetic Right Immediate   reg2 = reg2 >> (zero extend imm5) (sign-propagating)
  000111  c0sz   I  1  SAR    Shift Arithmetic Right Register    reg2 = reg2 >> reg1 (sign-propagating)
  010100  c0sz  II  1  SHL    Shift Left Immediate               reg2 = reg2 << (zero extend imm5)
  000100  c0sz   I  1  SHL    Shift Left Register                reg2 = reg2 << reg1
  010101  c0sz  II  1  SHR    Shift Right Immediate              reg2 = reg2 >> (zero extend imm5)
  000101  c0sz   I  1  SHR    Shift Right Register               reg2 = reg2 >> reg1
  001110  -0sz   I  1  XOR    Exclusive Or Register              reg2 = reg2 xor reg1
  101110  -0sz   V  1  XORI   Exclusive Or Immediate             reg2 = reg1 xor (zero extend imm16)
The arithmetic right shift is sign-propagating, meaning it makes a copy of the high bit to shift in on the left rather than shifting in a zero like the normal right shift does. This is primarily useful for manipulating signed numbers.

When using a register to specify a bit shift amount, the lower 5 bits of the register (reg1 & 0x1F) are used as an unsigned integer.

For bit shift instructions, the Carry flag will be equal to the last bit shifted out of the register. If the shift amount is 0, then Carry will be 0.

CPU Jump and Control Instructions

Normal Jumps
  101011  ----  IV   3  JAL   Jump and Link   r31 = PC + 4, PC = PC + disp26
  000110  ----   I   3  JMP   Jump register   PC = reg1
  101010  ----  IV   3  JR    Jump relative   PC = PC + disp26
Unlike most instructions, JMP operates off of its reg1 field, not its reg2 field.

Conditional Branches

While there is only one actual conditional branch instruction, there are assembly mnemonics for all varieties of its cond field. Bcond conditions check the status of flags in the PSW register.

The Bcond instruction has an opcode of 100, is stored in Format III, and represents the following operations according to the contents of its cond field:
  0000  ----  BV       *  Branch if overflow                 if OV = 1                then PC = PC + disp9
  0001  ----  BC/BL    *  Branch if carry/less than          if CY = 1                then PC = PC + disp9
  0010  ----  BZ/BE    *  Branch if zero/equal               if Z = 1                 then PC = PC + disp9
  0011  ----  BNH      *  Branch if not higher (unsigned)    if (CY or Z) = 1         then PC = PC + disp9
  0100  ----  BN       *  Branch if negative                 if S = 1                 then PC = PC + disp9
  0101  ----  BR       *  Branch always                      PC = PC + disp9
  0110  ----  BLT      *  Branch if less than (signed)       if (S xor OV) = 1        then PC = PC + disp9
  0111  ----  BLE      *  Branch if less/equal (signed)      if ((S xor OV) or Z) = 1 then PC = PC + disp9
  1000  ----  BNV      *  Branch if not overflow             if OV = 0                then PC = PC + disp9
  1001  ----  BNC/BNL  *  Branch if not carry/less than      if CY = 0                then PC = PC + disp9
  1010  ----  BNZ/BNE  *  Branch if not zero/equal           if Z = 0                 then PC = PC + disp9
  1011  ----  BH       *  Branch if higher (unsigned)        if (CY or Z) = 0         then PC = PC + disp9
  1100  ----  BP       *  Branch if positive                 if S = 0                 then PC = PC + disp9
  1101  ----  NOP      *  No operation (never branch)        (do nothing)
  1110  ----  BGE      *  Branch if greater/equal (signed)   if (S xor OV) = 0        then PC = PC + disp9
  1111  ----  BGT      *  Branch if greater than (signed)    if ((S xor OV) or Z) = 0 then PC = PC + disp9
* - If the branch is not taken, Bcond takes 1 cycle to execute. Otherwise, 3 cycles are used. This means the NOP instruction only takes 1 cycle.

Note that there are some pairs of mnemonics, such as BC with BL, and BNZ with BNE. Both mnemonics within a pair represent the same operation, and are likely provided as a convenience for the programmer as it pertains to the context of how the instruction is to be used. However, this makes it effectively impossible to disassemble according to programmer intent. It's a matter of preference at this point, but to disassemble to the BL, BE, BNL and BNE variants are more likely to correspond with programmer logic than their alternate representations.

CPU Control
  011010  ----  II   -  HALT   Halt CPU                     (wait for interrupt)
  011100  ****  II   1  LDSR   Load into System Register    regID** = reg2
  011001  ****  II  10  RETI   Return from Trap/IRQ         if NP = 1 then PC = FEPC, PSW = FEPSW
                                                              else         PC = EIPC, PSW = EIPSW
  011101  ----  II   1  STSR   Store from System Register   reg2 = regID**
  011000  ----  II  15  TRAP   Trap                         raise exception 0xFFA0 + vector*
* - The imm5 field of TRAP is used as a "trap vector", which is an application-defined value representing the source of the exception as it is stored in ECR. Two exception handlers can be defined for TRAP.
** - The imm5 field of the LDSR and STSR instructions represents the system register by ID; a value called regID. The system register ID values are as follows:
   0     EIPC   Exception/Interrupt PC
   1     EIPSW  Exception/Interrup PSW
   2     FEPC   Duplexed Exception PC
   3     FEPSW  Duplexed Exception PSW
   4     ECR*   Exception Cause Register
   5     PSW**  Program Status Word
   6     PIR*   Processor ID Register
   7     TKCW*  TasK Control Word
   8-23  (reserved***)
  24     CHCW   CacHe Control Word
  25     ADTRE  ADdress Trap Register for Execution
  26-31  (reserved***)
* - These registers are read-only and cannot be used with LDSR. However, attempting to do so will not trigger an exception; it will simply have no effect.
** - Program control of PSW can be done with LDSR on a bit-for-bit correspondence with the contents of reg2.
*** - Accessing reserved registers does not have guaranteed operation. Editor's Note: No exception is defined, so perhaps junk is assumed?

CPU Floating-Point Instructions

Instructions with an opcode field containing the bits 111110 are stored in Format VII and contain a sub-opcode field. In the V810 family instruction set, only floating-point instructions are defined as sub-opcodes of 111110, but Nintendo added a few instructions of their own here as well. Although there is room for 64 sub-opcodes, only 12 are used on Virtual Boy. The floating-point instructions are listed in this section, while the Nintendo proprietary instructions are listed in the CPU Nintendo Instructions section. All other values for the sub-opcode field represent invalid instructions.

Floating-Point Instructions
  000100  c0szR--VUP  ADDF.S    9-28   Add Floating Short                reg2 = reg2 + reg1
  000000  c0szR-----  CMPF.S    7-10   Compare Floating Short            result = reg2 - reg1
  000011  -0szRI---P  CVT.SW    9-14   Convert Floating Short to Word    reg2 = (word) round(reg1)
  000010  c0sz-----P  CVT.WS    5-16   Convert Word to Floating Short    reg2 = (float) reg1
  000111  c0szRIZVUP  DIVF.S      44   Divide Floating Short             reg2 = reg2 / reg1
  000110  c0szR--VUP  MULF.S    8-30   Multiply Floating Short           reg2 = reg2 * reg1
  000101  c0szR--VUP  SUBF.S   12-28   Subtract Floating Short           reg2 = reg2 - reg1
  001011  -0szRI---P  TRNC.SW   8-14   Truncate Floating Short to Word   reg2 = (word) truncate(reg1)
IMPORTANT: The floating-point program status flags can be set by these instructions, but if the condition they represent is not met, they will not be cleared by execution. If it's necessary to detect these flags as changes occur, use the LDSR instruction first to clear them.

To save space, this list uses one-letter abbreviations for the floating-point program status flags in the PSW register. The abbreviations correspond with the following flags in PSW:
  R   FRO   Floating-point reserved operand
  I   FIV   Floating-point invalid operation
  Z   FZD   Floating-point zero divide
  V   FOV   Floating-point overflow
  U   FUD   Floating-point underflow
  P   FPR   Floating-point precision degradation
The CMPF.S instruction discards its output. Its only use is to modify the status flags for the purpose of conditional execution.

The CVT.SW instruction's behavior is specified by the TKCW register, but that register has a fixed value on Virtual Boy to always specify rounding toward the nearest integer.

The TRNC.SW instruction will truncate the float value at the point, preserving the integer portion of the number.

The following chart shows which exceptions can be triggered by which instructions:

  ADDF.SCMPF.SCVT.SW CVT.WSDIVF.SMULF.S SUBF.STRNC.SW
FRO
Reserved Operand
 
FOV
Overflow
     
FZD
Zero Division
        
FIV
Invalid Operation
      

The TKCW register controls floating-point exception masking, and it has a fixed value such that FUD (underflow) and FPR (precision degradation) exceptions are permanently disabled.

Unfortunately, the specifics of how many CPU cycles are taken for various floating-point operations have not been disclosed for the V810 family. The only information provided consists of minimum and maximum cycle counts. For emulator timing considerations, it would not be a bad idea to always use the maximum cycle count, since it's guaranteed code won't run slower than that on a real Virtual Boy.

CPU Bit String Instructions

CPU About Bit String Instructions
CPU List of Bit String Instructions

CPU About Bit String Instructions

The bit string instructions on the V810 family processors are used to perform batch processing on bit data in memory. Due to their potentially long execution times, they can be aborted by interrupts and resumed once the interrupts have been processed.

Registers

All bit string instructions use registers r26-r30 to represent bit strings in this manner:

r30 - Source Word Address - Specifies the starting word address of the source string. The lowest 2 bits are masked to 0 before execution.

r29 - Destinaion Word Address - Specifies the starting word address of the destination string. The lowest 2 bits are masked to 0 before execution.

r28 - String Length - Specifies the length of the string(s) by number of bits. All 32 bits of this register are used as an unsigned value, meaning it can represent anywhere from 0 to (232 - 1) bits of length (up to 512 MB minus one bit).

r27 - Bit Offset in Source Word - The index of the starting bit (0-31) in the source word. The highest 27 bits are masked to 0 before execution.

r26 - Bit Offset in Destination Word - The index of the starting bit (0-31) in the destination word. The highest 27 bits are masked to 0 before execution.

Additionally, register r29 is used as output for the search instructions. This can work because there is no destination string for searches.

r29 - Number of Bits Skipped - Specifies the number of bits skipped during a search operation before the search completed. This register should be set to 0 prior to using a search instruction.

Aborting and Resuming

For all bit string instructions, registers r26-r30 are used as working variables, such that the instructions can be aborted by interrupts and later resumed. Editor's Note: Will the CPU retain state information for bit string instructions for each of normal execution, exception handling and duplexed exception handling?

Direction and Bit Order

Bit string instructions can operate either upward or downward. The direction in which the address increases is considered upward, and the direction in which the address decreases is considered downward.

Bits are read from words such that the most significant bit is in the upward direction and the least significant bit is in the downward direction.

Since words are read low byte first (little endian), bit strings can be visualized as having address 0x00000000 on the right and all bits extend to the left, in order of lowest to highest within each byte. In this context, the upward direction would be left and the downward direction would be right.

Overlapping Behavior

Bit string instructions will process source data intact; the output will never recurse into the input. This is similar to how the standard C function memmove() copies data to a temporary buffer before outputting: the output never gets read back in as input.

For that reason, it is safe to use bit string instructions with overlapping strings.

CPU List of Bit String Instructions

All bit string instructions have an opcode field containing the bits 011111, are stored in Format II and the imm5 value is used as a sub-opcode field. While there are 32 possible sub-opcodes, only 12 are used and the rest represent invalid instructions.

Arithmetic Instructions
  01001  ----  ANDBSU    And Bit String Upward                dest = dest and src
  01101  ----  ANDNBSU   And Not Bit String Upward            dest = dest and (not src)
  01011  ----  MOVBSU    Move Bit String Upward               dest = source
  01111  ----  NOTBSU    Not Bit String Upward                dest = not src
  01000  ----  ORBSU     Or Bit String Upward                 dest = dest or src
  01100  ----  ORNBSU    Or Not Bit String Upward             dest = dest or (not src)
  01010  ----  XORBSU    Exclusive Or Bit String Upward       dest = dest xor src 
  01110  ----  XORNBSU   Exclusive Or Not Bit String Upward   dest = dest xor (not src)
Note that address overlaps can cause undesired operation by overwriting the source before it can be written to the destination.

Search Instructions
  00001  ---z  SCH0BSD   Search Bit 0 Downward    Search downward for a 0
  00000  ---z  SCH0BSU   Search Bit 0 Upward      Search upward for a 0
  00011  ---z  SCH1BSD   Search Bit 1 Downward    Search downward for a 1
  00010  ---z  SCH1BSU   Search Bit 1 Upward      Search upward for a 1
If the search is not found, Z = 1. Otherwise, Z = 0.

Non-Search Instruction Cycles

The number of cycles taken for arithmetic instructions depends on the relationship between the word boundaries of the source and destination strings, and the length of the string being manipulated. There are seven significant situations to describe this relationship, called the boundary condition, and they are named TYPE1 through TYPE7.

Let N be the number of words occupied by the source string (by address), and Ndest the number of words occupied by the destination string.

The boundary condition types are defined as follows:

if length = 0 then
TYPE6
else
if (N = 1) and (Ndest = 1) and (source offset > destination offset) then
TYPE7
else if source offset = destination offset then
if (source offset + length) mod 4 = 0 then -- Source ends on a word boundary
TYPE1
else
TYPE2
end if
else
if N = Ndest then
if destinaton offset = 0 then -- Destination begins on a word boundary
TYPE3
else
TYPE5
end if
else
TYPE4
end if
end if
end if

The following chart lists the execution times for arithmetic bit string instructions. The specifics of how long instructions can take are only provided for optimal conditions (cache hit, no bus waiting) in the V810 family documentation. In practice, they will generally take slightly longer.

Boundary N = 1 N = 2 N > 2
Condition 32-bit bus* 16-bit bus 32-bit bus* 16-bit bus 32-bit bus* 16-bit bus
TYPE132384153 6N + 3012N + 30
TYPE232384254 6N + 3112N + 31
TYPE337434860 6N + 3512N + 35
TYPE443494961 6N + 3612N + 36
TYPE532384355 6N + 3112N + 31
TYPE61420-- --
TYPE73743-- --

* - Note that Virtual Boy always uses a 16-bit bus, so the 32-bit cycle counts are only provided for the sake of completeness.

Search Instruction Cycles

The number of cycles taken for search instructions depends on how many words and bits within words are searched. The specifics of how long instructions can take are only provided for optimal conditions (cache hit, no bus waiting) in the V810 family documentation. In practice, they will generally take slightly longer.

For the charts below, let the following values be defined:

N - The number of words occupied by the string (by address)
p - Any word after the 2nd but before the Nth
Start Bit - The source word's (1st) starting bit offset
Found Bit - The bit offset of a match, which is located in the Nth word

The following chart shows how many cycles are taken on a 16-bit bus for an upward search:

Start Bit Found Bit N Found 1st Found 2nd Found pth Found Nth Not Found
*-0 ---- 13
**1 31--- 31
0< 312 4043-- 44
> 0< 312 3051-- 51
> 0312 3056-- 50
0312 4045-- 39
0< 31> 2 40453p + 353N + 33 3N + 34
> 0< 31> 2 30563p + 463N + 44 3N + 45
> 031> 2 30563p + 463N + 46 3N + 40
031> 2 40453p + 353N + 35 3N + 29

The following chart shows how many cycles are taken on a 16-bit bus for a downward search:

Start Bit Found Bit N Found 1st Found 2nd Found pth Found Nth Not Found
*-0 ---- 15
**1 28--- 30
< 3102 3352-- 54
< 31> 02 3352-- 54
31> 02 4552-- 51
3102 4550-- 44
< 310> 2 33593p + 493N + 49 3N + 43
< 31> 0> 2 33593p + 493N + 51 3N + 50
31> 0> 2 45503p + 403N + 42 3N + 41
310> 2 45503p + 403N + 40 3N + 34

The Virtual Boy's bus always operates as 16-bit. Listed below are the 32-bit execution times for the sake of completeness.

The following chart shows how many cycles are taken on a 32-bit bus for an upward search:

Start Bit Found Bit N Found 1st Found 2nd Found pth Found Nth Not Found
*-0 ---- 13
**1 29--- 29
0< 312 3839-- 40
> 0< 312 2847-- 47
> 0312 2852-- 46
0312 3841-- 35
0< 31> 2 38413p + 353N + 33 3N + 34
> 0< 31> 2 28523p + 463N + 44 3N + 45
> 031> 2 28523p + 463N + 46 3N + 40
031> 2 38413p + 353N + 35 3N + 29

The following chart shows how many cycles are taken on a 32-bit bus for a downward search:

Start Bit Found Bit N Found 1st Found 2nd Found pth Found Nth Not Found
*-0 ---- 15
**1 26--- 28
< 3102 3148-- 50
< 31> 02 3148-- 50
31> 02 4348-- 47
3102 4346-- 40
< 310> 2 31553p + 493N + 49 3N + 43
< 31> 0> 2 31553p + 493N + 51 3N + 50
31> 0> 2 43463p + 403N + 42 3N + 41
310> 2 43463p + 403N + 40 3N + 34

CPU Miscellaneous Instructions

Miscellaneous Instructions
  111010  cvsz  VI  26  CAXI   Compare and Exchange Interlocked   (See below)
  010010  ----  II   1  SETF   Set Flag Condition                 reg2 = 1 if condition* true, 0 otherwise
* - The imm5 field of SETF specifies a condition to check for in the PSW register. The condition values match those used in the Bcond instruction, and are as follows:
  0000   V       OV = 1
  0001   C/L     CY = 1
  0010   Z       Z = 1
  0011   NH      (CY or Z) = 1
  0100   S/N     S = 1
  0101   T       (always 1)
  0110   LT      (S xor OV) = 1
  0111   LE      ((S xor OV) or Z) = 1
  1000   NV      OV = 0
  1001   NC/NL   CY = 0
  1010   NZ      Z = 0
  1011   H       (CY or Z) = 0
  1100   NS/P    S = 0
  1101   F       (always 0)
  1110   GE      (S xor OV) = 0
  1111   GT      ((S xor OV) or Z) = 0
 10000+  (undefined)*
As with Bcond, there are multiple assembly mnemonics for some conditions, but they represent the same status.

* - Editor's Note: What happens if you use these?

CAXI

The purpose of the CAXI instruction is to synchronize multiple processors by implementing a simple mutex mechanism. Three parameters are passed to the instruction: a memory address, a value to check for when a lock is desired, and a value to write to the address if the lock succeeds. All processors that share the given resource should check that address against the same value.

The CAXI instruction has the following parameters:
reg1
- The base value of the address to check
disp16
- The address relative to the base address
reg2
- The value to check at the resulting address
r30
- The value to write to the address if it matches reg2

The address, calculated as reg1 + disp16, is called the lock word. It has the lowest two bits masked to zero, forcing the lock address to start on a word boundary.

Let lock be the value of the lock word. During execution, CAXI will perform a comparison--CMP with reg2 - lock--and when it completes, lock will be stored into reg2. If lock was equal to reg2, then the value in r30 will have been written to the lock word. The program can quickly check what happened by examining the Z flag of the status register and branching accordingly.

To prevent bus conflicts, CAXI locks the bus during execution, which keeps other processors from accessing memory while it executes. This also eliminates race conditions on the lock word.

Since Virtual Boy only has one processor, the implementation of the CAXI instruction is roughly equivalent to this:
  addr = (reg1 + disp16) AND -4
  lock = word ptr [addr]
  compare reg2 - lock
  reg2 = lock
  if Z = 1 then word ptr [addr] = r30
If CAXI is used on a 32-bit bus, it will take 22 cycles. On 16-bits, it will take 26. Note that Virtual Boy always uses a 16-bit bus, so the 32-bit cycle count is only provided for the sake of completeness.

CPU Nintendo Instructions

When Nintendo adapted the V810 for use with the Virtual Boy, they introduced a handful of proprietary instructions for auxiliary functionality. They did not specify cycle counts, however, so that information may not be 100% accurate.

Of the 6 instructions Nintendo added to the V810 instruction set, 2 of them have their own opcodes and the other 4 occupy otherwise-unused sub-opcodes of the floating-point instructions.

Standalone Instructions
  010110  ----  II  1  CLI   Clear interrupt disable flag   I = 0
  011110  ----  II  1  SEI   Set interrupt disable flag     I = 1
Ordinarily, the interrupt disable flag in the status register can only be set and cleared via the LDSR instruction, but Nintendo implemented these two instructions that were present in the instruction sets for NES and SNES.

Instructions with an opcode field containing the bits 111110 are stored in Format VII and contain a sub-opcode field. For more information, refer to the CPU Floating-Point Instructions section. The remaining Nintendo instructions occupy sub-opcodes of 111110.

Sub-Opcode Instructions
  001100  ----  9  MPYHW   Multiply Halfword Signed*   reg2 = reg2 * reg1
  001010  ----  1  REV     Reverse Bits                reg2 = bit_reverse reg1
  001000  ----  1  XB      Swap Low Bytes**            reg2 bytes zyxw = zywx
  001001  ----  1  XH      Swap Halfwords**            reg2 bytes zyxw = xwzy
* - This instruction treats the values in reg1 and reg2 as signed halfwords. For this reason, the result will be incorrect if the upper 16 bits of each operand do not match the value of bit 15 within that operand.

** - These instructions must specify r0 for their reg1 field. Operation is not guaranteed if any other register is specified. Editor's Note: But what exactly would happen?

CPU List of Instructions by Opcode

Normal Instructions
  000000    I  MOV     Move Register                      reg2 = reg1
  000001    I  ADD     Add Register                       reg2 = reg2 + reg1
  000010    I  SUB     Subtract                           reg2 = reg2 - reg1
  000011    I  CMP     Compare Register                   result = reg2 - reg1
  000100    I  SHL     Shift Left Register                reg2 = reg2 << reg1
  000101    I  SHR     Shift Right Register               reg2 = reg2 >> reg1
  000110    I  JMP     Jump register                      PC = reg1
  000111    I  SAR     Shift Arithmetic Right Register    reg2 = reg2 >> reg1 (sign-propagating)
  001000    I  MUL     Multipy Signed                     result = reg2 * reg1, r30 = result high 32, reg2 = result low 32
  001001    I  DIV     Divide Signed                      r30 = reg2 mod reg1, reg2 = reg2 / reg1
  001010    I  MULU    Multipy Unsigned                   result = reg2 * reg1, r30 = result high 32, reg2 = result low 32
  001011    I  DIVU    Divide Unsigned                    r30 = reg2 mod reg1, reg2 = reg2 / reg1
  001100    I  OR      Or Register                        reg2 = reg2 or reg1
  001101    I  AND     And Register                       reg2 = reg2 and reg1
  001110    I  XOR     Exclusive Or Register              reg2 = reg2 xor reg1
  001111    I  NOT     Not                                reg2 = not reg1
  010000   II  MOV     Move Immediate                     reg2 = sign extend imm5
  010001   II  ADD     Add Immediate                      reg2 = reg2 + (sign extend imm5)
  010010   II  SETF    Set Flag Condition                 reg2 = 1 if condition true, 0 otherwise
  010011   II  CMP     Compare Immediate                  result = reg2 - (sign extend imm5)
  010100   II  SHL     Shift Left Immediate               reg2 = reg2 << (zero extend imm5)
  010101   II  SHR     Shift Right Immediate              reg2 = reg2 >> (zero extend imm5)
  010110   II  CLI     Clear interrupt disable flag       I = 0
  010111   II  SAR     Shift Arithmetic Right Immediate   reg2 = reg2 >> (zero extend imm5) (sign-propagating)
  011000   II  TRAP    Trap                               raise exception 0xFFA0 + vector
  011001   II  RETI    Return from Trap/IRQ               (See section)
  011010   II  HALT    Halt CPU                           (wait for interrupt)
  011011    !          == ILLEGAL OPCODE ==
  011100   II  LDSR    Load into System Register          regID = reg2
  011101   II  STSR    Store from System Register         reg2 = regID
  011110   II  SEI     Set interrupt disable flag         I = 1
  011111   II  *       (Bit string instructions)          (See section)
  100     III  Bcond   Conditional branches               (See section)
  101000    V  MOVEA   Add Immediate                      reg2 = reg1 + (sign extend imm16)
  101001    V  ADDI    Add Immediate                      reg2 = reg1 + (sign extend imm16)
  101010   IV  JR      Jump relative                      PC = PC + disp26
  101011   IV  JAL     Jump and Link                      r31 = PC + 4, PC = PC + disp26
  101100    V  ORI     OR Immediate                       reg2 = reg1 or (zero extended imm16)
  101101    V  ANDI    And Immediate                      reg2 = reg1 and (zero extend imm16)
  101110    V  XORI    Exclusive Or Immediate             reg2 = reg1 xor (zero extend imm16)
  101111    V  MOVHI   Add High Halfword                  reg2 = reg1 + (imm16 << 16)
  110000   VI  LD.B    Load Byte                          reg2 = sign extend (byte ptr [reg1 + disp16])
  110001   VI  LD.H    Load Halfword                      reg2 = sign extend (halfword ptr [reg1 + disp16])
  110010    !          == ILLEGAL OPCODE ==
  110011   VI  LD.W    Load Word                          reg2 = word ptr [reg1 + disp16]
  110100   VI  ST.B    Store Byte                         byte ptr [reg1 + disp16] = reg2 and 0xFF
  110101   VI  ST.H    Store Halfword                     halfword ptr [reg1 + disp16] = reg2 and 0xFFFF
  110110    !          == ILLEGAL OPCODE ==
  110111   VI  ST.W    Store Word                         word ptr [reg1 + disp16] = reg2
  111000   VI  IN.B    Input Byte                         reg2 = zero extend (byte ptr [reg1 + disp16])
  111001   VI  IN.H    Input Halfword                     reg2 = zero extend (halfword ptr [reg1 + disp16])
  111010   VI  CAXI    Compare and Exchange Interlocked   (See section)
  111011   VI  IN.W    Input Word                         reg2 = word ptr [reg1 + disp16]
  111100   VI  OUT.B   Output Byte                        byte ptr [reg1 + disp16] = reg2 and 0xFF
  111101   VI  OUT.H   Output Halfword                    halfword ptr [reg1 + disp16] = reg2 and 0xFFFF
  111110  VII  *       (Floating-point instructions)      (See section)
  111111   VI  OUT.W   Output Word                        word ptr [reg1 + disp16] = reg2
Bit String Instructions - Opcode = 011111
  00000  SCH0BSU   Search Bit 0 Upward                  Search upward for a 0
  00001  SCH0BSD   Search Bit 0 Downward                Search downward for a 0
  00010  SCH1BSU   Search Bit 1 Upward                  Search upward for a 1
  00011  SCH1BSD   Search Bit 1 Downward                Search downward for a 1
  00100-00111      == ILLEGAL OPCODE ==
  01000  ORBSU     Or Bit String Upward                 dest = dest or src
  01001  ANDBSU    And Bit String Upward                dest = dest and src
  01010  XORBSU    Exclusive Or Bit String Upward       dest = dest xor src
  01011  MOVBSU    Move Bit String Upward               dest = source
  01100  ORNBSU    Or Not Bit String Upward             dest = dest or (not src)
  01101  ANDNBSU   And Not Bit String Upward            dest = dest and (not src)
  01110  XORNBSU   Exclusive Or Not Bit String Upward   dest = dest xor (not src)
  01111  NOTBSU    Not Bit String Upward                dest = not src
  10000-11111      == ILLEGAL OPCODE ==
Floating-Point and Nintendo Instructions - Opcode = 111110
  000000  CMPF.S    Compare Floating Short            result = reg2 - reg1
  000001            == ILLEGAL OPCODE ==
  000010  CVT.WS    Convert Word to Floating Short    reg2 = float reg1
  000011  CVT.SW    Convert Floating Short to Word    reg2 = convert reg1
  000100  ADDF.S    Add Floating Short                reg2 = reg2 + reg1
  000101  SUBF.S    Subtract Floating Short           reg2 = reg2 - reg1
  000110  MULF.S    Multiply Floating Short           reg2 = reg2 * reg1
  000111  DIVF.S    Divide Floating Short             reg2 = reg2 / reg1
  001000  XB        Swap Low Bytes                    reg2 bytes zyxw = zywx
  001001  XH        Swap Halfwords                    reg2 bytes zyxw = xwzy
  001010  REV       Reverse Bits                      reg2 = bit_reverse reg1
  001011  TRNC.SW   Truncate Floating Short to Word   reg2 = truncate reg1
  001100  MPYHW     Multiply Halfword Signed          reg2 = reg2 * reg1
  001101-111111     == ILLEGAL OPCODE ==

CPU List of Instructions by Mnemonic

Normal Instructions
  010001   II  ADD     Add Immediate                      reg2 = reg2 + (sign extend imm5)
  000001    I  ADD     Add Register                       reg2 = reg2 + reg1
  101001    V  ADDI    Add Immediate                      reg2 = reg1 + (sign extend imm16)
  001101    I  AND     And Register                       reg2 = reg2 and reg1
  101101    V  ANDI    And Immediate                      reg2 = reg1 and (zero extend imm16)
  100     III  Bcond   Conditional branches               (See section)
  111010   VI  CAXI    Compare and Exchange Interlocked   (See section)
  010110   II  CLI     Clear interrupt disable flag       I = 0
  010011   II  CMP     Compare Immediate                  result = reg2 - (sign extend imm5)
  000011    I  CMP     Compare Register                   result = reg2 - reg1
  001001    I  DIV     Divide Signed                      r30 = reg2 mod reg1, reg2 = reg2 / reg1
  001011    I  DIVU    Divide Unsigned                    r30 = reg2 mod reg1, reg2 = reg2 / reg1
  011010   II  HALT    Halt CPU                           (wait for interrupt)
  111000   VI  IN.B    Input Byte                         reg2 = zero extend (byte ptr [reg1 + disp16])
  111001   VI  IN.H    Input Halfword                     reg2 = zero extend (halfword ptr [reg1 + disp16])
  111011   VI  IN.W    Input Word                         reg2 = word ptr [reg1 + disp16]
  101011   IV  JAL     Jump and Link                      r31 = PC + 4, PC = PC + disp26
  000110    I  JMP     Jump register                      PC = reg1
  101010   IV  JR      Jump relative                      PC = PC + disp26
  110000   VI  LD.B    Load Byte                          reg2 = sign extend (byte ptr [reg1 + disp16])
  110001   VI  LD.H    Load Halfword                      reg2 = sign extend (halfword ptr [reg1 + disp16])
  110011   VI  LD.W    Load Word                          reg2 = word ptr [reg1 + disp16]
  011100   II  LDSR    Load into System Register          regID = reg2
  010000   II  MOV     Move Immediate                     reg2 = sign extend imm5
  000000    I  MOV     Move Register                      reg2 = reg1
  101000    V  MOVEA   Add Immediate                      reg2 = reg1 + (sign extend imm16)
  101111    V  MOVHI   Add High Halfword                  reg2 = reg1 + (imm16 << 16)
  001000    I  MUL     Multipy Signed                     result = reg2 * reg1, r30 = result high 32, reg2 = result low 32
  001010    I  MULU    Multipy Unsigned                   result = reg2 * reg1, r30 = result high 32, reg2 = result low 32
  001111    I  NOT     Not                                reg2 = not reg1
  111100   VI  OUT.B   Output Byte                        byte ptr [reg1 + disp16] = reg2 and 0xFF
  111101   VI  OUT.H   Output Halfword                    halfword ptr [reg1 + disp16] = reg2 and 0xFFFF
  111111   VI  OUT.W   Output Word                        word ptr [reg1 + disp16] = reg2
  001100    I  OR      Or Register                        reg2 = reg2 or reg1
  101100    V  ORI     OR Immediate                       reg2 = reg1 or (zero extended imm16)
  011001   II  RETI    Return from Trap/IRQ               (See section)
  010111   II  SAR     Shift Arithmetic Right Immediate   reg2 = reg2 >> (zero extend imm5) (sign-propagating)
  000111    I  SAR     Shift Arithmetic Right Register    reg2 = reg2 >> reg1 (sign-propagating)
  011110   II  SEI     Set interrupt disable flag         I = 1
  010010   II  SETF    Set Flag Condition                 reg2 = 1 if condition true, 0 otherwise
  010100   II  SHL     Shift Left Immediate               reg2 = reg2 << (zero extend imm5)
  000100    I  SHL     Shift Left Register                reg2 = reg2 << reg1
  010101   II  SHR     Shift Right Immediate              reg2 = reg2 >> (zero extend imm5)
  000101    I  SHR     Shift Right Register               reg2 = reg2 >> reg1
  110100   VI  ST.B    Store Byte                         byte ptr [reg1 + disp16] = reg2 and 0xFF
  110101   VI  ST.H    Store Halfword                     halfword ptr [reg1 + disp16] = reg2 and 0xFFFF
  110111   VI  ST.W    Store Word                         word ptr [reg1 + disp16] = reg2
  011101   II  STSR    Store from System Register         reg2 = regID
  000010    I  SUB     Subtract                           reg2 = reg2 - reg1
  011000   II  TRAP    Trap                               raise exception 0xFFA0 + vector
  101110    V  XORI    Exclusive Or Immediate             reg2 = reg1 xor (zero extend imm16)
  001110    I  XOR     Exclusive Or Register              reg2 = reg2 xor reg1
  011111   II  *       (Bit string instructions)          (See section)
  111110  VII  *       (Floating-point instructions)      (See section)
Bit String Instructions - Opcode = 011111
  01001  ANDBSU    And Bit String Upward                dest = dest and src
  01101  ANDNBSU   And Not Bit String Upward            dest = dest and (not src)
  01011  MOVBSU    Move Bit String Upward               dest = source
  01111  NOTBSU    Not Bit String Upward                dest = not src
  01000  ORBSU     Or Bit String Upward                 dest = dest or src
  01100  ORNBSU    Or Not Bit String Upward             dest = dest or (not src)
  00001  SCH0BSD   Search Bit 0 Downward                Search downward for a 0
  00000  SCH0BSU   Search Bit 0 Upward                  Search upward for a 0
  00011  SCH1BSD   Search Bit 1 Downward                Search downward for a 1
  00010  SCH1BSU   Search Bit 1 Upward                  Search upward for a 1
  01010  XORBSU    Exclusive Or Bit String Upward       dest = dest xor src
  01110  XORNBSU   Exclusive Or Not Bit String Upward   dest = dest xor (not src)
Floating-Point and Nintendo Instructions - Opcode = 111110
  000100  ADDF.S    Add Floating Short                reg2 = reg2 + reg1
  000000  CMPF.S    Compare Floating Short            result = reg2 - reg1
  000011  CVT.SW    Convert Floating Short to Word    reg2 = convert reg1
  000010  CVT.WS    Convert Word to Floating Short    reg2 = float reg1
  000111  DIVF.S    Divide Floating Short             reg2 = reg2 / reg1
  001100  MPYHW     Multiply Halfword Signed          reg2 = reg2 * reg1
  000110  MULF.S    Multiply Floating Short           reg2 = reg2 * reg1
  001010  REV       Reverse Bits                      reg2 = bit_reverse reg1
  000101  SUBF.S    Subtract Floating Short           reg2 = reg2 - reg1
  001011  TRNC.SW   Truncate Floating Short to Word   reg2 = truncate reg1
  001000  XB        Swap Low Bytes                    reg2 bytes zyxw = zywx
  001001  XH        Swap Halfwords                    reg2 bytes zyxw = xwzy

CPU List of Instructions by Format

Normal Instructions
  000001    I  ADD     Add Register                       reg2 = reg2 + reg1
  001101    I  AND     And Register                       reg2 = reg2 and reg1
  000011    I  CMP     Compare Register                   result = reg2 - reg1
  001001    I  DIV     Divide Signed                      r30 = reg2 mod reg1, reg2 = reg2 / reg1
  001011    I  DIVU    Divide Unsigned                    r30 = reg2 mod reg1, reg2 = reg2 / reg1
  000110    I  JMP     Jump register                      PC = reg1
  000000    I  MOV     Move Register                      reg2 = reg1
  001000    I  MUL     Multipy Signed                     result = reg2 * reg1, r30 = result high 32, reg2 = result low 32
  001010    I  MULU    Multipy Unsigned                   result = reg2 * reg1, r30 = result high 32, reg2 = result low 32
  001111    I  NOT     Not                                reg2 = not reg1
  001100    I  OR      Or Register                        reg2 = reg2 or reg1
  000111    I  SAR     Shift Arithmetic Right Register    reg2 = reg2 >> reg1 (sign-propagating)
  000100    I  SHL     Shift Left Register                reg2 = reg2 << reg1
  000101    I  SHR     Shift Right Register               reg2 = reg2 >> reg1
  000010    I  SUB     Subtract                           reg2 = reg2 - reg1
  001110    I  XOR     Exclusive Or Register              reg2 = reg2 xor reg1
  010001   II  ADD     Add Immediate                      reg2 = reg2 + (sign extend imm5)
  010110   II  CLI     Clear interrupt disable flag       I = 0
  011010   II  HALT    Halt CPU                           (wait for interrupt)
  010011   II  CMP     Compare Immediate                  result = reg2 - (sign extend imm5)
  011100   II  LDSR    Load into System Register          regID = reg2
  010000   II  MOV     Move Immediate                     reg2 = sign extend imm5
  011001   II  RETI    Return from Trap/IRQ               (See section)
  010111   II  SAR     Shift Arithmetic Right Immediate   reg2 = reg2 >> (zero extend imm5) (sign-propagating)
  011110   II  SEI     Set interrupt disable flag         I = 1
  010010   II  SETF    Set Flag Condition                 reg2 = 1 if condition true, 0 otherwise
  010100   II  SHL     Shift Left Immediate               reg2 = reg2 << (zero extend imm5)
  010101   II  SHR     Shift Right Immediate              reg2 = reg2 >> (zero extend imm5)
  011101   II  STSR    Store from System Register         reg2 = regID
  011000   II  TRAP    Trap                               raise exception 0xFFA0 + vector
  011111   II  *       (Bit string instructions)          (See section)
  100     III  Bcond   Conditional branches               (See section)
  101011   IV  JAL     Jump and Link                      r31 = PC + 4, PC = PC + disp26
  101010   IV  JR      Jump relative                      PC = PC + disp26
  101001    V  ADDI    Add Immediate                      reg2 = reg1 + (sign extend imm16)
  101101    V  ANDI    And Immediate                      reg2 = reg1 and (zero extend imm16)
  101000    V  MOVEA   Add Immediate                      reg2 = reg1 + (sign extend imm16)
  101111    V  MOVHI   Add High Halfword                  reg2 = reg1 + (imm16 << 16)
  101100    V  ORI     OR Immediate                       reg2 = reg1 or (zero extended imm16)
  101110    V  XORI    Exclusive Or Immediate             reg2 = reg1 xor (zero extend imm16)
  111010   VI  CAXI    Compare and Exchange Interlocked   (See section)
  111000   VI  IN.B    Input Byte                         reg2 = zero extend (byte ptr [reg1 + disp16])
  111001   VI  IN.H    Input Halfword                     reg2 = zero extend (halfword ptr [reg1 + disp16])
  111011   VI  IN.W    Input Word                         reg2 = word ptr [reg1 + disp16]
  110000   VI  LD.B    Load Byte                          reg2 = sign extend (byte ptr [reg1 + disp16])
  110001   VI  LD.H    Load Halfword                      reg2 = sign extend (halfword ptr [reg1 + disp16])
  110011   VI  LD.W    Load Word                          reg2 = word ptr [reg1 + disp16]
  111100   VI  OUT.B   Output Byte                        byte ptr [reg1 + disp16] = reg2 and 0xFF
  111101   VI  OUT.H   Output Halfword                    halfword ptr [reg1 + disp16] = reg2 and 0xFFFF
  111111   VI  OUT.W   Output Word                        word ptr [reg1 + disp16] = reg2
  110100   VI  ST.B    Store Byte                         byte ptr [reg1 + disp16] = reg2 and 0xFF
  110101   VI  ST.H    Store Halfword                     halfword ptr [reg1 + disp16] = reg2 and 0xFFFF
  110111   VI  ST.W    Store Word                         word ptr [reg1 + disp16] = reg2
  111110  VII  *       (Floating-point instructions)      (See section)

System Reset

The initial state of the Virtual Boy system upon system reset/power-on is as follows.

Memory

All memory in the Virtual Boy, including WRAM, VIP memory and VSU memory, are undefined at system startup. The values in memory contain junk, and programs should not expect them to contain any particular value.

CPU Registers

The CPU registers are initialized to the following values:
r1-r31  Undefined
PC      0xFFFFFFF0
PSW     0x00008000
EIPC    Undefined
EIPSW   Undefined
FEPC    Undefined
FEPSW   Undefined
ECR     0x0000FFF0
When PSW is initialized, the NP flag is set. This must be reset manually using the LDSR instruction. Otherwise, any exceptions or interrupts that occur will result in an immediate deadlock.

The exception code and initial address in PC point to the Reset interrupt handler. Do not use the RETI instruction to return from the Reset interrupt.

VIP

The states of the VIP control registers and their associated functionality on system reset are as follows. Any bits marked as "not used" are treated as 0 in this list:
Interrupt Enable   0x0000
0x0005F800 - Interrupt Pending       Undefined
0x0005F802 - Interrupt Enable        0x0000
0x0005F820 - Display Status          See below
0x0005F824 - LED Brightness 1        Undefined
0x0005F826 - LED Brightness 2        Undefined
0x0005F828 - LED Brightness 3        Undefined
0x0005F82A - LED Brightness Idle     Undefined
0x0005F82E - Frame Repeat            Undefined
0x0005F840 - Drawing Status          See below
0x0005F848 - OBJ Group 0 Pointer     Undefined
0x0005F84A - OBJ Group 1 Pointer     Undefined
0x0005F84C - OBJ Group 2 Pointer     Undefined
0x0005F84E - OBJ Group 3 Pointer     Undefined
0x0005F860 - BG Palette 0            Undefined
0x0005F862 - BG Palette 1            Undefined
0x0005F864 - BG Palette 2            Undefined
0x0005F866 - BG Palette 3            Undefined
0x0005F868 - OBJ Palette 0           Undefined
0x0005F86A - OBJ Palette 1           Undefined
0x0005F86C - OBJ Palette 2           Undefined
0x0005F86E - OBJ Palette 3           Undefined
0x0005F870 - Clear Color             Undefined
Some bits in Display Status are undefined on system reset. The guaranteed values are as follows:
0 - Display Sync Signals Enabled
0 - VIP Memory is Refreshing
0 - Display Procedure Beginning
Some bits in Drawing Status are undefined as well. The guaranteed values are as follows:
0 - Drawing is Enabled
VSU

Editor's Note: Is any aspect of the VSU initialized? The sound channels all appear to be stopped, but the Nintendo boilerplate assembly sets Sound Disable before initializing static memory.

Hardware Control Registers

The states of the Hardware Control Registers and their associated functionality on system reset are as follows. Any bits marked as "not used" are treated as 0 in this list:
0x02000000 - Link Control Register             0x03
0x02000004 - Auxiliary Link Register           0x9F
0x02000008 - Link Transmit Data                0x00
0x0200000C - Link Receive Data                 0x00
0x02000010 - Game Pad Input Low                0x00
0x02000014 - Game Pad Input High               0x00
0x02000018 - Timer Counter/Reload Low          See below
0x0200001C - Timer Counter/Reload High         See below
0x02000020 - Timer Control Register            0x04
0x02000024 - Wait Control Register             0x00
0x02000028 - Game Pad Input Control Register   0x04
The initial count value of the timer is 0xFFFF, but its initial reload value is 0x0000.

About VB Sacred Tech Scroll

VB Sacred Tech Scroll
Version 0.91 (WIP) - January 4, 2013
ROUGH DRAFT! It still needs some work, but I'm putting it out there so people can get to it.
Written by Guy Perfect

Presentation and formatting largely inspired by the Nocash technical documents by Martin Korth: http://nocash.emubase.de/

Thanks & Credits

This document is a compilation of information published in other documents, but is otherwise original work. The sources used for this document are as follows:

Planet Virtual Boy
A community of people just like me. What more could you want?
http://www.planetvb.com/
Special thanks to these contributors in particular, in alphabetical order:
• Benjamin Stevens - Testing support
• bigmak - Testing support
• dasi - Resources and testing support
• DogP - Unwitting source of information
• HorvatM - Resources and testing support

V810 Family™ 32-bit Microprocessor User's Manual
Document No. U10082EJ1V0UM00 (1st edition) - October 1995
Written by NEC

Richard Hutchinson
Created the FlashBoy Plus flash cartridge, which was invaluable for original research.
Those listed above for "testing support" ran my test code on their own FlashBoy units when I didn't have one.

Project: Virtual Boy
Resource with various goods, including hardware specifics.
http://www.projectvb.com/

Virtual Boy™ Programmers Manual
Version 0.521 - January 2005
Written by David Tucker, with thanks to the following contributors:
Bob VanderClay, Ben Hanor, Alberto Covarrubias,
Amos Bieler, Frostgiant, Parasyte, DogP

Virtual Boy
Article on Wikipedia.
http://en.wikipedia.org/wiki/Virtual_Boy