The Vision Game System was a home video game console released by Vision Riders Entertainment in early 1986. It was a part of the third generation of video game consoles, competing directly with the Nintendo Entertainment System, the Sega Master System, and the Atari 7800. The system is believed to have been largely based on the architecture of the Sega Master System, as their technical specs are very similar.

(Note that portions of this page may contradict itself, as it is, and likely always will be, a work in progress.)

Table of Contents

  1. Technical Specifications
  2. Hardware
    1. CPU
    2. Clock Rate Timing
    3. RAM
    4. Memory Map
    5. Peripheral Ports
    6. Game Card
    7. Gamepad
    8. Save Data
  3. Graphics
    1. Registers
    2. VRAM
    3. Character Tables
    4. Palettes and Color Data
    5. Name Table (Tile Map)
    6. Sprites
    7. VRAM DMA
  4. Audio
    1. Channels
    2. Noise Channels
    3. PCM Playback
    4. Audio Registers
    5. YM2413 Comparison
  5. Software
    1. BIOS
    2. ROM Header

Technical Specifications

Hardware

CPU

The Vision Game System is driven by a custom CPU, the VR-2, which is most heavily based on the MOS 6502 used in the NES, Atari 2600, and Commodore 64 personal computer, among others. Like the Ricoh 2A03 variant of the MOS 6502 used in the NES, the VR-2 lacks a binary decimal mode.

The VR-2 is clocked at 3.58MHz in NTSC territories, about twice the speed of the NES's Ricoh 2A03. This gives it the clock speed of the Zilog Z80 used in many other 8-bit consoles like the Sega Master System, combined with the MOS 6502's lower cycles-per-instruction count, giving it a fair bit of processing power. It also addresses and fixes some of the MOS 6502's quirks, and introduces features used by other MOS 6502 variants such as the WDC 65C02. Unlike the MOS 6502, the VR-2 does not map peripherals to RAM space. Instead it communicates with them via IO port instructions akin to the Z80.

Overall, the VR-2's instruction set is completely different than the MOS 6502, and it has slightly different registers and the pin outs. Thus the two are incompatible.

In total, the VR-2 has seven registers, compared to the MOS 6502's six.

Code Name Size
P Program Counter 16 bits
A Accumulator 8 bits
I Iterator 8 bits
X X register 8 bits
Y Y register 8 bits
F Status flags 8 bits
S Stack pointer 8 bits

Program Counter

A 16-bit little endian address pointer. Indicates where the processor is in the program sequence by pointing to the next instruction to execute. The counter is incremented by one after processing each instruction.

Accumulator

The general-purpose register where the results of arithmetic and logic results are stored.

Iterator

A very simple iterator register, not present on the MOS 6502. The iterator can only be incremented by one or reset. It can not be set to an arbitrary value like the other registers.

X Register

The first of the VR-1's two index registers.

Y Register

The second of the VR-1's two index registers.

Stack Pointer

A simple 8-bit pointer to a 256 bytes stack. As in the MOS 6502, the stack is hard-wired to begin at memory address $0100. Care must be taken, as when the stack exceeds 256 bytes, it will overflow.

Status Flages

The VR-2 has an 8-bit status register, which contains bit flags detailing the status of the chip and its operations.

Bit Code Flag Purpose
7 S Sign Flag This is set if the result of an operation is negative, and cleared if it is positive.
6 V Overflow Flag When an arithmetic operation produces a result too large to be represented in a byte, V is set. Used primarily for signed arithmetic.
5      
4 B Break Flag This is automatically set when a software interrupt (break instruction) is executed.
3      
2 I Interrupt Flag If set, interrupts are disabled (masked). Otherwise, interrupts are enabled.
1 Z Zero Flag Indicates that the result of an arithmetic or a logical operation was zero. Perhaps ironically, a value of 1 indicates that the result was 0.
0 C Carry Flag Indicates that a carry took place or is needed for the most significant bit in the most recent arithmetic operation. Used primarily for unsigned arithmetic.

Clock Rate Timing

The VR-2 is clocked at 3.58 MHz in NTSC regions. More exactly, it's 3.579545 MHz, which means there's about 3,579,545 CPU cycles every second.

The console outputs about 60 frames per second in NTSC (it's closer to 59.92 frames per second, less the textbook 59.94 but is still within the display standard's tolerance), this means that there are about 59,659 CPU cycles each frame (ignoring the half a scanline at the end of each frame), and 227 CPU cycles per scanline.

As the console only outputs 224 scanlines, this leaves 38 scanlines for use during the VBlank period. This is the time when the software should disable the video display processor and perform any needed transfers to VRAM, such as uploading the sprite attribute table and updating the tile map. These 38 scanlines (plus the unused half a scanline) totals about 8,740 CPU cycles for use during the VBlank period. A little over 1,024 of these cycles during the VBlank will be burned by transferring the 512 byte sprite attribute table to VRAM, leaving 7,716 cycles for anything else the software wants to do.

The per-frame values work out to about the same thing in PAL, the main difference being that there are only about 59.7 frames per instead of about 59.92.

RAM

The system includes 8KiB of work RAM accessible by the CPU. Game cards can supplement this with additional memory, although most usually make do with system's RAM.

Memory Map

The VR-2 has a 16-bit address range. This table is an overview of how the CPU sees the rest of the system.

Region Size Maps To
$0000 - $1FFF 8 KiB System RAM
$0100 - $01FF 256 bytes VR-2 System Stack (hardwired)
$2000 - $3FFF 8 KiB Game Card RAM (or a mirror of system RAM if there is none)
$4000 - $5FFF 8 KiB Video RAM (bankable)
$6000 - $7FFF 8 KiB ROM (unbankable)
$8000 - $FFFF 32 KiB ROM (four bankable 8KiB pages)

The first 4KiB of ROM space (memory region $6000 - $7FFF) is always mapped to the first 8KiB of the game card (or the first 8KiB of the VGS's internal ROM before control is passed to the game card). The remaining 32 KiB after that are dedicated to the rest of the ROM by way of four bankable 8KiB pages.

The CPU also has direct access to the video RAM via memory region $4000 - $5FFF. This 8KiB area is bankable, and can be switched to either one of the two character tables, or the remaining 4KiB of VRAM where the nametable and sprite attribute table reside. When banked to this 4KiB section of VRAM, the address range $5000 - $5FFF mirrors $4000 - $4FFF.

Anything else that is not used mirrors the system RAM.

Peripheral Ports

The VR-2 can have up to 256 peripherals attached, however the VGS only uses a fraction of that number.

Port Peripheral
$08 ROM Banking ($8000 - $AFFF)
$09 ROM Banking ($A000 - $BFFF)
$0A ROM Banking ($C000 - $DFFF)
$0B ROM Banking ($E000 - $FFFF)
$10 Expansion Port I/O
$20 Game Card Custom Chip I/O
$30 VR-99 Display Processor
$3C VRAM Banking
$3E V Counter
$3F H Count
$70 VR-17 Audio Processor
$FC Gamepad 1
$FD Gamepad 2
$FE Gamepad 3 (or additional accessory data)
$FF Gamepad 2 (or additional accessory data)

Game Card

Vision Game System games are distributed on cartridges officially referred to as "game cards". They were smaller than most contemporary console cartridges, just a little larger the size of a standard audio cassette tape. This made them highly portable and easy to store. However, it also prevented the widespread use of add-on chips. Although the VGS had an interface for the game card to directly access RAM and VRAM, and supplement the CPU and video processor, very few games made use of this because the cards were so small and narrow that it made it hard to fit anything else inside them.

Game card capacity varies, and can be from 4KiB to 4MiB. Most games were in the 128KiB to 768KiB range.

For comparison, a single table worth of uncompressed graphics (256 characters) requires 8KiB of ROM. As such, an 8KiB ROM would not have enough room for a program and a full table worth of graphics. A 4KiB ROM doesn't even have enough room for an entire table of graphics. Thus, ROMs below 32KiB in size are rare, and virtually unused for any games.

However, these small ROMs were occasionally used for test cartridges. Even a 4KiB card used for system calibration was manufactured for developers and retailers.

Gamepad

The Vision Game System uses an 8 button gamepad, common for the era it was released. Data is sent to the console in the following format.

Bit 7 6 5 4 3 2 1 0
Button Start Cancel Select Mode Right Left Down Up

A value of 0 means the button has not been pressed, while 1 means the button has been pressed.

The Vision Game System has ports on the front of the console for two controllers. A multitap accessory was sold which could be plugged into the second player controller port and would allow for a total of four controllers.

Save Data

As opposed to the earlier generations of consoles, which were focused more on bringing arcade titles home, the Vision Game System was designed with larger game experiences in mind, such as those on home computers. However, while personal computers had plenty of storage media (thanks to their much higher cost), consoles were very hampered when it came to ways to store game data, effectively limiting the size and scope of games. Passwords were virtually the only option, but they could only store so much without becoming too long, and they longer they were the harder it was to write them down properly.

Nintendo would initially solve this problem on their own console by using the Famicom Computer Disk System add-on. Eventually they, and Sega, would settle on including battery-backed RAM on the catridge itself for games that needed it. Atari planned to go a different route, using a "High Score Cartridge" that would plug directly into the Atari 7800, with the game mounted on it.

Vision Riders chose a different direction, prefering to put the initial cost up front by including save RAM in the console itself. This made the system more expensive, but the games themselves were cheaper in turn because no additional save RAM was usually required to be manufactured inside the game cards.

The system used 2 KiB of storage memory for this purpose, divided into thrity-two 64 byte “slots” for save game data and high scores. When switched off, the memory was powered by a 9-volt transistor battery stored in a compartment at the bottom of the console. While the console was powered on, this battery could be changed without losing any data. But despite promising several years of battery life in the manual, the console was notorious for losing people's save games. Later builds of the console were better about not randomly losing data, and the manual was changed to encourage owners to change the battery every six to nine months.

Games that need lots of save data generally ignore the internal memory entirely and use their own in-card memory backed by a watch battery.

Graphics

The video display processor of the Vision Game System is the custom VR-99 "Ryder". The VR-99 boasts a wide palette of colors, giving games a bright, colorful look, especially in contrast to the more subdued NES. The chip is on par with the Sega Master System's TMS9918-derived VDP, although it has addition features, such as giving sprites the ability to select from either palette (only tiles may do so on the Master System), and the unique ability to "palette shift", effectively splitting the two 16-color palettes into four psuedo palettes.

Registers

The VR-99 has forty registers that can be written to by the CPU. Of those, thrity-two are used to define the palettes.

  7 6 5 4 3 2 1 0
$00   VBlank Interrupt HBlank Interrupt   Draw Sprites Draw BG   Chip Enable
$01   VScroll Enable HScroll Enable   Sprite Size      
$02                
$03                
$04                
$05                
$06 Vertical Scrolling
$07 Horizontal Scrolling (high byte)
$08 Horizontal Scrolling (low byte)
$08-$17 Palette #1
$18-$27 Palette #2

Chip Enable

When set to 1, the VR-99 will draw to the screen as usual. When set to 0, it will be disabled and only display the most recently cached value of the background color. This can be done in the middle of the frame, if desired.

The chip must be disabled before the CPU can access VRAM. While disabled, the chip will not generate any interrupts.

Draw Background

If set to 0, the nametable will not be displayed to the screen. Only the background color will be drawn.

Draw Sprites

If set to 0, no sprites will be drawn to the screen.

Setting both bits 2 and 3 of register $00 to zero is virtually the same as disabling the chip, but it doesn't give the CPU access to VRAM and doesn't stop the chip from triggering interrupts.

HBlank Interrupt

If set to 1, enables the HBlank maskable interrupt. This is generally set to 0 so that unused interrupts don't eat into the few cycles the CPU gets each scanline, but can be enabled if the program wants to do per-scanline effects like simple parallax scrolling or mid-frame palette changes.

Interrupts are not triggered while the VR-99 is disabled.

VBlank Interrupt

If set to 1, enables the VBlank maskable interrupt. During the VBlank period, the program can disable the VR-99 and begin updating the frame. There is rarely a reason to disable this.

Interrupts are not triggered while the VR-99 is disabled.

Sprite Size

When set to 0, all sprites will be 8×8 pixels in size. Setting the bit to 1 enables 8×16 sprite mode, where each sprite is made up of two characters, one below the other.

Scroll Enable

These two bits enable the scrolling on their given axis when set to 1. Setting them to zero is virtually the same as setting the scroll values to zero.

Palettes

Defines the thirty-two colors of the palettes. These are cached in internal registers at the start of each scanline, so values written on one scanline will not take effect until the next scanline.

VRAM

The Vision Game System has 24 KiB of VRAM dedicated for use by the video display processor, split between two 8 KiB memory chips, and one 4 KiB chip. The CPU has direct access to all 24 KiB of RAM via addresses $4000 through $5FFF, which can be banked between the three 8 KiB sections that make up VRAM. While unusual for a console, this was fairly common for 8-bit computers of the time.

VRAM Bank CPU Address Size Use
1 $4000 - $5FFF 8 KiB Tile Map Character Table
2 $4000 - $5FFF 8 KiB Sprite Character Table
3 $4000 - $41FF 512 bytes Sprite Attribute Table
3 $4200 - $4FFF 3.5 KiB Nametable

The CPU and the display processor share the same bus to VRAM, and only one has access to it at a time. If the VR-99 is active, it has access to VRAM. If the VR-99 is deactivated, the CPU has access to VRAM.

Thus, as RAM cannot be written to while the display processor is active, the character tables, nametable, and sprite attribute table cannot be altered during that time. The VR-99 must first be deactivated, then the software can read or write whatever is needed before reactivating the display processor. Normally this is done during the VBlank period between frames, although the display processor can be disabled during the frame as well. While disabled, the processor will display the background color it cached while still active.

The palettes and scrolling values, however, can be written to at any time, even while the display processor is active, because they are stored in the VR-99's internal registers. The VR-99 caches these values internally during the HBlank period, so any changes made mid-frame will take effect on the next scanline.

Character Tables

All graphics that can be displayed on the screen are stored as 8×8 "characters" in video memory. These characters can be used as sprites, or as entries in the nametable to form the background, depending on which table they're part of. Characters are pulled from the ROM and stored in one of two character tables. One character table is used exclusively by sprites, and the other is used exclusively by the nametable. Each character table contains 256 characters for a total of 512 between them.

Each individual character in the table takes up 32 bytes of data, and is stored planarly. Each plane is stored per-character like the Nintendo Entertainment System, not per-row like the Sega Master System. The first 16 bytes are the least significant bits of each pixel, with three more groups of 16 bytes containting increasingly more significant bits.

Palettes and Color Data

Two palettes are used by the hardware, both of which may be used by the tile map and sprites. However, the Vision Game System can simulate two additional palettes with the use of a unique technique known as "palette shifting". Below is a simulation of all 256 colors available to the system for use in palettes.

All Available Vision Game System 8-bit Colors

Palette Shifting

When a sprite of tile is palette shifted, all colors for the character data will be pulled from the color eight indices higher in the palette. For example, if a pixel is supposed to be color 1, it will be displayed as color 9 instead. 2 will be 11, 3 will be 12, and so on to 8 which wraps back to 0 and continues on to 15 which will appear as color index 7. Note that this is the only way to use color index 0 in the second palette. Since index 8 is being used instead of index 0 for transparency, color 8 becomes the one unavailable to palette shifted sprites.

Colors

Each palette can contain 16 colors from a choice of 256. Each color is 8-bit, using 3 bits each to store the red and green levels, and 2 bits to store the blue level.

Bit 7 6 5 4 3 2 1 0
Color Blue Green Red

For the tile map, the color at index 0 of the first palette is always the background color. This color will fill the overscan portion of the display, and sprites will never appear behind it regardless of priority settings. It is constant, regardless of palette and palette shifting.

For sprites, the color at index 0 is generally ignored, instead indicating transparency. It is only used when sprites are palette shifted, rendering the color at index 8 to be ignored in favor of transparency.

Nametable

The nametable (also sometimes called the "tile map") is a scrollable display matrix of characters displayed to the screen. The visible portion of the display is 32 characters wide and 28 characters tall. However, the actual nametable is considerably larger than this, at 56 tiles wide and 32 tiles tall. The additional portions of the nametable can be set, but will be off the edges of the visible screen and must be scrolled into view.

Each character in the nametable is assigned from the background character table. The characters can be individually flipped both horizontally and vertically, but cannot be rotated. Each entry in the nametable occupies 2 bytes in VRAM, and the entire nametable takes up 3.5KiB of memory.

Data Format

Byte Byte 1 Byte 2
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Function Unused Palette Shift Palette Priority Vertical Flip Horizontal Flip Character Index
Character Index
The index of the character in the tile map character table to use for this tile.
Horizontal Flip
If set to 1, this tile will be flipped horizontally.
Vertical Flip
If set to 1, this tile will be flipped vertically.
Priority
If set to 0, this tile will appear behind sprites. When set to 1, it will appear in front of sprites. (However, sprites have their own priority value that can alter this behaviour in their individual cases.)
Palette
Which of the two palettes to use for this tile. Regardless of palette, a value of zero in the character data for a pixel will always render the background color.
Palette Shift
When this flag is set, the tile will draw its colors from eight positions further into the palette, "wrapping" around at the end. Note that this can cause oddities, as a value of 8 (that is, actual palette color 0) is considered "solid" and will hide sprite pixels displayed behind it. Since palette color 0 is the background color, sprites can appear to hide behind the background color.

Scrolling

The Vision Game System allows for per-pixel scrolling of the tile map. Scrolling is controlled by three registers in the VR-99, one for the vertical coordinate, and two for the horizontal coordinate.

Both the vertical and horizontal scrolling values can be changed between scanlines, which allows for simple split-screen effects such as static status bars. However, splitting the screen vertically this way is impossible, even if very accurate timing was possible. At the beginning of each scanline, the VR-99 caches the scroll values elsewhere and so any changes are not reflected until the next scanline.

Note that sprites ignore tile map scrolling. To make the appear to move along with the tile map, they must be manually moved. Furthermore, sprites outside or partially outside the bounds of the display do not wrap around to the other side.

Bit 7 6 5 4 3 2 1 0
Function Starting Row Fine Scroll

For vertical scrolling, the value is a single byte split into two parts. The upper five bits give the row index in the name table to begin at (0 to 31), while the lower three bits give the starting pixel (0 - 7). Tiles beyond the bounds of the tile map are pulled from the opposite side, giving the illusion of infinite scrolling.

Since the starting row is the row that will appear at the top of the screen, this must be taken into account when changing the value mid-frame. If the starting row is changed, it will not become the starting row of that scanline. The scanline is still positioned in relation to the new top of the "screen".

Byte Byte 1 Byte 2
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Function Unused Starting Column Fine Scroll

Horizontal scrolling is slightly more complex, but works on the same logic. Because the nametable is wider than 32 characters, an additional register is used to add an extra bit to the value. The other seven bits of that register are ignored.

A starting column value of 56 to 63 is treated as a value of 0 to 7. For proper scrolling, the software should manually wrap the value once the starting column exceeds 55, or falls below 0.

Sprites

The Vision Game System has built-in support for 128 hardware sprites, which is twice the amount supported by either the NES or the Master System, allowing for larger and more vibrant graphics. Sprite data is contained in the sprite attribute table (SAT), a 512 byte region of VRAM.

There are two sprite display modes, which are set using a single bit in VRAM. In mode 0, each sprite displays a single 8×8 character from the sprite character table, while in mode 1 each sprite adds a second 8×8 character under the first resulting in a 8×16 sprite. In either case, sprites are usually displayed in groups to create larger objects. (These larger combined objects are sometimes themselves called sprites, especially in colloquial discouse.)

Only 16 sprites can be displayed on a single scanline, however. If more than 16 sprites occupy the same scanline, the extra sprites higher in the index will be ignored for the frame and thus will not be displayed. Again, this is double the amount per scanline supported by the NES or Master System, allowing for even more graphical elements on-screen.

Inter-sprite priority is affected solely by their position in the table. Sprites with higher indices will always appear below those with lower indices.

Sprite Attribute Table Contents

The SAT lists each sprite one after the other, starting with sprite index 0 and ending with sprite index 127.

Each individual sprite is controlled and defined by 4 bytes.

Byte Byte 1 Byte 2 Byte 3 Byte 4
Bit   7 6 5 4 3 2 1 0    
Function Character Unused Vertical Flip Horizontal Flip Palette Shift Palette Priority Scale Y-Coordinate X-Coordinate
Character
Defines the index of the character in the sprite character table that this sprite will use. When in 8×16 sprite mode, the bottom half of the sprite will use the character immediantly following this value.
Vertical Flip
If set to 1, this sprite will be flipped vertically. Its position on screen will be unaffected.
Horizontal Flip
If set to 1, this sprite will be flipped horizontally. Its position on screen will be unaffected.
Palette
Which of the two palettes to use for this sprite.
Palette Shift
When this flag is set, the sprite will be palette shifted. Each pixel will pull its color data from an index eight values higher than normal, "wrapping" around the ends. When a sprite is palette shifted, palette index 8 (referred to as index 0 by the sprite's character data) becomes the transparent color, and cannot be displayed by the sprite.
Priority
A priority value that can be used to further customize how sprites appear in relation to the background. A value of 00 or 11 indicates default behaviour. The sprite will appear above the tile map, except for tiles with their own individual priority flag set. The sprite will be displayed behind these, except for pixels set to the background color (color index 0 in the background palette), simulating transparency. A value of 01 will cause the sprite to appear behind all tiles, regardless of their priority flags, while a value of 10 will cause the sprite to always appear above the tile map. Note that this does not affect inter-sprite priority. Lower index sprites will always appear above higher index sprites, even if they're behind the tile map (creating a masking effect).
Scale
When set to 1, this causes the sprite to be scaled so that each individual pixel from the character table data becomes two pixels wide and two pixels high on-screen.
Y-Coordinate
The sprite's location on the y coordinate. A value of 0 will actually position the sprite at coordinate -8, completely off the top of the screen. A value of 255 will place the sprite at y-coordinate 247, three pixels off the bottom of the screen. Because sprites cannot be disabled, the usual way to make them "disappear" is to position them off the bottom of the screen.
X-Coordinate
The sprite's location on the x coordinate. A value of 0 will actually position the sprite at x-coordinate -4, slightly off the left side of the visible area. This means that, unlike most contemporary consoles, the Vision Game System can display sprites partially off the left side of the screen. The one drawback to this is that this means the sprite can never be displayed further than x-coordinate 251, five pixels sigh of disappearing off the right edge of the display.

VRAM DMA

Although the CPU has direct access to all of VRAM, the fastest way to write to VRAM is by using a DMA operation to copy blocks from RAM. A single DMA operation takes two CPU cycles to read/write a single byte, plus a few extra cycles to begin the operation. Manually doing the same thing would take eight CPU cycles for each read/write, plus any extra cycles needed to perform looping. However, DMA only works going from system RAM to VRAM. It cannot read from ROM, or from any extra RAM provided by the game card. Furthermore, it works in only one direction. You can not DMA a block of memory from VRAM back to RAM. The CPU is held up for the duration of the transfer, and all DMA transfer commands will be ignored while the VR-99 is active.

The VBlank period on the VGS consists of 38.5 scanlines, and is about 8,740 CPU cycles long. During this time, the software can disable the VR-99 and begin transferring data to VRAM. This is the approximate number of CPU cycles it takes to accomplish some of these tasks:

The developers have to decide what they want to accomplish and how best to spend their system RAM and CPU cycles each VBlank to update the display.

Audio

The Vision Game System uses a single custom audio chip for its output, the VR-17 "Ashlyn", capable of FM synthesis and stereo output. While somewhat crude, the chip's FM output gives the system a very warm sound compared to the harsher square wave tones of other consoles in the era.

Similar to the YM2413 by Yamaha used in the Japenese Sega Master System, the VR-17 was created as a budget price alternative to the more expensive FM chips of the day. This was done by cutting features and simplifying internal operation, while still trying to maintain a wide palette of sound (and avoiding Yamaha's tight patent hold on most FM synthesis of the time). The result is an FM synth chip that, unlike the YM2413, maintains a high level of customability. This was important to Vision Riders, ensuring that every game had the chance to sound unique. However, capared to the YM2413, sound quality suffers a bit more due to the specific corners that were cut (and quite possibly to Vision Riders' engineer's lack of experience with the technology compared to Yamaha).

One of the most dramatic cost-cutting measures was to use a completely integer-driven design. The audio chip does not have any a floating point unit, or any other means of using decimal-based math. This gives the chip a bit of a rougher sound than other FM synth chips. Each channel is rendered out to 24-bit internal register before all six channels are accumulated in two 32-bit registers, one for each channel of output (left and right). The final values are then divided by six to return them to 24-bit values, and finally the lower 8 bits are ignored, giving their final 16-bit signed integer outputs to the DAC.

The chip is clocked at ~3.57 MHz (for NTSC) and outputs a new sample every 74 cycles, giving a sample rate of roughly 48,372 Hz.

Channels

The VR-17 has a total of 6 audio channels. The first four channels are capable of frequency modulation synthesis (or, more specifically, phase modulation synthesis) through the use of two operators: a carrier, and a single modulator. An additional two channels are used for noise generation using a built-in pseudo random number generator. One of the noise channels, channel 5, is further capable of rudimentry 4-bit PCM playback.

Envelopes

Simple attack-decay-sustain-release (ADSR) audio envelopes are used by the VR-17. Each envelope is comprised of two bytes.

Byte Byte 1 Byte 2
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Function Attack Decay Sustain Release

Attack specifies how quickly the sound will amplify once "note on" is activated. Decay specifies how quickly the sound will lose amplification after hitting the maximum level. Sustain is the amplification level that the sound will remain at after the attack-decay portion of the envelope, so long as the note is on. Finally, release specifies how quickly the sound will lose amplification after "note off".

If a channel is set to "note off" in the middle of the attack-decay portion of the envelope, and the decay value is lower than release, it will lose amplification at the decay rate, until the sustain level is reached, and then it will use the normal release value. Otherwise, it will always use the release rate.

FM Channels

Internally, each operator has a 32 bit counter used to track the channel's progress through each repetition. This value is incremented each sample by a set integer value using a lookup table for each possible frequency.

Each of the four channels is controlled by a total of ten bytes. Two bytes control basic playback, while another eight determine the channel's tone. When changing "instruments", these eight bytes will thus be the ones copied to.

  Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Byte 1 Note On/Off Panning Channel Volume
Byte 2 Key Fine-Tune
  Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Byte 3                
Byte 4         Carrier Waveform Modulator Waveform
Byte 5   Feedback Value C. Mode Flag Carrier Multiplier
Byte 6 Carrier Attack Carrier Decay
Byte 7 Carrier Sustain Carrier Release
Byte 8 Modulator Intensity M. Mode Flag Modulator Multiplier
Byte 9 Modulator Attack Modulator Decay
Byte 10 Modulator Sustain Modulator Release

Note that the data is grouped by channel in blocks, other than the fact that the two byte playback registers are in a different location than the eight bytes of tone/operator setting registers. Unlike Yamaha-designed FM chips, they are not grouped by function with all the operator data lumped together. This seems to have been a deliberate decision by the engineers to make changing tone settings as easy as doing a continuous eight-byte memory copy from ROM to the chip's registers.

Volume (4 bits)

The master volume setting for the channel. $15 is full volume, and $0 is the lowest volume. Even at $0, however, the channel will still output sound.

Note (6 bits)

Determines the frequency to be played. Channels have a 64-note range, from A1 to C7. Actual frequency is determined from a lookup table and cannot be directly set. Note that even though only 64 notes are available, the audio chip's range can be extended by altering the multipliers of the channel's operators.

Fine-Tune (2 Bits)

This value fine-tunes a channel's frequency, allowing minor slides between notes.

A value of $0 plays the note normally. $1 increases the frequency by 25 cents. $2 increases the frequency by 50 cents (a half note). $3 increases the frequency by 75 cents.

Note On/Off (1 Bit)

This flag toggles the note on and off. When enabled, the operator's envelopes will start at the beginning. When disabled, the envelopes will release.

Panning (3 Bits)

The VR-17 is capable of realtively complex stereo output, given the era it was released, and unlike even many 16-bit consoles and personal computers the audio chip is not limited solely to hard-right or hard-left panning.

These three bits control the channel's panning. A value of $0 or $3 outputs equal volume to both the left and right speaker. A value of $1 outputs exclusively to the left, and $5 exclusively to the right. A value of $2 outputs slightly to the left speaker, but still carries slightly to the right speaker as well, giving a "mid-left" position. Value $4 works the same way to give a "mid-right" position.

Note that the chip's panning method is somewhat crude and different panning values may alter the audible volume of the channel's output.

Intensity (4 bits)

This is the modulation index. It controls how much of an effect the modulator will have on the carrier. This, in turn, controls the tone of the channel's sound. At $0, the modulator has virtually no effect on the operator.

Feedback (3 bits)

Controls the amount of feedback. Feedback can be used to create more complex and interesting tones. At $0, there is no feedback.

Each sample, the modulator's output is saved to an internal register. The value will then be fed back into the modulator the next sample, shifting its phase the same way the modulator shifts the phase of the carrier. Sufficently high feedback can create noise.

Envelope Mode Flag (1 Bit)

This flag toggles the envelope mode. When set to 1, the envelope will act in "percusive mode". In percussive mode, the envelope will enter the release phase of the envelope immediantly after hitting the sustain level. Instead of continuing at the normal release speed when the channel's key on flag is disabled, the release speed is doubled.

This mode can be useful for simulating the tones of instruments like a piano or guitar, as well as for making percussion sounds using the FM channels.

Noise Channels

Channels five and six are play white noise at a number of frequencies, using an internal 16-bit linear-feedback shift register as a pseudo-random number generator. The VR-17's reliance on harsh noise generation in an FM synth chip contributes to its unique sound.

Each noise channel is controlled by a single byte. Notice that there is no note on/off. Internally, the noise channels are always spitting out data. To "stop" a noise channel, the volume must be set to $0. Unlike the tonal channels, this value will in fact silence the channel.

Period (4 bits)

This value sets how often the channel will poll for a new sample from the LFSR. A lookup table is used to determine the exact length of each period. Higher values set a higher frequency.

Volume (4 bits)

The master volume setting for the channel. $15 is full volume, and $0 is the lowest volume. Even at $0, however, the channel will still output sound.

PCM Playback

Channel five of the VR-17, the first of the two noise channels, can be used to play 4-bit PCM samples. Only channel five is capable of this.

To initiate PCM mode, a flag must be enabled in the audio chip's registers. When this flag is set, noise playback will be replaced with PCM audio playback. The channel's frequency will be applied to playback, meaning that it can be used as an instrument. Unlike the NES APU's DMC, playback at all frequencies are in-tune (or, at least as much as everything else).

In PCM playback mode, channel 5 uses two additional bytes. The first is address of the PCM clip to play in system RAM, starting at address $C000, and in increments of 64 bytes per single increase in value. The second is the length of the clip in samples, in increments of 16 per single increase in value.

PCM playback has a range of 16 notes, controlled by the four bits that set channel 5's period value in noise mode. A value of $00 is tuned to be an A, and at this value playback is 4,400 Hz (4,400 samples a second). For a single second of playback at that rate, about 2.2KiB are needed. When simply playing back audio such as voice clips, the frequency value should generally be left at either $00 (4,400 Hz) or $12 (8,800 Hz, for higher quality samples) to perform playback at the intended speed. Since the other values are tuned to musical notes, they have awkward playback rates which are less useful.

VR-17 Registers

The VR-17 has a total of 48 registers that can be accessed from the CPU. The VR-17 is write-only. The VGS's CPU is unable to read from the VR-17.

  7 6 5 4 3 2 1 0
$00             Reset Chip Enable
$01                
$02 - $09 FM Channel Playback
$10 - $11 Noise Channels
$12 - $43 FM Instrument Data
$44 - $47 PCM Playback Data

Chip Enable (1 bit)

This flag enables or disables input to the chip. Setting it to zero is virtually the same as setting the noise channels' volume and all the FM channels' note-on values to zero. It does not actually silence the chip, as it will continue any remaining ADSR envelopes that have yet to finish. While the chip is disabled, the CPU can only write to bytes $00 and $01. Any other operations will be ignored.

Reset (1 bit)

Setting this value to one will reset all instrument and playback data to its default state.

YM2413 Comparison

As already noted, the VR-17 can be quite closely compared to the Yamaha YM2413. Both are FM synthesizers created with reduced production costs in mind, both have channels limited to a single carrier and a single modulator, and both have noticable limitations compared to contemporary FM synth chips.

The most striking difference is the fact that the VR-17 allows game developers to customize all four FM channels with their own instrument settings. The YM2413 has nine channels, three more than the VR-17, but it only allows one user-defined instrument at a time. Channels on the YM2413 may select from the user-defined instrument or one of fifteen predefined instruments.

The YM2413 also has a "rythm mode". When enabled, three channels are switched from tone generation to percussion, leaving only six channels for melody. There are a total of five percussion sounds available: bass drum, snare drum, tom-tom, top cymbal, and high hat. The VR-17 doesn't need a rythm mode, because all of the channels can be customized.

The VR-17 also lacks a few of the features of the YM2413. The YM2413 has two basic waveforms for used by its operators: a sine and a rectified sine. The VR-17 only has a sine. The two chips also handle feedback differently. The VR-17 favors lower amounts of feedback for a wider range of melodic tones, at the cost of more percussive sounds. To make up for this, the VR-17 has two channels that can independantly switch to white noise generation.

Finally, as the VR-17 was designed from the ground up with a console in mind, it includes the ability to play 4-bit PCM samples on one of its channels. The YM2413 lacks this ability altogether.

Software

BIOS

The Vision Game System has 16KiB of boot ROM inside the system used for the BIOS. This includes a simple “operating system” for managing the save RAM slots, along with some other basic functions like a calculator and calendar. The operating system is accessed by powering up the console without a game card in the slot, or by holding the Mode Button at the boot screen.

ROM Header

Every game card contains header information in the ROM that is checked by the BIOS at startup. The header is used primarily as a santiy-check, to make sure the data being accesed is meant for the system, but is also used by the console's "operating system". The header was unusually large for consoles of the time, occupying a total of 30 bytes at the beginning of the ROM.

File Signature (4 bytes)

The first four bytes of the header must be "VGS " encoded in ASCII. In hex this is $56 $47 $53 $20.

If this exact string is not present, the BIOS will display an "invalid game card" error and the software will not be run.

Checksum (2 bytes)

The ROM checksum immediantly follows the file signature and is stored in little-endian format. The BIOS will calculate the checksum and compare it against the stored value to determine if the ROM data is valid. If the two values do not match, the "invalid game card" error will be displayed by the BIOS.

The checksum is simply the 16-bit sum of every byte in the ROM (other than the header) added together.

Calculating the checksum depends on the value for ROM size.

Region (1 nibble)

The high nibble of the next byte contains the region code, describing the software's intended release region.

Value Region
$0 International
$1 North America (US and Canada)
$2 Mexico and Latin America
$3 Europe (UK, Ireland)
$4 Europe (Germany)
$5 Europe (France)
$6 Europe (Spain)
$7 Europe (Italy)
$8 Europe (Other)
$9 Japan
$A Korea

The Vision Game System never implemented region protection, so the software will run regardless of region. The region information is primarily used by the operating system to correctly format the game title. Games from other regions may or may not display their title correctly, depending on the font of a given VGS's internal OS.

ROM Size (1 nibble)

The low nibble of the byte contains a code describing the total size of the ROM. This value must be correct, or else the system may refuse to properly map parts of the ROM beyond the size limit.

Value ROM Size
$0 4 KiB
$1 8 KiB
$2 16 KiB
$3 24 KiB
$4 32 KiB
$5 48 KiB
$6 64 KiB
$7 128 KiB
$8 256 KiB
$9 384 KiB
$A 512 KiB
$B 768 KiB
$C 1 MiB
$D 1.5 MiB
$E 2 MiB
$F 4 MiB

Software Code (2 bytes)

Little-endian encoded 4 character software code, with each character consisting of 4 nibbles. The first three characters are always a digit, while the last character is a letter from A to P. The software code identifies the game and should match the code printed on the label of the game card itself. The code is printed using the format X-XX-X.

As an example, value $82 $57 is considered to be code 5-78-B.

Software Title (16 bytes)

Sixteen character software title, padded by spaces at the end. Formatting is determined by region code. Most regions (including "International") use ASCII. In order to fit in the space provided, the software title may be truncated or slightly different from the game's actual title.

Build Date Year (2 Bytes)

Little-endian encoded 4 character year. Value $54 $13 would be 1984.

Build Date Month (1 nibble)

The high nibble of the next byte gives the build date month. $1 is Janurary, $2 is February, $3 is March, and so on to $B for December. All other values, including $0 are unused.

Version Number (1 Nibble)

The low nibble of the byte is the version number. Generally starts at $0 for the initial release, and is increased by one for each rerelease that includes changes or bug fixes. Reprints of game cards without changes may rarely increase the version number for no real reason.

Start of Graphics Data (2 Bytes)

An unsigned, little-endian encoded value that informs the video chip where the graphics data begins in the ROM. Because of how the Vision Game System's chip pulls data, the graphics need to be contained sequentially starting at the given address. They must also begin somewhere in the first 65536 bytes of the ROM, as this is only a 16-bit value.