remstart

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

remend

////////////////////////////////////////////////////////////////////////////////////////////// 1 // 0x0FFF
//  Calls RCA 1802 program at address NNN. Not necessary for most ROMs. 
//  opcode 1 is barely used in any rom and most emulators skip it
function opcode_0NNN()
    print("Calls RCA 1802 program at address NNN. Not necessary for most ROMs.  ")
    sync()
    sleep (1000)
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 2 // 0x00E0
//  Clears the screen. 
function opcode_00E0()
    undim gfx[]
    global dim gfx[32*64]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 3 // 0x00EE
//  Returns from a subroutine. 
function opcode_00EE()
    dec stack_pointer
    Program_counter = stack[stack_pointer]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 4 // 0x1000
//  Jumps to address NNN. 
function opcode_1NNN()
    Program_counter = opcode && NNN
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 5 // 0x2000
//  Calls subroutine at NNN. 
function opcode_2NNN()
    inc stack_pointer
    stack[stack_pointer] = Program_counter
    Program_counter = opcode && NNN
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 6 // 0x3000
//  Skips the next instruction if VX equals NN. 
function opcode_3XNN()
    if V[ vx ] = opcode && NN then inc Program_counter,2
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 7 // 0x4000
//  Skips the next instruction if VX doesn't equal NN. 
function opcode_4XNN()
    if V[ vx ] <> (opcode && NN) then inc Program_counter,2
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 8 // 0x5000
// Skips the next instruction if VX equals VY. 
function opcode_5XY0()
    if V[ vx ] = v[ vy ] then inc Program_counter,2
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 9 // 0x6000
// Sets VX to NN. 
function opcode_6XNN()
    V[ vx ] = opcode && NN
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 10 // 0x7000
// Adds NN to VX. 
function opcode_7XNN()
    V[ vx ] = (V[ vx ] + (opcode && val("0x0FF",Read_as_Hex))) && NN
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 11 // 0x8000
// Sets VX to the value of VY. 
function opcode_8XY0()
    V[ vx ] = V[ vy ]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 12 0x8001
// Sets VX to VX or VY.
function opcode_8XY1()
    V[ vx ] = V[ vx ] || V[ vy ]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 13 // 0x8002
// Sets VX to VX and VY.
function opcode_8XY2()
    V[ vx ] = V[ vx ] && V[ opcode && val("0x0F0",Read_as_Hex) >>4 ]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 14 // 0x8003
// Sets VX to VX xor VY.
function opcode_8XY3()
    V[ vx ] = exclusive_or(V[ vx ],V[ vy ])   //V[ vx ] ~~ V[ vy ] ?
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 15 // 0x8004
// Adds VY to VX. VF is set to 1 when there's a carry, and to 0 when 
// there isn't.
function opcode_8XY4()
    if (V[ vx ] + V[ vy ]) > val("0xFF",Read_as_Hex)
       V[val("0xF",Read_as_Hex)] = 1
    else
	   V[val("0xF",Read_as_Hex)] = 0
	   // V[ vx ] = (V[ vx ] + V[ vy ]) && val("0xFF",Read_as_Hex) ?
	endif
       
    V[ vx ] = (V[ vx ] + V[ vy ]) && val("0xFF",Read_as_Hex)
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 16 // 0x8005
// VY is subtracted from VX. VF is set to 0 when there's a borrow, and 1 
// when there isn't.
function opcode_8XY5()
    if V[vx] > V[vy]
	   V[val("0xF",Read_as_Hex)] = 1
	else
	   V[val("0xF",Read_as_Hex)] = 0
	   //V[vx] = (V[vx] - V[vy]) && val("0xFF",Read_as_Hex) ?
    endif
       
    V[vx] = (V[vx] - V[vy]) && val("0xFF",Read_as_Hex)
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 17 // 0x8006
remstart
   8XY6 ( Extra note )
   On the original interpreter, the value of VY is shifted, 
   and the result is stored into VX. On current implementations, 
   Y is ignored.
remend
// Shifts VX right by one. VF is set to the value of the least significant 
// bit of VX before the shift.
function opcode_8XY6()
    V[val("0xF",Read_as_Hex)] = V[ opcode && vx ] && val("0x1",Read_as_Hex)
    V[ opcode && vx ] = V[ opcode && vx ] >>1
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 18 // 0x8007
// Sets VX to VY minus VX. VF is set to 0 when there's a borrow, and 1 
// when there isn't.
function opcode_8XY7()
    if V[ (opcode && val("0x0F00",Read_as_Hex)) >>8 ] > V[ (opcode && val("0x00F0",Read_as_Hex)) >>4 ]	// VY-VX
	   V[val("0xF",Read_as_Hex)] = 0 
    else
	   V[val("0xF",Read_as_Hex)] = 1
	   //V[ (opcode && val("0x0F00",Read_as_Hex)) >>8  ] = V[ (opcode && val("0x00F0",Read_as_Hex)) >>4 ] - V[ vx ]
    endif
       
    V[ (opcode && val("0x0F00",Read_as_Hex)) >>8  ] = V[ (opcode && val("0x00F0",Read_as_Hex)) >>4 ] - V[ vx ]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 19 // 0x800E
remstart
   8XYE ( Extra note )
   On the original interpreter, the value of VY is shifted, 
   and the result is stored into VX. On current implementations, 
   Y is ignored.
