Virtual Boy - Sacred Tech Scroll

Overview
Memory Map
ROM Format
System Reset
About
Change Colors

System Components
CPU - NVC/V810 Family Microprocessor
Communication Port
Game Pad
Game Pak
Timer
Wait Controller
VIP - Virtual Image Processor
VSU - Virtual Sound Unit


Memory Map

The Virtual Boy memory bus is 27 bits wide and is organized by hardware component:

0x00000000 - 0x00FFFFFF VIP - Virtual Image Processor
0x01000000 - 0x01FFFFFF VSU - Virtual Sound Unit
0x02000000 - 0x02FFFFFF Miscellaneous Hardware
0x03000000 - 0x03FFFFFF Unmapped
0x04000000 - 0x04FFFFFF Game Pak Expansion
0x05000000 - 0x05FFFFFF WRAM
0x06000000 - 0x06FFFFFF Game Pak RAM
0x07000000 - 0x07FFFFFF Game Pak ROM
0x08000000 - 0xFFFFFFFF Mirroring of memory map

The upper 5 bits of any address in the 0x08000000 - 0xFFFFFFFF range are masked, making the maximum effective address 0x07FFFFFF and producing mirrors of the contents of memory across the entire address range.

Writes to the unmapped address range 0x03000000 - 0x03FFFFFF have no effect, and reads in that range will return zero.

WRAM is 64 KiB in size: its effective address range is 0x05000000 - 0x0500FFFF. Any addresses in the 0x05010000 - 0x05FFFFFF range consequently have bits 16-23 masked, producing mirrors of the contents of WRAM across the entire address range.

For information on the Game Pak Expansion, Game Pak RAM and Game Pak ROM address ranges, see Game Pak.

WRAM

WRAM is pseudostatic RAM that has specific initialization requirements:

Wait 200 µs before accessing.
Perform 8 dummy read accesses before any other accesses.

Virtual Boy software must account for this initialization before accessing WRAM, or else its behavior is undefined.

Miscellaneous Hardware

Registers for various hardware components occupy addresses 0x02000000 - 0x02FFFFFF in the system memory map:

0x02000000 CCR Link Communication Control Register
0x02000004 CCSR Link COMCNT Control Register
0x02000008 CDTR Link Transmitted Data Register
0x0200000C CDRR Link Received Data Register
0x02000010 SDLR Game Pad Serial Data Low Register
0x02000014 SDHR Game Pad Serial Data High Register
0x02000018 TLR Timer Timer Counter Low Register
0x0200001C THR Timer Timer Counter High Register
0x02000020 TCR Timer Timer Control Register
0x02000024 WCR Game Pak Wait Control Register
0x02000028 SCR Game Pad Serial Control Register
0x02000040 - 0x02FFFFFF Mirroring of hardware component memory map

Hardware I/O registers are intended to be accessed as bytes. However, the registers are spaced 4 bytes apart, so any type of access can be used with them.

Writing to unmapped addresses has no apparent effect, and all bits in any byte not listed above will be undefined when read.


ROM Format

Memory addresses 0xFFFFFDE0 - 0xFFFFFFF must contain specific kinds of data. Due to the address mirroring behavior of the memory map, these addresses correspond with addresses 0x07FFFDE0 - 0x07FFFFFF in the game pak ROM address range. The significance of these addresses is described below.

Due to the address mirroring behavior of the game pak ROM address range in all commercial game paks, addresses starting at 0x07FFFDE0 are traditionally located at the end of the ROM data, regardless of the size of the ROM module.

ROM Header

Memory addresses 0xFFFFFDE0 - 0xFFFFFDFF contain the ROM header:

0xFFFFFDE0 - 0xFFFFFDF3 Title
0xFFFFFDF4 - 0xFFFFFDF8 Reserved
0xFFFFFDF9 - 0xFFFFFDFA Maker code
0xFFFFFDFB - 0xFFFFFDFE Game code
0xFFFFFDFF Version

Title The game's title in Shift JIS character encoding.
Reserved Reserved bytes and should be zeroes.
Maker code A 2-character ASCII identifier for the game's developer.
Game code A 4-character ASCII identifier for the game.
Version An unsigned byte representing the minor version number of the software. The major version number is always 1.

Nintendo maintains a list of maker codes that is beyond the scope of this document.

The game codes for commercial software are printed on the packaging and game pak labels.

Exception Handlers

Memory addresses 0xFFFFFE00 - 0xFFFFFFFF contain the CPU exception handlers:

0xFFFFFE00 - 0xFFFFFE0F Game pad interrupt
0xFFFFFE10 - 0xFFFFFE1F Timer zero interrupt
0xFFFFFE20 - 0xFFFFFE2F Game pak interrupt
0xFFFFFE30 - 0xFFFFFE3F Communication interrupt
0xFFFFFE40 - 0xFFFFFE4F VIP interrupt
0xFFFFFE50 - 0xFFFFFEFF Unused
0xFFFFFF00 - 0xFFFFFF5F Unused
0xFFFFFF60 - 0xFFFFFF6F Floating-point exception
0xFFFFFF70 - 0xFFFFFF7F Unused
0xFFFFFF80 - 0xFFFFFF8F Zero division exception
0xFFFFFF90 - 0xFFFFFF9F Illegal opcode exception
0xFFFFFFA0 - 0xFFFFFFAF TRAP instruction (vector < 16)
0xFFFFFFB0 - 0xFFFFFFBF TRAP instruction (vector ≥ 16)
0xFFFFFFC0 - 0xFFFFFFCF Address trap
0xFFFFFFD0 - 0xFFFFFFDF Duplexed exception
0xFFFFFFE0 - 0xFFFFFFEF Unused
0xFFFFFFF0 - 0xFFFFFFFF Reset

The data at these addresses is CPU instructions for processing the exceptions. At 16 bytes each, there is enough room to construct an address and jump to it.


CPU - NVC/V810 Family Microprocessor

Overview
Specifications
Data Types
Register Set
Instruction Cache
Instruction Formats

Exceptions
Exceptions
Exception Processing
List of Exceptions

Instruction Set
Memory and Register
Arithmetic
Bitwise
CPU Control
Floating-Point
Bit Strings
Miscellaneous
Nintendo

Appendix
Assembly Notation
Condition Numbers
Opcode Map
System Register Numbers


Specifications

Virtual Boy uses a modified NEC V810 CPU called NVC:

Name: NVC
Bus width: 16 bits
Clock speed: 20.0 MHz
General registers: 32
Instruction cache: 1 KiB
Instruction set: RISC
Manufacturer: Nintendo
Word size: 32 bits
Year: 1995

A handful of instructions were added by Nintendo, but otherwise the processor is the same as the stock V810.

The I/O bus is mapped to the memory bus: all read and write instructions access the same data.

Editor's Note: Three system registers are functional on NVC that are not mentioned in the V810 manual. It's possible Nintendo may have introduced them, but so far no record of where they came from can be found.


Data Types

Operations on NVC registers can take place on five different types of data:

Byte An 8-bit, two's complemement integer.
Halfword A 16-bit, two's complemement integer.
Word A 32-bit, two's complemement integer.
Floating Short A 32-bit floating-point value in the IEEE 754-1985 format. Only normal real numbers and zero are accepted by the CPU: indefinites, NaNs and non-zero denormal values are regarded as invalid operands and cannot be processed.
Bit String A sequence of contiguous bits, starting at a given offset (0 to 31) within a given word in memory and extending for a given number of bits in length. For more information, see Bit Strings.

All multi-byte data types are accessed in memory with the lowest-order byte at the lowest address within the data type (little-endian).

Memory accesses are aligned: the address being accessed is divisible by the number of bytes in the corresponding data type. If an unaligned access is attempted, the lowest-order bits of the address are ignored and the effective address is rounded down to the next lower multiple of the size in bytes of the data type.

Dedicated instructions exist for converting between word and floating short data types.


Register Set

All CPU registers are 32 bits wide.

Program Counter

The program counter (PC) stores the address of the current instruction being executed. After an instruction completes, the address in PC is updated in preparation of the next instruction. This is done automatically, although a branch or jump instruction specifies the new address directly.

If an instruction raises an exception, PC will generally not be changed. Accordingly, it is the responsibility of the exception handler to modify the corresponding "PC" status-saving register before returning in order to prevent the exception from immediately being raised again.

The lowest-order bit of PC is always clear: instructions always begin on a 16-bit boundary.

Program Registers

There are 32 general-purpose registers that can be used by programs for whatever reason, called program registers. Program registers are named r0 through r31 and they all behave the same way, with the exception of r0, which has a fixed value of zero.

While program registers can be used for whatever purpose by the program, specific registers are used by certain instructions as input or output targets. The following program registers have significance regarding the execution of CPU instructions:

r0 Contains a fixed value of zero.
r26 Bit string destination bit offset.
r27 Bit string source bit offset.
r28 Bit string length.
r29 Multiple uses:
Bit string destination word address.
Bit string number of bits skipped in a search.
r30 Multiple uses:
Stores upper 32 bits of integer multiplication results.
Stores remainder of integer division results.
Represents the exchange value for the CAXI instruction.
Bit string source word address.
r31 Stores the return address of the JAL instruction.

Certain program registers have names according to their intended use by compilers and assemblers:

r0 Zero Register Contains a fixed value of zero.
r1 Assembler Reserved To be used for the construction 32-bit immediate data.
r2 hp Handler Stack Pointer Stack pointer within exception handlers. [note]
r3 sp Stack Pointer Program stack pointer. Points to the value most recently added to the stack ("full stack" convention).
r4 gp Global Pointer References global memory.
r5 tp Text Pointer References the beginning of text data. [note]
r31 lp Link Pointer Return address of a function call.

[note] These registers have no designated purpose on Virtual Boy.

Calling Convention

Upon entering a function, the calling convention defines the following roles for program registers:

r6 First argument, if applicable.
r7 Second argument, if applicable.
r8 Third argument, if applicable.
r9 Fourth argument, if applicable.
r31 Return address.

When a function completes, any return value will be stored in r10.

If more than four arguments are passed to a function, additional arguments will be located on the stack such that the fifth argument is pointed to by r3 + 16 and subsequent arguments follow at consecutively higher addresses. The callee is not responsible for cleaning up these arguments from the stack before returning: the value of r3 will remain the same when returning as it was upon entering the function.

The 16 bytes preceding the fifth argument on the stack are designated as spill space in the caller's stack frame and may be written by the callee.

Registers r1 and r6 through r31 are not guaranteed to be preserved during a function call.

Editor's Note: Is it correct that the spill area is in the caller's stack frame? Is it absent when fewer than five arguments are present?

System Registers

System registers are additional registers that can't be used by the program directly, but represent and configure CPU operating behavior. There are 13 system registers:

25 ADTRE Address Trap Register for Execution Configures the execution address for the hardware breakpoint.
24 CHCW Cache Control Word Configures the instruction cache.
4 ECR Exception Cause Register Stores values indicating the source of exceptions or interrupts.
0 EIPC Exception/Interrupt PC Stores the value to restore to PC when an exception finishes processing.
1 EIPSW Exception/Interrupt PSW Stores the value to restore to PSW when an exception finishes processing.
2 FEPC Fatal Error PC Stores the value to restore to PC when a duplexed exception finishes processing.
3 FEPSW Fatal Error PSW Stores the value to restore to PSW when a duplexed exception finishes processing.
6 PIR Processor ID Register Indicates to the program what kind of processor it's being run on.
5 PSW Program Status Word Contains status flags and the interrupt masking level.
7 TKCW Task Control Word Specifies the behavior of floating-point instructions.
29 29 [note] This system register has unknown significance.
30 30 [note] This system register has unknown significance.
31 31 [note] Calculates the absolute value of the number written into it.

[note] The official names of these system registers are unknown.

System registers can be accessed by the program through the LDSR and STSR instructions, which transfer values between system registers and program registers.

The format and functionality of each system register is described below.

ADTRE - Address Trap Register for Execution

Configures the execution address of the address trap, which is a hardware breakpoint feature.

31 0
TA
32
TA Trap Address R/W The memory address to monitor for address traps. The lowest-order bit is always clear.

CHCW - Cache Control Word

Configures the instruction cache. The significance of the bits varies depending on the context in which the register is used:

31 20 19 8 7 6 5 4 3 2 1 0
CEN CEC RFU
ICR
ICD
RFU
ICE
ICC
12 12 2 1 1 2 1 1
31 8 7 6 5 4 3 2 1 0
SA RFU
ICR
ICD
RFU
ICE
ICC
24 2 1 1 2 1 1
RFU Reserved for Future Use R These bits have no function and are read as zeroes.
CEN Clear Entry Number W The index of the first cache entry to clear. Read as zeroes.
CEC Clear Entry Count W The number of cache entries to clear. Read as zeroes.
SA Spill-Out Base Address W The higher 24 bits of of the address to use for dump and restore operations. The lower 8 bits will be zero. Read as zeroes.
ICR Instruction Cache Restore W When set, a cache restore operation is performed. Read as zero.
ICD Instruction Cache Dump W When set, a cache dump operation is performed. Read as zero.
ICE Instruction Cache Enable R/W When set, the instruction cache is enabled.
ICC Instruction Cache Clear W When set, a cache clear operation is performed. Read as zero.

If CEN ≥ 128, no dump or restore operation will be performed.

If CEC > 128, the actual number of entries to clear becomes 128.

A clear operation will stop after it clears entry 127.

If more than one of ICR, ICD or ICC are specified simultaneously, the operation is undefined.

ECR - Exception Cause Register

Indicates the source of an exception:

31 16 15 0
FECC EICC
16 16
FECC Fatal Error Cause Code R The exception code of the source of a duplexed exception.
EICC Exception/Interrupt Cause Code R The exception code of the source of a regular exception or interrupt.

This register cannot be modified by the LDSR instruction.

EIPC, EIPSW, FEPC, FEPSW - Status-saving registers

Whenever an exception occurs, the values of PC and PSW are copied into the corresponding status-saving registers prior to handling the exception:

EIPC, EIPSW in case of a regular exception or interrupt.
FEPC, FEPSW in case of a duplexed exception.

EIPC and FEPC share the same format as PC: the lowest-order bit is always clear.

EIPSW and FEPSW share the same format as PSW: reserved bits in PSW likewise cannot be written in EIPSW or FEPSW.

PIR - Processor ID Register

Contains the identification code of the processor:

31 16 15 0
RFU PT
16 16
RFU Reserved for Future Use R These bits have no function and are read as zeroes.
PT Processor Type R The numeric value 0x5346.

This register is read-only and contains a fixed value of 0x00005346.

Editor's Note: The NVC format of PIR differs slightly from the V810 format.

PSW - Program Status Word

Contains status flags and an interrupt masking level:

31 20 19 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
RFU I
NP
EP
AE
ID
RFU
FRO
FIV
FZD
FOV
FUD
FPR
CY
OV
S Z
12 4 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1
RFU Reserved for Future Use R These bits have no function and are read as zeroes.
I Interrupt Level R/W If an interrupt is requested and the interrupt's level is less than I, the interrupt will be masked.
NP NMI Pending R/W Set during processing of a duplexed exception or reset.
EP Exception Pending R/W Set during processing of an exception or interrupt.
AE Address Trap Enable R/W If set, the address trap feature will be enabled.
ID Interrupt Disable R/W If set, all interrupts will be masked.
FRO Floating Reserved Operand R/W Set when a floating-point operation is attempted with a reserved operand.
FIV Floating Invalid R/W Set when an invalid floating-point operation attempted.
FZD Floating Zero Divide R/W Set when the DIVF.S instruction is executed with a divisor of zero.
FOV Floating Overflow R/W Set when the result of a floating-point operation is too large to be represented by the floating short data type.
FUD Floating Underflow R/W Set when the result of a floating-point operation is too small to be represented as a normal floating short value.
FPR Floating Precision R/W Set when the result of a floating-point operation is subjected to rounding and suffers precision degradation.
CY Carry R/W Set when an operation produces a carry.
OV Overflow R/W Set when an operation results in integer overflow.
S Sign R/W Set when the result of an operation is negative.
Z Zero R/W Set when the result of an operation is zero.

During the operation of the Bcond and SETF instructions, certain flag state combinations are checked in PSW.

TKCW - Task Control Word

Specifies how floating-point operations are to be processed:

31 9 8 7 6 5 4 3 2 1 0
RFU
OTM
FIT
FZT
FVT
FUT
FPT
RDI
RD
23 1 1 1 1 1 1 1 2
RFU Reserved for Future Use R These bits have no function and are read as zeroes.
OTM Operand Trap Mask R If set, floating-point invalid operand exceptions will be masked.
FIT Floating Invalid Operation Trap Enable R If set, floating-point invalid operation exceptions will be enabled.
FZT Floating-Zero Divide Trap Enable R If set, floating-point zero division exceptions will be enabled.
FVT Floating-Overflow Trap Enable R If set, floating-point overflow exceptions will be enabled.
FUT Floating-Underflow Trap Enable R If set, floating-point underflow exceptions will be enabled.
FPT Floating-Precision Trap Enable R If set, floating-point precision degradation exceptions will be enabled.
RDI Floating Rounding Control Bit
for Integer Conversion
R Specifies the direction of floating-point rounding operations when converting to integer:
0 = Same as RD
1 = Undocumented
RD Floating Rounding Control R Specifies the direction of floating-point rounding operations:
0 = Toward nearest
1 = Undocumented
2 = Undocumented
3 = Undocumented

This register is read-only and contains a fixed value of 0x000000E0. This corresponds to the following configuration:

OTM = 0 Invalid operand exceptions will be raised.
FIT = 1 Invalid operation exceptions will be raised.
FZT = 1 Zero-division exceptions will be raised.
FVT = 1 Overflow exceptions will be raised.
FUT = 0 Underflow exceptions will not be raised.
FPT = 0 Precision degradation exceptions will not be raised.
RDI = 0 Rounding to integer uses nearest value.
RD = 0 Rounding to floating short uses nearest value.

Editor's Note: Since this register was never intended to be modifiable, the effects of other values for RDI and RD were not provided in the documentation for the V810 or V830 processors.

29 - System register 29

This register has unknown significance:

31 0
???
32
??? R/W Unknown. All 32 bits of this field can be read and written.

30 - System register 30

This register has unknown significance:

31 0
???
32
??? R Unknown.

This register is read-only and contains a fixed value of 0x00000004.

31 - System register 31

Calculates the absolute value of a signed word:

31 0
???
32
??? R/W Any signed word value.

Reading from this register will give the absolute value of the most recent value written to it.


Instruction Cache

NVC provides 1 KiB of CPU instruction cache. There are 128 cache entries with a block size of 8 bytes each for a total of 1,024 bytes of cache memory. The benefit of using the instruction cache is to accelerate the execution of program code. This is accomplished by storing program code directly on the CPU so that it doesn't need to be read from the memory bus every time it is needed.

The instruction cache is managed through the CHCW system regster. Cache entries can be cleared directly, and the full contents of the cache can be dumped to and restored from main memory.

Associated with each cache entry is a tag representing the upper 22 bits of the memory address of the corresponding data, and a bit specifying whether the entry contains valid cached data. These fields are used in conjunction with the block memory to represent the cached data.

When an instruction fetch read is performed, the address to be accessed is parsed in the following way:

31 10 9 3 2 0
Tag Index Offset
22 7 3
Tag The upper bits of the source address of the block data.
Index The index of the cache entry that may contain the requested data.
Offset The position within the block data being requested.

The cache entry is selected by Index. If the entry does not contain valid data or if its tag does not match Tag, the corresponding data is read from memory and stored into the cache entry.

During dump and restore operations, both the block data and the tag data are written to/read from main memory. At the memory location specified by SA in CHCW, all 128 8-byte blocks are stored in order, followed by all 128 4-byte tags for a total of 1,536 bytes.

The format of the tag data dumped or restored for one cache entry is as follows:

31 28 27 23 22 21 0
- NECRV
Valid
TAG
4 5 1 22
- Unused. Tag memory in the cache is only 27 bits wide.
NECRV NEC Reserved The significance of this field is not documented.
Valid Valid bit Set if the entry contains actual cache data.
TAG Tag The upper 22 bits of the corresponding memory address.

Valid can be explicitly reset by performing a clear operation through CHCW. This will immediately free the cache entry and the next access whose Index matches will be loaded into cache memory.

Interrupts are postponed until the completion of dump and restore operations.


Instruction Formats

Instructions are fetched as halfword units from the bus and may be 16 or 32 bits in size. A common opcode field is present in the highest-order bits of the first halfword of every instruction, which is used to determine the instruction's binary format and whether an additional 16 bits need to be fetched.

If an instruction is 32 bits in size, a second halfword is fetched from the bus at the immediate next higher halfword address. The resulting word value is formed by taking the first halfword (bits 0-15) as the upper 16 bits and the second halfword (bits 16-31) as the lower 16 bits.

Every instruction is encoded into one of seven binary formats, referred to as Format I through Format VII. The structure of each of these instruction formats is described below.

Format I - Register-Register

16 bits. Used for register-to-register operations.

15 10 9 5 4 0
opcode reg2 reg1
6 5 5
opcode The instruction's opcode.
reg2 Destination register and left-hand operand.
reg1 Source register and right-hand operand.

Format II - Immediate-Register

16 bits. Used for immediate-to-register operations.

15 10 9 5 4 0
opcode reg2 imm
6 5 5
15 10 9 5 4 3 0
opcode reg2 - cond
6 5 1 4
15 10 9 5 4 0
opcode reg2 regID
6 5 5
15 10 9 5 4 0
opcode reg2 vector
6 5 5
15 10 9 5 4 0
opcode reg2 sub-opcode
6 5 5
- This bit has no significance.
opcode The instruction's opcode.
reg2 Destination register and left-hand operand.
imm Source value and right-hand operand.
cond Condition for the SETF instruction.
regID The zero-extended system register index for the LDSR and STSR instructions.
vector The zero-extended vector for the TRAP instruction.
sub-opcode Additional opcode bits for bit string instructions.

Depending on the instruction, imm may or may not be sign-extended.

Format III - Conditional Branch

16 bits. Used by the Bcond instruction for short-distance branches.

15 13 12 9 8 0
opcode cond disp
3 4 9
opcode The instruction's opcode.
cond Condition for branch to occur.
disp Sign-extended displacement offset.

For the numeric codes of each condition, see Bcond.

The displacement offset is measured in bytes relative to the address of the first byte of the instruction.

This is the only format that does not have a 6-bit opcode field. The 3 bits that represent the Bcond instruction's opcode (100) are not shared as the upper 3 bits of any other instruction's opcode.

Format IV - Middle-Distance Jump

32 bits. Used for middle-distance jumps using a displacement offset.

15 10 9 0 31 16
opcode disp
6 26
opcode The instruction's opcode.
disp Sign-extended displacement offset.

The displacement offset is measured in bytes relative to the address of the first byte of the instruction.

Format V - 3-Operand

32 bits. Used for operations that require three operands.

15 10 9 5 4 0 31 16
opcode reg2 reg1 imm
6 5 5 16
opcode The instruction's opcode.
reg2 Destination register.
reg1 Source register and left-hand operand.
imm Source value and right-hand operand.

Depending on the instruction, imm may or may not be sign-extended.

Format VI - Load/Store

32 bits. Used for memory access operations.

15 10 9 5 4 0 31 16
opcode reg2 reg1 disp
6 5 5 16
opcode The instruction's opcode.
reg2 Data register.
reg1 Base address register.
disp Sign-extended address displacement offset.

The effective address of the memory access operation is determined by adding disp to the value in register reg1.

For load and input operations, register reg2 receives the value read. For store and output operations, it supplies the value to write.

Format VII - Extended

32 bits. Functions similarly to Format I, but with additional opcodes.

15 10 9 5 4 0 31 26 25 16
opcode reg2 reg1 sub-opcode RFU
6 5 5 6 10
opcode The instruction's opcode.
reg2 Destination register and left-hand operand.
reg1 Source register and right-hand operand.
sub-opcode Additional opcode bits.
RFU Reserved for Future Use. These bits are ignored.

Exceptions

Certain events can cause the CPU to break its current execution, save its status and begin execution somewhere else according to what happened. The general term for such an occurrence is exception, and exceptions come in three froms:

Exception The processing of an instruction resulted in a error condition.
Interrupt A hardware component requested a program break.
Address Trap A hardware execute breakpoint was triggered.

Every exception has an associated 16-bit code and a 32-bit handler address. When an exception is raised, the code is stored into ECR and the handler address into PC. For a list of codes and handler addresses, see List of Exceptions.

Exception

Processing of CPU instructions can raise exceptions on their own. This can happen in the following situations:

The opcode or sub-opcode of the instruction being decoded does not correspond with any valid instruction.
The operation cannot be performed with the given operands.
The TRAP instruction was executed.

Interrupt

Hardware components other than the CPU are allowed to request interrupts. This provides a mechanism to synchronize all system operations as well as a way for a hardware component to signal the program when certain conditions are met.

Interrupts can be disabled by setting the ID flag in PSW. The CLI and SEI instructions manipulate this flag directly, and the LDSR instruction can also be used to configure it.

Each hardware component that can request an interrupt is assigned a numeric level. Interrupts with greater levels are given priority over and are accepted before interrupts with lesser levels. If the interrupt's level is less than the value of the I field in PSW, the interrupt request will be ignored.

When an interrupt is requested, it will not be accepted until after the current CPU instruction or cache dump or restore operation has finished processing.

Interrupts are ignored during exception processing: when either of the EP or NP flags is set in PSW.

The HALT instruction will stop all CPU activity until an interrupt request is accepted, at which point it will resume with exception processing.

Address Trap

A hardware breakpoint can be configured to raise an exception when the CPU is about to execute an instruction at the configured address.

The ADTRE system register can be configured with the breakpoint address, and the address trap function can be enabled by setting the AE flag in PSW. Under these conditions, if the value of PC matches ADTRE prior to fetching the instruction at that address, an address trap exception will be raised.

Duplexed Exception

If an exception is raised during the processing of another exception, a duplexed exception occurs. The return status of both exceptions is held in ECR and the status-saving registers, and a special handler specifically for duplexed exceptions is run.

If an exception is raised during the processing of a duplexed exception, a fatal exception occurs. Debugging information is written to the memory bus and the CPU enters a permanent halt state until reset. For more information, see Exception Processing.


Exception Processing

Restore PC

When exception handling begins, the contents of PC and PSW are transferred into the appropriate status-saving registers. The value used for PC in this case is known as the restore PC, and is determined relative to the address of the current instruction being executed.

The following exceptions will use the address of the current instruction, known as current PC, as the restore PC:

Any regular exception not raised by the TRAP instruction.
Any interrupt that is accepted during the processing of a bit string instruction.
An address trap.

The following exceptions will use the address of the following instruction, known as next PC, as the restore PC:

The TRAP instruction.
Any interrupt that does not occur during the processing of a bit string instruction.

Interrupt Handling

An interrupt that is requested will only be accepted if all of the following conditions are met:

ID = 0 in PSW.
EP = 0 in PSW.
NP = 0 in PSW.
I in PSW is less than or equal to the interrupt's level.

Exception Handling

When an exception is raised, the following algorithm is carried out:

If the NP flag in PSW is set, a fatal exception occurs:
The exception's code is OR'd with 0xFFFF0000 and the result is written to memory address 0x00000000.
The value in PSW is written to memory address 0x00000004.
The value in PC is written to memory address 0x00000008.
× The CPU halts until system reset.
If the EP flag in PSW is set, a duplexed exception occurs:
The exception's code is stored into the FECC field of ECR.
The value in PSW is stored into FEPSW.
The restore PC is stored into FEPC.
The NP flag in PSW is set.
0xFFFFFFD0 is stored into PC.
Else, a regular exception occurs:
The exception's code is stored into the EICC field of ECR.
The value in PSW is stored into EIPSW
The restore PC is stored into EIPC.
The EP flag in PSW is set.
The exception's handler address is stored into PC.
If the exception was an interrupt:
1 is added to the interrupt's level and the result is stored into the I field of PSW. [note]
Any pending HALT instruction completes.
The ID flag in PSW is set.
The AE flag in PSW is cleared.

[note] If an interrupt's level is 15, 15 will be stored into the I field of PSW. This will never occur on an unmodified Virtual Boy because no interrupt is assigned level 15.

Editor's Note: Research is needed to determine the number of cycles taken by this process.

Returning from Exceptions

When handling of an exception is completed, control is returned to the program with the RETI instruction.

According to the NP flag of PSW, RETI will restore PC and PSW from the appropriate status-saving registers.


List of Exceptions

Name Type Code Level Handler Address Restore PC Note
Reset Interrupt 0xFFF0 - 0xFFFFFFF0 - Occurs at system power-on
Duplexed exception Exception - - 0xFFFFFFD0 Current PC Exception during exception processing
VIP Interrupt 0xFE40 4 0xFFFFFE40 [note] Various video conditions
Communication Interrupt 0xFE30 3 0xFFFFFE30 [note] Completion of communication port transfer
Game Pak Interrupt 0xFE20 2 0xFFFFFE20 [note] Initiated by the game pak
Timer Zero Interrupt 0xFE10 1 0xFFFFFE10 [note] The timer counter reached zero
Game Pad Interrupt 0xFE00 0 0xFFFFFE00 [note] Controller button press
Address trap Address trap 0xFFC0 - 0xFFFFFFC0 Current PC Hardware breakpoint
TRAP instruction (vector < 16) Exception 0xFFA0 + vector - 0xFFFFFFA0 Next PC Instruction operation
TRAP instruction (vector ≥ 16) Exception 0xFFA0 + vector - 0xFFFFFFB0 Next PC Instruction operation
Illegal opcode Exception 0xFF90 - 0xFFFFFF90 Current PC Invalid opcode or sub-opcode
Zero division Exception 0xFF80 - 0xFFFFFF80 Current PC Integer division by zero
Floating-point reserved operand Exception 0xFF60 - 0xFFFFFF60 Current PC Indefinites, NaNs or non-zero denormals
Floating-point invalid operation Exception 0xFF70 - 0xFFFFFF60 Current PC Undefined operation
Floating-point zero division Exception 0xFF68 - 0xFFFFFF60 Current PC Division by zero
Floating-point overflow Exception 0xFF64 - 0xFFFFFF60 Current PC Result is too large for data type

[note] If an interrupt occurs during the processing of a bit string instruction, current PC is used. Otherwise, next PC is used.

This list is ordered such that items that appear earlier in the list have higher priority than items that appear later in the list. If any two exceptions should coincide, the one with the highest priority is the one that will be processed.

Although interrupts are given high priority, they cannot occur simultaneously with instruction exceptions because the CPU checks for interrupt requests in between executing instructions. Bit string instructions are not actually interrupted during processing, but rather they are executed repeatedly and only update PC once they fully complete.

The reset interrupt is automatically acknowledged when the CPU is initialized. PSW is initialized in such a way that the I field is zero, so reset has no meaningful interrupt level.

If a floating-point instruction satisfies multiple error conditions (such as dividing NaN by zero), only the one with the highest priority will be processed and have its status flag set in PSW.


Memory and Register

Register Transfer

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
MOV 010000 II - - - - 1 Move Immediate reg2 = (sign extend) imm
MOV 000000 I - - - - 1 Move Register reg2 = reg1
MOVEA 101000 V - - - - 1 Add reg2 = reg1 + (sign extend) imm
MOVHI 101111 V - - - - 1 Add reg2 = reg1 + (imm << 16)

The purpose of the MOVEA and MOVHI instructions is to provide a means for populating a register with 32 bits of immediate data without modifying the status flags in PSW.

Since MOVEA sign-extends its immediate value, care needs to be taken to ensure that the appropriate value is stored in the upper halfword of the register via MOVHI.

Load and Input

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
IN.B 111000 VI - - - - * Input Byte from Port reg2 = (zero extend) (byte ptr) [reg1 + disp]
IN.H 111001 VI - - - - * Input Halfword from Port reg2 = (zero extend) (halfword ptr) [reg1 + disp]
IN.W 111011 VI - - - - * Input Word from Port reg2 = (word ptr) [reg1 + disp]
LD.B 110000 VI - - - - * Load Byte reg2 = (sign extend) (byte ptr) [reg1 + disp]
LD.H 110001 VI - - - - * Load Halfword reg2 = (sign extend) (halfword ptr) [reg1 + disp]
LD.W 110011 VI - - - - * Load Word reg2 = (word ptr) [reg1 + disp]

Halfword operations will mask the lowest bit of the effective address to 0, and word operations will mask the two lowest bits to 0. This ensures that data in memory is accessed on a boundary the same size as the data type.

Since Virtual Boy maps the I/O bus to the memory bus, the input instructions access the same data as the load instructions. They're nearly identical in function, except the input instructions zero-extend the data being read whereas the load instructions sign-extend it.

The number of cycles taken by load instructions depends on prior bus activity:

1 cycle When used immediately after an instruction that takes many cycles [note] and which does not conflict with the operation of the load instruction.
4 cycles When immediately following another load instruction.
5 cycles When used in an isolated context.

[note] Editor's Note: The V810 documentation uses the phrase "many cycles" with regards to a one-cycle load operation, but it doesn't explicitly define exactly how many is "many". Logic suggests that the instruction needs only take long enough for the pipeline to ready the load operation with its effective address, then can immediately execute it when the long instruction finishes. Either way, this needs some research.

Editor's Note: The cycle counts for input instructions needs to be researched, as they may be identical to the load instructions' counts.

Editor's Note: While the number of CPU cycles taken for an input or load instruction may be small, the actual amount of time taken depends on the speed of whatever is being accessed on the bus (video memory, WRAM, etc.). The exact latencies for reads needs to be researched.

Store and Output

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
OUT.B 111100 VI - - - - * Output Byte to Port (byte ptr) [reg1 + disp] = reg2 AND 0xFF
OUT.H 111101 VI - - - - * Output Halfword to Port (halfword ptr) [reg1 + disp] = reg2 AND 0xFFFF
OUT.W 111111 VI - - - - * Output Word to Port (word ptr) [reg1 + disp] = reg2
ST.B 110100 VI - - - - * Store Byte (byte ptr) [reg1 + disp] = reg2 AND 0xFF
ST.H 110101 VI - - - - * Store Halfword (halfword ptr) [reg1 + disp] = reg2 AND 0xFFFF
ST.W 110111 VI - - - - * Store Word (word ptr) [reg1 + disp] = reg2

Halfword operations will mask the lowest bit of the effective address to 0, and word operations will mask the two lowest bits to 0. This ensures that data in memory is accessed on a boundary the same size as the data type.

Since Virtual Boy maps the I/O bus to the memory bus, the output instructions access the same data as the store instructions. They're identical in function.

The number of cycles taken by store instructions depends on prior bus activity:

1 cycle The first two consecutive executions of store instructions.
4 cycles Subsequent consecutive executions.

Editor's Note: The cycle counts for output instructions needs to be researched, as they may be identical to the store instructions' counts.

Editor's Note: While the number of CPU cycles taken for an output or store instruction may be small, the actual amount of time taken depends on the speed of whatever is being accessed on the bus (video memory, WRAM, etc.). The exact latencies for writes needs to be researched.


Arithmetic

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
ADD 010001 II 1 Add Immediate reg2 = reg2 + (sign extend) imm
ADD 000001 I 1 Add Register reg2 = reg2 + reg1
ADDI 101001 V 1 Add Immediate reg2 = reg1 + (sign extend) imm
CMP 010011 II 1 Compare Immediate (discard) = reg2 - (sign extend) imm
CMP 000011 I 1 Compare Register (discard) = reg2 - reg1
DIV 001001 I - 38 Divide r30 = reg2 MOD reg1, reg2 = reg2 / reg1
DIVU 001011 I 0 - 36 Divide Unsigned r30 = reg2 MOD reg1, reg2 = reg2 / reg1
MUL 001000 I - 13 Multiply (result) = reg2 * reg1, r30 = (result) >> 32, reg2 = (result)
MULU 001010 I - 13 Multiply Unsigned (result) = reg2 * reg1, r30 = (result) >> 32, reg2 = (result)
SUB 000010 I 1 Subtract reg2 = reg2 - reg1

Compare operations perform subtraction and update the status flags accordingly, but discard the result.

Division operations produce the arithmetic quotient without any fractional part (round towards zero), and the remainder, which shares the same sign as the dividend. The remainder is first stored into r30, then the result is stored into reg2. If a division is attempted with a divisor of zero, a Zero Division exception will be raised with a code of 0xFF80 and a restore PC of current PC.

The result of multiplication operations is 64 bits in size. The upper 32 bits are first stored into r30, then the lower 32 bits are stored into reg2.

The zero flag (Z) is set when the result of any operation is zero, or is cleared otherwise. For multiply operations, only the lower 32 bits of the result are considered.

The sign flag (S) is a copy of the highest-order bit of the result of any operation. For multiply operations, only the lower 32 bits of the result are considered.

The overflow flag (OV) is set in the following situations, or is cleared otherwise:

The operands of an addition have the same sign and the result has the opposite sign.
The operands of a subtraction have opposite signs and the left operand and result have opposite signs.
The DIV instruction is performed dividing 0x80000000 by -1. In this situation, the result is 0x80000000 and the remainder is zero.
The full 64-bit result of a multiplication is not equivalent to the 64-bit value produced by sign-extending (signed) or zero-filling (unsigned) the lower 32 bits of the product.

The carry flag (CY) is set when addition or subtraction results in unsigned wrap-around, or is cleared otherwise. For example, carry will be set when subtracting an unsigned value from a lesser value.


Bitwise

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
AND 001101 I 0 - 1 And reg2 = reg2 AND reg1
ANDI 101101 V 0 0 - 1 And Immediate reg2 = reg1 AND (zero extend) imm
NOT 001111 I 0 - 1 Not reg2 = NOT reg1
OR 001100 I 0 - 1 Or reg2 = reg2 OR reg1
ORI 101100 V 0 - 1 Or Immediate reg2 = reg1 OR (zero extend) imm
SAR 010111 II 0 1 Shift Arithmetic Right by Immediate reg2 = reg2 >> (zero extend) imm (sign-propagating)
SAR 000111 I 0 1 Shift Arithmetic Right by Register reg2 = reg2 >> (reg1 AND 0x1F) (sign-propagating)
SHL 010100 II 0 1 Shift Logical Left by Immediate reg2 = reg2 << (zero extend) imm
SHL 000100 I 0 1 Shift Logical Left by Register reg2 = reg2 << (reg1 AND 0x1F)
SHR 010101 II 0 1 Shift Logical Right by Immediate reg2 = reg2 >> (zero extend) imm (zero-filling)
SHR 000101 I 0 1 Shift Logical Right by Register reg2 = reg2 >> (reg1 AND 0x1F) (zero-filling)
XOR 001110 I 0 - 1 Exclusive Or reg2 = reg2 XOR reg1
XORI 101110 V 0 - 1 Exclusive Or Immediate reg2 = reg1 XOR (zero extend) imm

