CHIP-8

From Wikipedia, the free encyclopedia
Screenshot of Pong implemented in CHIP-8
Telmac 1800 running CHIP-8 game Space Intercept (Joseph Weisbecker, 1978)

CHIP-8 is an interpreted programming language, developed by Joseph Weisbecker on his 1802 Microprocessor. It was initially used on the COSMAC VIP and Telmac 1800 8-bit microcomputers in the mid-1970s. CHIP-8 programs are run on a CHIP-8 virtual machine. It was made to allow video games to be more easily programmed for these computers. The simplicity of CHIP-8, and its long history and popularity, has ensured that CHIP-8 emulators and programs are still being made to this day.

Roughly fifteen years after CHIP-8 was introduced, derived interpreters appeared for some models of graphing calculators (from the late 1980s onward, these handheld devices in many ways have more computing power than most mid-1970s microcomputers for hobbyists).

An active community of users and developers existed in the late 1970s, beginning with ARESCO's "VIPer" newsletter whose first three issues revealed the machine code behind the CHIP-8 interpreter.[1]

CHIP-8 applications[edit]

There are a number of classic video games ported to CHIP-8, such as Pong, Space Invaders, Tetris, and Pac-Man. There are also applications like a random maze generator and Conway's Game of Life.

CHIP-8 extensions and variations[edit]

During the 1970s and 1980s, CHIP-8 users shared CHIP-8 programs, but also changes and extensions to the CHIP-8 interpreter, in the COSMAC VIP users' newsletter, VIPER magazine. These extensions included CHIP-10 and Hi-Res CHIP-8, which introduced a higher resolution than the standard 64x32, and CHIP-8C and CHIP-8X, which extended the monochrome display capabilities to support limited color, among other features.[2] These extensions were mostly backwards compatible, as they were based on the original interpreter, although some repurposed rarely used opcodes for new instructions.[3]

In 1979, Electronics Australia ran a series of articles on building a kit computer similar to the COSMAC VIP, based on the Motorola 6800 architecture.[4] This computer, the DREAM 6800, came with its own version of CHIP-8. A newsletter similar to VIPER, called DREAMER[5], was used to share CHIP-8 games for this interpreter. In 1981, Electronics Today International (ETI) ran a series of articles on building a computer, the ETI-660, which also was very similar to the VIP (and used the same microprocessor). ETI ran regular ETI-660 and general CHIP-8 columns[6] until 1985.

In 1990, a CHIP-8 interpreter called CHIP-48 was made for HP-48 graphing calculators so games could be programmed more easily. Erik Bryntse later created another interpreter based on CHIP-48, called SCHIP, S-CHIP or Super-Chip. SCHIP extended the CHIP-8 language with a larger resolution and several additional opcodes meant to make programming easier.[7] If it were not for the development of the CHIP-48 interpreter, CHIP-8 would not be as well known today.[citation needed]

David Winter's emulator, disassembler, and extended technical documentation popularized CHIP-8/SCHIP on many other platforms. It laid out a complete list of undocumented opcodes and features[8], and was distributed across many hobbyist forums. Many emulators used these works as a starting point.

However, CHIP-48 subtly changed the semantics of a few of the opcodes, and SCHIP continued to use those new semantics in addition to changing other opcodes. Many online resources about CHIP-8 propagate these new semantics, so many modern CHIP-8 games are not backwards compatible with the original CHIP-8 interpreter for the COSMAC VIP, even if they do not specifically use the new SCHIP extensions.[9]

CHIP-8 today[edit]

There is a CHIP-8 implementation for almost every platform, as well as some development tools. Games are still being developed and cataloged for CHIP-8 today, in addition to older games resurfacing online in digital archives.[10][11]

While CHIP-8 and SCHIP have commonly been implemented as emulators, a pure hardware implementation (written in the Verilog language) also exists for certain FPGA boards.

Virtual machine description[edit]

Memory[edit]