remend
// Shifts VX left by one. VF is set to the value of the most significant 
// bit of VX before the shift.[
function opcode_8XYE()
    V[val("0xF",Read_as_Hex)] = V[ (opcode && val("0x0F00",Read_as_Hex)) >>8 ] >>7
	V[ (opcode && val("0x0F00",Read_as_Hex)) >>8 ] = V[ (opcode && val("0x0F00",Read_as_Hex)) >>8 ] <<1
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 20 // 0x9000
// Skips the next instruction if VX doesn't equal VY.
function opcode_9XY0()
    if V[ vx ] <> V[ vy ] then inc Program_counter,2
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 21 // 0xA000
// Sets I to the address NNN.
function opcode_ANNN()
    Index_register = opcode && NNN
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 22 // 0xB000
// Jumps to the address NNN plus V0.
function opcode_BNNN()
    Program_counter = (opcode && NNN )+V[0]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 23 // 0xC000
// Sets VX to the result of a bitwise and operation on a random number and NN.
function opcode_CXNN()
    V[ vx ] = random(0,256) && (opcode && val("0x0FF",Read_as_Hex))
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 24 // 0xD000
// 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 doesn’t 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 doesn’t happen
function opcode_DXYN()
    x = V[(opcode && val("0x0F00",Read_as_Hex)) >> 8]
    y = V[(opcode && val("0x00F0",Read_as_Hex)) >> 4]
	height = opcode && val("0x000F",Read_as_Hex)
	 
	pixel = 0
	V[val("0xF",Read_as_Hex)] = 0
	for yline = 0 to height-1
	    pixel = memory[Index_register + yline]
	    for xline = 0 to 8
			if (pixel && (val("0x80",Read_as_Hex) >> xline)) <> 0
			   b=(x + xline + ((y + yline) * 64))  // some roms spike it over 16 000 ?
			   // if b>lcd or b<0 then Message( str(b)+"  "+str(height) )
			   // if b>lcd then b=b/((y+yline)*64)
			   if gfx[ b ] = 1 then v[val("0xF",Read_as_Hex)] = 1                                   
			   /////////////////////////////////////////////////////
	           //The bitwise ^ operator performs a bitwise exclusive OR operation
	           gfx[x + xline + ((y + yline) * 64)] = gfx[x + xline + ((y + yline) * 64)] ~~ 1
	           //gfx[b]=exclusive_or(gfx[b],1)
			endif
	    next xline
    next yline
    drawFlag = true		
    
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 25 // 0xE09E
// Skips the next instruction if the key stored in VX is pressed.
function opcode_EX9E()
    if key[ V[ vx ] ] = true then inc Program_counter,2
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 26 // 0xE0A1
// Skips the next instruction if the key stored in VX isn't pressed.
function opcode_EXA1()
    if key[ V[ vx ] ] = false then inc Program_counter,2
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 27 // 0xF007
// Sets VX to the value of the delay timer.
function opcode_FX07()
    V[ vx ] = delay_timer && val("0xFF",Read_as_Hex)
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 28 // 0xF00A
// A key press is awaited, and then stored in VX.
function opcode_FX0A()
    keyPress = false
	kp=0
    while keyPress = false
          if key[kp] > false
	         V[ (opcode && val("0x0F00",Read_as_Hex)) >>8 ] = kp
		     keyPress = true
		  endif
		  inc kp
		  if kp>16 then kp = 0
	endwhile // if no key is pressed, return and try again
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 29 // 0xF015
// Sets the delay timer to VX.
function opcode_FX15()
    delay_timer = V[ vx ]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 30 // 0xF018
// Sets the sound timer to VX.
function opcode_FX18()
    sound_timer = V[ vx ]
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 31 // 0xF01E
remstart
   FX1E ( Extra note )
   VF is set to 1 when range overflow (I+VX>0xFFF), and 0 when 
   there isn't. This is undocumented feature of the CHIP-8 and 
   used by Spacefight 2091! game.
remend
// Adds VX to I.
function opcode_FX1E()
    Index_register = (Index_register+V[ vx ]) && val("0xFFF",Read_as_Hex)
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 32 // 0xF029
// Sets I to the location of the sprite for the character in VX. 
// Characters 0-F (in hexadecimal) are represented by a 4x5 font.
function opcode_FX29()
    Index_register = V[ vx  ]*5
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 33 // 0xF033
// 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.)
function opcode_FX33()
    x = (opcode && val("0xF00",Read_as_Hex)) >> 8
    memory[Index_register] =  (V[x] / 100) || 0
	memory[Index_register+1] = ((V[x] - memory[Index_register]*100) / 10) || 0
	memory[Index_register+2] = (V[x] - memory[Index_register]*100 - memory[Index_register+1]*10) || 0
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 34 // 0xF055
remstart
   FX55 ( Extra note )
   On the original interpreter, when the operation is done, I=I+X+1. 
   On current implementations, I is left unchanged.
remend
// Stores V0 to VX (including VX) in memory starting at address I.[
function opcode_FX55()
    x = (opcode && val("0xF00",Read_as_Hex)) >> 8
    for t = 0 to x 
	    memory[Index_register+t] = V[t]
    next t
    Index_register=Index_register+x+1
Endfunction

////////////////////////////////////////////////////////////////////////////////////////////// 35 // 0xF065
remstart
   FX65 ( Extra note )
   On the original interpreter, when the operation is done, I=I+X+1. 
   On current implementations, I is left unchanged.
remend
// Fills V0 to VX (including VX) with values from memory starting at address I.
function opcode_FX65()
    x = (opcode && val("0xF00",Read_as_Hex)) >> 8
    for t = 0 to x 
	    V[t] = memory[Index_register+t]
    next t
    Index_register=Index_register+x+1
Endfunction