Arithmetic right shift will produce copies of the highest-order bit when filling from the left. Logical right shift will fill with zeroes.

The zero flag (Z) is set when the result of any operation is zero, or is cleared otherwise.

The sign flag (S) is a copy of the highest-order bit of the result of any operation.

The carry flag (CY) is a copy of the last bit shifted out of the register during a shift operation, or cleared if the shift amount was zero.


CPU Control

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
Bcond 100 [note] III - - - - * Branch on Condition if cond = true then PC = PC + disp
HALT 011010 II - - - - - Halt Wait for interrupt
JAL 101011 IV - - - - 3 Jump and Link r31 = PC + 4, PC = PC + disp
JMP 000110 I - - - - 3 Jump Register PC = reg1
JR 101010 IV - - - - 3 Jump Relative PC = PC + disp
LDSR 011100 II * * * * 8 Load to System Register SystemRegister[regID] = reg2
RETI 011001 II * * * * 10 Return from Trap or Interrupt if NP = 1 then PC = FEPC, PSW = FEPSW else PC = EIPC, PSW = EIPSW
STSR 011101 II - - - - 8 Store Contents of System Register reg2 = SystemRegister[regID]
TRAP 011000 II - - - - 15 Trap Raise exception (0xFFA0 + vector)

[note] Format III has a 3-bit opcode field. No other instruction contains an opcode whose highest 3 bits match the opcode of Bcond.

If the Bcond instruction's condition as specified by cond in PSW is true, then PC is updated directly. Otherwise, PC advances to the next instruction as usual.

The HALT instruction will cause the CPU to stop all processing until an interrupt is accepted. If all interrupts are masked or disabled, HALT cannot finish and the CPU will be stopped until reset.

Because the lowest-order bit of PC is always clear, the effective addresses of branch and jump instructions will have their lowest bit masked to a 16-bit boundary.

Status flags in PSW will only be modified by the LDSR instruction if PSW itself is the system register being loaded into. Their states are determined directly by the value being loaded.

The resulting exception raised by the TRAP instruction will have a code of (0xFFA0 + vector) and a restore PC of next PC.

The number of cycles taken by Bcond varies depending on whether the branch is taken:

1 cycle The branch is not taken.
3 cycles The branch is taken.

All conditional branch instructions are permutations of the Bcond instruction, just with different values for cond. Each permutation is given its own mnemonic. The following conditions and mnemonics can be checked by the Bcond instruction:

Value Mnemonic Condition Test Note
0 BV Overflow if OV = 1
1 BC, BL Carry, Lower if CY = 1 Unsigned
2 BE, BZ Equal, Zero if Z = 1
3 BNH Not higher if (CY OR Z) = 1 Unsigned
4 BN Negative if S = 1
5 BR Always if true
6 BLT Less than if (OV XOR S) = 1 Signed
7 BLE Less than or equal if ((OV XOR S) OR Z) = 1 Signed
8 BNV Not overflow if OV = 0
9 BNC, BNL Not carry, Not lower if CY = 0 Unsigned
10 BNE, BNZ Not equal, Not zero if Z = 0
11 BH Higher if (CY OR Z) = 0 Unsigned
12 BP Positive if S = 0
13 NOP Not always if false Never branches
14 BGE Greater than or equal if (OV XOR S) = 0 Signed
15 BGT Greater than if ((OV XOR S) OR Z) = 0 Signed

Certain conditions have more than one mnemonic. In these situations, either mnemonic can be used and the two are interchangeable.

The Bcond instruction's cond field uses the same numeric values for each condition as the SETF instruction.

The following numeric codes for system registers are used by the LDSR and STSR instructions:

0 EIPC
1 EIPSW
2 FEPC
3 FEPSW
4 ECR [note]
5 PSW
6 PIR [note]
7 TKCW [note]
Reserved
24 CHCW
25 ADTRE
Reserved
29 29
30 30 [note]
31 31

[note] Attempting to load to these system registers with the LDSR instruction will have no effect.

Attempting to load to a reserved system register will have no effect, and they are all read as zero.

Editor's Note: Research is needed to determine whether a conditional branch with a displacement to the following instruction still take 3 cycles, even though it's equivalent to a non-branch.


Floating-Point

All of the floating-point instructions are stored in Format VII and share a common opcode of 111110. They are identified by their sub-opcode field.

Mnemonic Sub-Opcode Z S OV CY FRO FIV FZD FOV FUD FPR Cycles Name Operation
ADDF.S 000100 0 - - 9-28 Add Floating Short reg2 = reg2 + reg1
CMPF.S 000000 0 - - - - - 7-10 Compare Floating Short (discard) = reg2 - reg1
CVT.SW 000011 0 - - - - 9-14 Convert Short Floating to Word Integer reg2 = (word) round(reg1)
CVT.WS 000010 0 - - - - - 5-16 Convert Word Integer to Short Floating reg2 = (float) reg1
DIVF.S 000111 0 44 Divide Floating Short reg2 = reg2 / reg1
MULF.S 000110 0 - - 8-30 Multiply Floating Short reg2 = reg2 * reg1
SUBF.S 000101 0 - - 12-28 Subtract Floating Short reg2 = reg2 - reg1
TRNC.SW 001011 0 - - - - 9-14 Truncate Short Floating to Word Integer reg2 = (word) truncate(reg1)

The CVT.SW and TRNC.SW instructions produce an approximate word value from a floating short value. CVT.SW will round to the nearest integer value, wheras TRNC.SW will round toward zero.

The zero flag (Z) is set when the result of any operation is zero, or is cleared otherwise.

The carry flag (CY) and sign flag (S) are both copies of the highest-order bit of the result of any operation.

PSW contains status flags that pertain only to floating-point operations. When a floating-point status condition is met, the corresponding flag is set in PSW, but otherwise will not be modified. The floating-point status conditions are as follows:

Flag Code Name Condition
FRO 0xFF60 Reserved operand Either operand is a NaN, an indefinite, or a non-zero denormal value.
FIV 0xFF70 Invalid operation Multiple conditions:
A conversion or truncation was attempted on a value beyond the range of the word data type.
DIVF.S was attempted to divide zero by zero.
FZD 0xFF68 Zero division DIVF.S was attempted to divide non-zero by zero.
FOV 0xFF64 Overflow The result was beyond the maximum normal range of the floating short data type.
FUD - Underflow The result was beyond the minimum normal range of the floating short data type. Zero is used as the result.
FPR - Precision degradation Underflow did not occur, and the result was subjected to rounding and suffered a loss of precision.

Status conditions in the list with an associated code will raise an exception with that code if they are met. They are ordered in the list such that items that appear earlier in the list have higher priority than items that appear later in the list. In the event an instruction satisfies more than one such condition, only the one with the highest priority will be processed and have its corresponding flag set in PSW. Flags are set in PSW prior to raising an exception.

Editor's Note: The overflow condition appears to process the result as usual, updating FPR and reg2 as appropriate, then raises the overflow exception when writing the exponent field. Research is needed to determine exactly which values are produced in this situation.

Editor's Note: While the V810 documentation gives ranges for the number of cycles taken for each floating-point instruction, it does not give specifics about which situations result in which cycle counts. Research is needed to determine how long any given operation will take.


Bit Strings

Overview

Bit strings are contiguous sequences of bits in memory. Operations can be performed on one or two bit strings.

Bit strings are defined with three parameters:

Word address The address in memory of the word containing the first bit of the bit string.
Bit offset The binary position within the word where the first bit of the bit string is located, with 0 representing the least-significant bit.
Length The number of bits in the bit string. Bit strings of length zero are valid.

Data storage for bit strings follows the order of least-significant to most-significant for bits within words, and by memory address for words. If a bit string extends higher than bit 31 of word address 0xFFFFFFFC or lower than bit 0 of word address 0x00000000, the following bit will wrap around to the other end of the address space.

Registers r26 through r30 are used to define bit strings:

r30 Source string word address. The lowest 2 bits are cleared prior to operation.
r29 Multiple meanings:
Destination string word address. The lowest 2 bits are cleared prior to operation.
Incremented for each bit skipped in a search. Not modified prior to operation.
r28 String length. All 32 bits are regarded as an unsigned integer.
r27 Source string bit offset. The highest 27 bits are cleared prior to operation.
r26 Destination string bit offset. The highest 27 bits are cleared prior to operation.

Search operations use the registers designated for the "source" bit string.

Bit string operations are carried out in either an "upward" or "downward" direction. In an upwards operation, the offset of bits within a word increases and the words in memory increase in address. Conversely, a downward operation observes decreased bit offsets and word addresses.

All of the bit string instructions are stored in Format II and share a common opcode of 011111. They are identified by their sub-opcode field.

Bitwise

Mnemonic Sub-Opcode Z S OV CY Cycles Name Operation
ANDBSU 01001 - - - - * And Bit String Upward dest = dest AND src
ANDNBSU 01101 - - - - * And Not Bit String Upward dest = dest AND (NOT src)
MOVBSU 01011 - - - - * Move Bit String Upward dest = src
NOTBSU 01111 - - - - * Not Bit String Upward dest = NOT src
ORBSU 01000 - - - - * Or Bit String Upward dest = dest OR src
ORNBSU 01100 - - - - * Or Not Bit String Upward dest = dest OR (NOT src)
XORBSU 01010 - - - - * Exclusive Or Bit String Upward dest = dest XOR src
XORNBSU 01110 - - - - * Exclusive Or Not Bit String Upward dest = dest XOR (NOT src)

These operations read from the source bit string and store new bits into the destination bit string, performing the specified operation on the corresponding bits from both strings to produce the final output bits. All of these instructions will clear the 2 lowest-order bits in r30 and r29, and clear the 27 highest-order bits in r27 and r26.

When a bit string instruction is invoked, it will process one word of output and complete. Only after the entire bit string has been processed will PC be advanced to the next instruction. During each invocation, the values in registers r26 through r30 are updated to reflect the current state. This implementation facilitates the handling of interrupts even in the midst of time-consuming bit string operations.

After a bit string instruction fully completes, the source and destination bit strings as specified by registers r30/r27 and r29/r26 respectively will represent the next higher bit in memory. r28 will be zero, as there are no bits remaining to be processed.

During each invocation of a bit string instruction, all of the bits for the current destination word are processed, leaving the following destination word to begin at bit offset zero (as specified by r26). In this way, the destination bit string is processed in full word units across the minimum number of write accesses.

If the source and destination bit strings overlap and the destination bit string begins later than the source bit string, then the source bit string may become corrupted by overwriting data as output before reading it as input. Due to read buffering in the CPU, this will only occur during an invocation of a bit string instruction when the destination bit string begins 64 or more bits after the source bit string.

Editor's Note: The V810 manual provides a table of cycle timings for various configurations of these operations that needs to be incorporated into this document.

Mnemonic Sub-Opcode Z S OV CY Cycles Name Operation
SCH0BSD 00001 - - - * Search Bit 0 Downward Search downward for 0
SCH0BSU 00000 - - - * Search Bit 0 Upward Search upward for 0
SCH1BSD 00011 - - - * Search Bit 1 Downward Search downward for 1
SCH1BSU 00010 - - - * Search Bit 1 Upward Search upward for 1

These operations scan through the source bit string in the specified direction for a bit with the specified state. At the start of processing, the zero flag (Z) is set and is only cleared if the specified bit was found. All of these instructions will clear the 2 lowest-order bits in r30 and clear the 27 highest-order bits in r27.

When a search instruction is invoked, it will process one word of input and complete. Only after the entire bit string has been processed will PC be advanced to the next instruction. During each invocation, the values in registers r27 through r30 are updated to reflect the current state. This implementation facilitates the handling of interrupts even in the midst of time-consuming search operations.

During each invocation of a search instruction, all of the bits for the current source word are processed, leaving the following source word to begin at bit offset zero (if upward) or 31 (if downward), specified by r27. In this way, the source bit string is processed in full word units across the minimum number of read accesses.

r29 is incremented for each bit processed during a search that does not match the specified bit. It is not modified prior to operation.

After a search instruction fully completes, the source bit string specified by registers r30 and r27 will point to the next bit in memory in the specified direction that follows the matched bit (if a match is found) or the entire string (if no match is found). Register r28 will contain the number of remaining bits in the bit string including the one pointed to by r30 and r27.

Editor's Note: The V810 manual provides a table of cycle timings for various configurations of these operations that needs to be incorporated into this document.


Miscellaneous

CAXI - Compare and Exchange Interlocked

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
CAXI 111010 VI 26 Compare and Exchange Interlocked See below.

This instruction facilitates synchronization between multiple processors. It has four operands:

reg1 Base address of lock word.
disp Lock word address displacement offset.
reg2 Compare value.
r30 Exchange value.

When executing this instruction, the following algorithm is carried out:

The bus is locked, causing other CPUs to block when accessing it.
A value is loaded, as though with LD.W, from reg1 + disp.
A comparison is performed, as though with CMP, using reg2 - value.
If the result is equal (Z = 1):
A store is performed, as though with ST.W, storing r30 into reg1 + disp.
Otherwise:
A store is performed, as though with ST.W, storing value back into reg1 + disp.
value is stored into reg2.
The lock on the bus is released.

The program can check the zero flag (Z) to determine what action was taken.

Virtual Boy only has one processor, so the CAXI instruction has limited utility.

SETF - Set Flag Condition

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
SETF 010010 II - - - - 1 Set Flag Condition if cond then reg2 = 1 else reg2 = 0

Tests a condition in PSW. If the condition is true, stores 0x00000001 into reg2; otherwise, stores 0x00000000 into reg2.

The purpose of SETF is to provide a means for evaluating simple conditional operations without performing a branch via Bcond. Branching disrupts the pipeline flow and takes more cycles than the corresponding SETF implementations for such operations. For example, either-or assignments such as absolute value and sign benefit from the use of SETF.

The cond field is 4 bits in size. The following conditions can be checked:

Value Mnemonic Condition Test Note
0 V Overflow if OV = 1
1 C, L Carry, Lower if CY = 1 Unsigned
2 E, Z Equal, Zero if Z = 1
3 NH Not higher if (CY OR Z) = 1 Unsigned
4 N Negative if S = 1
5 T Always if true Always 1
6 LT Less than if (OV XOR S) = 1 Signed
7 LE Less than or equal if ((OV XOR S) OR Z) = 1 Signed
8 NV Not overflow if OV = 0
9 NC, NL Not carry, Not lower if CY = 0 Unsigned
10 NE, NZ Not equal, Not zero if Z = 0
11 H Higher if (CY OR Z) = 0 Unsigned
12 P Positive if S = 0
13 F Not always if false Always 0
14 GE Greater than or equal if (OV XOR S) = 0 Signed
15 GT Greater than if ((OV XOR S) OR Z) = 0 Signed

Certain conditions have more than one mnemonic. In these situations, either mnemonic can be used and the two are interchangeable.

The cond field uses the same numeric values for each condition as the Bcond instruction.


Nintendo

Standalone

These instructions have unique opcodes.

Mnemonic Opcode Format Z S OV CY Cycles Name Operation
CLI 010110 II - - - - 12 Clear Interrupt Disable Flag ID = 0
SEI 011110 II - - - - 12 Set Interrupt Disable Flag ID = 1

These instructions facilitate manipulation of the ID flag in PSW through a mechanism that is simpler than using the LDSR and STSR instructions.

Editor's Note: These instructions were borrowed from the 6502/65816 instruction set used by the NES and SNES. When NEC developed the V830 in 1997, they introduced the EI and DI instructions (Enable Maskable Interrupt and Disable Maskable Interrupt, respectively), which use the same opcodes and perform the same operations as NVC's CLI and SEI instructions. However, EI and DI only take 2 cycles to complete.

Extended

These instructions are stored in Format VII and share a common opcode of 111110. They are identified by their sub-opcode field.

Mnemonic Sub-Opcode Z S OV CY Cycles Name Operation
MPYHW 001100 - - - - 9 Multiply Halfword reg2 = reg2 * (reg1 << 15 >> 15 (sign-propagating))
REV 001010 - - - - 22 Reverse Bits in Word reg2 = ReverseBits(reg1)
XB 001000 - - - - 6 Exchange Byte reg2 = (reg2 AND 0xFFFF0000) OR ((reg2 << 8) AND 0xFF00) OR ((reg2 >> 8) AND 0x00FF)
XH 001001 - - - - 1 Exchange Halfword reg2 = (reg2 >> 16 (zero-filling)) OR (reg2 << 16)

The MPYHW instruction performs a 32-bit signed multiplication. The right-hand operand is produced by sign-extending the lower 17 bits of reg1.

The REV instruction reverses the order of the bits in reg2: the highest-order bit of the input becomes the lowest-order bit of the output and so-on.

Editor's Note: One source suggests that XB and XH must supply r0 in the binary encoding of the reg1 field, or else the behavior is undefined. This could use further testing, as no misbehavior has been observed regardless of the value of reg1.


Assembly Notation

The following conventions, except as described below, apply to all instructions in the official V810 assembly notation:

When multiple operands are present, the destination is on the right.
When three operands are present, the immediate value is on the left.
The target address of reads and writes is the displacement offset followed by the base address register in [square brackets]. If the displacement offset is zero, it may be omitted.
The target address of jumps and branches is the absolute address, not the relative displacement.

The following instructions have additional conventions:

Bcond Multiple notations:
For any condition other than NOP, written as a one-operand instruction using the condition's mnemonic.
NOP is written as a zero-operand instruction.
JMP Although the operation does not perform an indirection, the operand is enclosed in [square brackets].
LDSR, STSR May use the symbolic name of the system register or its numeric index.
SETF Multiple notations: [note]
V810 Written as a two-operand instruction, the first being either the condition's mnemonic or numeric code.
IAR Written as a one-operand instruction, where the mnemonic is the concatenation of "SETF" followed by the conditon's mnemonic.

[note] The "V810" notation is used by official NEC V810 documents, the GNU assembler, Nintendo's own Virtual Boy development tools, and NEC/Renesas-produced development tools. In the final draft of the V810 specification, this was the notation that was intended to be used.
The "IAR" notation has been known to be used by NEC in V810 presentations during development, the IAR Systems V850 assembler, and Hudson Soft's development tools for PC-FX.

The notation for each instruction is as follows:

Mnemonic Name Notation
ADD Add Immediate ADD imm, reg2
ADD Add Register ADD reg1, reg2
ADDF.S Add Floating Short ADDF.S reg1, reg2
ADDI Add Immediate ADDI imm, reg1, reg2
AND And AND reg1, reg2
ANDBSU And Bit String Upward ANDBSU
ANDI And Immediate ANDI imm, reg1, reg2
ANDNBSU And Not Bit String Upward ANDNBSU
Bcond Branch on Condition BNZ address
NOP
CAXI Compare and Exchange Interlocked CAXI disp[reg1], reg2
CLI Clear Interrupt Disable Flag CLI
CMP Compare Immediate CMP imm, reg2
CMP Compare Register CMP reg1, reg2
CMPF.S Compare Floating Short CMPF.S reg1, reg2
CVT.SW Convert Short Floating to Word Integer CVT.SW reg1, reg2
CVT.WS Convert Word Integer to Short Floating CVT.WS reg1, reg2
DIV Divide DIV reg1, reg2
DIVF.S Divide Floating Short DIVF.S reg1, reg2
DIVU Divide Unsigned DIVU reg1, reg2
HALT Halt HALT
IN.B Input Byte from Port IN.B disp[reg1], reg2
IN.H Input Halfword from Port IN.H disp[reg1], reg2
IN.W Input Word from Port IN.W disp[reg1], reg2
JAL Jump and Link JAL address
JMP Jump Register JMP [reg1]
JR Jump Relative JR address
LD.B Load Byte LD.B disp[reg1], reg2
LD.H Load Halfword LD.H disp[reg1], reg2
LD.W Load Word LD.W disp[reg1], reg2
LDSR Load to System Register LDSR reg2, regID
MOV Move Immediate MOV imm, reg2
MOV Move Register MOV reg1, reg2
MOVBSU Move Bit String Upward MOVBSU
MOVEA Add MOVEA imm, reg1, reg2
MOVHI Add MOVHI imm, reg1, reg2
MPYHW Multiply Halfword MPYHW reg1, reg2
MUL Multiply MUL reg1, reg2
MULF.S Multiply Floating Short MULF.S reg1, reg2
MULU Multiply Unsigned MULU reg1, reg2
NOT Not NOT reg1, reg2
NOTBSU Not Bit String Upward NOTBSU
OR Or OR reg1, reg2
ORBSU Or Bit String Upward ORBSU
ORI Or Immediate ORI imm, reg1, reg2
ORNBSU Or Not Bit String Upward ORNBSU
OUT.B Output Byte to Port OUT.B reg2, disp[reg1]
OUT.H Output Halfword to Port OUT.H reg2, disp[reg1]
OUT.W Output Word to Port OUT.W reg2, disp[reg1]
RETI Return from Trap or Interrupt RETI
REV Reverse Bits in Word REV reg1, reg2
SAR Shift Arithmetic Right by Immediate SAR imm, reg2
SAR Shift Arithmetic Right by Register SAR reg1, reg2
SCH0BSD Search Bit 0 Downward SCH0BSD
SCH0BSU Search Bit 0 Upward SCH0BSU
SCH1BSD Search Bit 1 Downward SCH1BSD
SCH1BSU Search Bit 1 Upward SCH1BSU
SEI Set Interrupt Disable Flag SEI
SETF Set Flag Condition SETF cond, reg2
SETFNZ reg2
SHL Shift Logical Left by Immediate SHL imm, reg2
SHL Shift Logical Left by Register SHL reg1, reg2
SHR Shift Logical Right by Immediate SHR imm, reg2
SHR Shift Logical Right by Register SHR reg1, reg2
ST.B Store Byte ST.B reg2, disp[reg1]
ST.H Store Halfword ST.H reg2, disp[reg1]
ST.W Store Word ST.W reg2, disp[reg1]
STSR Store Contents of System Register STSR regID, reg2
SUB Subtract SUB reg1, reg2
SUBF.S Subtract Floating Short SUBF.S reg1, reg2
TRAP Trap TRAP vector
TRNC.SW Truncate Short Floating to Word Integer TRNC.SW reg1, reg2
XB Exchange Byte XB reg2
XH Exchange Halfword XH reg2
XOR Exclusive Or XOR reg1, reg2
XORBSU Exclusive Or Bit String Upward XORBSU
XORI Exclusive Or Immediate XORI imm, reg1, reg2
XORNBSU Exclusive Or Not Bit String Upward XORNBSU

Opcode Map

Attempting to execute any invalid opcode or sub-opcode will raise an exception with code 0xFF90 and a restore PC of current PC.

Opcode Format Mnemonic Operation
000000 I MOV reg2 = reg1
000001 I ADD reg2 = reg2 + reg1
000010 I SUB reg2 = reg2 - reg1
000011 I CMP (discard) = reg2 - reg1
000100 I SHL reg2 = reg2 << (reg1 AND 0x1F)
000101 I SHR reg2 = reg2 >> (reg1 AND 0x1F) (zero-filling)
000110 I JMP PC = reg1
000111 I SAR reg2 = reg2 >> (reg1 AND 0x1F) (sign-propagating)
001000 I MUL (result) = reg2 * reg1, r30 = (result) >> 32, reg2 = (result)
001001 I DIV r30 = reg2 MOD reg1, reg2 = reg2 / reg1
001010 I MULU (result) = reg2 * reg1, r30 = (result) >> 32, reg2 = (result)
001011 I DIVU r30 = reg2 MOD reg1, reg2 = reg2 / reg1
001100 I OR reg2 = reg2 OR reg1
001101 I AND reg2 = reg2 AND reg1
001110 I XOR reg2 = reg2 XOR reg1
001111 I NOT reg2 = NOT reg1
010000 II MOV reg2 = (sign extend) imm
010001 II ADD reg2 = reg2 + (sign extend) imm
010010 II SETF if cond then reg2 = 1 else reg2 = 0
010011 II CMP (discard) = reg2 - (sign extend) imm
010100 II SHL reg2 = reg2 << (zero extend) imm
010101 II SHR reg2 = reg2 >> (zero extend) imm (zero-filling)
010110 II CLI ID = 0
010111 II SAR reg2 = reg2 >> (zero extend) imm (sign-propagating)
011000 II TRAP Raise exception (0xFFA0 + vector)
011001 II RETI if NP then PC = FEPC, PSW = FEPSW else PC = EIPC, PSW = EIPSW
011010 II HALT Wait for interrupt
011011 - Invalid
011100 II LDSR SystemRegister[regID] = reg2
011101 II STSR reg2 = SystemRegister[regID]
011110 II SEI ID = 1
011111 II * Bit string: see below
100    III Bcond if cond = true then PC = PC + disp
101000 V MOVEA reg2 = reg1 + (sign extend) imm
101001 V ADDI reg2 = reg1 + (sign extend) imm
101010 IV JR PC = PC + disp
101011 IV JAL r31 = PC + 4, PC = PC + disp
101100 V ORI reg2 = reg1 OR (zero extend) imm
101101 V ANDI reg2 = reg1 AND (zero extend) imm
101110 V XORI reg2 = reg1 XOR (zero extend) imm
101111 V MOVHI reg2 = reg1 + (imm << 16)
110000 VI LD.B reg2 = (sign extend) (byte ptr) [reg1 + disp]
110001 VI LD.H reg2 = (sign extend) (halfword ptr) [reg1 + disp]
110010 - Invalid
110011 VI LD.W reg2 = (word ptr) [reg1 + disp]
110100 VI ST.B (byte ptr) [reg1 + disp] = reg2 AND 0xFF
110101 VI ST.H (halfword ptr) [reg1 + disp] = reg2 AND 0xFFFF
110110 - Invalid
110111 VI ST.W (word ptr) [reg1 + disp] = reg2
111000 VI IN.B reg2 = (zero extend) (byte ptr) [reg1 + disp]
111001 VI IN.H reg2 = (zero extend) (halfword ptr) [reg1 + disp]
111010 VI CAXI See instruction section.
111011 VI IN.W reg2 = (word ptr) [reg1 + disp]
111100 VI OUT.B (byte ptr) [reg1 + disp] = reg2 AND 0xFF
111101 VI OUT.H (halfword ptr) [reg1 + disp] = reg2 AND 0xFFFF
111110 VII * Floating-point and Nintendo: see below
111111 VI OUT.W (word ptr) [reg1 + disp] = reg2

Bit string instructions are stored in Format II and share a common opcode of 011111. They are identified by their sub-opcode field.

Sub-Opcode Mnemonic Operation
00000 SCH0BSU Search upward for 0
00001 SCH0BSD Search downward for 0
00010 SCH1BSU Search upward for 1
00011 SCH1BSD Search downward for 1
Invalid
01000 ORBSU dest = dest OR src
01001 ANDBSU dest = dest AND src
01010 XORBSU dest = dest XOR src
01011 MOVBSU dest = src
01100 ORNBSU dest = dest OR (NOT src)
01101 ANDNBSU dest = dest AND (NOT src)
01110 XORNBSU dest = dest XOR (NOT src)
01111 NOTBSU dest = NOT src
Invalid

Floating-point and Nintendo instructions are stored in Format VII and share a common opcode of 111110. They are identified by their sub-opcode field.

Sub-Opcode Mnemonic Operation
000000 CMPF.S (discard) = reg2 - reg1
000001 Invalid
000010 CVT.WS reg2 = (float) reg1
000011 CVT.SW reg2 = (word) round(reg1)
000100 ADDF.S reg2 = reg2 + reg1
000101 SUBF.S reg2 = reg2 - reg1
000110 MULF.S reg2 = reg2 * reg1
000111 DIVF.S reg2 = reg2 / reg1
001000 XB reg2 = (reg2 AND 0xFFFF0000) OR ((reg2 << 8) AND 0xFF00) OR ((reg2 >> 8) AND 0x00FF)
001001 XH reg2 = (reg2 >> 16 (zero-filling)) OR (reg2 << 16)
001010 REV reg2 = ReverseBits(reg1)
001011 TRNC.SW reg2 = (word) truncate(reg1)
001100 MPYHW reg2 = reg2 * (reg1 << 15 >> 15 (sign-propagating))
Invalid

Communication Port

Contents
Overview
Pinout
Communication Control
Signal Control
Data Registers
Communication Interrupt


Overview

On the underside of the Virtual Boy unit, next to the controller port, is a port labeled "EXT." that can be used for communication between two linked Virtual Boys. Although a link cable was developed for use with the system, no commercial games made use of it and the cable itself was never made available to consumers.

Communication exchanges 8 bits at a time between Virtual Boy units. Bits come from dedicated data registers for transmitted and received data.

The hardware controls the entire communication operation, exchanging bits at a rate of 50 KHz per bit for a total of 160 µs. When the operation completes, a communication interrupt can be configured to be raised.

An additional auxiliary signal can be used for negotiating communication status independently from the actual bits sent and received.


Pinout

The following diagram depicts the pin configuration of the communication port when looking into it from the bottom of the Virtual Boy unit:

1
2
3
4
5
6
7
8

The pins have the following significance:

1. COMCNT
2. +5V DC
3. Communication clock
4. Data receive
5. Sync in
6. Sync out
7. Ground
8. Data transmit

Within a link cable, pins are connected to each end in the following way:

COMCNT 1 1 COMCNT
+5V DC 2 2 +5V DC
Communication clock 3 3 Communication clock
Data receive 4 8 Data transmit
Sync in 5 6 Sync out
Sync out 6 5 Sync in
Ground 7 7 Ground
Data transmit 8 4 Data receive

+5V DC is not connected because it is not used in link communications. It can be used to power some external device.
Sync in and Sync out do not form a round-trip connection in a link cable because doing so would result in clock feedback.

Communication Control

The primary communication operation is performed through the data registers and a single control register:

0x02000000 Communication Control Register
7 6 5 4 3 2 1 0
C-Int-Inh
-
C-Clk-Sel
-
C-Start
C-Stat
-
1 2 1 1 1 1 1
- These bits have no function and are set when read.
C-Int-Inh R/W When clear, the communication interrupt is enabled for communications. When set, it is acknowledged and disabled.
C-Clk-Sel R/W When clear, the unit uses its internal communication clock signal. When set, it relies on the signal from an external unit.
C-Start W When set, a communication operation begins. Always set when read.
C-Stat R Set while a communication is underway, or cleared otherwise.

The primary function of the communication port is to exchange 8 bits of data between two Virtual Boy units. The hardware performs the operation when requested, sending the data in CDTR and receiving data into CDRR.

If C-Int-Inh is clear when the communication operation completes, a communication interrupt is raised.

C-Clk-Sel determines the communication clock signal to use for synchronizing communication operations:

0 Internal Uses own clock.
1 External Uses another unit's clock.

When C-Start is set, a communication operation is initiated. If the external clock is selected, the unit will wait for a communication signal from a linked unit before performing the operation. If the internal clock is selected, the operation begins immediately. When the operation completes, the bits received from the other unit will be loaded into CDRR.

If the internal clock is selected and C-Start is set without another unit waiting for an external clock, a peerless communication will be performed immediately and the bits in CDRR will be undefined.

C-Stat is set as soon as C-Start is set, and will remain set until the communication operation completes. If C-Start is set while C-Stat is already set, nothing happens.

Changing the clock selection while C-Stat is set will not abort the communication operation, but will merely change the clock signal source. If both units are waiting for an external clock and one changes to the internal clock (with or without writing to C-Start) the communication will be carried out normally.

A communication operation cannot be canceled once initiated. The only way C-Stat will be cleared is when the operation completes.


Signal Control

An auxiliary signal channel is present on the communication port intended for use in negotiations between peers. It is managed through a single register:

0x02000004 COMCNT Control Register
7 6 5 4 3 2 1 0
CC-Int-Inh
-
CC-Int-Lev
CC-Sig
CC-Smp
CC-Wr
CC-Rd
1 2 1 1 1 1 1
- These bits have no function and are set when read.
CC-Int-Inh R/W When clear, the communication interrupt is enabled for signals. When set, it is acknowledged and disabled.
CC-Int-Lev R/W When CC-Smp becomes equal to CC-Int-Lev, the interrupt condition is satisfied.
CC-Sig R/W The automatic signal status to be used after a communication operation completes.
CC-Smp R Automatically sampled from the signal after a communication operation completes.
CC-Wr R/W The manual signal status to be used on write.
CC-Rd R The current manual signal status on read.

There are two bits in CCSR that are managed by the hardware:

CC-Rd Manually configured by software writes to CCSR. The value of this bit on both connected units is the bitwise AND of the CC-Wr bits on both units.
CC-Smp Automatically configured when communication operations via CCR complete. The value of this bit on both connected units is the bitwise AND of the CC-Sig bits on both units as well as another bitwise AND with the value of CC-Rd.

If there is no second unit connected, the values of CC-Rd and CC-Smp are processed as though a connected unit had the same CCSR configuration.

When a communication operation completes and CC-Smp is updated, its value is compared with CC-Int-Lev. If the two bits match, the interrupt condition is satisfied and will be raised if CC-Int-Inh is clear.


Data Registers

When performing communication operations via CCR, the data transmitted and received is loaded/stored in dedicated registers:

0x02000008 Transmitted Data Register
0x0200000C Received Data Register

Both of these registers are 8 bits of software-assigned data. CDTR is read/write and CDRR is read-only.


Communication Interrupt

When a communication operation via CCR completes, two interrupts can be optionally raised:

Communication Configured in CCR and occurs any time a communication operation completes.
COMCNT Input Configured in CCSR and occurs when a communication operation completes and the CC-Int-Lev and CC-Smp bits match.

Under either situation, an interrupt will be requested on the CPU with a code of 0xFE30. Each situation is capable of independently requesting an interrupt, and must be acknowledged individually. To acknowlege each type of communication iterrupt:

Communication Set C-Int-Inh in CCR.
COMCNT Input Set CC-Int-Inh in CCSR.

Game Pad

Contents
Layout
Pinout
Game Pad Control
Data Registers

The game pad is an 8-direction, 6-buton controller 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 sold separately. The button state can be read from the controller either through software or through a hardware function, and an interrupt can be configured to raise when a button is pressed.


Layout

The game pad has the following input configuration:

Front
Left
D-pad
Select
Start
Power
B
A
Right
D-pad
Back
R
L

The game pad is responsible for supplying power to the system. On the back of the game pad is a bracket that can hold a power source, which could be either a pack of 6 AA batteries or an A/C wall adapter.


Pinout

The following diagram depicts the pin configuration of the game pad port when looking into it from the bottom of the Virtual Boy unit:

1
2
3
4
5
6

The pins have the following significance:

1. Data
2. +5V DC
3. Reset
4. Clock
5. Ground
6. Power (VCC)

Game Pad Control

Button state information is read from the game pad one bit at a time over a serial port. There are two signals that control this operation: one to reset the entire process and one to clock the bits being sent back to the console. This process of reading button state information can be handled either by the program or by a hardware function.

All game pad operations are managed through a single register:

0x02000028 SCR Serial Control Register
7 6 5 4 3 2 1 0
K-Int-Inh
-
Para/Si
Soft-Ck
-
HW-SI
SI-Stat
S-Abt/Dis
1 1 1 1 1 1 1 1
- These bits have no function and are set when read.
K-Int-Inh R/W When clear, the key input interrupt is enabled. When set, it is acknowledged and disabled.
Para/Si R/W When set, a latch signal resets the game pad's read operation.
Soft-Ck R/W Sends the inverse read bit to the game pad. (See below)
HW-SI W Set to initiate a hardware button state read. (See below)
SI-Stat R Set while a hardware button state read is in progress.
S-Abt/Dis R/W When set, any active hardware button state read is aborted.

Software Read

Setting Para/Si sends a latch signal to the game pad that resets the button read operation. This bit should be cleared when subsequently using Soft-Ck, or else the operation will be repeatedly reset.

To perform a software read, set Para/Si once to reset the operation, then write alternating states for Soft-Ck 16 times. After the 16th bit has been clocked, the data registers will contain the button state bits. Before the 16th bit has been clocked, the contents of the data registers will be undefined.

Writing to Soft-Ck sends the inverse bit to the game pad (0 becomes 1 and vice-versa). In order to properly read the button state, the game pad must receive a 0 followed by a 1 for each button for a total of 33 writes to Soft-Ck.

Editor's Note: If the ambient humidity is high enough, an assembly-optimized software read routine will attempt to process game pad bits so fast that the game pad will respond with unstable data. A dummy MUL instruction between bits seems to add enough latency to address this problem, but may or may not be sufficient in all cases.

Hardware Read

Setting HW-SI will initiate a hardware read operation, which will handle the latch and clock signals automatically. When the operation completes, the data registers will contain the button state bits. Setting HW-SI while a hardware read operation is already underway will have no effect.

HW-SI is always set when read.

While a hardware read operation is underway, SI-Stat will be set. When the operation completes, SI-Stat will be clear.

Setting S-Abt/Dis during a hardware read operation will cancel it immediately.

The hardware read operation clocks buttons at a rate of 31.25 KHz per button for a total of 512 µs. This is significantly slower than the speeds that can be achieved through a software read.

Key Input Interrupt

When a hardware read operation completes and K-Int-Inh is clear, an interrupt will be raised if any bit in the data registers from 15 through 4 is set, but will not be raised if any bit from 3 through 1 is set. Since the standard Virtual Boy controller always sets bit 1, it is impossible for it to raise a key input interrupt.

The key input interrupt has a code of 0xFE00.


Data Registers

After reading button state information from the game pad, a 16-bit value is loaded into two read-only registers, one for the lower 8 bits and one for the higher 8 bits:

0x02000010 SDLR Serial Data Low Register
0x02000014 SDHR Serial Data High Register
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
RD
RL
SEL
STA
LU
LD
LL
LR
RR
RU
LT
RT
B A
SGN
PWR
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
RD Right D-pad down
RL Right D-pad left
SEL Select button
STA Start button
LU Left D-pad up
LD Left D-pad down
LL Left D-pad left
LR Left D-pad right
RR Right D-pad right
RU Right D-pad up
LT L button
RT R button
B B button
A A button
SGN Signature (see below)
PWR Low battery

When using the standard Virtual Boy controller, SGN is always set. This prevents the key input interrupt from ever being raised.


Game Pak

Contents
Memory
Pinout

A game pak is a cartridge containing a ROM module and optionally a RAM module, battery and/or other circuitry. It is inserted into the Virtual Boy unit and supplies the software.

The game pak is able to request an interrupt with a code of 0xFE20. No commercial game paks make use of this.


Memory

The following address ranges in the memory map are allocated to the game pak:

0x04000000 - 0x04FFFFFF Game Pak Expansion
0x06000000 - 0x06FFFFFF Game Pak RAM
0x07000000 - 0x07FFFFFF Game Pak ROM

The game pak expansion range is provided for game pak-specific use, but was not used in any commercial game pak.

Game paks may or may not contain RAM modules. Commercial game paks that contained RAM modules were battery-backed, retaining RAM contents while the power is off (SRAM).

Every game pak must supply program data, typically provided by a ROM module.

In all commercial game paks, the sizes in bytes of the ROM and RAM (if present) data are powers of 2. Addresses into game pak memory that exceed the size of the corresponding data simply have their upper bits masked, producing mirrors of the data across the entire respective address range.


Pinout

The following diagram depicts the pin configuration of the game pak as seen looking at the bottom of the cartridge. Pins follow a zig-zag pattern with odd-numbered pins on one row and even-numbered pins on the other:

1
59
2
60

The pins have the following significance:

1. Ground 21. Address 5 41. Data 1
2. Ground 22. Address 11 42. Data 14
3. RAM write enable 23. Address 4 43. Data 9
4. Expansion select 24. Address 12 44. Data 6
5. Expansion write enable 25. Address 3 45. Data 2
6. RAM select 26. Address 13 46. Data 13
7. Reset 27. Address 2 47. Data 10
8. +5V DC 28. Address 14 48. Data 5
9. Interrupt request 29. Address 1 49. Data 3
10. Address 23 30. Address 15 50. Data 12
11. Address 19 31. ROM select 51. Data 11
12. Address 22 32. Address 16 52. Data 4
13. Address 18 33. Ground 53. +5V DC
14. Address 21 34. Address 17 54. +5V DC
15. Address 8 35. Output enable 55. Right audio in
16. Address 20 36. +5V DC 56. Left audio in
17. Address 7 37. Data 0 57. Right audio out
18. Address 9 38. Data 15 58. Left audio out
19. Address 6 39. Data 8 59. Ground
20. Address 10 40. Data 7 60. Ground

The expansion, ROM and RAM memory addresses activate the corresponding "select" pins when accessing the game pak. Only one such pin should be active at a time.

There is no Address 0 pin because there are 16 data lines: all accesses are 16-bit aligned.

The direction of the audio lines in the chart above is relative to the game pak itself: "in" lines enter the game pak, and "out" lines exit it.


Timer

Contents
Counter and Reload
Timer Control
Timer Zero Interrupt

The timer component contains a 16-bit counter that is decremented at a specified interval. An interrupt can be configured to raise whenever the counter reaches zero. After the counter reaches zero, it is reinitialized with a supplied reload value and counting continues.


Counter and Reload

The timer contains a 16-bit counter that is decremented by one at the configured interval. After the counter reaches zero, a preset reload value is loaded into the counter and counting continues.

The counter and reload values can be accessed 8 bits at a time through the following registers:

0x02000018 TLR Timer Counter Low Register
0x0200001C THR Timer Counter High Register

These registers represent both the counter and the reload value. The "High" register represents the upper 8 bits of the corresponding 16-bit value, and the "Low" register represents the lower 8 bits.

When reading from these registers, the bits returned will be the current value of the counter. Since the timer continues to count independently from program activity, it should be stopped before accessing the counter value.

When writing to these registers, a new reload value is specified for the corresponding 8 bits. When either register is written, the entire 16-bit value will be loaded into the counter and reset the current timer tick to the beginning of its wait interval.


Timer Control

All timer operations are managed through a single register:

0x02000020 TCR Timer Control Register
7 5 4 3 2 1 0
-
T-Clk-Sel
Tim-Z-Int
Z-Stat-Clr
Z-Stat
T-Enb
3 1 1 1 1 1
- These bits have no function and are set when read.
T-Clk-Sel R/W Specifies the timer interval. (See below)
Tim-Z-Int R/W When set, the timer zero interrupt is enabled.
Z-Stat-Clr W Clears Z-Stat and acknowledges interrupt. (See below)
Z-Stat R Set when the timer counter becomes zero.
T-Enb R/W When set, the timer is enabled.

The value of T-Clk-Sel determines the frequency at which the timer will count:

0 100 µs
1 20 µs

Z-Stat-Clr will clear Z-Stat and acknowledge a timer zero interrupt if the counter is non-zero or, if the counter is zero, if the timer is disabled. This bit is always set when read.

Z-Stat becomes set whenever the counter is zero while the timer is enabled. This bit will remain set until Z-Stat-Clr performs an action as specified above.

If both T-Enb is cleared and Z-Stat-Clr is set while the timer is enabled, then the timer is disabled, but zero status is not cleared (nor is an interrupt acknowledged).


Timer Zero Interrupt

If enabled in TCR, a timer zero interrupt will be raised whenever the counter value changes from a non-zero value to zero. This can occur either by timer activity or by writing to the reload value registers. The timer loading a reload value of zero into the counter does not satisfy the interrupt condition.

Timer zero interrupts have a code of 0xFE10 and can be acknowledged in two ways via writes to TCR:

Disabling the interrupt by clearing Tim-Z-Int
Clearing zero status by setting Z-Stat-Clr under the conditions outlined in Timer Control.


Wait Controller

The wait controller component generates wait signals for the game pak expansion and ROM address ranges. The wait controller is managed through the following register:

0x02000024 WCR Wait Control Register
7 2 1 0
-
EXP1W
ROM1W
6 1 1
- These bits have no function and are set when read.
EXP1W R/W Controls the wait count in the game pak expansion address range.
ROM1W R/W Controls the wait count in the game pak ROM address range.

For both EXP1W and ROM1W, 2 waits are generated for accesses in the respective address range if clear, and 1 wait is generated if set.


VIP - Virtual Image Processor

Overview
Overview
Memory Map
Drawing and Display Procedures

Memory
Characters
Objects
Background Maps
Worlds
Column Table
Frame Buffer

Registers
Display
Drawing
Brightness
Palettes
Interrupts
Miscellaneous


Overview

The displays used in the Virtual Boy were invented by Reflection Technology, Inc. and pitched to Nintendo, who accepted the proposal and initiated the Virtual Boy project. Each display consists of a single column of red LEDs and creates the illusion of a two-dimensional image by precicely projecting light onto an oscillating mirror. The two mirrors oscillate opposite one another to maintain balance and optimize power consumption.

A double-buffered, stereoscopic frame buffer is read from video memory to transmit to the eyes. Typically, this frame buffer is manipulated by the VIP during its drawing procedure. Alternately, the drawing functionality can be disabled and the frame buffer can be accessed directly by the CPU, facilitating software rendering.

Images on Virtual Boy are 384×224 pixels per eye and are transmitted at a rate of 50.0 Hz.

Image Elements

The atomic unit of graphics on Virtual Boy is the character, also known as a "tile". Characters are 8×8 pixel graphics with 2 bits per pixel. They can be used on their own in a scene or as part of a larger mosaic. There is memory for 2,048 characters.

Individual characters can be displayed anywhere on the screen by using them in an object, often called a "sprite". There is memory for 1,024 objects.

Background maps are 64×64-character mosaics that themselves are arranged into larger mosaics called backgrounds. There is memory for 14 full background maps.

The top-level unit of graphics on Virtual Boy is the world, also known as a "window". A world specifies a rectangular region in the scene where a background can be drawn. The portion of a background that appears within a world can be determined in a number of ways, from simple scrolling to affine transformations. There is memory for 32 worlds.

Other Features

The VIP is capable of raising an interrupt for a number of different conditions. This is the primary means by which a program is synchronized with the video hardware.

Three levels of brightness can be configured before a frame is displayed. Used in conjunction with a black value, there can be four base shades of red in a given image.

A column table exists that is used by the physical display unit to maintain pixel proportions as the mirror oscillates, since the mirror's angle relative to the LEDs is constantly changing. The column table can also be used to indirectly influence the absolute brightness of columns of pixels in the output independently from the brightness settings.

The drawing feature can be configured to swap the front and back frame buffers after some number of display cycles rather than every cycle, thereby tuning the frame rate of the program.


Memory Map

The VIP occupies addresses 0x00000000 - 0x00FFFFFF in the system memory map.

Memory Map

0x00000000 - 0x00005FFF Left frame buffer 0
0x00006000 - 0x00007FFF Character table 0
0x00008000 - 0x0000DFFF Left frame buffer 1
0x0000E000 - 0x0000FFFF Character table 1
0x00010000 - 0x00015FFF Right frame buffer 0
0x00016000 - 0x00017FFF Character table 2
0x00018000 - 0x0001DFFF Right frame buffer 1
0x0001E000 - 0x0001FFFF Character table 3
0x00020000 - 0x0003D7FF Background maps and world parameters
0x0003D800 - 0x0003DBFF World attributes
0x0003DC00 - 0x0003DDFF Left column table
0x0003DE00 - 0x0003DFFF Right column table
0x0003E000 - 0x0003FFFF Object attributes
0x00040000 - 0x0005DFFF Unmapped
0x0005E000 - 0x0005FFFF I/O Registers (see below)
0x00060000 - 0x00077FFF Unmapped
0x00078000 - 0x00079FFF Mirror of character table 0
0x0007A000 - 0x0007BFFF Mirror of character table 1
0x0007C000 - 0x0007DFFF Mirror of character table 2
0x0007E000 - 0x0007FFFF Mirror of character table 3
0x00080000 - 0x00FFFFFF Mirroring of VIP memory map

Writing to unmapped addresses has no apparent effect, and their values are undefined when read.

I/O Registers

0x0005F800 INTPND Interrupt Pending
0x0005F802 INTENB Interrupt Enable
0x0005F804 INTCLR Interrupt Clear
0x0005F820 DPSTTS Display Control Read Register
0x0005F822 DPCTRL Display Control Write Register
0x0005F824 BRTA Brightness Control Register A
0x0005F826 BRTB Brightness Control Register B
0x0005F828 BRTC Brightness Control Register C
0x0005F82A REST Rest Control Register
0x0005F82E FRMCYC Game Frame Control Register
0x0005F830 CTA Column Table Read Start Address
0x0005F840 XPSTTS Drawing Control Read Register
0x0005F842 XPCTRL Drawing Control Write Register
0x0005F844 VER VIP Version Register
0x0005F848 SPT0 OBJ Control Register 0
0x0005F84A SPT1 OBJ Control Register 1
0x0005F84C SPT2 OBJ Control Register 2
0x0005F84E SPT3 OBJ Control Register 3
0x0005F860 GPLT0 BG Palette Control Register 0
0x0005F862 GPLT1 BG Palette Control Register 1
0x0005F864 GPLT2 BG Palette Control Register 2
0x0005F866 GPLT3 BG Palette Control Register 3
0x0005F868 JPLT0 OBJ Palette Control Register 0
0x0005F86A JPLT1 OBJ Palette Control Register 1
0x0005F86C JPLT2 OBJ Palette Control Register 2
0x0005F86E JPLT3 OBJ Palette Control Register 3
0x0005F870 BKCOL BG Color Palette Control Register

VIP I/O registers are intended to be accessed as halfwords. All reads, halfword writes and word writes function normally, but byte writes behave anomalously:

If a byte write is attempted on an even address, a halfword write is performed using the lowest 16 bits of the source register.
If a byte write is attempted on an odd address, a halfword write is performed using a value produced by taking the lowest 8 bits of the source regsiter and shifting them left 8 bits.

Any address in the 0x0005E000 - 0x0005FFFF range that does not correspond with one of the above I/O registers is unused. Writing to these addresses has no apparent effect, and their values are undefined when read.


Drawing and Display Procedures

Frame Types

A frame is an image presented to the user. The image may be produced by the VIP itself through its drawing procedure, the drawing feature can be disabled and the image produced through software, or a mixture of both. In all cases, the image to be displayed is stored in the frame buffer.

The primary clock signal used to produce and display images is the display frame, which drives the physical display unit. Display frames occur at a fixed interval of 20 ms, or 50 Hz. During each display frame, the contents of the frame buffer are transmitted to the LEDs for display to the user.

Drawing, if enabled, produces a new image in the frame buffer. The interval at which this occurs is a game frame. The timing of game frames is relative to display frames: the FRMCYC register can be used to configure how many display frames to wait between game frames.

Drawing Procedure

If enabled, the VIP will draw a new image into the frame buffer every game frame using settings from VIP memory such as characters, worlds and palettes.

When appropriate, the drawing procedure begins when the FCLK flag gets set in DPSTTS. The value in FRMCYC is loaded into a counter that is decremented with each display frame to determine when to begin the next drawing task. If the previous drawing task is still ongoing when this occurs, the OVERTIME flag in DPSTTS is set.

Because the VIP memory bus is 16 bits wide and frame buffer memory is 2 bits per pixel stored in column-major order, a halfword access into frame buffer memory corresponds to a 1×8 pixel unit of data. The VIP only writes each location in frame buffer memory once per frame, performing all graphical processing necessary for the current halfword internally.

Halfwords are processed into the frame buffer in left-to-right order, thereby processing 8 rows of pixels at a time. Groups of 8 rows of pixels are procesed in top-to-bottom order. When all 28 groups of 8 rows of pixels have been processed, the drawing procedure completes.

For each 1×8 halfword unit of frame buffer data, the following algorithm is carried out:

All pixels in the halfword are initialized to the value specified by BKCOL.
A temporary object group counter is initialized to 3.
For each world from 31 to 0:
If the END flag is set (control world):
Stop processing worlds.
If the LON and RON flags are both clear (dummy world):
Skip to the next world.
If BGM = 3 (object world):
Draw the object group specified by the temporary counter.
Decrement the object group counter (wraps back to 3 after 0).
Otherwise (background world):
Draw the world's background.
Store the halfword into the frame buffer.

Drawing is performed on frame buffer 0 or 1, alternating each time the drawing procedure is carried out. This enables drawing to one frame buffer while the other is being displayed.

Editor's Note: The amount of time taken by the drawing procedure depends on the complexity of the image being drawn. Affine worlds in particular are computationally expensive and cannot fill the screen without reducing the frame rate. Research is needed to determine exactly how long each type of graphic takes to draw. When no image is being drawn whatsoever (such that the frame buffer's contents are merely erased), the drawing procedure takes approximately 2.8 ms.

Editor's Note: Research is needed to determine exactly when the active frame buffer is toggled. It may occur when FCLK goes high.

Display Procedure

If enabled, then each display frame, the frame buffer is transmitted to the LEDs for display to the user.

Each display frame, the following sequence of events takes place:

0 ms FCLK in DPSTTS goes high.
3 ms The appropriate left frame buffer begins to display.
8 ms The left frame buffer finishes displaying.
10 ms FCLK goes low.
13 ms The appropriate right frame buffer begins to display.
18 ms The right frame buffer finishes displaying.
20 ms Start of next display frame.

When displaying a frame buffer for one eye, the following algorithm is carred out:

An internal column table pointer is initialized using the corresponding value from CTA.
The corresponding DPBSY flag is set in DPSTTS.
For every group of 4 columns of pixels from left to right:
The pixels are emitted using the current frame buffer, brightness and column table values.
If the LOCK flag in DPSTTS is clear:
The internal column table pointer is decremented to the next entry's address.
Advance to the next group of 4 columns.
The corresponding DPBSY flag is cleared in DPSTTS.

Editor's Note: There doesn't appear to be any way to select in software the frame buffer to be displayed. The only known way to leverage double buffering is to use the hardware drawing feature.

Editor's Note: Research is needed to determine whether frame buffer 0 is necessarily used as the default after reset. The drawing function can be used for one frame and DPSTTS monitored to determine which frame buffer it used.


Characters

The fundamental graphical element on Virtual Boy is the character, or "tile", which is an 8×8 pixel image with 2 bits per pixel. There is memory for 2,048 characters broken up into four blocks of 512 characters each:

0x00006000 - 0x00007FFF Character table 0
0x0000E000 - 0x0000FFFF Character table 1
0x00016000 - 0x00017FFF Character table 2
0x0001E000 - 0x0001FFFF Character table 3

These address ranges exist in between frame buffer memory and are not contiguous. In ordrer to facilitate fully linear access, virtual addresses are provided that map to character memory in such a way that all addresses are consecutive:

0x00078000 - 0x00079FFF Mirror of character table 0
0x0007A000 - 0x0007BFFF Mirror of character table 1
0x0007C000 - 0x0007DFFF Mirror of character table 2
0x0007E000 - 0x0007FFFF Mirror of character table 3

Format

A character is an 8×8 pixel graphic represented by 16 bytes. Bytes are stored in the character data consecutively by address.

Each halfword contains 8 pixels at 2 bits per pixel in the following format:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
p7 p6 p5 p4 p3 p2 p1 p0
2 2 2 2 2 2 2 2

Each halfword represents one row of pixels in the character. Pixels at lower-order positions are displayed to the left of pixels at higher-order positions. Rows within the character are ordered top-to-bottom for a total of 8 halfwords.


Objects

Individual characters can appear anywhere in the scene by using them as objects, or "sprites". There is memory (OAM) for 1,024 objects:

0x0003E000 - 0x0003FFFF Object attributes

Object elements are 8 bytes in size, organized into 4 halfwords with the following format:

0
15 10 9 0
- JX
6 10
1
15 14 13 10 9 0
JLON
JRON
- JP
1 1 4 10
2
15 8 7 0
- JY
8 8
3
15 14 13 12 11 10 0
JPLTS
JHFLP
JVFLP
- JCA
2 1 1 1 11
- Unused These bits are not used by the VIP, but are functional memory.
JX Display Pointer X The signed horizontal coordinate of the left edge of the object from the left edge of the image.
JLON Left Display On If set, the object will be drawn to the left image.
JRON Right Display On If set, the object will be drawn to the right image.
JP Parallax The signed parallax offset applied to the horizontal coordinate. (See below)
JY Display Pointer Y The vertical coordinate of the top edge of the object from the top edge of the image. (See below)
JPLTS Palette Selector Specifies the palette index to use for this object.
JHFLP Horizontal Flip If set, the character graphic will be reversed horizontally.
JVFLP Vertical Flip If set, the character graphic will be reversed vertically.
JCA Character Number The index of the character to draw.

The JP field is used to specify the apparent depth of the object in the frame. This is achieved by modifying its horizontal position differently for each eye. The final horizontal position for each of the left and right images is calculated as follows:

Left: JX - JP
Right: JX + JP

