Skip to content

Commit

Permalink
Add load long operation. (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
craigthomas authored Jun 25, 2024
1 parent 87c41a7 commit bed04f1
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 8 deletions.
42 changes: 36 additions & 6 deletions chip8/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ def __init__(
# CPU starts with F (e.g. operand Fn07 would call
# self.move_delay_timer_into_reg)
self.misc_routine_lookup = {
0x00: self.index_load_long, # F000 - LOADLONG
0x01: self.set_bitplane, # Fn01 - BITPLANE n
0x07: self.move_delay_timer_into_reg, # Ft07 - LOAD Vt, DELAY
0x0A: self.wait_for_keypress, # Ft0A - KEYD Vt
Expand Down Expand Up @@ -244,11 +245,17 @@ def keyboard_routines(self):

# Skip if the key specified in the source register is pressed
if operation == 0x9E:
self.pc += 2 if keys_pressed[KEY_MAPPINGS[key_to_check]] else 0
if keys_pressed[KEY_MAPPINGS[key_to_check]]:
self.pc += 2
if self.memory[self.pc - 2] == 0xF0 and self.memory[self.pc - 1] == 0x00:
self.pc += 2

# Skip if the key specified in the source register is not pressed
if operation == 0xA1:
self.pc += 2 if not keys_pressed[KEY_MAPPINGS[key_to_check]] else 0
if not keys_pressed[KEY_MAPPINGS[key_to_check]]:
self.pc += 2
if self.memory[self.pc - 2] == 0xF0 and self.memory[self.pc - 1] == 0x00:
self.pc += 2

def misc_routines(self):
"""
Expand Down Expand Up @@ -396,7 +403,10 @@ def skip_if_reg_equal_val(self):
advancing it by 2 bytes.
"""
x = (self.operand & 0x0F00) >> 8
self.pc += 2 if self.v[x] == (self.operand & 0x00FF) else 0
if self.v[x] == (self.operand & 0x00FF):
self.pc += 2
if self.memory[self.pc - 2] == 0xF0 and self.memory[self.pc - 1] == 0x00:
self.pc += 2
self.last_op = f"SKE V{x:01X}, {self.operand & 0x00FF:02X}"

def skip_if_reg_not_equal_val(self):
Expand All @@ -414,7 +424,10 @@ def skip_if_reg_not_equal_val(self):
"""
x = (self.operand & 0x0F00) >> 8
self.last_op = f"SKNE V{x:X}, {self.operand & 0x00FF:02X} (comparing {self.v[x]:02X} to {self.operand & 0xFF:02X})"
self.pc += 2 if self.v[x] != (self.operand & 0x00FF) else 0
if self.v[x] != (self.operand & 0x00FF):
self.pc += 2
if self.memory[self.pc - 2] == 0xF0 and self.memory[self.pc - 1] == 0x00:
self.pc += 2

def skip_if_reg_equal_reg(self):
"""
Expand All @@ -431,7 +444,10 @@ def skip_if_reg_equal_reg(self):
"""
x = (self.operand & 0x0F00) >> 8
y = (self.operand & 0x00F0) >> 4
self.pc += 2 if self.v[x] == self.v[y] else 0
if self.v[x] == self.v[y]:
self.pc += 2
if self.memory[self.pc - 2] == 0xF0 and self.memory[self.pc - 1] == 0x00:
self.pc += 2
self.last_op = f"SKE V{x:01X}, V{y:01X}"

def move_value_to_reg(self):
Expand Down Expand Up @@ -661,7 +677,10 @@ def skip_if_reg_not_equal_reg(self):
"""
x = (self.operand & 0x0F00) >> 8
y = (self.operand & 0x00F0) >> 4
self.pc += 2 if self.v[x] != self.v[y] else 0
if self.v[x] != self.v[y]:
self.pc += 2
if self.memory[self.pc - 2] == 0xF0 and self.memory[self.pc - 1] == 0x00:
self.pc += 2
self.last_op = f"SKNE V{x:01X}, V{y:01X} (comparing {self.v[x]:02X} to {self.v[y]:02X})"

def load_index_reg_with_value(self):
Expand Down Expand Up @@ -823,6 +842,17 @@ def draw_extended(self, x_pos, y_pos):
self.v[0xF] += 1
self.screen.update()

def index_load_long(self):
"""
F000 - LOADLONG
Loads the index register with a 16-bit long value. Consumes the next two
bytes from memory and increments the PC by two bytes.
"""
self.index = (self.memory[self.pc] << 8) + self.memory[self.pc+1]
self.pc += 2
self.last_op = f"LOADLONG {self.index:04X}"

def set_bitplane(self):
"""
Fn01 - BITPLANE n
Expand Down
79 changes: 77 additions & 2 deletions test/test_chip8cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ def test_skip_if_reg_equal_value(self):
else:
self.assertEqual(self.cpu.pc, 0)

def test_skip_if_reg_equal_val_load_long_exception(self):
self.cpu.memory[0x0200] = 0xF0
self.cpu.memory[0x0201] = 0x00
self.cpu.v[1] = 1
self.cpu.operand = 0x3101
self.cpu.skip_if_reg_equal_val()
self.assertEqual(0x0204, self.cpu.pc)

def test_skip_if_reg_not_equal_val(self):
for register in range(0x10):
for value in range(0, 0xFF, 0x10):
Expand All @@ -133,6 +141,14 @@ def test_skip_if_reg_not_equal_val(self):
else:
self.assertEqual(self.cpu.pc, 0)

def test_skip_if_reg_not_equal_val_load_long_exception(self):
self.cpu.memory[0x0200] = 0xF0
self.cpu.memory[0x0201] = 0x00
self.cpu.v[1] = 1
self.cpu.operand = 0x4102
self.cpu.skip_if_reg_not_equal_val()
self.assertEqual(0x0204, self.cpu.pc)

def test_skip_if_reg_equal_reg(self):
for reg_num in range(0x10):
self.cpu.v[reg_num] = reg_num
Expand All @@ -155,6 +171,15 @@ def test_skip_if_reg_equal_reg(self):
else:
self.assertEqual(self.cpu.pc, 0)

def test_skip_if_reg_equal_reg_load_long_exception(self):
self.cpu.memory[0x0200] = 0xF0
self.cpu.memory[0x0201] = 0x00
self.cpu.v[1] = 1
self.cpu.v[2] = 1
self.cpu.operand = 0x5120
self.cpu.skip_if_reg_equal_reg()
self.assertEqual(0x0204, self.cpu.pc)

def test_move_value_to_reg(self):
val = 0x23
for reg_num in range(0x10):
Expand Down Expand Up @@ -410,6 +435,15 @@ def test_skip_if_reg_not_equal_reg(self):
else:
self.assertEqual(self.cpu.pc, 0)

def test_skip_if_reg_not_equal_reg_load_long_exception(self):
self.cpu.memory[0x0200] = 0xF0
self.cpu.memory[0x0201] = 0x00
self.cpu.v[1] = 1
self.cpu.v[2] = 2
self.cpu.operand = 0x9120
self.cpu.skip_if_reg_not_equal_reg()
self.assertEqual(0x0204, self.cpu.pc)

def test_load_index_reg_with_value(self):
for value in range(0x10000):
self.cpu.operand = value
Expand Down Expand Up @@ -679,6 +713,18 @@ def test_operation_9E_pc_skips_if_key_pressed(self):
self.assertTrue(key_mock.asssert_called)
self.assertEqual(2, self.cpu.pc)

def test_operation_9E_pc_skips_if_key_pressed_load_long_exception(self):
self.cpu.operand = 0x09E
self.cpu.v[0] = 1
result_table = [False] * 512
self.cpu.memory[0x0200] = 0xF0
self.cpu.memory[0x0201] = 0x00
result_table[pygame.K_1] = True
with mock.patch("pygame.key.get_pressed", return_value=result_table) as key_mock:
self.cpu.keyboard_routines()
self.assertTrue(key_mock.asssert_called)
self.assertEqual(0x0204, self.cpu.pc)

def test_operation_9E_pc_does_not_skip_if_key_not_pressed(self):
self.cpu.operand = 0x09E
self.cpu.v[0] = 1
Expand All @@ -699,6 +745,17 @@ def test_operation_A1_pc_skips_if_key_not_pressed(self):
self.assertTrue(key_mock.asssert_called)
self.assertEqual(2, self.cpu.pc)

def test_operation_A1_pc_skips_if_key_not_pressed_load_long_exception(self):
self.cpu.operand = 0x0A1
self.cpu.v[0] = 1
result_table = [False] * 512
self.cpu.memory[0x0200] = 0xF0
self.cpu.memory[0x0201] = 0x00
with mock.patch("pygame.key.get_pressed", return_value=result_table) as key_mock:
self.cpu.keyboard_routines()
self.assertTrue(key_mock.asssert_called)
self.assertEqual(0x0204, self.cpu.pc)

def test_operation_A1_pc_does_not_skip_if_key_pressed(self):
self.cpu.operand = 0x0A1
self.cpu.v[0] = 1
Expand Down Expand Up @@ -749,10 +806,10 @@ def test_execute_logical_instruction_raises_exception_on_unknown_op_codes(self):
self.cpu.execute_logical_instruction()

def test_misc_routines_raises_exception_on_unknown_op_codes(self):
self.cpu.operand = 0x0
self.cpu.operand = 0xF0FF
with self.assertRaises(UnknownOpCodeException) as context:
self.cpu.misc_routines()
self.assertEqual("Unknown op-code: 0000", str(context.exception))
self.assertEqual("Unknown op-code: F0FF", str(context.exception))

def test_scroll_down_called(self):
self.cpu.operand = 0x00C4
Expand Down Expand Up @@ -1006,6 +1063,24 @@ def test_read_subset_regs_integration(self):
self.assertEqual(9, self.cpu.v[2])
self.assertEqual(8, self.cpu.v[3])

def test_load_long(self):
self.cpu.index = 0x5000
self.cpu.memory[0x0200] = 0x12
self.cpu.memory[0x0201] = 0x34
self.cpu.index_load_long()
self.assertEqual(0x1234, self.cpu.index)
self.assertEqual(0x0202, self.cpu.pc)

def test_load_long_integration(self):
self.cpu.index = 0x5000
self.cpu.memory[0x0200] = 0xF0
self.cpu.memory[0x0201] = 0x00
self.cpu.memory[0x0202] = 0x12
self.cpu.memory[0x0203] = 0x34
self.cpu.execute_instruction()
self.assertEqual(0x1234, self.cpu.index)
self.assertEqual(0x0204, self.cpu.pc)

# M A I N #####################################################################


Expand Down

0 comments on commit bed04f1

Please sign in to comment.