CHIP-8 was most commonly implemented on 4K systems, such as the Cosmac VIP and the Telmac 1800. These machines had 4096 (0x1000) memory locations, all of which are 8 bits (a byte) which is where the term CHIP-8 originated. However, the CHIP-8 interpreter itself occupies the first 512 bytes of the memory space on these machines. For this reason, most programs written for the original system begin at memory location 512 (0x200) and do not access any of the memory below the location 512 (0x200). The uppermost 256 bytes (0xF00-0xFFF) are reserved for display refresh, and the 96 bytes below that (0xEA0-0xEFF) were reserved for the call stack, internal use, and other variables.

In modern CHIP-8 implementations, where the interpreter is running natively outside the 4K memory space, there is no need to avoid the lower 512 bytes of memory (0x000-0x1FF), and it is common to store font data there.

Registers[edit]

CHIP-8 has 16 8-bit data registers named V0 to VF. The VF register doubles as a flag for some instructions; thus, it should be avoided. In an addition operation, VF is the carry flag, while in subtraction, it is the "no borrow" flag. In the draw instruction VF is set upon pixel collision.

The address register, which is named I, is 12 bits wide and is used with several opcodes that involve memory operations.

The stack[edit]

The stack is only used to store return addresses when subroutines are called. The original RCA 1802 version allocated 48 bytes for up to 12 levels of nesting;[12] modern implementations usually have more.[13][14]

Timers[edit]

CHIP-8 has two timers. They both count down at 60 hertz, until they reach 0.

  • Delay timer: This timer is intended to be used for timing the events of games. Its value can be set and read.
  • Sound timer: This timer is used for sound effects. When its value is nonzero, a beeping sound is made. Its value can only be set.

Input[edit]

Input is done with a hex keyboard that has 16 keys ranging 0 to F. The '8', '4', '6', and '2' keys are typically used for directional input. Three opcodes are used to detect input. One skips an instruction if a specific key is pressed, while another does the same if a specific key is not pressed. The third waits for a key press, and then stores it in one of the data registers.

Graphics and sound[edit]

Original CHIP-8 Display resolution is 64×32 pixels, and color is monochrome. Graphics are drawn to the screen solely by drawing sprites, which are 8 pixels wide and may be from 1 to 15 pixels in height. Sprite pixels are XOR'd with corresponding screen pixels. In other words, sprite pixels that are set flip the color of the corresponding screen pixel, while unset sprite pixels do nothing. The carry flag (VF) is set to 1 if any screen pixels are flipped from set to unset when a sprite is drawn and set to 0 otherwise. This is used for collision detection.

As previously described, a beeping sound is played when the value of the sound timer is nonzero.

Opcode table[edit]

CHIP-8 has 35 opcodes, which are all two bytes long and stored big-endian. The opcodes are listed below, in hexadecimal and with the following symbols:

  • NNN: address
  • NN: 8-bit constant
  • N: 4-bit constant
  • X and Y: 4-bit register identifier
  • PC : Program Counter
  • I : 12bit register (For memory address) (Similar to void pointer);
  • VN: One of the 16 available variables. N may be 0 to F (hexadecimal);

There have been many implementations of the CHIP-8 instruction set since 1978. The following specification is based on the SUPER-CHIP specification from 1991 (but without the additional opcodes that provide extended functionality), as that is the most commonly encountered extension set today. Footnotes denote incompatibilities with the original CHIP-8 instruction set from 1978.

