Skip to content

Instantly share code, notes, and snippets.

@bmerrill42
Created March 3, 2018 00:44
Show Gist options
  • Save bmerrill42/76755345c2660dc6426cc01e6a164283 to your computer and use it in GitHub Desktop.
Save bmerrill42/76755345c2660dc6426cc01e6a164283 to your computer and use it in GitHub Desktop.
chip8 emulator by a ruby noob
require 'curses'
class Chip
fontset = [
0xF0, 0x90, 0x90, 0x90, 0xF0,#0
0x20, 0x60, 0x20, 0x20, 0x70,#1
0xF0, 0x10, 0xF0, 0x80, 0xF0,#2
0xF0, 0x10, 0xF0, 0x10, 0xF0,#3
0x90, 0x90, 0xF0, 0x10, 0x10,#4
0xF0, 0x80, 0xF0, 0x10, 0xF0,#5
0xF0, 0x80, 0xF0, 0x90, 0xF0,#6
0xF0, 0x10, 0x20, 0x40, 0x40,#7
0xF0, 0x90, 0xF0, 0x90, 0xF0,#8
0xF0, 0x90, 0xF0, 0x10, 0xF0,#9
0xF0, 0x90, 0xF0, 0x90, 0x90,#A
0xE0, 0x90, 0xE0, 0x90, 0xE0,#B
0xF0, 0x80, 0x80, 0x80, 0xF0,#C
0xE0, 0x90, 0x90, 0x90, 0xE0,#D
0xF0, 0x80, 0xF0, 0x80, 0xF0,#E
0xF0, 0x80, 0xF0, 0x80, 0x80#F
]
def initialize
# initialize registers and memory
memory = Array.new(4096, 0)
v = Array.new(16, 0)
vf = 0
i = 0
pc = 0x200
gfx = Array.new(64*32)
delay_timer = 0
sound_timer = 0
opcode = 0
stack = Array.new(16, 0)
sp = 0
key = Array.new(16)
memory[0..(fontset.length - 1)] = fontset[0..(fontset.length - 1)]
end
def loadgame
# figure out how to load file into array
buffer = []
for i in buffer.len
memory[i + 0x200] = buffer[i]
end
end
def emulate_cycle
# fetch opcode
opcode = memory[pc] << 8 | memory[pc + 1]
# decode opcode
nnn = opcode & 0x0FFF
n = opcode & 0x000F
x = opcode 0x0F00 >> 8
y = opcode 0x00F0 >> 4
kk = opcode & 0x00FF
case opcode & 0xF000
when 0x0000
case opcode & 0x000F
when 0x0000
#clear the screen
when 0x000E
#return from subroutine
end
when 0x1000
pc = nnn
when 0x2000
sp += 1
stack[sp] = pc
pc = nnn
when 0x3000
if v[x] == kk
pc += 4
else
pc += 2
end
when 0x4000
if v[x] != kk
pc += 4
else
pc += 2
end
when 0x5000
if v[x] == v[y]
pc += 4
else
pc += 2
end
when 0x6000
v[x] = kk
pc += 2
when 0x7000
v[x] = v[x] + (kk)
pc += 2
when 0x8000
case n
when 0x0000
v[x] = v[y]
pc += 2
when 0x0001
v[x] = v[x] | v[y]
pc += 2
when 0x0002
v[x] = v[x] & v[y]
pc += 2
when 0x0003
v[x] = v[x] ^ v[y]
pc += 2
when 0x0004
if (v[x] + v[y]) > 0xFF
vf = 1
v[x] = (v[x] + v[y]) & 0xFF
else
vf = 0
v[x] = (v[x] + v[y])
end
pc += 2
when 0x0005
if v[x] > v[y]
vf = 1
else
vf = 0
end
v[x] = (v[x] - v[y])
pc += 2
when 0x0006
if v[x] & 0x0001 == 1
vf = 1
else
vf = 0
end
v[x] = (v[x] >> 1) & 0xFF
pc += 2
when 0x0007
pc += 2
when 0x000E
if v[x] & 0x8000 == 1
vf = 1
else
vf = 0
end
v[x] = (v[x] << 1) & 0xFF
pc += 2
end
when 0x9000
if v[x] != v[y]
pc += 4
else
pc += 2
end
when 0xA000
i = nnn
pc += 2
when 0xB000
pc = nnn + v[0]
when 0xC000
v[x] = rand(255) & kk
pc += 2
when 0xD000
pc += 2
when 0xE000
pc += 2
when 0xF000
case kk
when 0x07
v[x] = delay_timer
pc += 2
when 0x0A
#keypress listen
pc += 2
when 0x15
delay_timer = v[x]
pc += 2
when 0x18
sound_timer = v[x]
pc += 2
when 0x1E
pc += 2
when 0x29
pc += 2
when 0x55
pc += 2
when 0x65
pc += 2
else
puts "unknown opcode #{opcode.to_s(16)}"
pc += 2
end
end
end
begin
chip8 = Chip.new
setup_graphics
setup_input
chip8.loadgame("pong")
loop do
chip8.emulate_cycle
if chip8.draw_flag != 0
draw_graphics
end
chip8.set_keys
end
end
=begin
Curses.init_screen
begin
nb_lines = Curses.lines
nb_cols = Curses.cols
Curses.addstr("cols: #{nb_cols}\n")
Curses.addstr("lines: #{nb_lines}")
Curses.refresh
Curses.getch
ensure
Curses.close_screen
end
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment