XXIIVV

CHIP-8 was created by RCA engineer Joe Weisbecker in 1977 for the COSMAC VIP microcomputer.

The Chip-8 language is capable of accessing up to 4KB(4096 bytes) of RAM, from location 0x000 to 0xFFF(0-4095). The first 512 bytes, from 0x000 to 0x1FF, are where the original interpreter was located, and should not be used by programs.

Registers

RegisterSizeDescription
V[16]byteGeneral purpose
IshortGeneral purpose
PCshortProgram counter
SPbyteStack pointer
DTbyteDelay timer
STbyteSound timer

Keypad

The computers which originally used the Chip-8 Language had a 16-key hexadecimal keypad.

123C
456D
789E
A0BF

Screen

The original implementation of the Chip-8 language used a 64x32-pixel monochrome display. Programs may also refer to a group of sprites representing the hexadecimal digits 0 through F. These sprites are 5 bytes long, or 8x5 pixels. The data should be stored in the interpreter area of Chip-8 memory (0x000 to 0x1FF).

Instructions

CHIP-8 instructions are always 2 bytes long and arranged in big-endian order, that is with the most significant byte first. The original implementation of the Chip-8 language includes 36 different instructions, including math, graphics, and flow control functions.

All instructions are 2 bytes long and are stored most-significant-byte first. In memory, the first byte of each instruction should be located at an even addresses. If a program includes sprite data, it should be padded so any instructions following it will be properly situated in RAM.

OpcodeTypeC PseudoExplanation
0NNNCallCalls machine code routine (RCA 1802 for COSMAC VIP) at address NNN. Not necessary for most ROMs.
00E0Displaydisp_clear()Clears the screen.
00EEFlowreturn;Returns from a subroutine.
1NNNgoto NNN;Jumps to address NNN.
2NNN*(0xNNN)()Calls subroutine at NNN.
3XNNCondif (Vx == NN)Skips the next instruction if VX equals NN. (Usually the next instruction is a jump to skip a code block);
4XNNif (Vx != NN)Skips the next instruction if VX does not equal NN. (Usually the next instruction is a jump to skip a code block);
5XY0if (Vx == Vy)Skips the next instruction if VX equals VY. (Usually the next instruction is a jump to skip a code block);
6XNNConstVx = NSets VX to NN.
7XNNVx += NAdds NN to VX. (Carry flag is not changed);
8XY0AssigVx = VySets VX to the value of VY.
8XY1BitOpVx |= VySets VX to VX or VY. (Bitwise OR operation);
8XY2Vx &= VySets VX to VX and VY. (Bitwise AND operation);
8XY3Vx ^= VySets VX to VX xor VY.
8XY4MathVx += VyAdds VY to VX. VF is set to 1 when there's a carry, and to 0 when there is not.
8XY5Vx -= VyVY is subtracted from VX. VF is set to 0 when there's a borrow, and 1 when there is not.
8XY6BitOpVx >>= 1Stores the least significant bit of VX in VF and then shifts VX to the right by 1.[b]
8XY7MathVx = Vy - VxSets VX to VY minus VX. VF is set to 0 when there's a borrow, and 1 when there is not.
8XYEBitOpVx <<= 1Stores the most significant bit of VX in VF and then shifts VX to the left by 1.[b]
9XY0Condif (Vx != Vy)Skips the next instruction if VX does not equal VY. (Usually the next instruction is a jump to skip a code block);
ANNNMEMI = NNNSets I to the address NNN.
BNNNFlowPC = V0 + NNNJumps to the address NNN plus V0.
CXNNRandVx = rand() & NNSets VX to the result of a bitwise and operation on a random number (Typically: 0 to 255) and NN.
DXYNDispdraw(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
EX9EKeyOpif (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);
EXA1if (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);
FX07TimerVx = get_delay()Sets VX to the value of the delay timer.
FX0AKeyOpVx = get_key()A key press is awaited, and then stored in VX. (Blocking Operation. All instruction halted until next key event);
FX15Timerdelay_timer(Vx)Sets the delay timer to VX.
FX18Soundsound_timer(Vx)Sets the sound timer to VX.
FX1EMEMI += VxAdds VX to I. VF is not affected.[c]
FX29I = 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.
FX33BCD
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 most significant of three digits at the address in I, the middle digit at I plus 1, and the least significant digit at I plus 2. (In other words, take the decimal representation of VX, place the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.);
FX55MEMreg_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]
FX65reg_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 written, but I itself is left unmodified.[d]

incoming uxn devlog