Opcode Type C Pseudo Explanation
0NNN Call Calls machine code routine (RCA 1802 for COSMAC VIP) at address NNN. Not necessary for most ROMs.[13]
00E0 Display disp_clear() Clears the screen.[13]
00EE Flow return; Returns from a subroutine.[13]
1NNN Flow goto NNN; Jumps to address NNN.[13]
2NNN Flow *(0xNNN)() Calls subroutine at NNN.[13]
3XNN Cond if (Vx == NN) Skips the next instruction if VX equals NN (usually the next instruction is a jump to skip a code block).[13]
4XNN Cond if (Vx != NN) Skips the next instruction if VX does not equal NN (usually the next instruction is a jump to skip a code block).[13]
5XY0 Cond if (Vx == Vy) Skips the next instruction if VX equals VY (usually the next instruction is a jump to skip a code block).[13]
6XNN Const Vx = NN Sets VX to NN.[13]
7XNN Const Vx += NN Adds NN to VX (carry flag is not changed).[13]
8XY0 Assig Vx = Vy Sets VX to the value of VY.[13]
8XY1 BitOp Vx |= Vy Sets VX to VX or VY. (bitwise OR operation).[13]
8XY2 BitOp Vx &= Vy Sets VX to VX and VY. (bitwise AND operation).[13]
8XY3[a] BitOp Vx ^= Vy Sets VX to VX xor VY.[13]
8XY4 Math Vx += Vy Adds VY to VX. VF is set to 1 when there's an overflow, and to 0 when there is not.[13]
8XY5 Math Vx -= Vy VY is subtracted from VX. VF is set to 0 when there's an underflow, and 1 when there is not. (i.e. VF set to 1 if VX >= VY and 0 if not).[13]
8XY6[a] BitOp Vx >>= 1 Stores the least significant bit of VX in VF and then shifts VX to the right by 1.[b][13]
8XY7[a] Math Vx = Vy - Vx Sets VX to VY minus VX. VF is set to 0 when there's an underflow, and 1 when there is not. (i.e. VF set to 1 if VY >= VX).[13]
8XYE[a] BitOp Vx <<= 1 Stores the most significant bit of VX in VF and then shifts VX to the left by 1.[b][13]
9XY0 Cond if (Vx != Vy) Skips the next instruction if VX does not equal VY. (Usually the next instruction is a jump to skip a code block).[13]
ANNN MEM I = NNN Sets I to the address NNN.[13]
BNNN Flow PC = V0 + NNN Jumps to the address NNN plus V0.[13]
CXNN Rand Vx = rand() & NN Sets VX to the result of a bitwise and operation on a random number (Typically: 0 to 255) and NN.[13]
DXYN Display draw(Vx, Vy, N) Draws a sprite at coordinate (VX, VY) that has a width of 8 pixels and a height of N pixels. Each row of 8 pixels is read as bit-coded starting from memory location I; I value does not change after the execution of this instruction. As described above, VF is set to 1 if any screen pixels are flipped from set to unset when the sprite is drawn, and to 0 if that does not happen.[13]
EX9E KeyOp if (key() == Vx) Skips the next instruction if the key stored in VX is pressed (usually the next instruction is a jump to skip a code block).[13]
EXA1 KeyOp if (key() != Vx) Skips the next instruction if the key stored in VX is not pressed (usually the next instruction is a jump to skip a code block).[13]
FX07 Timer Vx = get_delay() Sets VX to the value of the delay timer.[13]
FX0A KeyOp Vx = get_key() A key press is awaited, and then stored in VX (blocking operation, all instruction halted until next key event).[13]
FX15 Timer delay_timer(Vx) Sets the delay timer to VX.[13]
FX18 Sound sound_timer(Vx) Sets the sound timer to VX.[13]
FX1E MEM I += Vx Adds VX to I. VF is not affected.[c][13]
FX29 MEM I = sprite_addr[Vx] Sets I to the location of the sprite for the character in VX. Characters 0-F (in hexadecimal) are represented by a 4x5 font.[13]
FX33 BCD
set_BCD(Vx)
*(I+0) = BCD(3);
*(I+1) = BCD(2);
*(I+2) = BCD(1);
Stores the binary-coded decimal representation of VX, with the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.[13]
FX55 MEM reg_dump(Vx, &I) Stores from V0 to VX (including VX) in memory, starting at address I. The offset from I is increased by 1 for each value written, but I itself is left unmodified.[d][13]
FX65 MEM reg_load(Vx, &I) Fills from V0 to VX (including VX) with values from memory, starting at address I. The offset from I is increased by 1 for each value read, but I itself is left unmodified.[d][13]

Notes[edit]

  1. ^ a b c d The logical opcodes 8XY3, 8XY6, 8XY7 and 8XYE were not documented in the original CHIP-8 specification, as all the 8000 opcodes were dispatched to instructions in the 1802's ALU, and not located in the interpreter itself; these four additional opcodes were therefore presumably unintentional functionality.
  2. ^ a b CHIP-8's opcodes 8XY6 and 8XYE (the bit shift instructions), which were in fact undocumented opcodes in the original interpreter, shifted the value in the register VY and stored the result in VX. The CHIP-48 and SCHIP implementations instead ignored VY, and simply shifted VX.[9]
  3. ^ Most CHIP-8 interpreters' FX1E instructions do not affect VF, with one exception: the CHIP-8 interpreter for the Commodore Amiga sets VF to 1 when there is a range overflow (I+VX>0xFFF), and to 0 when there is not.[15] The only known game that depends on this behavior is Spacefight 2091!, while at least one game, Animal Race, depends on VF not being affected.
  4. ^ a b In the original CHIP-8 implementation, and also in CHIP-48, I is left incremented after this instruction had been executed. In SCHIP, I is left unmodified.

See also[edit]

References[edit]

  1. ^ "VIPER for RCA VIP owner". Intelligent Machines Journal (InfoWorld). InfoWorld Media Group. 1978-12-11. p. 9. Retrieved 2010-01-30.
  2. ^ https://github.com/mattmikolay/chip-8/wiki/CHIP%E2%80%908-Extensions-Reference
  3. ^ https://github.com/trapexit/chip-8_documentation
  4. ^ https://archive.org/stream/EA1979/EA%201979-05%20May#page/n85/mode/2up
  5. ^ https://archive.org/details/dreamer_newsletter_01/mode/2up
  6. ^ https://archive.org/stream/ETIA1981/ETI%201981-11%20November#page/n113/mode/2up
  7. ^ https://github.com/Chromatophore/HP48-Superchip
  8. ^ http://vanbeveren.byethost13.com/stuff/CHIP8.pdf
  9. ^ a b https://github.com/JohnEarnest/Octo/blob/gh-pages/docs/SuperChip.md#compatibility
  10. ^ https://johnearnest.github.io/chip8Archive/
  11. ^ https://rcastudio2.blogspot.com/
  12. ^ RCA COSMAC VIP CDP18S711 Instruction Manual. Somerville: RCA Solid State Division. 1978. p. 36.
  13. ^ a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah ai aj Greene, Thomas P. (1997-08-30). "Cowgod's Chip-8 Technical Reference". devernay.free.fr. Archived from the original on 2024-01-03. Retrieved 2020-02-03.
  14. ^ Mikolay, Matthew. "Mastering CHIP-8 : Subroutines". mattmik.com. Retrieved 2020-02-03.
  15. ^ "FX1E and VF · Issue #2 · Chromatophore/HP48-Superchip · GitHub". GitHub.

Further reading[edit]

  • "RCA COSMAC VIP CDP18S711 Instruction Manual," RCA Solid State Division, Somerville, NJ 08776, February 1978. Part VIP-311. pp. 13–18, 35–37.
  • BYTE magazine, December 1978, pp. 108–122. "An Easy Programming System," by Joseph Weisbecker. Describes CHIP-8 with specific example of a rocketship and UFO shooting-gallery game.
  • Archive of Chip8.com Website dedicated to CHIP-8 and related systems. Maintains the most complete collection of CHIP-8 programs on the net.
  • Mastering CHIP-8, an accurate reference to the original CHIP-8 instruction set
  • David Winter's CHIP-8 Emulator, utilities and games.
  • BytePusher A minimalist virtual machine inspired by the CHIP-8.
  • RCA COSMAC group on Yahoo, with authorized scans of the VIPER magazine.
  • OChip8 A CHIP-8 emulator in a browser
  • Dream 6800 The popular Dream 6800 Microcomputer featured in Electronics Australia in 1979 ran CHIP-8.
  • FPGA SuperChip A Verilog implementation of the SCHIP specification.
  • Octo is an Online CHIP-8 IDE, Development System, Compiler/Assembler and Emulator, with a proprietary scripting language
  • Cowgod's Chip-8 Technical Reference (CHIP-48/SCHIP)
  • Matt Mikolay CHIP-8 Extensions Reference
  • CHIP-8.com CHIP-8 Classic Computer Manual