The palette index specified by JPLTS selects one of the object ("OBJ") palettes.

JY is not formally two's complement, but is effectively the lower 8 bits of a signed halfword value. It can express values in the range of -8 to +224. Values 0xE0 through 0xF8 are beyond the bounds of the image, so the exact range of the field is unknown.

JCA indexes characters consecutively across all four character tables. The virtual mirroring address of the character in question can be calculated as 0x00078000 + JCA * 16.


Background Maps

A background map is a mosaic of 64×64 characters. Background maps are stored in a region of memory that is shared with world parameters:

0x00020000 - 0x0003D7FF Background maps and world parameters

There is enough memory in this address range for 14 full background maps, plus a few more bytes. When accessing background maps, a full 16 indexes are allowed, but indexes 14 and 15 will access memory not intended for background maps.

Background maps are each 8,192 bytes in size and appear consecutively in memory by address.

Background maps contain 64×64 = 4,096 cells. Cell elements are halfwords with the following format:

15 14 13 12 11 10 0
GPLTS
BHFLP
BVFLP
- Character
2 1 1 1 11
- Unused These bits are not used by the VIP, but are functional memory.
GPLTS Palette Selector Specifies the palette index to use for this cell.
BHFLP Horizontal Flip If set, the character graphic will be reversed horizontally.
BVFLP Vertical Flip If set, the character graphic will be reversed vertically.
Character Character Number The index of the character to draw.

The palette index specified by GPLTS selects one of the background ("BG") palettes.

Character indexes characters consecutively across all four character tables. The virtual mirroring address of the character in question can be calculated as 0x00078000 + Character.

The order of cells in a background map is first left-to-right for each row, then top-to-bottom row order.


Worlds

Overview
Overview
Backgrounds
World Attributes

Types
Normal Worlds
H-Bias Worlds
Affine Worlds
Object Worlds


Overview

All scenes drawn by the VIP are defined in worlds. Worlds can specify either backgrounds or objects to be drawn, both of which use pixel data stored in characters.

Worlds containing backgrounds define a rectangular region of pixels in the image, with position and dimension attributes. The contents of this area involve the world's background, which can be manipulated in various ways.

Worlds containing objects do not specify a windowed region. When an object world is processed, all of its child objects are drawn to the image at the locations specified in their own attributes.

There is memory for 32 worlds, and they are processed in reverse order: beginning with world 31 and working backwards to world 0. Worlds with higher indexes will appear behind, and be obscured by, worlds of lesser indexes. If at any time a control world is encountered (its END flag is set), that world and all subsequent worlds are skipped and the drawing procedure immediately completes.

Worlds come in six varieties:

Normal The world's background is drawn normally, without any special modifications.
H-Bias Contains all of the features of Normal, but also allows each row of pixels within the background to be shifted horizontally, independently from one another.
Affine Each row of pixels is processed with a source coordinate within the background, and a vector, allowing for affine transformations of the background such as rotation and scaling, and can even be used to achieve perspective.
Object Draws a group of objects.
Dummy Configured to produce no output. This occurs when both the LON and RON flags are clear in the world's attributes.
Control Signals early termination of the drawing procedure. This is specified by setting the END flag in the world's attributes.

For more information regarding world configuration, see World Attributes.


Backgrounds

Every world mode except object selects pixels from a background to draw into the image. The background is composed of 1 to 8 background maps arranged in some number of rows and columns within the world.

Backgrounds specify one background map as a base, and any additional background maps are selected sequentially from memory. The background map to use as the base is specified by the BG Map Base field of the world's attributes. For example, if a background consisting of four background maps uses 8 as its base map, the background will consist of maps 8, 9, 10 and 11.

The dimensions of the world's background are specified in units of background map, which are each 512×512 pixels in size. The number of background maps wide or tall a background can be is any power of 2 from 1 BG map to 8 BG maps. However, no more than 8 BG maps total are intended to be used in a single background, restricting which combinations of width and height are intended to be used.

For backgrounds consisting of 8 or fewer background maps, the arrangement of maps regardless of dimension is left-to-right for each row, then top-to-bottom row order. For example, a background that is 4 maps wide and 2 maps tall with a base map of 0 will be arranged as follows:

0 1 2 3
4 5 6 7

For backgrounds consisting of more than 8 background maps, the behavior of the VIP is unintended but nonetheless well-defined. Initially, the background is treated as the largest 8-map background that can be expressed with the specified height. This vertical arrangement is then repeated horizontally as many times as is necessary to fill in the entire background. For example, a 4×4 Background with a base map of 0 will be arranged as follows:

0 1 0 1
2 3 2 3
4 5 4 5
6 7 6 7

The actual index of the background map to use as the base depends on the number of maps in the background. Generally speaking, the value written to BG Map Base in the world's attributes will automatically be rounded down to the next multiple of the total number of background maps. For example, if a background consists of 4 maps and the base map index is 11, the actual map used as the base will be rounded down to 8. For the purposes of determining which map to use as the base, backgrounds consisting of more than 8 maps are treated as though they contain only 8, making their effective base map indexes either 0 or 8.


World Attributes

There is memory for 32 worlds:

0x0003D800 - 0x0003DBFF World attributes

World elements are 32 bytes in size, organized into 16 halfwords with the following format:

0
15 14 13 12 11 10 19 8 7 6 5 4 3 0
LON
RON
BGM SCX SCY
OVER
END
-
BG Map
Base
1 1 2 2 2 1 1 2 4
4
15 13 12 0
- MX
3 13
8
15 0
H
16
1
15 10 9 0
- GX
6 10
5
15 14 0
- MP
1 15
9
15 0
Param Base
16
2
15 10 9 0
- GP
6 10
6
15 13 12 0
- MY
3 13
10
15 0
Overplane Character
16
3
15 0
GY
16
7
15 13 0
- W
3 13
11 - 15
15 0
-
16
- Work memory These bits do not specify world attributes, but are used by the VIP as work memory.
LON Left Display On If set, the world will be drawn to the left image.
RON Right Display On If set, the world will be drawn to the right image.
BGM BG Modification Indicates the world's contents. (See below)
SCX Screen X Size Raise 2 to this power for the width of the world's background in background maps.
SCY Screen Y Size Raise 2 to this power for the height of the world's background in background maps.
OVER Overplane If clear, the world's background will repeat indefinitely. If set, characters beyond the background's bounds will use the character specified by Overplane Character.
END End World Specification Flag If set, this world and all worlds of lesser index will not be drawn to the frame buffer.
BG Map Base The index of the first background map in the world's background.
GX BG X Destination The signed horizontal coordinate of the left edge of the world from the left edge of the image.
GP BG Parallax Destination The signed parallax offset applied to the world's horizontal coordinate. (See below)
GY BG Y Destination The signed vertical coordinate of the top edge of the world from the top edge of the image.
MX BG X Source The signed horizontal source coordinate of the pixel within the world's background, relative to the top-left corner of the background, to be displayed in the top-left corner of the world.
MP BG Parallax Source The signed parallax offset applied to the background's horizontal source coordinate. (See below)
MY BG Y Source The signed vertical source coordinate of the pixel within the world's background, relative to the top-left corner of the background, to be displayed in the top-left corner of the world.
W Window Width Add 1 to this figure to yield the width in pixels of the world. This field's format depends on BGM. (See below)
H Window Height Add 1 to this figure to yield the height in pixels of the world. This value is signed. (See below)
Param Base Specifies the location in world parameter memory where this world's parameters can be found. (See below)
Overplane Character When OVER is set, characters beyond the background's bounds will use the cell in background map memory at the index given by this field.
The corresponding address is 0x00020000 + Overplane_Character × 2

BGM determines the type of content displayed in the world:

0 Normal BG
1 H-Bias BG
2 Affine BG
3 OBJ

The GP field is used to specify the apparent depth of the world in the image. This is achieved by modifying its horizontal position differently for each eye. The final horizontal destination position for each of the left and right images is calculated as follows:

Left: GX - GP
Right: GX + GP

The MP field is used to specify the apparent depth of the background within the world. This is achieved by modifying its horizontal background source position differently for each eye. The final horizontal background source position for each of the left and right images is calculated as follows:

Left: MX - MP
Right: MX + MP

For normal and H-bias worlds, W is a 13-bit signed value. For affine worlds, it is a 10-bit unsigned value.

The minimum height of normal and H-bias worlds is 8 pixels, even if H is in the range of 0 to 6. Affine worlds can be any height.

The Param Base field specifies where in world attribute memory the parameters for this world are located. The corresponding CPU address is as follows:

0x00020000 + Param_Base × 2

Parameter elements are stored sequentially for each row of pixels in the world at the address given by Param Base. The first element is for the top row of pixels, and each subsequent element is for each subsequent row of pixels down.

World parameter elements are always located in the 0x00020000 - 0x0003FFFF range of VIP memory, which is contains all of the background maps, worlds, world parameters, the column table and objects. Care must be taken to prevent accessing data used for other purposes. If the address for the parameters of a given row of pixels would exceed 0x0003FFFF, it will wrap back around to 0x00020000 and continue counting up from there.

Editor's Note: One case suggests that Overplane Character may have restrictions regarding the range of characters it is able to access. Some experimentation is in order.

Editor's Note: Extensive research is required in order to determine the exact behavior of the VIP when drawing worlds with unintended attributes, such as negative or large dimensions, excessive parallax, etc. Research is also needed to determine which bits of world attribute memory are used by the VIP as work memory and in what ways.

Normal Worlds

A normal world is defined entirely with an entry in world attribute memory. All attributes except Param Base apply to normal worlds, and BGM must be 0.


H-Bias Worlds

An H-bias world inherits all of the features of normal worlds and introduces the ability to manipulate the horizontal scrolling of each row of pixels independently. All fields in world attribute memory apply to H-bias worlds, and BGM must be 1.

The Param Base attribute points to the location in world parameter memory where H-bias parameters can be found. The number of H-bias elements required for a world is equal to the height in pixels of the world, as there is one element for each row of pixels starting with the top row.

H-bias elements are 4 bytes in size, organized into 2 halfwords with the following format:

0
15 13 12 0
- HOFSTL
3 13
1
15 13 12 0
- HOFSTR
3 13
- Unused These bits are not used by the VIP, but are functional memory.
HOFSTL Left The signed horizontal offset to apply to the row of pixels for the left eye.
HOFSTR Right The signed horizontal offset to apply to the row of pixels for the right eye.

H-bias offsets function by adjusting the horizontal source position within the world's background for each row of pixels. The final horizontal background source position for each of the left and right images is calculated as follows:

Left: MX - MP + HOFSTL
Right: MX + MP + HOFSTR

The VIP appears to determine the address of HOFSTR by OR'ing the address of HOFSTL with 2. If the Param Base attribute in the world is not divisibe by 4, this will result in HOFSTL being used for both the left and right images, and HOFSTR will not be accessed.


Affine Worlds

An affine world inherits some basic features of normal worlds, but replaces the specifics of how each row of pixels is drawn. All fields in world attribute memory except MX, MP and MY apply to affine worlds, and BGM must be 2.

The Param Base attribute points to the location in world parameter memory where affine parameters can be found. The number of affine elements required for a world is equal to the height of the world in pixels, as there is one element for each row of pixels starting with the top row.

Affine elements are 16 bytes in size, organized into 8 halfwords with the following format:

0
15 0
MX
16
3
15 0
DX
16
1
15 0
MP
16
4
15 0
DY
16
2
15 0
MY
16
5 - 7
15 0
-
16
- Work memory These bits do not specify affine parameters, but are used by the VIP as work memory.
MX BG X Source 13.3 fixed-point signed horizontal source coordinate of the pixel within the world's background, relative to the top-left corner of the background, to be displayed in the left-most column of the current row of pixels.
MP BG Parallax Source The 16-bit signed parallax offset applied to the background's source coordinates. (See below)
MY BG Y Source 13.3 fixed-point signed vertical source coordinate of the pixel within the world's background, relative to the top-left corner of the background, to be displayed in the left-most column of the current row of pixels.
DX BG X Direction 7.9 fixed-point signed horizontal source offset added to the coordinate of the previous source pixel in the current row of pixels for each column of pixels in the world.
DY BG Y Direction 7.9 fixed-point signed vertical source offset added to the coordinate of the previous source pixel in the current row of pixels for each column of pixels in the world.

The affine parameters MX and MY are analogous to the world attributes of the same names, but specify source coordinates with sub-pixel precision. They will be used as the source background coordinates of the left-most column in the corresponding row of output pixels in the world. The source background coordinates for each subsequent column are produced by adding DX and DY to the source background coordinates of the pixel in the previous column.

The affine parameter MP is analogous to the world attribute of the same name. It is processed as though producing output for pixels in the world that are shifted horizontally. For instance, a value of 1 in MP will produce output pixels as though they were 1 world column to the right of their actual position.

If MP is negative, it only applies to the left-eye image. Otherwise, it only applies to the right-eye image.

The final background source positions for each of the left and right images, for each column of pixels i where i = 0 is the left-most column, are calculated as follows:

If MP < 0:
Left X: MX + DX × (i - MP)
Left Y: MY + DY × (i - MP)
Right X: MX + DX × i
Right Y: MY + DY × i
If MP ≥ 0:
Left X: MX + DX × i
Left Y: MY + DY × i
Right X: MX + DX × (i - MP)
Right Y: MY + DY × (i - MP)

Editor's Note: Research is needed to determine which bits of affine parameter memory are used by the VIP as work memory and in what ways.

Editor's Note: IMPORTANT - Affine parameters should always be configured to begin on a 16-byte boundary (lowest 3 bits of Param Base are clear). The VIP appears to determine field addresses with a bitwise OR rather than addition, but writes to halfwords 5, 6 and 7 with addition. Unaligned parameter elements will result in corruption of subsequent elements.


Object Worlds

An object world is used only to display objects and therefore ignores all attributes in world attribute memory except BGM, which must be 3.

The LON and RON world attributes do not influence which eyes objects get drawn to: object visibility is determined entirely by object attributes. However, if both flags are clear, the world will be interpreted as a dummy world and will be skipped. In this situation, the world does not count as an object world.

Objects are organized into one of four object groups, which are managed through global object group registers:

0x0005F848 SPT0 OBJ Control Register 0
0x0005F84A SPT1 OBJ Control Register 1
0x0005F84C SPT2 OBJ Control Register 2
0x0005F84E SPT3 OBJ Control Register 3

The format of all object group registers is the same:

15 10 9 0
- OBJ End Number
6 10
- These bits have no function and are undefined when read.
OBJ End Number R/W The ending index of objects in the group.

An object group defines a range of objects with a start index and an end index. The end index is given by the corresponding object group register. The start index is 1 greater than the register of the next lower group. The start index of group 0 is always 0.

An internal object world counter is initialized to 3 at the start of image processing. Each time an object world is processed, the object group with the same index as the counter is drawn, then the counter is decremented by 1. The counter will reset to 3 every time it is decremented from 0, allowing each object group to be processed multiple times in one frame.

Objects within an object group are drawn in reverse order, beginning with the end index of the group and counting down until the start index of the group has been processed. If the end index is less than the start index, the process is still carried out as usual, continuing with processing of object index 1,023 after object index 0.


Column Table

While the LEDs are emitting light during the display procedure, the angles between the mirrors and the user's eyes are constantly changing. If LED emissions were of constant duration for each column of pixels, then pixels on one side of the image would appear wider than pixels on the other side of the image. In order to correct for this, the column table was implemented.

0x0003DC00 - 0x0003DDFF Left column table
0x0003DE00 - 0x0003DFFF Right column table

An entry in the column table is loaded during the display of every 4 columns of pixels. Column table entries are stored in column table memory consecutively by address, with lower addresses representing columns that are more to the right. There are 512 column table entries total, 256 for each eye. Column table entries are halfwords with the following format:

15 8 7 0
Repeat Column Length
8 8
Repeat R/W Add 1 to this figure for the number of times to produce LED pulses for each column of pixels.
Column Length R/W Add 1 to this figure for the amount of time to spend emitting light for each column of pixels, in units of 200 nanoseconds.

The exact column table entries used during LED operation are determined by the servo and may change from one frame to the next. The VIP prefers to use the middle 96 entries, with the others providing room for adjustments to compensate for the physical behavior of the mirrors. The starting addresses for each eye's column table entries are made available via CTA.

CTA - Column Table Read Start Address

As the image is being displayed, a column table entry is loaded every 4 columns of pixels from left to right. The addresses of the left-most 4 columns can be queried with the following register:

0x0005F830 CTA Column Table Read Start Address
15 8 7 0
CTA_R CTA_L
8 8
CTA_R R Index into the right column table. The corresponding address is 0x0003DE00 + (CTA_R × 2)
CTA_L R Index into the left column table. The corresponding address is 0x0003DC00 + (CTA_L × 2)

The VIP has an internal pointer that is initialized with the corresponding value from CTA when displaying a frame buffer. After each 4 columns of pixels are displayed, the pointer is decremented, causing it to point to the next 4 columns of pixels to the right. This decrement operation can be prevented by setting the LOCK flag in DPCTRL.

LED Emission

The LEDs in the display unit cannot actually emit light of varying intensity, so brightness is instead achieved by adjusting how long each pixel emits light. The less light that reaches the eye when displaying a pixel, the dimmer that pixel will appear to be. For the configuration of the base durations of LED emission for each level of brightness, see Brightness.

In addition to the LED emission interval per brightness level, there is also an idle interval register:

0x0005F82A REST Rest Control Register
15 8 7 0
- Duration
8 8
- These bits have no function and are undefined when read.
Duration R/W Specifies the duration in units of 5 nanoseconds.

When a pixel is displayed, its value is loaded from the frame buffer. The LED will pulse for the appropriate brightness duration, then idle for the REST duration. The number of times this occurs for each column of pixels is given by the Repeat field in the column table. Since more light reaching the eye produces a brighter pixel, Repeat serves as a sort of brightness multiplier for the column.

If the total configured brightness + idle duration exceeds the time allotted for the corresponding column of pixels, the display will stop emitting and move onto the next column.

Apparent Brightness

After a certain amount of time spent emitting light, the full intensity of the LEDs can be perceived by the human eye, and longer emissions will not appear to get any brighter.

The measurable brightness of a pixel is given by the duration of its brightness level multiplied by the Repeat field in the column table. If this measurement reaches about 128, then any longer durations will not appear brighter to the user.

Recommended Column Table

Nintendo provides a recommended column table configuration that is used by all commercial software. The following data is to be loaded to addresses 0x0003DC00 and 0x0003DE00:

+000
+010
+020
+030
+040
+050
+060
+070
+080
+090
+0A0
+0B0
+0C0
+0D0
+0E0
+0F0
+100
+110
+120
+130
+140
+150
+160
+170
+180
+190
+1A0
+1B0
+1C0
+1D0
+1E0
+1F0
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 E0 00 BC 00
A6 00 96 00 8A 00 82 00  7A 00 74 00 6E 00 6A 00
66 00 62 00 60 00 5C 00  5A 00 58 00 56 00 54 00
52 00 50 00 50 00 4E 00  4C 00 4C 00 4A 00 4A 00
48 00 48 00 46 00 46 00  46 00 44 00 44 00 44 00
42 00 42 00 42 00 40 00  40 00 40 00 40 00 40 00
3E 00 3E 00 3E 00 3E 00  3E 00 3E 00 3E 00 3C 00
3C 00 3C 00 3C 00 3C 00  3C 00 3C 00 3C 00 3C 00
3C 00 3C 00 3C 00 3C 00  3C 00 3C 00 3C 00 3C 00
3C 00 3C 00 3C 00 3C 00  3C 00 3C 00 3C 00 3C 00
3C 00 3C 00 3C 00 3C 00  3C 00 3C 00 3C 00 3C 00
3C 00 3E 00 3E 00 3E 00  3E 00 3E 00 3E 00 3E 00
40 00 40 00 40 00 40 00  40 00 42 00 42 00 42 00
44 00 44 00 44 00 46 00  46 00 46 00 48 00 48 00
4A 00 4A 00 4C 00 4C 00  4E 00 50 00 50 00 52 00
54 00 56 00 58 00 5A 00  5C 00 60 00 62 00 66 00
6A 00 6E 00 74 00 7A 00  82 00 8A 00 96 00 A6 00
BC 00 E0 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00
FE 00 FE 00 FE 00 FE 00  FE 00 FE 00 FE 00 FE 00

The exact association between entries in the column table and physical columns of pixels is dynamic and can change without notice during system operation. The starting position in the column table during the display procedure each frame can be inspected using CTA.


Frame Buffer

Virtual Boy processes images in a double-buffered, stereoscopic frame buffer. The drawing procedure automatically alternates between buffers 0 and 1 for each eye, allowing one frame to be drawn while the previous frame is being displayed.

0x00000000 - 0x00005FFF Left frame buffer 0
0x00008000 - 0x0000DFFF Left frame buffer 1
0x00010000 - 0x00015FFF Right frame buffer 0
0x00018000 - 0x0001DFFF Right frame buffer 1

A frame buffer is a 384×256 pixel image represented by 24,576 bytes. Bytes are stored in the frame buffer data consecutively by address.

Each halfword contains 8 pixels at 2 bits per pixel in the following format:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
p7 p6 p5 p4 p3 p2 p1 p0
2 2 2 2 2 2 2 2

Pixels at lower-order positions are displayed above pixels at higher-order positions.

Pixels are stored in column-major order in the frame buffer in order to transfer them more efficiently when displayed by the scanner. The order of pixels in the frame buffer is first top-to-bottom for each column, then left-to-right column order.

The VIP will only draw and display the top 224 rows of pixels in the frame buffer. In the interest of simplifying design and manufacture, additional memory is present for 32 rows below the bottom of the image within each frame buffer. This memory is never modified by the VIP but is fully functional.


Display

The display unit in the VIP processes two images: one for each eye. A vertical column of LEDs is reflected off of oscillating mirrors in order to produce the illusion of a two-dimensional image.

The display is configured through two registers:

0x0005F820 DPSTTS Display Control Read Register
0x0005F822 DPCTRL Display Control Write Register

Both display registers have the same format:

15 11 10 9 8 7 6 5 4 3 2 1 0
-
LOCK
SYNCE
RE
FCLK
SCANRDY
R1BSY
L1BSY
R0BSY
L0BSY
DISP
DPRST
5 1 1 1 1 1 1 1 1 1 1 1
- These bits have no function and are undefined when read.
LOCK R/W When set, CTA is prevented from updating.
SYNCE R/W When clear, display sync signals are not sent to the display servo, preventing images from being displayed.
RE R/W When clear, memory refresh signals will not be issued on VIP memory.
FCLK R The display frame clock signal is high.
SCANRDY R When set, the mirrors are stable.
R1BSY [note] R Right frame buffer 1 is being displayed.
L1BSY [note] R Left frame buffer 1 is being displayed.
R0BSY [note] R Right frame buffer 0 is being displayed.
L0BSY [note] R Left frame buffer 0 is being displayed.
DISP R/W When set, the display is enabled.
DPRST W When set, display functions are reset. When clear, no action occurs.

[note] These fields are formally sub-fields of a 4-bit field called DPBSY.

DPSTTS is read-only and writes have no effect. DPCTRL is write-only and undefined when read. As such, fields marked "R" above apply to DPSTTS and fields marked "W" apply to DPCTRL.

SYNCE and DISP must both be set in order for images to be displayed. With precise timing, SYNCE might be used to enable only one image at a time, but its function is effectively the same as DISP.

While RE is clear, any VIP memory not used by the drawing procedure will degrade after several seconds.

Setting the DPRST flag will cause the following flags in DPSTTS to be undefined: LOCK, FCLK, SCANRDY and all four DPBSY flags.

Setting the DPRST flag will clear the following flags in INTENB and INTPND: TIMEERR, FRAMESTART, GAMESTART, RFBEND, LFBEND and SCANERR.

For more informaiton on the display frame clock signal, see Drawing and Display Procedures.


Drawing

The VIP has a drawing feature built in that can produce images for display using graphics data supplied by the software. This drawing feature can be disabled, allowing software rendering through direct access to the frame buffer.

Drawing is configured through two registers:

0x0005F840 XPSTTS Drawing Control Read Register
0x0005F842 XPCTRL Drawing Control Write Register

Both drawing registers have the same format:

15 14 13 12 8 7 5 4 3 2 1 0
SBOUT
-
SBCOUNT /
SBCMP
-
OVERTIME
F1BSY
F0BSY
XPEN
XPRST
1 2 5 3 1 1 1 1 1
- These bits have no function and are undefined when read.
SBOUT R Set when a group of 8 rows of pixels begins to draw. (See below)
SBCOUNT R The current group of 8 rows of pixels, relative to the top of the image, currently being drawn.
SBCMP W The group of 8 rows of pixels, relative to the top of the image, to compare with while drawing.
OVERTIME R The drawing procedure has taken longer than the allotted time.
F1BSY [note] R Frame buffer 1 is being drawn to.
F0BSY [note] R Frame buffer 0 is being drawn to.
XPEN R/W When set, drawing is enabled.
XPRST W When set, drawing functions are reset. When clear, no action occurs.

[note] These fields are formally sub-fields of a 2-bit field called XPBSY.

XPSTTS is read-only and writes have no effect. XPCTRL is write-only and undefined when read. As such, fields marked "R" above apply to XPSTTS and fields marked "W" apply to XPCTRL.

The VIP will draw to the frame buffer in units of 1×8 pixels, from left to right. This corresponds to a halfword write into frame buffer memory. For this reason, the vertical position of drawing into the frame buffer is tracked in units of 8 rows of pixels relative to the top of the image. SBCOUNT is the current group of 8 rows of pixels being processed during the drawing procedure.

SBOUT is set each time SBCOUNT is incremented, at the start of processing for each group of 8 rows of pixels. SBOUT will automatically clear itself shortly thereafter. [note]

[note] The formal specification states that SBOUT will be cleared after 56 µs, but testing has shown it to persist for as long as 120 µs and overrun into the following group of 8 rows of pixels. SBOUT is not a reliable way to detect changes to SBCOUNT.

Setting the XPRST flag will clear the XPEN flag in XPSTTS.

Setting the XPRST flag will clear the following flags in INTENB and INTPND: TIMEERR, XPEND and SBHIT.

For more informaiton on drawing processing, see Drawing and Display Procedures.


Brightness

The displays in the Virtual Boy are only capable of emitting red light, but the intensity of that light can be adjusted in order to produce four shades of red per image, one of which is always black. The intensity of the other three can be controlled with global brightness settings:

0x0005F824 BRTA Brightness Control Register A
0x0005F826 BRTB Brightness Control Register B
0x0005F828 BRTC Brightness Control Register C

The format of all brightness registers is the same:

15 8 7 0
- Duration
8 8
- These bits have no function and are undefined when read.
Duration R/W Specifies the duration in units of 5 nanoseconds.

The LEDs in the display unit cannot actually emit light of varying intensity, so brightness is instead achieved by adjusting how long each pixel emits light. The less light that reaches the eye when displaying a pixel, the dimmer that pixel will appear to be. For additional information regarding LED emission periods and apparent brightness, see Column Table.

The brightness of each pixel in the frame buffer is determined by the pixel's value. Since pixels are 2 bits in size, there are four possible brightness levels:

0 Black
1 Brightness level A
2 Brightness level B
3 Brightness level C

Brightness levels A and B are configured directly, with zero representing no intensity and larger durations appearing brighter.

The actual duration of brightness level C is the sum of the durations in all three brightness registers: A + B + C.


Palettes

When a character is drawn by the VIP, a palette is applied to each pixel before storing the result into the frame buffer. The palette used depends on the context in which the character is used: there are distinct palettes for background maps and objects.

0x0005F860 GPLT0 BG Palette Control Register 0
0x0005F862 GPLT1 BG Palette Control Register 1
0x0005F864 GPLT2 BG Palette Control Register 2
0x0005F866 GPLT3 BG Palette Control Register 3
0x0005F868 JPLT0 OBJ Palette Control Register 0
0x0005F86A JPLT1 OBJ Palette Control Register 1
0x0005F86C JPLT2 OBJ Palette Control Register 2
0x0005F86E JPLT3 OBJ Palette Control Register 3

The format of all palette registers is the same:

15 8 7 6 5 4 3 2 1 0
- c3 c2 c1 -
8 2 2 2 2
- These bits have no function and are undefined when read.
c3 R/W The frame buffer pixel value for character pixel value 3.
c2 R/W The frame buffer pixel value for character pixel value 2.
c1 R/W The frame buffer pixel value for character pixel value 1.

A pixel value of 0 in a character is interpreted as a transparent pixel and will not modify the contents of the frame buffer when drawn. Accordingly, there is no palette entry for character pixel value 0.

One of four palettes can be selected for each character, which is applied to every pixel within the character. The "BG" palettes are selected when the character is used in a background map, and the "OBJ" palettes are selected when the character is used in an object.

Background Color

If any given pixel in the frame buffer is never drawn to by a character, its color will be determined by a global background color:

0x0005F870 BKCOL R/W BG Color Palette Control Register
15 2 1 0
-
value
14 2
- These bits have no function and are undefined when read.
value R/W The initial frame buffer pixel value.

After BKCOL is written, the new background color will not be applied until after the first 8 rows of pixels are drawn to the frame buffer the next time a frame is drawn.


Interrupts

The VIP is capable of raising an interrupt for a number of different conditions. Regardless of the cause, all VIP interrupts have a code of 0xFE40.

VIP interrupts are configured through three registers:

0x0005F800 INTPND Interrupt Pending
0x0005F802 INTENB Interrupt Enable
0x0005F804 INTCLR Interrupt Clear

All interrupt registers have the same format:

15 14 13 12 5 4 3 2 1 0
TIMEERR
XPEND
SBHIT
-
FRAMESTART
GAMESTART
RFBEND
LFBEND
SCANERR
1 1 1 8 1 1 1 1 1
- These bits have no function and are undefined when read.
TIMEERR Drawing is still in progress when the drawing procedure should begin. Detects the OVERTIME flag in XPSTTS.
XPEND The drawing procedure has finished.
SBHIT Drawing has begun on the group of 8 rows of pixels specified in the SBCMP field of XPCTRL.
FRAMESTART The display procedure has begun.
GAMESTART The drawing procedure has begun.
RFBEND The display procedure has completed for the right eye.
LFBEND The display procedure has completed for the left eye.
SCANERR The mirrors are not stable.

INTPND is read-only and writes have no effect. INTCLR is write-only and is undefined when read.

Interrupt conditions are enabled or disabled by writing to INTENB. If the corresponding flag is set, the interrupt condition will be enabled, and if it is clear, the interrupt condition will be disabled.

When an interrupt condition is satisfied, regardless of whether or not the condition is enabled, the corresponding flag in INTPND will be set. If any flag is set in both INTENB and INTPND, the VIP will issue an interrupt request signal to the CPU.

Interrupt conditions are acknowledged by writing to INTCLR, which will clear the corresponding flags in INTPND.

Setting the DPRST flag in DPCTRL will clear the following flags in INTENB and INTPND: TIMEERR, FRAMESTART, GAMESTART, RFBEND, LFBEND and SCANERR.

Setting the XPRST flag in XPCTRL will clear the following flags in INTENB and INTPND: TIMEERR, XPEND and SBHIT.

For more information on the SBHIT interrupt condition, see Display.


Miscellaneous Registers

FRMCYC - Game Frame Control Register

A game frame is the interval between invocations of the VIP drawing procedure. One game frame can be synchronized with a particular number of display frames:

0x0005F82E FRMCYC Game Frame Control Register
15 4 3 0
- FRMCYC
12 4
- These bits have no function and are undefined when read.
FRMCYC R/W Add 1 to this figure for the number of display frames for each game frame.

For more information regarding the synchronization of game frame and display frame, see Drawing and Display Procedures.

Editor's Note: If FRMCYC is set to a value lower than the internal frame counter in between game frames, what happens? Will the next frame be a game frame? Will it wrap around at 15 and keep counting?

VER - VIP Version Register

The version of the current VIP hardware can be queried with the following register:

0x0005F844 VER VIP Version Register
15 5 4 0
- VER
11 5
- These bits have no function and are undefined when read.
VER R The version number of the current VIP hardware.

Only one model of Virtual Boy was ever produced. Its VIP version is 2.


VSU - Virtual Sound Unit

Overview
Overview
Memory Map
Output Procedure

Channels
PCM Waveforms
Channel Control
Stereo Levels
Frequency
Envelope
Sweep & Modulation
Noise
Master Control


Overview

Virtual Boy's sound unit has 6 channels, five of which produce tones by sampling from PCM memory and one of which produces binary noise.

Channels are named 1 through 6 and have the following features:

All channels
Duration control
Stereo output levels/balance
Sampling frequency
Master envelope level with shrink/grow and repeat
Channels 1 through 4
Sampling from PCM wave memory
Channel 5
Sampling from PCM wave memory
Frequency sweep and modulation
Channel 6
Sampling from pseudorandom noise generator

Audio output from the mixer is 10-bit digital stereo at 41,700 Hz. Peripherals include two built-in stereo speakers, a volume wheel and a 3.5 mm headphone jack.


Memory Map

The VSU occupies addresses 0x01000000 - 0x01FFFFFF in the system memory map.

All VSU addresses must be accessed with 8-bit writes. 16- and 32-bit writes have undefined behavior. All reads are undefined.

Memory Map

0x01000000 - 0x0100007F Waveform 1 RAM
0x01000080 - 0x010000FF Waveform 2 RAM
0x01000100 - 0x0100017F Waveform 3 RAM
0x01000180 - 0x010001FF Waveform 4 RAM
0x01000200 - 0x0100027F Waveform 5 RAM
0x01000280 - 0x010002FF Modulation RAM
0x01000300 - 0x010003FF Unmapped
0x01000400 - 0x010007FF I/O Registers (see below)
0x01000800 - 0x01FFFFFF Mirroring of VSU memory map

Writing to unmapped addresses has no apparent effect.

I/O Registers

0x01000400 S1INT Channel 1 Sound Interval Specification Register
0x01000404 S1LRV Channel 1 Level Setting Register
0x01000408 S1FQL Channel 1 Frequency Setting Low Register
0x0100040C S1FQH Channel 1 Frequency Setting High Register
0x01000410 S1EV0 Channel 1 Envelope Specification Register 0
0x01000414 S1EV1 Channel 1 Envelope Specification Register 1
0x01000418 S1RAM Channel 1 Base Address Setting Register
 
0x01000440 S2INT Channel 2 Sound Interval Specification Register
0x01000444 S2LRV Channel 2 Level Setting Register
0x01000448 S2FQL Channel 2 Frequency Setting Low Register
0x0100044C S2FQH Channel 2 Frequency Setting High Register
0x01000450 S2EV0 Channel 2 Envelope Specification Register 0
0x01000454 S2EV1 Channel 2 Envelope Specification Register 1
0x01000458 S2RAM Channel 2 Base Address Setting Register
 
0x01000480 S3INT Channel 3 Sound Interval Specification Register
0x01000484 S3LRV Channel 3 Level Setting Register
0x01000488 S3FQL Channel 3 Frequency Setting Low Register
0x0100048C S3FQH Channel 3 Frequency Setting High Register
0x01000490 S3EV0 Channel 3 Envelope Specification Register 0
0x01000494 S3EV1 Channel 3 Envelope Specification Register 1
0x01000498 S3RAM Channel 3 Base Address Setting Register
 
0x010004C0 S4INT Channel 4 Sound Interval Specification Register
0x010004C4 S4LRV Channel 4 Level Setting Register
0x010004C8 S4FQL Channel 4 Frequency Setting Low Register
0x010004CC S4FQH Channel 4 Frequency Setting High Register
0x010004D0 S4EV0 Channel 4 Envelope Specification Register 0
0x010004D4 S4EV1 Channel 4 Envelope Specification Register 1
0x010004D8 S4RAM Channel 4 Base Address Setting Register
 
0x01000500 S5INT Channel 5 Sound Interval Specification Register
0x01000504 S5LRV Channel 5 Level Setting Register
0x01000508 S5FQL Channel 5 Frequency Setting Low Register
0x0100050C S5FQH Channel 5 Frequency Setting High Register
0x01000510 S5EV0 Channel 5 Envelope Specification Register 0
0x01000514 S5EV1 Channel 5 Envelope Specification Register 1
0x01000518 S5RAM Channel 5 Base Address Setting Register
0x0100051C S5SWP Sweep/Modulation Register
 
0x01000540 S6INT Channel 6 Sound Interval Specification Register
0x01000544 S6LRV Channel 6 Level Setting Register
0x01000548 S6FQL Channel 6 Frequency Setting Low Register
0x0100054C S6FQH Channel 6 Frequency Setting High Register
0x01000550 S6EV0 Channel 6 Envelope Specification Register 0
0x01000554 S6EV1 Channel 6 Envelope Specification Register 1
 
0x01000580 SSTOP Stop All Sound Output Register

Output Procedure

Digital Output

An unsigned, 6-bit input sample is produced for each of the 6 audio channels. Wave channel samples come directly from wave memory, and the noise channel's sample is generated according to the noise generation algorithm. If a channel is not active, 0 is used for its input sample.

Each channel has a master output level determined by its current envelope value, even if the envelope is not doing anything, and the left/right levels as determined by the channel's stereo levels configuration. This section refers to the left and right channel output streams in singular, but this algorithm applies to each stream independently.

For each channel:

The 4-bit stereo level is multiplied with the 4-bit envelope level.
Of the resulting 8 bits, only the highest 5 are used as the amplitude value.
If neither level was zero, 1 is added to the amplitude value.
The 6-bit input sample is multiplied with the 5-bit amplitude value to produce the 11-bit channel output value.

Once all channels have been processed:

The 11-bit channel output values for all channels are added together.
Of the resulting 14 bits, only the highest 10 are used as the final output.

Output is sampled at 41,700 Hz. The maximum output value is 685.

Analog Output

When converting to analog, the VSU implements an RC circuit to block the DC bias, effectively producing a first-order high-pass filter with a very low cutoff frequency. This prevents the output voltage from being exclusively non-negative without affecting the audible significance of the stream.

The RC circuit is implemented with a 100 Ω resistor and a 220 µF capacitor, resulting in a cutoff frequency of 1 / (2π × 100 × 0.000220) ≈ 7.234 Hz. It can be discretized with an arbitrary sampling rate using the following formulas:

