improved implementation of indirect bug across page boundaries including indexed indirects as well

This commit is contained in:
James Tauber 2011-08-07 01:22:48 -04:00
parent 044c86325c
commit 44099ae4f2
2 changed files with 58 additions and 7 deletions

View File

@ -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()

View File

@ -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()