def test_indirect_indexed_y_page_boundary(): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode registers.y_index = 0x3 AddressingModes.cycle_count = 0 with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xB1 0x2a memory at 0x2a = [0xfe, 0x40] mock_memory_controller.read.side_effect = [0x2a, 0xfe, 0x40] # 'LDA' 0xB9 opcode uses indirect addressing value = addressing_modes.handle(0xB1, registers, mock_memory_controller) assert mock_memory_controller.read.call_count == 3 assert mock_memory_controller.read.call_args_list[ 0] == unittest.mock.call(1) assert mock_memory_controller.read.call_args_list[ 1] == unittest.mock.call(0x2a) assert mock_memory_controller.read.call_args_list[ 2] == unittest.mock.call(0x2b) assert registers.pc == 2 assert value == 0x4101 assert AddressingModes.cycle_count == 1
def test_indirect(): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode registers.y_index = 0xff with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0x6C 0x03 0xf0 and value at [0xf003] = 0x1234 mock_memory_controller.read.side_effect = [3, 0xf0, 0x34, 0x12] # 'JMP' 0x6C opcode uses indirect addressing value = addressing_modes.handle(0x6C, registers, mock_memory_controller) assert mock_memory_controller.read.call_count == 4 assert mock_memory_controller.read.call_args_list[ 0] == unittest.mock.call(1) assert mock_memory_controller.read.call_args_list[ 1] == unittest.mock.call(2) assert mock_memory_controller.read.call_args_list[ 2] == unittest.mock.call(0xf003) assert mock_memory_controller.read.call_args_list[ 3] == unittest.mock.call(0xf004) assert registers.pc == 3 assert value == 0x1234
def test_set_NZV_non_zero_negative_no_overflow(): registers = Registers() registers.accumulator = 4 registers.set_NZV(-3, 1) assert registers.negative_flag == False assert registers.zero_flag == False assert registers.overflow_flag == False
def test_set_NZV_non_zero_not_negative_overflow(): registers = Registers() registers.accumulator = 0x80 # Here we act as if we have done -128 + -1 registers.set_NZV(0xff, 0x7f) assert registers.negative_flag == False assert registers.zero_flag == False assert registers.overflow_flag
def test_set_NZV_non_zero_negative_overflow(): registers = Registers() registers.accumulator = 0x7f # Here we act as if we have done 127 + 1 registers.set_NZV(1, 0x80) assert registers.negative_flag assert registers.zero_flag == False assert registers.overflow_flag
def test_execute_iny_255_to_0(): opcode = OpCode() registers = Registers() registers.y_index = 0xff opcode.execute(0xC8, registers, None) assert registers.y_index == 0 assert registers.negative_flag == False assert registers.zero_flag
def test_execute_dey_0_to_minus1(): opcode = OpCode() registers = Registers() registers.y_index = 0 opcode.execute(0x88, registers, None) assert registers.y_index == 255 assert registers.negative_flag assert registers.zero_flag == False
def test_execute_dey_128_to_127(): opcode = OpCode() registers = Registers() registers.y_index = 0x80 opcode.execute(0x88, registers, None) assert registers.y_index == 0x7f assert registers.negative_flag == False assert registers.zero_flag == False
def test_execute_iny_127_to_128(): opcode = OpCode() registers = Registers() dummy_value = 0x7f registers.y_index = dummy_value opcode.execute(0xC8, registers, None) assert registers.y_index == dummy_value + 1 assert registers.negative_flag assert registers.zero_flag == False
def test_execute_nop(): opcode = OpCode() registers = Registers() with patch.object(MemoryController, 'read', return_value=None) as mock_memory_controller: count = opcode.execute(0xEA, registers, mock_memory_controller) assert count == 2 mock_memory_controller.assert_not_called() assert registers == Registers()
def test_implied_has_no_effect(): addressing_modes = AddressingModes() registers = Registers() with patch.object(MemoryController, 'read', return_value=None) as mock_memory_controller: # 'RTS' opcode is implied address mode count = addressing_modes.handle(0x60, registers, mock_memory_controller) assert count == None mock_memory_controller.assert_not_called() assert registers == Registers()
def test_execute_dey_1_to_0(): opcode = OpCode() registers = Registers() registers.y_index = 1 with patch.object(MemoryController, 'read', return_value=None) as mock_memory_controller: count = opcode.execute(0x88, registers, mock_memory_controller) assert count == 2 mock_memory_controller.assert_not_called() assert registers.y_index == 0 assert registers.negative_flag == False assert registers.zero_flag
def test_execute_iny_0_to_1(): opcode = OpCode() registers = Registers() dummy_value = 0x0 registers.y_index = dummy_value with patch.object(MemoryController, 'read', return_value=None) as mock_memory_controller: count = opcode.execute(0xC8, registers, mock_memory_controller) assert count == 2 mock_memory_controller.assert_not_called() assert registers.y_index == dummy_value + 1 assert registers.negative_flag == False assert registers.zero_flag == False
def test_execute_tya(): opcode = OpCode() registers = Registers() dummy_value = 0x7c # (positive, not zero) registers.y_index = dummy_value with patch.object(MemoryController, 'read', return_value=None) as mock_memory_controller: count = opcode.execute(0x98, registers, mock_memory_controller) assert count == 2 mock_memory_controller.assert_not_called() assert registers.y_index == dummy_value assert registers.accumulator == registers.y_index assert registers.negative_flag == False assert registers.zero_flag == False
def test_execute_txs(): opcode = OpCode() registers = Registers() dummy_value = 0x7c # (positive, not zero) registers.x_index = dummy_value with patch.object(MemoryController, 'read', return_value=None) as mock_memory_controller: count = opcode.execute(0x9A, registers, mock_memory_controller) assert count == 2 mock_memory_controller.assert_not_called() assert registers.x_index == dummy_value assert registers.sp == dummy_value assert registers.negative_flag == False # default sp should be $fd assert registers.zero_flag == False
def test_zero_page_calls_read_correctly(self): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xa5 0x22 and value at [0x0022] = 1 mock_memory_controller.read.side_effect = [0x22, 1] # 'LDA' 0xA5 opcode is zero page address mode value = addressing_modes.handle(0xA5, registers, mock_memory_controller) self.assertEqual(mock_memory_controller.read.call_count, 2) self.assertEqual(mock_memory_controller.read.call_args_list[1], unittest.mock.call(0x22)) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(registers.pc, 2) self.assertEqual(value, 1)
def test_execute_bvs_branch_taken(): opcode = OpCode() registers = Registers() registers.overflow_flag = True registers.pc = 0xc000 with patch.object(MemoryController, 'read') as mock_memory_controller: mock_memory_controller.read.side_effect = [0xfe] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x70, registers, mock_memory_controller) assert count == 3 # Tested more thoroughly in addressing_modes_tests assert mock_memory_controller.read.call_count == 1 assert registers.pc == 0xc000
def test_execute_bmi_branch_not_taken(): opcode = OpCode() registers = Registers() registers.negative_flag = False registers.pc = 0xc000 with patch.object(MemoryController, 'read') as mock_memory_controller: mock_memory_controller.read.side_effect = [0x02] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x30, registers, mock_memory_controller) assert count == 2 # Tested more thoroughly in addressing_modes_tests assert mock_memory_controller.read.call_count == 1 assert registers.pc == 0xc002
def test_absolute_jmp_calls_read_correctly(self): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xa5 0x22 and value at [0x0022] = 1 mock_memory_controller.read.side_effect = [0x22, 0x23, 1] # 'JMP' 0x4c opcode is absolute address mode value = addressing_modes.handle(0x4C, registers, mock_memory_controller) self.assertEqual(mock_memory_controller.read.call_count, 2) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(mock_memory_controller.read.call_args_list[1], unittest.mock.call(2)) self.assertEqual(registers.pc, 3) self.assertEqual(value, 0x2322)
def test_execute_sbc_immediate_borrow_in_no_borrow_out_overflow_positive_result(): opcode = OpCode() registers = Registers() registers.accumulator = 0xd0 #start with negative acc this time with patch.object(MemoryController, 'read') as mock_memory_controller: # Mocking 0xE9 0x70 so subtracting 0xd0 - 0x70 (-48 - 112 = 96 (overflow)) mock_memory_controller.read.return_value = 0x70 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xE9, registers, mock_memory_controller) assert count == 2 assert registers.accumulator == 0x5f assert registers.zero_flag == False assert registers.negative_flag == False assert registers.carry_flag assert registers.overflow_flag
def execute_adc_carry_clear( actual_opcode, expected_clocks): opcode = OpCode() registers = Registers() registers.accumulator = 5 registers.zero_flag = True registers.negative_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: mock_memory_controller.read.return_value = 0x22 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(actual_opcode, registers, mock_memory_controller) assert count == expected_clocks assert registers.accumulator == 0x27 assert registers.zero_flag == False assert registers.negative_flag == False assert registers.carry_flag == False
def test_execute_sty_zeropage(): opcode = OpCode() registers = Registers() registers.y_index = 5 mock_memory_controller = Mock() # we're mocking 0x84 0x30 mock_memory_controller.read.side_effect = [0x30] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x84, registers, mock_memory_controller) assert count == 3 assert mock_memory_controller.read.call_count == 1 assert mock_memory_controller.read.call_args_list[0] == unittest.mock.call( 1) mock_memory_controller.write.assert_called_with(0x30, 5) assert registers.pc == 2
def test_execute_cmp_immediate_lessthan(opcode, registers, mock_memory_controller): registers = Registers() registers.accumulator = 3 mock_memory_controller.read.side_effect = [0x21] # we're mocking 0xC9 0x21 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xC9, registers, mock_memory_controller) assert count == 2 assert mock_memory_controller.read.call_count == 1 assert mock_memory_controller.read.call_args_list[0] == unittest.mock.call( 1) assert registers.pc == 2 assert registers.zero_flag == False assert registers.carry_flag == False assert registers.negative_flag
def test_execute_sbc_immediate_borrow_in_no_borrow_out_overflow_positive_result(self): opcode = OpCode() registers = Registers() registers.accumulator = 0xd0 #start with negative acc this time with patch.object(MemoryController, 'read') as mock_memory_controller: # Mocking 0xE9 0x70 so subtracting 0xd0 - 0x70 (-48 - 112 = 96 (overflow)) mock_memory_controller.read.return_value = 0x70 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xE9, registers, mock_memory_controller) self.assertEqual(count, 2) self.assertEqual(registers.accumulator, 0x5f) self.assertFalse(registers.zero_flag) self.assertFalse(registers.negative_flag) self.assertTrue(registers.carry_flag) self.assertTrue(registers.overflow_flag)
def test_execute_lda_immediate_negative(): opcode = OpCode() registers = Registers() registers.zero_flag = True registers.negative_flag = False with patch.object(MemoryController, 'read') as mock_memory_controller: mock_memory_controller.read.return_value = -1 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xA9, registers, mock_memory_controller) assert count == 2 mock_memory_controller.read.assert_called_with(1) assert registers.accumulator == -1 assert registers.pc == 2 assert registers.zero_flag == False assert registers.negative_flag
def test_zero_page_y_index_deals_with_wraparound(self): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode registers.y_index = 0xff with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xB6 0x03 and value at [0x02] = 1 mock_memory_controller.read.side_effect = [3, 1] # 'LDX 0xB6 opcode is zero page x indexed address mode value = addressing_modes.handle(0xB6, registers, mock_memory_controller) self.assertEqual(mock_memory_controller.read.call_count, 2) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(mock_memory_controller.read.call_args_list[1], unittest.mock.call(2)) self.assertEqual(registers.pc, 2) self.assertEqual(value, 1)
def test_execute_ldx_immediate_zero(): opcode = OpCode() registers = Registers() registers.zero_flag = False registers.negative_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: mock_memory_controller.read.return_value = 0x0 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xA2, registers, mock_memory_controller) assert count == 2 mock_memory_controller.read.assert_called_with(1) assert registers.x_index == 0x0 assert registers.pc == 2 assert registers.zero_flag assert registers.negative_flag == False
def test_execute_sta_zeropage(): opcode = OpCode() registers = Registers() registers.accumulator = 3 mock_memory_controller = Mock() # we're mocking 0x85 0x21 mock_memory_controller.read.side_effect = [0x21] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x85, registers, mock_memory_controller) assert count == 3 assert mock_memory_controller.read.call_count == 1 assert mock_memory_controller.read.call_args_list[0] == unittest.mock.call( 1) mock_memory_controller.write.assert_called_with(0x21, 3) assert registers.pc == 2
def execute_adc_should_set_carry(self, actual_opcode, expected_clocks): opcode = OpCode() registers = Registers() registers.accumulator = 1 registers.zero_flag = False registers.negative_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: mock_memory_controller.read.return_value = 0xff registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(actual_opcode, registers, mock_memory_controller) self.assertEqual(count, expected_clocks) self.assertTrue(registers.accumulator == 0) self.assertTrue(registers.zero_flag) self.assertFalse(registers.negative_flag) self.assertTrue(registers.carry_flag)
def test_execute_asl_accumulator_negative(self): opcode = OpCode() registers = Registers() registers.accumulator = -3 mock_memory_controller = Mock() # we're mocking 0x0A 0x21 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x0A, registers, mock_memory_controller) self.assertEqual(count, 2) mock_memory_controller.read.assert_not_called() self.assertEqual(registers.pc, 1) self.assertEqual(registers.accumulator, 0xfa) self.assertFalse(registers.zero_flag) self.assertTrue(registers.carry_flag) self.assertTrue(registers.negative_flag)
def test_execute_rol_zeropage_carry_clear_sign_set(self): opcode = OpCode() registers = Registers() registers.accumulator = 0xc0 mock_memory_controller = Mock() mock_memory_controller.read.side_effect = [0x30, 0xc0] # we're mocking 0x26 0x30 and [0x30] = 0xc0 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x26, registers, mock_memory_controller) self.assertEqual(count, 5) mock_memory_controller.write.assert_called_with(0x30, 0x80) self.assertEqual(registers.pc, 2) self.assertFalse(registers.zero_flag) self.assertTrue(registers.carry_flag) self.assertTrue(registers.negative_flag)
def test_execute_cmp_immediate_equalto(self): opcode = OpCode() registers = Registers() registers.accumulator = 4 mock_memory_controller = Mock() mock_memory_controller.read.side_effect = [0x4] # we're mocking 0xC9 0x21 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xC9, registers, mock_memory_controller) self.assertEqual(count, 2) self.assertEqual(mock_memory_controller.read.call_count, 1) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(registers.pc, 2) self.assertTrue(registers.zero_flag) self.assertTrue(registers.carry_flag) self.assertFalse(registers.negative_flag)
def test_execute_sbc_immediate_no_borrow_in_borrow_out_overflow_negative_result(self): opcode = OpCode() registers = Registers() registers.accumulator = 0x50 registers.carry_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: # Mocking 0xE9 0xb0 so subtracting 0x50 - 0xb0 (80 - -80) mock_memory_controller.read.return_value = 0xb0 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xE9, registers, mock_memory_controller) self.assertEqual(count, 2) self.assertTrue(registers.accumulator == 0xa0) self.assertFalse(registers.zero_flag) self.assertTrue(registers.negative_flag) self.assertFalse(registers.carry_flag) self.assertTrue(registers.overflow_flag)
def test_execute_rol_absolute_carry_set_sign_clear(self): opcode = OpCode() registers = Registers() registers.carry_flag = True mock_memory_controller = Mock() mock_memory_controller.read.side_effect = [0x00, 0x30, 3] # we're mocking 0x2E 0x30 and [0x3000] = 3 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x2E, registers, mock_memory_controller) self.assertEqual(count, 6) self.assertEqual(mock_memory_controller.read.call_count, 3) mock_memory_controller.write.assert_called_with(0x3000, 7) self.assertEqual(registers.pc, 3) self.assertFalse(registers.zero_flag) self.assertFalse(registers.carry_flag) self.assertFalse(registers.negative_flag)
def test_execute_rol_accumulator_carry_set_sign_clear(self): opcode = OpCode() registers = Registers() registers.accumulator = 3 registers.carry_flag = True mock_memory_controller = Mock() # we're mocking 0x2A registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x2A, registers, mock_memory_controller) self.assertEqual(count, 2) mock_memory_controller.read.assert_not_called() self.assertEqual(registers.pc, 1) self.assertEqual(registers.accumulator, 7) self.assertFalse(registers.zero_flag) self.assertFalse(registers.carry_flag) self.assertFalse(registers.negative_flag)
def test_execute_sbc_immediate_no_borrow_in_borrow_out_overflow_negative_result(): opcode = OpCode() registers = Registers() registers.accumulator = 0x50 registers.carry_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: # Mocking 0xE9 0xb0 so subtracting 0x50 - 0xb0 (80 - -80) mock_memory_controller.read.return_value = 0xb0 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xE9, registers, mock_memory_controller) assert count == 2 assert registers.accumulator == 0xa0 assert registers.zero_flag == False assert registers.negative_flag assert registers.carry_flag == False assert registers.overflow_flag
def test_zp_index_indirect_x_wraparound_2(self): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode registers.x_index = 0xfe with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xA1 0x03 and value at [0xff] = 0x12, [0x00] = 0x34 mock_memory_controller.read.side_effect = [1, 0x34, 0x12] # 'LDA' 0xA1 opcode uses indirect addressing value = addressing_modes.handle(0xA1, registers, mock_memory_controller) self.assertEqual(mock_memory_controller.read.call_count, 3) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(mock_memory_controller.read.call_args_list[1], unittest.mock.call(0xff)) self.assertEqual(mock_memory_controller.read.call_args_list[2], unittest.mock.call(0)) self.assertEqual(registers.pc, 2) self.assertEqual(value, 0x1234)
def test_execute_sta_absolute_y(): opcode = OpCode() registers = Registers() registers.accumulator = 0x20 registers.y_index = 3 mock_memory_controller = Mock() # we're mocking 0x99 0x2100 so write is to [0x2103] mock_memory_controller.read.side_effect = [0, 0x21] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x99, registers, mock_memory_controller) assert count == 5 # these are checked more thoroughly in addressing_modes_tests assert mock_memory_controller.read.call_count == 2 mock_memory_controller.write.assert_called_with(0x2103, 0x20) assert registers.pc == 3
def test_execute_cpx_immediate_greaterthan(self): opcode = OpCode() registers = Registers() registers.x_index = 4 mock_memory_controller = Mock() mock_memory_controller.read.side_effect = [0x3] # we're mocking 0xE0 0x03 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xE0, registers, mock_memory_controller) self.assertEqual(count, 2) self.assertEqual(mock_memory_controller.read.call_count, 1) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(registers.pc, 2) self.assertFalse(registers.zero_flag) self.assertTrue(registers.carry_flag) self.assertFalse(registers.negative_flag)
def test_execute_sty_absolute(): opcode = OpCode() registers = Registers() registers.y_index = 0x20 mock_memory_controller = Mock() # we're mocking 0x8C 0x21 so store to [0x0024] mock_memory_controller.read.side_effect = [0, 0x20] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x8C, registers, mock_memory_controller) assert count == 4 # these are checked more thoroughly in addressing_modes_tests assert mock_memory_controller.read.call_count == 2 assert mock_memory_controller.read.call_args_list[0] == unittest.mock.call( 1) mock_memory_controller.write.assert_called_with(0x2000, 0x20) assert registers.pc == 3
def test_execute_adc_absolute(): opcode = OpCode() registers = Registers() registers.accumulator = 5 registers.zero_flag = True registers.negative_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xb5 0x21 0x22 and value at [0x2221] = 1 mock_memory_controller.read.side_effect = [0x21, 0x22, 1] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x6D, registers, mock_memory_controller) assert count == 4 assert registers.accumulator == 6 assert registers.zero_flag == False assert registers.negative_flag == False assert registers.carry_flag == False
def test_zero_page_calls_read_correctly(): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xa5 0x22 and value at [0x0022] = 1 mock_memory_controller.read.side_effect = [0x22, 1] # 'LDA' 0xA5 opcode is zero page address mode value = addressing_modes.handle(0xA5, registers, mock_memory_controller) assert mock_memory_controller.read.call_count == 2 assert mock_memory_controller.read.call_args_list[ 1] == unittest.mock.call(0x22) assert mock_memory_controller.read.call_args_list[ 0] == unittest.mock.call(1) assert registers.pc == 2 assert value == 1
def test_absolute_jmp_calls_read_correctly(): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xa5 0x22 and value at [0x0022] = 1 mock_memory_controller.read.side_effect = [0x22, 0x23, 1] # 'JMP' 0x4c opcode is absolute address mode value = addressing_modes.handle(0x4C, registers, mock_memory_controller) assert mock_memory_controller.read.call_count == 2 assert mock_memory_controller.read.call_args_list[ 0] == unittest.mock.call(1) assert mock_memory_controller.read.call_args_list[ 1] == unittest.mock.call(2) assert registers.pc == 3 assert value == 0x2322
def test_indirect(self): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode registers.y_index = 0xff with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0x6C 0x03 0xf0 and value at [0xf003] = 0x1234 mock_memory_controller.read.side_effect = [3, 0xf0, 0x34, 0x12] # 'JMP' 0x6C opcode uses indirect addressing value = addressing_modes.handle(0x6C, registers, mock_memory_controller) self.assertEqual(mock_memory_controller.read.call_count, 4) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(mock_memory_controller.read.call_args_list[1], unittest.mock.call(2)) self.assertEqual(mock_memory_controller.read.call_args_list[2], unittest.mock.call(0xf003)) self.assertEqual(mock_memory_controller.read.call_args_list[3], unittest.mock.call(0xf004)) self.assertEqual(registers.pc, 3) self.assertEqual(value, 0x1234)
def test_absolute_y_page_boundary(self): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode registers.y_index = 0x3 AddressingModes.cycle_count = 0 with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xB9 0xc000 mock_memory_controller.read.side_effect = [0xfe, 0xc0] # 'LDA' 0xB9 opcode uses indirect addressing value = addressing_modes.handle(0xB9, registers, mock_memory_controller) self.assertEqual(mock_memory_controller.read.call_count, 2) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(mock_memory_controller.read.call_args_list[1], unittest.mock.call(2)) self.assertEqual(registers.pc, 3) self.assertEqual(value, 0xc101) self.assertEqual(AddressingModes.cycle_count, 1)
def test_execute_adc_absolute(self): opcode = OpCode() registers = Registers() registers.accumulator = 5 registers.zero_flag = True registers.negative_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xb5 0x21 0x22 and value at [0x2221] = 1 mock_memory_controller.read.side_effect = [0x21, 0x22, 1] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x6D, registers, mock_memory_controller) self.assertEqual(count, 4) self.assertTrue(registers.accumulator == 6) self.assertFalse(registers.zero_flag) self.assertFalse(registers.negative_flag) self.assertFalse(registers.carry_flag)
def test_execute_cpy_zeropage_lessthan(self): opcode = OpCode() registers = Registers() registers.y_index = 3 mock_memory_controller = Mock() mock_memory_controller.read.side_effect = [0x21, 6] # we're mocking 0xC4 0x21 and [0x21] = 6 registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0xC4, registers, mock_memory_controller) self.assertEqual(count, 3) self.assertEqual(mock_memory_controller.read.call_count, 2) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(mock_memory_controller.read.call_args_list[1], unittest.mock.call(0x21)) self.assertEqual(registers.pc, 2) self.assertFalse(registers.zero_flag) self.assertFalse(registers.carry_flag) self.assertTrue(registers.negative_flag)
def test_execute_asl_absolute_x(self): opcode = OpCode() registers = Registers() registers.x_index = 3 mock_memory_controller = Mock() # we're mocking 0x1E 0x2100 so write is to [0x2103] mock_memory_controller.read.side_effect = [0, 0x21, 0xfe] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x1E, registers, mock_memory_controller) self.assertEqual(count, 7) # these are checked more thoroughly in addressing_modes_tests self.assertEqual(mock_memory_controller.read.call_count, 3) mock_memory_controller.write.assert_called_with(0x2103, 0xfc) self.assertEqual(registers.pc, 3) self.assertFalse(registers.zero_flag) self.assertTrue(registers.carry_flag) self.assertTrue(registers.negative_flag)
def test_indirect_indexed_y_zp_boundary(self): addressing_modes = AddressingModes() registers = Registers() registers.pc = 1 #fake loading of opcode registers.y_index = 0x3 AddressingModes.cycle_count = 0 with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0xB1 0xff memory at 0xff = [0x28, 0x40] mock_memory_controller.read.side_effect = [0xff, 0x28, 0x40] # 'LDA' 0xB9 opcode uses indirect addressing value = addressing_modes.handle(0xB1, registers, mock_memory_controller) self.assertEqual(mock_memory_controller.read.call_count, 3) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) self.assertEqual(mock_memory_controller.read.call_args_list[1], unittest.mock.call(0xff)) self.assertEqual(mock_memory_controller.read.call_args_list[2], unittest.mock.call(0x00)) self.assertEqual(registers.pc, 2) self.assertEqual(value, 0x402b) self.assertEqual(AddressingModes.cycle_count, 0)
def test_execute_adc_indirect_indexed_y_page_boundary(self): opcode = OpCode() registers = Registers() registers.accumulator = 5 registers.y_index = 3 registers.zero_flag = True registers.negative_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0x71 0x2a memory at 0x2a = [0x28, 0x40], [0x4101] = 3 mock_memory_controller.read.side_effect = [0x2a, 0xfe, 0x40, 3] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x71, registers, mock_memory_controller) self.assertEqual(count, 6) self.assertEqual(mock_memory_controller.read.call_count, 4) self.assertTrue(registers.accumulator == 8) self.assertFalse(registers.zero_flag) self.assertFalse(registers.negative_flag) self.assertFalse(registers.carry_flag)
def test_execute_asl_absolute(self): opcode = OpCode() registers = Registers() registers.accumulator = 0x20 mock_memory_controller = Mock() # we're mocking 0x0E 0x0 0x20 so store to [0x2000] mock_memory_controller.read.side_effect = [0, 0x20, 0x21] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x0E, registers, mock_memory_controller) self.assertEqual(count, 6) # these are checked more thoroughly in addressing_modes_tests self.assertEqual(mock_memory_controller.read.call_count, 3) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) mock_memory_controller.write.assert_called_with(0x2000, 0x42) self.assertEqual(registers.pc, 3) self.assertFalse(registers.zero_flag) self.assertFalse(registers.carry_flag) self.assertFalse(registers.negative_flag)
def test_execute_adc_indexed_indirect_x(self): opcode = OpCode() registers = Registers() registers.accumulator = 5 registers.x_index = 3 registers.zero_flag = True registers.negative_flag = True with patch.object(MemoryController, 'read') as mock_memory_controller: # we're mocking 0x61 0x03 and value at [0x06] = 0x1234, [0x1234] = 3 mock_memory_controller.read.side_effect = [3, 0x34, 0x12, 3] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x61, registers, mock_memory_controller) self.assertEqual(count, 6) self.assertEqual(mock_memory_controller.read.call_count, 4) self.assertTrue(registers.accumulator == 8) self.assertFalse(registers.zero_flag) self.assertFalse(registers.negative_flag) self.assertFalse(registers.carry_flag)
def test_execute_asl_zeropage_x_wrap(self): opcode = OpCode() registers = Registers() registers.x_index = 3 mock_memory_controller = Mock() # we're mocking 0x16 0x21 so store to [0x0024] mock_memory_controller.read.side_effect = [0xfe, 0xf0] registers.pc += 1 #need to fake the cpu reading the opcode count = opcode.execute(0x16, registers, mock_memory_controller) self.assertEqual(count, 6) # these are checked more thoroughly in addressing_modes_tests self.assertEqual(mock_memory_controller.read.call_count, 2) self.assertEqual(mock_memory_controller.read.call_args_list[0], unittest.mock.call(1)) mock_memory_controller.write.assert_called_with(0x01, 0xe0) self.assertEqual(registers.pc, 2) self.assertFalse(registers.zero_flag) self.assertTrue(registers.carry_flag) self.assertTrue(registers.negative_flag)