Added, clear, jmp, ld, add, set and draw ops.
Also cleaned up comments for now will add better clear ones later down the line for future reference.
This commit is contained in:
+73
-5
@@ -31,19 +31,87 @@ cycle :: proc(s: ^System) {
|
||||
switch opcode {
|
||||
case 0x00E0: op_cls(s)
|
||||
}
|
||||
case 0x1: op_jp_add(s)
|
||||
case 0xD: log.info("D instruction a draw call!")
|
||||
case 0x1: op_jp_add(s, opcode)
|
||||
case 0x6: op_ld(s, opcode)
|
||||
case 0x7: op_add(s, opcode)
|
||||
case 0xA: op_set(s, opcode)
|
||||
case 0xD: op_draw(s, opcode)
|
||||
}
|
||||
}
|
||||
|
||||
debug_opcode :: proc(opcode: u16) {
|
||||
log.debugf("opcode: 0x%04X", opcode)
|
||||
}
|
||||
|
||||
// Instruction procs
|
||||
// -----------------------------------
|
||||
// CLS: Clear the display
|
||||
op_cls :: proc(s: ^System) {
|
||||
log.info("found clear screen instruction, zero out display buffer")
|
||||
// log.info("found clear screen instruction, zero out display buffer")
|
||||
|
||||
// Odin lets you zero a fixed array with just: {} is the zero value,
|
||||
// so it clears the entire buffer in one shot.
|
||||
s.display = {}
|
||||
}
|
||||
|
||||
// JP addr: Jump to location nnn
|
||||
op_jp_add :: proc(s: ^System) {
|
||||
log.info("found jump instruction, set pc to nnn")
|
||||
op_jp_add :: proc(s: ^System, opcode: u16) {
|
||||
addr := (opcode & 0x0FFF)
|
||||
s.pc = addr
|
||||
}
|
||||
|
||||
// LD: Load value kk into x register
|
||||
op_ld :: proc(s: ^System, opcode: u16) {
|
||||
register := (opcode & 0x0F00) >> 8
|
||||
value := (opcode & 0x00FF)
|
||||
|
||||
s.v[register] = u8(value)
|
||||
}
|
||||
|
||||
// ADD: Adds the value kk to the value of register Vx, then stores the result in Vx.
|
||||
op_add :: proc(s: ^System, opcode: u16) {
|
||||
register := (opcode & 0x0F00) >> 8
|
||||
value := (opcode & 0x00FF)
|
||||
s.v[register] += u8(value)
|
||||
}
|
||||
|
||||
// SET: The value of register I is set to nnn.
|
||||
op_set :: proc(s: ^System, opcode: u16) {
|
||||
index_addr := (opcode & 0x0FFF)
|
||||
s.i = index_addr
|
||||
}
|
||||
|
||||
// DRAW: Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
|
||||
op_draw :: proc(s: ^System, opcode: u16) {
|
||||
x_register := (opcode & 0x0F00) >> 8
|
||||
y_register := (opcode & 0x00F0) >> 4
|
||||
|
||||
// Handle wrapping
|
||||
x_coord := (s.v[x_register] & 0x03F)
|
||||
y_coord := (s.v[y_register] & 0x1F)
|
||||
|
||||
s.v[0xF] = 0
|
||||
|
||||
n_bytes := (opcode & 0x000F)
|
||||
|
||||
for row in 0..<n_bytes {
|
||||
sprite_row := s.memory[s.i + row]
|
||||
// log.debugf("sr: 0x%X", sprite_row)
|
||||
|
||||
for col in 0..<8 {
|
||||
mask := u8(0x80) >> u8(col)
|
||||
|
||||
if sprite_row & mask != 0 {
|
||||
// this bit is set Xor the pixel
|
||||
y_pos := ((y_coord + u8(row)) % 32)
|
||||
x_pos := ((x_coord + u8(col)) % 64)
|
||||
|
||||
pixel := &s.display[y_pos][x_pos]
|
||||
if pixel^ == 1 {
|
||||
s.v[0xF] = 1
|
||||
}
|
||||
pixel^ = pixel^ ~ 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user