RC = 100 × 0.000220 = 0.022
α = RC / (RC + 1 / SamplingRateHz)

Then, for each sample:

Output[n] = α × ( Output[n - 1] + Input[n] - Input[n - 1] )

If no output line is plugged into the 3.5 mm headphone jack, the output will be sent to the internal stereo speakers. Otherwise, the output will be sent through the connected line and not to the speakers.


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 Waveform 1 RAM
0x01000080 - 0x010000FF Waveform 2 RAM
0x01000100 - 0x0100017F Waveform 3 RAM
0x01000180 - 0x010001FF Waveform 4 RAM
0x01000200 - 0x0100027F Waveform 5 RAM

Samples are 6-bit, unsigned integers. They are accessed on word boundaries (4 bytes apart, lowest address), but must be written using 8-bit store or output instructions. The upper 2 bits of the 8-bit value are ignored. 16- and 32-bit writes have undefined behavior.

PCM wave memory can only be written while all sound channels are inactive, including the noise channel. Attempts to write to it during sound generation will have no effect.

When a channel's SxINT register is written, the channel's current sampling position within wave memory will be reset to the first sample.

PCM waveforms are associated with audio channels through dedicated registers:

0x01000418 S1RAM Channel 1 Base Address Setting Register
0x01000458 S2RAM Channel 2 Base Address Setting Register
0x01000498 S3RAM Channel 3 Base Address Setting Register
0x010004D8 S4RAM Channel 4 Base Address Setting Register
0x01000518 S5RAM Channel 5 Base Address Setting Register
7 3 2 0
- Wave
5 3
- These bits have no function and are undefined when read.
Wave W The index of the waveform.

Wave specifies which PCM wave table to use on the sound channel, such that a value of zero corresponds with waveform 1.

If a value greater than 4 (PCM wave 5) is specified for Wave, the channel will still play, but will not produce any sound. PCM wave memory still cannot be written while any channel is active in this manner.


Channel Control

Channels are enabled and disabled through designated registers:

0x01000400 S1INT Channel 1 Sound Interval Specification Register
0x01000440 S2INT Channel 2 Sound Interval Specification Register
0x01000480 S3INT Channel 3 Sound Interval Specification Register
0x010004C0 S4INT Channel 4 Sound Interval Specification Register
0x01000500 S5INT Channel 5 Sound Interval Specification Register
0x01000540 S6INT Channel 6 Sound Interval Specification Register
7 6 5 4 0
Enb
-
Auto
Interval
1 1 1 5
- This bit has no function and is undefined when read.
Enb W Set to enable sound generation.
Auto W Set to schedule automatic channel deactivation.
Interval W The time to wait before deactivating the channel.

When Enable is set, the channel will begin generating sound. Otherwise, the channel will be disabled and cease sound generation.

When Auto is set, the channel will play for the amount of time specified by Interval and then automatically disable itself. Otherwise, the channel will play until the software disables it.

Interval specifies how long the channel should generate sound before automatically shutting itself off as described above. The value plus 1 represents time in units of ≈ 3.84 ms (= 260.4 Hz).

Various state settings within the sound channel will be reset when its SxINT register is written:

The frequency delay counter will be reset to the beginning of its current sample.
The current position in PCM wave memory will be reset to the first sample.
The envelope step timer will be reset to the start of its step interval.
The frequency modification timer will be reset to the start of its modification interval.
The current position in modulation memory will be reset to the first value.
The noise generator's shift register will be reset to all zeroes.


Stereo Levels

The left and right stereo levels of a channel are configured through designated registers:

0x01000404 S1LRV Channel 1 Level Setting Register
0x01000444 S2LRV Channel 2 Level Setting Register
0x01000484 S3LRV Channel 3 Level Setting Register
0x010004C4 S4LRV Channel 4 Level Setting Register
0x01000504 S5LRV Channel 5 Level Setting Register
0x01000544 S6LRV Channel 6 Level Setting Register
7 4 3 0
Left Right
4 4
Left W The left volume.
Right W The right volume.

Each field controls the output level of the corresponding stereo stream. The level scales linearly with 0 being silence and 15 being maximum amplitude.


Frequency

A channel's frequency specifies the interval at which it produces new samples.

Frequency Values

All channels define a sampling rate with a base clock and a configurable delay. The base clock depends on the channel and cannot be changed, while the delay setting is used to configure how many base clocks to wait before moving on to the next sample.

A channel's base clock frequency depends on the channel:

5,000,000 Hz Channels 1-5
500,000 Hz Channel 6

The channel's delay setting specifies how many base clocks to wait between changing the sample value on the channel. To wait zero clocks is to update samples at the base clock frequency, and longer delays will update at slower intervals. This document refers to the delay setting as the "frequency value".

The number of base clocks to wait is calculated by subtracting the frequency value from 2,048 (1 greater than the 11-bit maximum value). In this way, higher frequency values correspond with higher frequencies.

Channels maintain two frequency values internally: the most recent value written to the frequency registers (see below) and the current value used as the delay counter during sound generation. Both values are unsigned 11-bit, with one byte representing the lower 8 bits and a second byte representing the upper 3 bits (the upper 5 bits of this byte are ignored).

Writing an 8-bit value to one of the frequency registers will update the corresponding bits of both the most recent value and the current value. Frequency modifications that occur during sound generation will only update the current value. Since frequency modifications can alter all 11 bits of the current value, programs should use both frequency registers to ensure the entire value is updated.

Since the VSU samples output from channels at 41,700 Hz, any frequency value that specifies a higher sampling rate will be subject to aliasing.

When a channel's SxINT register is written, its sampling delay counter is reset to the beginning of the current sample.

Frequency Registers

11-bit frequency values are configured through two registers per channel, one for the lower 8 bits of the value and the other for the upper 3 bits:

0x01000408 S1FQL Channel 1 Frequency Setting Low Register
0x01000448 S2FQL Channel 2 Frequency Setting Low Register
0x01000488 S3FQL Channel 3 Frequency Setting Low Register
0x010004C8 S4FQL Channel 4 Frequency Setting Low Register
0x01000508 S5FQL Channel 5 Frequency Setting Low Register
0x01000548 S6FQL Channel 6 Frequency Setting Low Register
7 0
Low
8
Low W The lower 8 bits of the frequency value.

0x0100040C S1FQH Channel 1 Frequency Setting High Register
0x0100044C S2FQH Channel 2 Frequency Setting High Register
0x0100048C S3FQH Channel 3 Frequency Setting High Register
0x010004CC S4FQH Channel 4 Frequency Setting High Register
0x0100050C S5FQH Channel 5 Frequency Setting High Register
0x0100054C S6FQH Channel 6 Frequency Setting High Register
7 3 2 0
- High
5 3
- These bits have no function and are undefined when read.
High W The upper 3 bits of the frequency value.

Frequency values are 11-bit, but must be written as two individual bytes because the VSU bus is only 8 bits wide. The lower 8 bits come from the SxFQL register and the upper 3 bits come from the SxFQH register.

These registers will update the corresponding bits in both the channel's most recent and current frequency values. The bits from the register not written will remain unaffected.


Envelope

The envelope feature maintains a channel envelope level that acts like a master volume setting independent from the stereo levels. The envelope can be configured to grow or decay automatically over time, and optionally reload a pre-configured value and repeat the grow/decay process. Even if automatic modifications are disabled, the envelope level must be initialized to some non-zero value in order for audible sound to be produced on the channel.

The envelope is controlled through two registers:

0x01000410 S1EV0 Channel 1 Envelope Specification Register 0
0x01000450 S2EV0 Channel 2 Envelope Specification Register 0
0x01000490 S3EV0 Channel 3 Envelope Specification Register 0
0x010004D0 S4EV0 Channel 4 Envelope Specification Register 0
0x01000510 S5EV0 Channel 5 Envelope Specification Register 0
0x01000550 S6EV0 Channel 6 Envelope Specification Register 0
7 4 3 1 0
Value
Dir
Interval
4 1 3
Value W The initial and reload value of the envelope.
Dir W Specifies the direction in which the envelope is modified. (See below)
Interval W Specifies the time between envelope modifications. (See below)

0x01000414 S1EV1 Channel 1 Envelope Specification Register 1
0x01000454 S2EV1 Channel 2 Envelope Specification Register 1
0x01000494 S3EV1 Channel 3 Envelope Specification Register 1
0x010004D4 S4EV1 Channel 4 Envelope Specification Register 1
0x01000514 S5EV1 Channel 5 Envelope Specification Register 1
0x01000554 S6EV1 Channel 6 Envelope Specification Register 1
7 6 4 3 2 1 0
- (Ext) -
Rep
Enb
1 3 2 1 1
- These bits have no function and are undefined when read.
(Ext) * These bits have significance with regards to the frequency modification and noise features.
Rep W Specifies whether envelope modification loops. (See below)
Enb W When set, envelope modification is enabled.

Writing to Value changes the current envelope level and stores a new reload value.

When Dir is set, automatic envelope modifications will add 1 to the current envelope level (grow). When clear, modifications will subtract 1 from the current level (decay).

Interval specifies how long each envelope level lasts before being automatically modified. The value plus 1 represents time in units of ≈ 15.36 ms (65.1 Hz).

If Enb is set, the envelope level is automatically modified by 1 in the direction specified by Dir at the interval specified by Interval. The envelope level can grow until it reaches 15 or decay until it reaches 0. If Enb is clear, automatic envelope modifications will not occur.

If Rep is set while Enb is set, then after the envelope is processed at its maximum (if Dir is set) or minimum (if Dir is clear) level for one interval, the most recent value written to Value is reloaded as the envelope level for one interval and automatic modifications will resume. If Rep is not set while Enb is set, then the envelope level will remain at its maximum or minimum value depending on Dir.

Writing to S6EV1 will reset the noise generator's shift register to all zeroes.

Envelope Procedure

The following procedure takes place for each envelope frame as specified by Interval:

Sound is generated for Interval time.
If Enb is clear:
The current envelope level remains the same.
Otherwise, if Dir is clear and the current envelope level is not 0:
Decrease the current envelope level by 1.
Otherwise, if Dir is set and the current envelope level is not 15:
Increase the current envelope level by 1.
Otherwise, if Rep is set:
The current envelope level is replaced by Value.

When the channel's SxINT register is written, the current envelope frame is reset (needs to wait for the entire Interval again).

Editor's Note: When the channel is enabled while the envelope's Enb is set, it will generate samples of value 0 for the first 5-10 milliseconds but otherwise function normally. It is not clear exactly why this happens or whether it's consistent, so it could bear some further investigation.


Sweep & Modulation

Channel 5 has, in addition to all of the features of Channels 1-4, support for frequency sweep and modulation functions. These functions will modify the current frequency value, but not the frequency value most recently written to the frequency registers.

Regardless of the frequency modification function used, a new frequency value is calculated at the beginning of the current frequency modification frame. After audio is generated for the current frame, the current frequency value is replaced by the calculated new value.

Sweep

The sweep function produces a new frequency value relative to the current frequency value. The new frequency value is calculated by shifting the current frequency value right by a specified number of bits, then adding or subtracting the result to or from the current frequency value. This results in a sliding pitch on the logarithmic scale, as though along octaves.

If the calculated new frequency value is greater than 2,047, channel 5 will immediately be stopped without generating any further sound. A bug in the hardware implementation of the sweep function allows this to occur even if the sweep function is disabled (if either modifications are disabled or the modification interval is zero).

Because automatic channel shutoff occurs at the beginning of the current frequency modification frame (inspecting the calculated new frequency value), it will prevent the highest valid frequency value from being used in audio generation.

Modulation

The modulation function produces a new frequency value by reading modulation values from VSU memory. Each frequency modification frame, a new frequency value is calculated by reading a modulation value and adding it to the most recent frequency value written to the frequency registers, retaining only the lowest 11 bits of the result.

After processing all 32 modulation values, frequency modification processing can either stop or continue from the first modulation value.

Writing to S5INT will reset the current modulation position to the first value in modulation memory.

There are 32 values in modulation memory:

0x01000280 - 0x010002FF Modulation Data RAM

Modulation values are 8-bit, two's complement signed integers. They are accessed on word boundaries (4 bytes apart, lowest address), but must be written using 8-bit store or output instructions. 16- and 32-bit writes have undefined behavior.

Modulation memory can only be written while sound channel 5 is inactive. Attempts to write to it while the channel is generating sound will have no effect.

Sweep/Modulation Control Registers

Frequency modifications are controlled through two registers. Frequency modification bits exist in S5EV1 that do not pertain to envelope functionality:

0x01000514 S5EV1 Channel 5 Envelope Specification Register 1
7 6 5 4 3 2 1 0
-
Enb
Rep
Func
- (Env)
1 1 1 1 2 2
- These bits have no function and are undefined when read.
Enb W When set, frequency modification is enabled.
Rep W Specifies whether modulation loops. (See below)
Func W Specifies the frequency modification function. (See below)
(Env) * These bits have significance with regards to the envelope feature.

0x0100051C S5SWP Sweep/Modulation Register
7 6 4 3 2 0
Clk
Interval
Dir
Shift
1 3 1 3
Clk W Specifies the base modification clock. (See below)
Interval W Specifies the modification interval. (See below)
Dir W Specifies the sweep direction. (See below)
Shift W Specifies the sweep shift amount. (See below)

If Enb is set and Interval is not zero, frequency modifications will be performed. Otherwise, the frequency will not be modified.

Func specifies which type of frequency modification is to take place:

0 Sweep
1 Modulation

If Rep is clear while the modulation function is selected, then the 32 values in modulation memory will only be processed once, leaving the frequency at the final value. Otherwise, if Repeat is set, modulation memory will continue to be processed by wrapping back to the first value and continuing from there.

Clk specifies the base clock for the frequency modification interval:

0 ≈ 0.96 ms (1041.6 Hz)
1 ≈ 7.68 ms (130.2 Hz)

Interval specifies how long each frequency lasts before being automatically modified. The value exactly represents time in the unit specified by Clk. If Interval is zero, the frequency modification feature is disabled.

If Dir is set while the sweep function is selected, the shifted result is added to the current frequency value. Otherwise, if Dir is clear, the shifted result is subtracted from the current frequency value.

When the sweep function is selected, Shift specifies the number of bits to shift the current frequency value to the right when calculating a new frequency value.

Frequency Modification Procedure

For either frequency modification function, the following procedure takes place for each frequency modification frame as specified by Clk and Interval:

A new frequency value is calculated, but is not yet applied.
If the new frequency value is greater than 2,047:
× The channel is immediately stopped.
Sound is generated for the modification interval.
If Enb is set and Interval is not zero:
The current frequency value is replaced with the previously calculated new frequency value.

When S5INT is written, the current frequency modification frame is reset to the beginning of its interval. The current frequency value itself will not be changed by S5INT, meaning the most recent current frequency value will be used for one frequency modification frame after re-enabling the channel.

If S5SWP is written specifying a new frequency modification interval, and the amount of time since the start of the current frequency modification frame is already greater than the new interval being set, the current frame will continue to be processed using the previous interval. However, if the new interval specifies a time that hasn't been fully processed yet during the current frame, the new interval will take effect immediately.


Noise

Channel 6 produces sound by generating pseudorandom noise. The 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.

Noise generation bits exist in S6EV1 that do not pertain to envelope functionality:

0x01000554 S6EV1 Channel 6 Envelope Specification Register 1
7 6 4 3 2 0
- Tap - (Env)
1 3 2 2
- These bits have no function and are undefined when read.
Tap W Specifies the bit to use in noise generation. (See below)
(Env) * These bits have significance with regards to the envelope feature.

Tap 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:

0 Bit 14 Sequence length of 32,767
1 Bit 10 Sequence length of 1,953
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

Bit positions listed above are zero-based. That is, bit 0 is the bit at position 0x0001 and bit 14 is the bit at position 0x4000.

At the interval specified by the current frequency value, 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.

Noise Procedure

Noise generation begins by initializing the 15-bit shift register to all zeroes. This happens when either S6INT or S6EV1 is written.

For each pseudorandom sample, the following algorithm takes place:

From the shift register, bit 7 (0x0080) is XORed with the bit at Tap and the result inverted to produce a pseudorandom bit.
The value in the register is shifted left one bit.
The pseudorandom bit is used as the new bit 0 of the shift register.
The pseudorandom bit is scaled to 63 to produce the output sample.


Master Control

All channels can be globally controlled through a master control register:

0x01000580 SSTOP Stop All Sound Output Register
7 1 0
-
Stop
7 1
- These bits have no function and are undefined when read.
Stop W When set, stops all active channels.

If Stop is set, all active channels will be disabled. Clearing Stop has no effect.

This register will not prevent sounds from being generated: it only stops active channels. Channels can be restarted without writing a 0 to Stop.


System Reset

System components are initialized in the following ways when the Virtual Boy is powered on.

CPU

The following system registers are initialized on reset:

ECR 0x0000FFF0
PC 0xFFFFFFF0
PSW 0x00008000 [note]

[note] The only bit set in PSW on reset is the NP flag.

All other system registers and all program registers (except r0) are undefined on reset.

Editor's Note: Research is needed to determine whether the cache is initialized during reset.

Communication Port

CCR All fields zero
CCSR All fields set
CDRR 0x00
CDTR 0x00

Game Pad

SCR All fields zero
SDHR 0x00
SDLR 0x00

Timer

Counter 0xFFFF
Reload 0x0000
TCR All fields zero

Because the reload value is loaded into the counter when either of the reload registers is written, reset is the only time when the two figures can have different values.

Wait Controller

WCR All fields zero

VIP

The contents of VIP memory is undefined on reset.

The following fields in I/O registers are initialized on reset:

DPSTTS SYNCE = 0
RE = 0
DISP = 0
INTENB All fields zero
XPSTTS XPEN = 0

All other registers (including INTPND) and other fields within the above registers are undefined on reset.

VSU

Editor's note: The VSU appears to be initialized to all zeroes/disabled on reset, but this hasn't been definitively verified. If nothing else, SSTOP should probably be used on boot.

WRAM

The contents of WRAM are undefined on reset.


About

Virtual Boy - Sacred Tech Scroll
October 20, 2024
Written by Guy Perfect

Produced for Planet Virtual Boy.
https://www.virtual-boy.com/

Special thanks to the following individuals:

Benjamin Stevens
bigmak
blitter
dasi
DogP
enthusi
Gookanheimer
HorvatM
jwestfall
Kevin Mellott
KR155E
Matt Mozingo
MineStorm
optiroc
overlord
SonicSwordcane
The Beesh-Spweesh!
Triverske
Yeti_dude

References

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

Project: Virtual Boy
Website by DogP
Link

The Unofficial Virtual Boy Home Page
Website by David Tucker
Link

IAR Assembler Reference Guide for V850
October 2010
Document No. AV850-4 (fourth edition)
Written by IAR Systems
Download

V830 Family™ 32-bit Microprocessor User's Manual
December 1997
Document No. U12496EJ2V0UM00 (2nd edition)
Written by Renesas Technology Corporation
Download

Unraveling The Enigma Of Nintendo's Virtual Boy, 20 Years Later
August 21, 2015
Article detailing the history of the Virtual Boy's development
Written by Benj Edwards.
Link

And countless hours of original research.


October 20, 2024