diff --git a/applepy.py b/applepy.py index 0b5acff..44ac7aa 100644 --- a/applepy.py +++ b/applepy.py @@ -39,6 +39,12 @@ class Memory: def read_word(self, address): return self.read_byte(address) + (self.read_byte(address + 1) << 8) + def read_word_bug(self, address): + if address % 0x100 == 0xFF: + return self.read_byte(address) + (self.read_byte(address & 0xFF00) << 8) + else: + return self.read_word(address) + def write_screen(self, address, value): base = address - 0x400 hi, lo = divmod(base, 0x80) @@ -366,17 +372,13 @@ class CPU: return (self.zero_page_mode() + signed(self.y_index)) % 0x100 def indirect_mode(self): - address = self.absolute_mode() - hi = address + 1 - # emulate a known bug in 6502 - hi = (address & 0xFF00) + (((address & 0xFF) + 1) & 0xFF) - return self.memory.read_byte(address) + (self.memory.read_byte(hi) << 8) + return self.memory.read_word_bug(self.absolute_mode()) def indirect_x_mode(self): - return self.memory.read_word((self.read_pc_byte() + signed(self.x_index)) % 0x100) + return self.memory.read_word_bug((self.read_pc_byte() + signed(self.x_index)) % 0x100) def indirect_y_mode(self): - return self.memory.read_word(self.read_pc_byte()) + signed(self.y_index) + return self.memory.read_word_bug(self.read_pc_byte()) + signed(self.y_index) def relative_mode(self): pc = self.get_pc() diff --git a/tests.py b/tests.py index 5b90e86..611b522 100644 --- a/tests.py +++ b/tests.py @@ -949,5 +949,54 @@ class TestSystemFunctionOperations(unittest.TestCase): self.cpu.NOP() +class Test6502Bugs(unittest.TestCase): + + def setUp(self): + self.memory = Memory(0x10000) + self.cpu = CPU(self.memory) + + def test_zero_page_x(self): + self.cpu.x_index = 0x01 + self.memory.load(0x1000, [0x00, 0x7F, 0xFF]) + self.cpu.program_counter = 0x1000 + self.assertEqual(self.cpu.zero_page_x_mode(), 0x01) + self.assertEqual(self.cpu.zero_page_x_mode(), 0x80) + self.assertEqual(self.cpu.zero_page_x_mode(), 0x00) + + def test_indirect(self): + self.memory.load(0x20, [0x00, 0x20]) + self.memory.load(0x00, [0x12]) + self.memory.load(0xFF, [0x34]) + self.memory.load(0x100, [0x56]) + self.memory.load(0x1000, [0x20, 0x20, 0xFF, 0xFF, 0x00, 0x45, 0x23]) + self.memory.load(0x2000, [0x05]) + self.memory.load(0x1234, [0x05]) + self.memory.load(0x2345, [0x00, 0xF0]) + + self.cpu.program_counter = 0x1000 + + self.cpu.x_index = 0x00 + self.cpu.LDA(self.cpu.indirect_x_mode()) + self.assertEqual(self.cpu.accumulator, 0x05) + + self.cpu.y_index = 0x00 + self.cpu.LDA(self.cpu.indirect_y_mode()) + self.assertEqual(self.cpu.accumulator, 0x05) + + self.cpu.y_index = 0x00 + self.cpu.LDA(self.cpu.indirect_y_mode()) + self.assertEqual(self.cpu.accumulator, 0x05) + + self.cpu.x_index = 0x00 + self.cpu.LDA(self.cpu.indirect_x_mode()) + self.assertEqual(self.cpu.accumulator, 0x05) + + self.cpu.x_index = 0xFF + self.cpu.LDA(self.cpu.indirect_x_mode()) + self.assertEqual(self.cpu.accumulator, 0x05) + + self.assertEqual(self.cpu.indirect_mode(), 0xF000) + + if __name__ == "__main__": unittest.main()