whitespace
This commit is contained in:
parent
fe80bc897d
commit
d340d9cb5f
78
applepy.py
78
applepy.py
|
@ -17,7 +17,7 @@ import wave
|
||||||
|
|
||||||
|
|
||||||
class Display:
|
class Display:
|
||||||
|
|
||||||
characters = [
|
characters = [
|
||||||
[0b00000, 0b01110, 0b10001, 0b10101, 0b10111, 0b10110, 0b10000, 0b01111],
|
[0b00000, 0b01110, 0b10001, 0b10101, 0b10111, 0b10110, 0b10000, 0b01111],
|
||||||
[0b00000, 0b00100, 0b01010, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001],
|
[0b00000, 0b00100, 0b01010, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001],
|
||||||
|
@ -84,7 +84,7 @@ class Display:
|
||||||
[0b00000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00010, 0b00100, 0b01000],
|
[0b00000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00010, 0b00100, 0b01000],
|
||||||
[0b00000, 0b01110, 0b10001, 0b00010, 0b00100, 0b00100, 0b00000, 0b00100]
|
[0b00000, 0b01110, 0b10001, 0b00010, 0b00100, 0b00100, 0b00000, 0b00100]
|
||||||
]
|
]
|
||||||
|
|
||||||
lores_colours = [
|
lores_colours = [
|
||||||
(0, 0, 0), # black
|
(0, 0, 0), # black
|
||||||
(208, 0, 48), # magenta / dark red
|
(208, 0, 48), # magenta / dark red
|
||||||
|
@ -103,7 +103,7 @@ class Display:
|
||||||
(64, 255, 144), # aquamarine / light green
|
(64, 255, 144), # aquamarine / light green
|
||||||
(255, 255, 255), # white
|
(255, 255, 255), # white
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.screen = pygame.display.set_mode((560, 384))
|
self.screen = pygame.display.set_mode((560, 384))
|
||||||
pygame.display.set_caption("ApplePy")
|
pygame.display.set_caption("ApplePy")
|
||||||
|
@ -115,7 +115,7 @@ class Display:
|
||||||
self.page = 1
|
self.page = 1
|
||||||
self.text = True
|
self.text = True
|
||||||
self.colour = False
|
self.colour = False
|
||||||
|
|
||||||
self.chargen = []
|
self.chargen = []
|
||||||
for c in self.characters:
|
for c in self.characters:
|
||||||
chars = [[pygame.Surface((14, 16)), pygame.Surface((14, 16))],
|
chars = [[pygame.Surface((14, 16)), pygame.Surface((14, 16))],
|
||||||
|
@ -134,33 +134,33 @@ class Display:
|
||||||
pixels[2 * col + 1][2 * row] = on if bit else off
|
pixels[2 * col + 1][2 * row] = on if bit else off
|
||||||
del pixels
|
del pixels
|
||||||
self.chargen.append(chars)
|
self.chargen.append(chars)
|
||||||
|
|
||||||
def txtclr(self):
|
def txtclr(self):
|
||||||
self.text = False
|
self.text = False
|
||||||
|
|
||||||
def txtset(self):
|
def txtset(self):
|
||||||
self.text = True
|
self.text = True
|
||||||
self.colour = False
|
self.colour = False
|
||||||
|
|
||||||
def mixclr(self):
|
def mixclr(self):
|
||||||
self.mix = False
|
self.mix = False
|
||||||
|
|
||||||
def mixset(self):
|
def mixset(self):
|
||||||
self.mix = True
|
self.mix = True
|
||||||
self.colour = True
|
self.colour = True
|
||||||
|
|
||||||
def lowscr(self):
|
def lowscr(self):
|
||||||
self.page = 1
|
self.page = 1
|
||||||
|
|
||||||
def hiscr(self):
|
def hiscr(self):
|
||||||
self.page = 2
|
self.page = 2
|
||||||
|
|
||||||
def lores(self):
|
def lores(self):
|
||||||
self.high_res = False
|
self.high_res = False
|
||||||
|
|
||||||
def hires(self):
|
def hires(self):
|
||||||
self.high_res = True
|
self.high_res = True
|
||||||
|
|
||||||
def update(self, address, value):
|
def update(self, address, value):
|
||||||
if self.page == 1:
|
if self.page == 1:
|
||||||
start_text = 0x400
|
start_text = 0x400
|
||||||
|
@ -170,33 +170,33 @@ class Display:
|
||||||
start_hires = 0x4000
|
start_hires = 0x4000
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
if start_text <= address <= start_text + 0x3FF:
|
if start_text <= address <= start_text + 0x3FF:
|
||||||
base = address - start_text
|
base = address - start_text
|
||||||
self.flash_chars[self.page - 1][base] = value
|
self.flash_chars[self.page - 1][base] = value
|
||||||
hi, lo = divmod(base, 0x80)
|
hi, lo = divmod(base, 0x80)
|
||||||
row_group, column = divmod(lo, 0x28)
|
row_group, column = divmod(lo, 0x28)
|
||||||
row = hi + 8 * row_group
|
row = hi + 8 * row_group
|
||||||
|
|
||||||
if row_group == 3:
|
if row_group == 3:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.text or not self.mix or not row < 20:
|
if self.text or not self.mix or not row < 20:
|
||||||
mode, ch = divmod(value, 0x40)
|
mode, ch = divmod(value, 0x40)
|
||||||
|
|
||||||
if mode == 0:
|
if mode == 0:
|
||||||
inv = True
|
inv = True
|
||||||
elif mode == 1:
|
elif mode == 1:
|
||||||
inv = self.flash_on
|
inv = self.flash_on
|
||||||
else:
|
else:
|
||||||
inv = False
|
inv = False
|
||||||
|
|
||||||
self.screen.blit(self.chargen[ch][self.colour][inv], (2 * (column * 7), 2 * (row * 8)))
|
self.screen.blit(self.chargen[ch][self.colour][inv], (2 * (column * 7), 2 * (row * 8)))
|
||||||
else:
|
else:
|
||||||
pixels = pygame.PixelArray(self.screen)
|
pixels = pygame.PixelArray(self.screen)
|
||||||
if not self.high_res:
|
if not self.high_res:
|
||||||
lower, upper = divmod(value, 0x10)
|
lower, upper = divmod(value, 0x10)
|
||||||
|
|
||||||
for dx in range(14):
|
for dx in range(14):
|
||||||
for dy in range(8):
|
for dy in range(8):
|
||||||
x = column * 14 + dx
|
x = column * 14 + dx
|
||||||
|
@ -207,7 +207,7 @@ class Display:
|
||||||
y = row * 16 + dy
|
y = row * 16 + dy
|
||||||
pixels[x][y] = self.lores_colours[lower]
|
pixels[x][y] = self.lores_colours[lower]
|
||||||
del pixels
|
del pixels
|
||||||
|
|
||||||
elif start_hires <= address <= start_hires + 0x1FFF:
|
elif start_hires <= address <= start_hires + 0x1FFF:
|
||||||
if self.high_res:
|
if self.high_res:
|
||||||
base = address - start_hires
|
base = address - start_hires
|
||||||
|
@ -215,21 +215,21 @@ class Display:
|
||||||
hi, lo = divmod(b, 0x80)
|
hi, lo = divmod(b, 0x80)
|
||||||
row_group, column = divmod(lo, 0x28)
|
row_group, column = divmod(lo, 0x28)
|
||||||
row = 8 * (hi + 8 * row_group) + row8
|
row = 8 * (hi + 8 * row_group) + row8
|
||||||
|
|
||||||
if self.mix and row >= 160:
|
if self.mix and row >= 160:
|
||||||
return
|
return
|
||||||
|
|
||||||
if row < 192 and column < 40:
|
if row < 192 and column < 40:
|
||||||
|
|
||||||
pixels = pygame.PixelArray(self.screen)
|
pixels = pygame.PixelArray(self.screen)
|
||||||
msb = value // 0x80
|
msb = value // 0x80
|
||||||
|
|
||||||
for b in range(7):
|
for b in range(7):
|
||||||
c = value & (1 << b)
|
c = value & (1 << b)
|
||||||
xx = (column * 7 + b)
|
xx = (column * 7 + b)
|
||||||
x = 2 * xx
|
x = 2 * xx
|
||||||
y = 2 * row
|
y = 2 * row
|
||||||
|
|
||||||
if msb:
|
if msb:
|
||||||
if xx % 2:
|
if xx % 2:
|
||||||
pixels[x][y] = (0, 0, 0)
|
pixels[x][y] = (0, 0, 0)
|
||||||
|
@ -252,10 +252,10 @@ class Display:
|
||||||
pixels[x][y] = (255, 0, 255) if c else (0, 0, 0)
|
pixels[x][y] = (255, 0, 255) if c else (0, 0, 0)
|
||||||
pixels[x + 1][y] = (0, 0, 0)
|
pixels[x + 1][y] = (0, 0, 0)
|
||||||
pixels[x + 1][y] = (255, 0, 255) if c else (0, 0, 0) # @@@
|
pixels[x + 1][y] = (255, 0, 255) if c else (0, 0, 0) # @@@
|
||||||
|
|
||||||
pixels[x][y + 1] = (0, 0, 0)
|
pixels[x][y + 1] = (0, 0, 0)
|
||||||
pixels[x + 1][y + 1] = (0, 0, 0)
|
pixels[x + 1][y + 1] = (0, 0, 0)
|
||||||
|
|
||||||
del pixels
|
del pixels
|
||||||
|
|
||||||
def flash(self):
|
def flash(self):
|
||||||
|
@ -268,15 +268,15 @@ class Display:
|
||||||
|
|
||||||
|
|
||||||
class Speaker:
|
class Speaker:
|
||||||
|
|
||||||
CPU_CYCLES_PER_SAMPLE = 60
|
CPU_CYCLES_PER_SAMPLE = 60
|
||||||
CHECK_INTERVAL = 1000
|
CHECK_INTERVAL = 1000
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pygame.mixer.pre_init(11025, -16, 1)
|
pygame.mixer.pre_init(11025, -16, 1)
|
||||||
pygame.init()
|
pygame.init()
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def toggle(self, cycle):
|
def toggle(self, cycle):
|
||||||
if self.last_toggle is not None:
|
if self.last_toggle is not None:
|
||||||
l = (cycle - self.last_toggle) / Speaker.CPU_CYCLES_PER_SAMPLE
|
l = (cycle - self.last_toggle) / Speaker.CPU_CYCLES_PER_SAMPLE
|
||||||
|
@ -284,18 +284,18 @@ class Speaker:
|
||||||
self.buffer.extend((l - 2) * [16384] if self.polarity else [-16384])
|
self.buffer.extend((l - 2) * [16384] if self.polarity else [-16384])
|
||||||
self.polarity = not self.polarity
|
self.polarity = not self.polarity
|
||||||
self.last_toggle = cycle
|
self.last_toggle = cycle
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.last_toggle = None
|
self.last_toggle = None
|
||||||
self.buffer = []
|
self.buffer = []
|
||||||
self.polarity = False
|
self.polarity = False
|
||||||
|
|
||||||
def play(self):
|
def play(self):
|
||||||
sample_array = numpy.int16(self.buffer)
|
sample_array = numpy.int16(self.buffer)
|
||||||
sound = pygame.sndarray.make_sound(sample_array)
|
sound = pygame.sndarray.make_sound(sample_array)
|
||||||
sound.play()
|
sound.play()
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def update(self, cycle):
|
def update(self, cycle):
|
||||||
if self.buffer and (cycle - self.last_toggle) > self.CHECK_INTERVAL:
|
if self.buffer and (cycle - self.last_toggle) > self.CHECK_INTERVAL:
|
||||||
self.play()
|
self.play()
|
||||||
|
@ -322,13 +322,13 @@ class Cassette:
|
||||||
|
|
||||||
|
|
||||||
class SoftSwitches:
|
class SoftSwitches:
|
||||||
|
|
||||||
def __init__(self, display, speaker, cassette):
|
def __init__(self, display, speaker, cassette):
|
||||||
self.kbd = 0x00
|
self.kbd = 0x00
|
||||||
self.display = display
|
self.display = display
|
||||||
self.speaker = speaker
|
self.speaker = speaker
|
||||||
self.cassette = cassette
|
self.cassette = cassette
|
||||||
|
|
||||||
def read_byte(self, cycle, address):
|
def read_byte(self, cycle, address):
|
||||||
assert 0xC000 <= address <= 0xCFFF
|
assert 0xC000 <= address <= 0xCFFF
|
||||||
if address == 0xC000:
|
if address == 0xC000:
|
||||||
|
@ -409,11 +409,11 @@ class Apple2:
|
||||||
self.display.update(addr, val)
|
self.display.update(addr, val)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
quit = True
|
quit = True
|
||||||
|
|
||||||
if event.type == pygame.KEYDOWN:
|
if event.type == pygame.KEYDOWN:
|
||||||
key = ord(event.unicode) if event.unicode else 0
|
key = ord(event.unicode) if event.unicode else 0
|
||||||
if event.key == pygame.K_LEFT:
|
if event.key == pygame.K_LEFT:
|
||||||
|
@ -424,7 +424,7 @@ class Apple2:
|
||||||
if key == 0x7F:
|
if key == 0x7F:
|
||||||
key = 0x08
|
key = 0x08
|
||||||
self.softswitches.kbd = 0x80 + (key & 0x7F)
|
self.softswitches.kbd = 0x80 + (key & 0x7F)
|
||||||
|
|
||||||
update_cycle += 1
|
update_cycle += 1
|
||||||
if update_cycle >= 1024:
|
if update_cycle >= 1024:
|
||||||
self.display.flash()
|
self.display.flash()
|
||||||
|
@ -432,7 +432,7 @@ class Apple2:
|
||||||
if self.speaker:
|
if self.speaker:
|
||||||
self.speaker.update(cycle)
|
self.speaker.update(cycle)
|
||||||
update_cycle = 0
|
update_cycle = 0
|
||||||
|
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
print >>sys.stderr, "ApplePy - an Apple ][ emulator in Python"
|
print >>sys.stderr, "ApplePy - an Apple ][ emulator in Python"
|
||||||
|
|
|
@ -18,13 +18,13 @@ def write_screen(win, address, value):
|
||||||
hi, lo = divmod(base, 0x80)
|
hi, lo = divmod(base, 0x80)
|
||||||
row_group, column = divmod(lo, 0x28)
|
row_group, column = divmod(lo, 0x28)
|
||||||
row = hi + 8 * row_group
|
row = hi + 8 * row_group
|
||||||
|
|
||||||
# skip if writing to row group 3
|
# skip if writing to row group 3
|
||||||
if row_group == 3:
|
if row_group == 3:
|
||||||
return
|
return
|
||||||
|
|
||||||
c = chr(0x20 + ((value + 0x20) % 0x40))
|
c = chr(0x20 + ((value + 0x20) % 0x40))
|
||||||
|
|
||||||
if value < 0x40:
|
if value < 0x40:
|
||||||
attr = curses.A_DIM
|
attr = curses.A_DIM
|
||||||
elif value < 0x80:
|
elif value < 0x80:
|
||||||
|
@ -33,7 +33,7 @@ def write_screen(win, address, value):
|
||||||
attr = curses.A_UNDERLINE
|
attr = curses.A_UNDERLINE
|
||||||
else:
|
else:
|
||||||
attr = curses.A_DIM
|
attr = curses.A_DIM
|
||||||
|
|
||||||
try:
|
try:
|
||||||
win.addch(row, column, c, attr)
|
win.addch(row, column, c, attr)
|
||||||
except curses.error:
|
except curses.error:
|
||||||
|
@ -95,7 +95,7 @@ def run(win):
|
||||||
pass
|
pass
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
print >>sys.stderr, "ApplePy - an Apple ][ emulator in Python"
|
print >>sys.stderr, "ApplePy - an Apple ][ emulator in Python"
|
||||||
|
|
306
cpu6502.py
306
cpu6502.py
|
@ -22,50 +22,50 @@ def signed(x):
|
||||||
|
|
||||||
|
|
||||||
class ROM:
|
class ROM:
|
||||||
|
|
||||||
def __init__(self, start, size):
|
def __init__(self, start, size):
|
||||||
self.start = start
|
self.start = start
|
||||||
self.end = start + size - 1
|
self.end = start + size - 1
|
||||||
self._mem = [0x00] * size
|
self._mem = [0x00] * size
|
||||||
|
|
||||||
def load(self, address, data):
|
def load(self, address, data):
|
||||||
for offset, datum in enumerate(data):
|
for offset, datum in enumerate(data):
|
||||||
self._mem[address - self.start + offset] = datum
|
self._mem[address - self.start + offset] = datum
|
||||||
|
|
||||||
def load_file(self, address, filename):
|
def load_file(self, address, filename):
|
||||||
with open(filename, "rb") as f:
|
with open(filename, "rb") as f:
|
||||||
for offset, datum in enumerate(f.read()):
|
for offset, datum in enumerate(f.read()):
|
||||||
self._mem[address - self.start + offset] = ord(datum)
|
self._mem[address - self.start + offset] = ord(datum)
|
||||||
|
|
||||||
def read_byte(self, address):
|
def read_byte(self, address):
|
||||||
assert self.start <= address <= self.end
|
assert self.start <= address <= self.end
|
||||||
return self._mem[address - self.start]
|
return self._mem[address - self.start]
|
||||||
|
|
||||||
|
|
||||||
class RAM(ROM):
|
class RAM(ROM):
|
||||||
|
|
||||||
def write_byte(self, address, value):
|
def write_byte(self, address, value):
|
||||||
self._mem[address] = value
|
self._mem[address] = value
|
||||||
|
|
||||||
|
|
||||||
class Memory:
|
class Memory:
|
||||||
|
|
||||||
def __init__(self, options=None, use_bus=True):
|
def __init__(self, options=None, use_bus=True):
|
||||||
self.use_bus = use_bus
|
self.use_bus = use_bus
|
||||||
self.rom = ROM(0xD000, 0x3000)
|
self.rom = ROM(0xD000, 0x3000)
|
||||||
|
|
||||||
if options:
|
if options:
|
||||||
self.rom.load_file(0xD000, options.rom)
|
self.rom.load_file(0xD000, options.rom)
|
||||||
|
|
||||||
self.ram = RAM(0x0000, 0xC000)
|
self.ram = RAM(0x0000, 0xC000)
|
||||||
|
|
||||||
if options and options.ram:
|
if options and options.ram:
|
||||||
self.ram.load_file(0x0000, options.ram)
|
self.ram.load_file(0x0000, options.ram)
|
||||||
|
|
||||||
def load(self, address, data):
|
def load(self, address, data):
|
||||||
if address < 0xC000:
|
if address < 0xC000:
|
||||||
self.ram.load(address, data)
|
self.ram.load(address, data)
|
||||||
|
|
||||||
def read_byte(self, cycle, address):
|
def read_byte(self, cycle, address):
|
||||||
if address < 0xC000:
|
if address < 0xC000:
|
||||||
return self.ram.read_byte(address)
|
return self.ram.read_byte(address)
|
||||||
|
@ -73,16 +73,16 @@ class Memory:
|
||||||
return self.bus_read(cycle, address)
|
return self.bus_read(cycle, address)
|
||||||
else:
|
else:
|
||||||
return self.rom.read_byte(address)
|
return self.rom.read_byte(address)
|
||||||
|
|
||||||
def read_word(self, cycle, address):
|
def read_word(self, cycle, address):
|
||||||
return self.read_byte(cycle, address) + (self.read_byte(cycle + 1, address + 1) << 8)
|
return self.read_byte(cycle, address) + (self.read_byte(cycle + 1, address + 1) << 8)
|
||||||
|
|
||||||
def read_word_bug(self, cycle, address):
|
def read_word_bug(self, cycle, address):
|
||||||
if address % 0x100 == 0xFF:
|
if address % 0x100 == 0xFF:
|
||||||
return self.read_byte(cycle, address) + (self.read_byte(cycle + 1, address & 0xFF00) << 8)
|
return self.read_byte(cycle, address) + (self.read_byte(cycle + 1, address & 0xFF00) << 8)
|
||||||
else:
|
else:
|
||||||
return self.read_word(cycle, address)
|
return self.read_word(cycle, address)
|
||||||
|
|
||||||
def write_byte(self, cycle, address, value):
|
def write_byte(self, cycle, address, value):
|
||||||
if address < 0xC000:
|
if address < 0xC000:
|
||||||
self.ram.write_byte(address, value)
|
self.ram.write_byte(address, value)
|
||||||
|
@ -116,9 +116,9 @@ class Disassemble:
|
||||||
def __init__(self, cpu, memory):
|
def __init__(self, cpu, memory):
|
||||||
self.cpu = cpu
|
self.cpu = cpu
|
||||||
self.memory = memory
|
self.memory = memory
|
||||||
|
|
||||||
self.setup_ops()
|
self.setup_ops()
|
||||||
|
|
||||||
def setup_ops(self):
|
def setup_ops(self):
|
||||||
self.ops = [(1, "???")] * 0x100
|
self.ops = [(1, "???")] * 0x100
|
||||||
self.ops[0x00] = (1, "BRK", )
|
self.ops[0x00] = (1, "BRK", )
|
||||||
|
@ -272,14 +272,14 @@ class Disassemble:
|
||||||
self.ops[0xF9] = (3, "SBC", self.absolute_y_mode)
|
self.ops[0xF9] = (3, "SBC", self.absolute_y_mode)
|
||||||
self.ops[0xFD] = (3, "SBC", self.absolute_x_mode)
|
self.ops[0xFD] = (3, "SBC", self.absolute_x_mode)
|
||||||
self.ops[0xFE] = (3, "INC", self.absolute_x_mode)
|
self.ops[0xFE] = (3, "INC", self.absolute_x_mode)
|
||||||
|
|
||||||
def absolute_mode(self, pc):
|
def absolute_mode(self, pc):
|
||||||
a = self.cpu.read_word(pc + 1)
|
a = self.cpu.read_word(pc + 1)
|
||||||
return {
|
return {
|
||||||
"operand": "$%04X" % a,
|
"operand": "$%04X" % a,
|
||||||
"memory": [a, 2, self.cpu.read_word(a)],
|
"memory": [a, 2, self.cpu.read_word(a)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def absolute_x_mode(self, pc):
|
def absolute_x_mode(self, pc):
|
||||||
a = self.cpu.read_word(pc + 1)
|
a = self.cpu.read_word(pc + 1)
|
||||||
e = a + self.cpu.x_index
|
e = a + self.cpu.x_index
|
||||||
|
@ -287,7 +287,7 @@ class Disassemble:
|
||||||
"operand": "$%04X,X" % a,
|
"operand": "$%04X,X" % a,
|
||||||
"memory": [e, 1, self.cpu.read_byte(e)],
|
"memory": [e, 1, self.cpu.read_byte(e)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def absolute_y_mode(self, pc):
|
def absolute_y_mode(self, pc):
|
||||||
a = self.cpu.read_word(pc + 1)
|
a = self.cpu.read_word(pc + 1)
|
||||||
e = a + self.cpu.y_index
|
e = a + self.cpu.y_index
|
||||||
|
@ -295,19 +295,19 @@ class Disassemble:
|
||||||
"operand": "$%04X,Y" % a,
|
"operand": "$%04X,Y" % a,
|
||||||
"memory": [e, 1, self.cpu.read_byte(e)],
|
"memory": [e, 1, self.cpu.read_byte(e)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def immediate_mode(self, pc):
|
def immediate_mode(self, pc):
|
||||||
return {
|
return {
|
||||||
"operand": "#$%02X" % (self.cpu.read_byte(pc + 1)),
|
"operand": "#$%02X" % (self.cpu.read_byte(pc + 1)),
|
||||||
}
|
}
|
||||||
|
|
||||||
def indirect_mode(self, pc):
|
def indirect_mode(self, pc):
|
||||||
a = self.cpu.read_word(pc + 1)
|
a = self.cpu.read_word(pc + 1)
|
||||||
return {
|
return {
|
||||||
"operand": "($%04X)" % a,
|
"operand": "($%04X)" % a,
|
||||||
"memory": [a, 2, self.cpu.read_word(a)],
|
"memory": [a, 2, self.cpu.read_word(a)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def indirect_x_mode(self, pc):
|
def indirect_x_mode(self, pc):
|
||||||
z = self.cpu.read_byte(pc + 1)
|
z = self.cpu.read_byte(pc + 1)
|
||||||
a = self.cpu.read_word((z + self.cpu.x_index) % 0x100)
|
a = self.cpu.read_word((z + self.cpu.x_index) % 0x100)
|
||||||
|
@ -315,7 +315,7 @@ class Disassemble:
|
||||||
"operand": "($%02X,X)" % z,
|
"operand": "($%02X,X)" % z,
|
||||||
"memory": [a, 1, self.cpu.read_byte(a)],
|
"memory": [a, 1, self.cpu.read_byte(a)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def indirect_y_mode(self, pc):
|
def indirect_y_mode(self, pc):
|
||||||
z = self.cpu.read_byte(pc + 1)
|
z = self.cpu.read_byte(pc + 1)
|
||||||
a = self.cpu.read_word(z) + self.cpu.y_index
|
a = self.cpu.read_word(z) + self.cpu.y_index
|
||||||
|
@ -323,19 +323,19 @@ class Disassemble:
|
||||||
"operand": "($%02X),Y" % z,
|
"operand": "($%02X),Y" % z,
|
||||||
"memory": [a, 1, self.cpu.read_byte(a)],
|
"memory": [a, 1, self.cpu.read_byte(a)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def relative_mode(self, pc):
|
def relative_mode(self, pc):
|
||||||
return {
|
return {
|
||||||
"operand": "$%04X" % (pc + signed(self.cpu.read_byte(pc + 1) + 2)),
|
"operand": "$%04X" % (pc + signed(self.cpu.read_byte(pc + 1) + 2)),
|
||||||
}
|
}
|
||||||
|
|
||||||
def zero_page_mode(self, pc):
|
def zero_page_mode(self, pc):
|
||||||
a = self.cpu.read_byte(pc + 1)
|
a = self.cpu.read_byte(pc + 1)
|
||||||
return {
|
return {
|
||||||
"operand": "$%02X" % a,
|
"operand": "$%02X" % a,
|
||||||
"memory": [a, 1, self.cpu.read_byte(a)],
|
"memory": [a, 1, self.cpu.read_byte(a)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def zero_page_x_mode(self, pc):
|
def zero_page_x_mode(self, pc):
|
||||||
z = self.cpu.read_byte(pc + 1)
|
z = self.cpu.read_byte(pc + 1)
|
||||||
a = (z + self.cpu.x_index) % 0x100
|
a = (z + self.cpu.x_index) % 0x100
|
||||||
|
@ -343,7 +343,7 @@ class Disassemble:
|
||||||
"operand": "$%02X,X" % z,
|
"operand": "$%02X,X" % z,
|
||||||
"memory": [a, 1, self.cpu.read_byte(a)],
|
"memory": [a, 1, self.cpu.read_byte(a)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def zero_page_y_mode(self, pc):
|
def zero_page_y_mode(self, pc):
|
||||||
z = self.cpu.read_byte(pc + 1)
|
z = self.cpu.read_byte(pc + 1)
|
||||||
a = (z + self.cpu.y_index) % 0x100
|
a = (z + self.cpu.y_index) % 0x100
|
||||||
|
@ -351,7 +351,7 @@ class Disassemble:
|
||||||
"operand": "$%02X,Y" % z,
|
"operand": "$%02X,Y" % z,
|
||||||
"memory": [a, 1, self.cpu.read_byte(a)],
|
"memory": [a, 1, self.cpu.read_byte(a)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def disasm(self, pc):
|
def disasm(self, pc):
|
||||||
op = self.cpu.read_byte(pc)
|
op = self.cpu.read_byte(pc)
|
||||||
info = self.ops[op]
|
info = self.ops[op]
|
||||||
|
@ -501,19 +501,19 @@ class ControlHandlerFactory:
|
||||||
|
|
||||||
|
|
||||||
class CPU:
|
class CPU:
|
||||||
|
|
||||||
STACK_PAGE = 0x100
|
STACK_PAGE = 0x100
|
||||||
RESET_VECTOR = 0xFFFC
|
RESET_VECTOR = 0xFFFC
|
||||||
|
|
||||||
def __init__(self, options, memory):
|
def __init__(self, options, memory):
|
||||||
self.memory = memory
|
self.memory = memory
|
||||||
|
|
||||||
self.control_server = BaseHTTPServer.HTTPServer(("127.0.0.1", 6502), ControlHandlerFactory(self))
|
self.control_server = BaseHTTPServer.HTTPServer(("127.0.0.1", 6502), ControlHandlerFactory(self))
|
||||||
|
|
||||||
self.accumulator = 0x00
|
self.accumulator = 0x00
|
||||||
self.x_index = 0x00
|
self.x_index = 0x00
|
||||||
self.y_index = 0x00
|
self.y_index = 0x00
|
||||||
|
|
||||||
self.carry_flag = 0
|
self.carry_flag = 0
|
||||||
self.zero_flag = 0
|
self.zero_flag = 0
|
||||||
self.interrupt_disable_flag = 0
|
self.interrupt_disable_flag = 0
|
||||||
|
@ -521,18 +521,18 @@ class CPU:
|
||||||
self.break_flag = 1
|
self.break_flag = 1
|
||||||
self.overflow_flag = 0
|
self.overflow_flag = 0
|
||||||
self.sign_flag = 0
|
self.sign_flag = 0
|
||||||
|
|
||||||
self.stack_pointer = 0xFF
|
self.stack_pointer = 0xFF
|
||||||
|
|
||||||
self.cycles = 0
|
self.cycles = 0
|
||||||
|
|
||||||
self.setup_ops()
|
self.setup_ops()
|
||||||
self.reset()
|
self.reset()
|
||||||
if options.pc is not None:
|
if options.pc is not None:
|
||||||
self.program_counter = options.pc
|
self.program_counter = options.pc
|
||||||
self.running = True
|
self.running = True
|
||||||
self.quit = False
|
self.quit = False
|
||||||
|
|
||||||
def setup_ops(self):
|
def setup_ops(self):
|
||||||
self.ops = [None] * 0x100
|
self.ops = [None] * 0x100
|
||||||
self.ops[0x00] = lambda: self.BRK()
|
self.ops[0x00] = lambda: self.BRK()
|
||||||
|
@ -686,10 +686,10 @@ class CPU:
|
||||||
self.ops[0xF9] = lambda: self.SBC(self.absolute_y_mode())
|
self.ops[0xF9] = lambda: self.SBC(self.absolute_y_mode())
|
||||||
self.ops[0xFD] = lambda: self.SBC(self.absolute_x_mode())
|
self.ops[0xFD] = lambda: self.SBC(self.absolute_x_mode())
|
||||||
self.ops[0xFE] = lambda: self.INC(self.absolute_x_mode(rmw=True))
|
self.ops[0xFE] = lambda: self.INC(self.absolute_x_mode(rmw=True))
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.program_counter = self.read_word(self.RESET_VECTOR)
|
self.program_counter = self.read_word(self.RESET_VECTOR)
|
||||||
|
|
||||||
def run(self, bus_port):
|
def run(self, bus_port):
|
||||||
global bus
|
global bus
|
||||||
bus = socket.socket()
|
bus = socket.socket()
|
||||||
|
@ -725,7 +725,7 @@ class CPU:
|
||||||
else:
|
else:
|
||||||
self.ops[op]()
|
self.ops[op]()
|
||||||
count -= 1
|
count -= 1
|
||||||
|
|
||||||
def test_run(self, start, end):
|
def test_run(self, start, end):
|
||||||
self.program_counter = start
|
self.program_counter = start
|
||||||
while True:
|
while True:
|
||||||
|
@ -741,34 +741,34 @@ class CPU:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.ops[op]()
|
self.ops[op]()
|
||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
def get_pc(self, inc=1):
|
def get_pc(self, inc=1):
|
||||||
pc = self.program_counter
|
pc = self.program_counter
|
||||||
self.program_counter += inc
|
self.program_counter += inc
|
||||||
return pc
|
return pc
|
||||||
|
|
||||||
def read_byte(self, address):
|
def read_byte(self, address):
|
||||||
return self.memory.read_byte(self.cycles, address)
|
return self.memory.read_byte(self.cycles, address)
|
||||||
|
|
||||||
def read_word(self, address):
|
def read_word(self, address):
|
||||||
return self.memory.read_word(self.cycles, address)
|
return self.memory.read_word(self.cycles, address)
|
||||||
|
|
||||||
def read_word_bug(self, address):
|
def read_word_bug(self, address):
|
||||||
return self.memory.read_word_bug(self.cycles, address)
|
return self.memory.read_word_bug(self.cycles, address)
|
||||||
|
|
||||||
def read_pc_byte(self):
|
def read_pc_byte(self):
|
||||||
return self.read_byte(self.get_pc())
|
return self.read_byte(self.get_pc())
|
||||||
|
|
||||||
def read_pc_word(self):
|
def read_pc_word(self):
|
||||||
return self.read_word(self.get_pc(2))
|
return self.read_word(self.get_pc(2))
|
||||||
|
|
||||||
def write_byte(self, address, value):
|
def write_byte(self, address, value):
|
||||||
self.memory.write_byte(self.cycles, address, value)
|
self.memory.write_byte(self.cycles, address, value)
|
||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
def status_from_byte(self, status):
|
def status_from_byte(self, status):
|
||||||
self.carry_flag = [0, 1][0 != status & 1]
|
self.carry_flag = [0, 1][0 != status & 1]
|
||||||
self.zero_flag = [0, 1][0 != status & 2]
|
self.zero_flag = [0, 1][0 != status & 2]
|
||||||
|
@ -777,143 +777,143 @@ class CPU:
|
||||||
self.break_flag = [0, 1][0 != status & 16]
|
self.break_flag = [0, 1][0 != status & 16]
|
||||||
self.overflow_flag = [0, 1][0 != status & 64]
|
self.overflow_flag = [0, 1][0 != status & 64]
|
||||||
self.sign_flag = [0, 1][0 != status & 128]
|
self.sign_flag = [0, 1][0 != status & 128]
|
||||||
|
|
||||||
def status_as_byte(self):
|
def status_as_byte(self):
|
||||||
return self.carry_flag | self.zero_flag << 1 | self.interrupt_disable_flag << 2 | self.decimal_mode_flag << 3 | self.break_flag << 4 | 1 << 5 | self.overflow_flag << 6 | self.sign_flag << 7
|
return self.carry_flag | self.zero_flag << 1 | self.interrupt_disable_flag << 2 | self.decimal_mode_flag << 3 | self.break_flag << 4 | 1 << 5 | self.overflow_flag << 6 | self.sign_flag << 7
|
||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
def push_byte(self, byte):
|
def push_byte(self, byte):
|
||||||
self.write_byte(self.STACK_PAGE + self.stack_pointer, byte)
|
self.write_byte(self.STACK_PAGE + self.stack_pointer, byte)
|
||||||
self.stack_pointer = (self.stack_pointer - 1) % 0x100
|
self.stack_pointer = (self.stack_pointer - 1) % 0x100
|
||||||
|
|
||||||
def pull_byte(self):
|
def pull_byte(self):
|
||||||
self.stack_pointer = (self.stack_pointer + 1) % 0x100
|
self.stack_pointer = (self.stack_pointer + 1) % 0x100
|
||||||
return self.read_byte(self.STACK_PAGE + self.stack_pointer)
|
return self.read_byte(self.STACK_PAGE + self.stack_pointer)
|
||||||
|
|
||||||
def push_word(self, word):
|
def push_word(self, word):
|
||||||
hi, lo = divmod(word, 0x100)
|
hi, lo = divmod(word, 0x100)
|
||||||
self.push_byte(hi)
|
self.push_byte(hi)
|
||||||
self.push_byte(lo)
|
self.push_byte(lo)
|
||||||
|
|
||||||
def pull_word(self):
|
def pull_word(self):
|
||||||
s = self.STACK_PAGE + self.stack_pointer + 1
|
s = self.STACK_PAGE + self.stack_pointer + 1
|
||||||
self.stack_pointer += 2
|
self.stack_pointer += 2
|
||||||
return self.read_word(s)
|
return self.read_word(s)
|
||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
def immediate_mode(self):
|
def immediate_mode(self):
|
||||||
return self.get_pc()
|
return self.get_pc()
|
||||||
|
|
||||||
def absolute_mode(self):
|
def absolute_mode(self):
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
return self.read_pc_word()
|
return self.read_pc_word()
|
||||||
|
|
||||||
def absolute_x_mode(self, rmw=False):
|
def absolute_x_mode(self, rmw=False):
|
||||||
if rmw:
|
if rmw:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
return self.absolute_mode() + self.x_index
|
return self.absolute_mode() + self.x_index
|
||||||
|
|
||||||
def absolute_y_mode(self, rmw=False):
|
def absolute_y_mode(self, rmw=False):
|
||||||
if rmw:
|
if rmw:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
return self.absolute_mode() + self.y_index
|
return self.absolute_mode() + self.y_index
|
||||||
|
|
||||||
def zero_page_mode(self):
|
def zero_page_mode(self):
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
return self.read_pc_byte()
|
return self.read_pc_byte()
|
||||||
|
|
||||||
def zero_page_x_mode(self):
|
def zero_page_x_mode(self):
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
return (self.zero_page_mode() + self.x_index) % 0x100
|
return (self.zero_page_mode() + self.x_index) % 0x100
|
||||||
|
|
||||||
def zero_page_y_mode(self):
|
def zero_page_y_mode(self):
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
return (self.zero_page_mode() + self.y_index) % 0x100
|
return (self.zero_page_mode() + self.y_index) % 0x100
|
||||||
|
|
||||||
def indirect_mode(self):
|
def indirect_mode(self):
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
return self.read_word_bug(self.absolute_mode())
|
return self.read_word_bug(self.absolute_mode())
|
||||||
|
|
||||||
def indirect_x_mode(self):
|
def indirect_x_mode(self):
|
||||||
self.cycles += 4
|
self.cycles += 4
|
||||||
return self.read_word_bug((self.read_pc_byte() + self.x_index) % 0x100)
|
return self.read_word_bug((self.read_pc_byte() + self.x_index) % 0x100)
|
||||||
|
|
||||||
def indirect_y_mode(self, rmw=False):
|
def indirect_y_mode(self, rmw=False):
|
||||||
if rmw:
|
if rmw:
|
||||||
self.cycles += 4
|
self.cycles += 4
|
||||||
else:
|
else:
|
||||||
self.cycles += 3
|
self.cycles += 3
|
||||||
return self.read_word_bug(self.read_pc_byte()) + self.y_index
|
return self.read_word_bug(self.read_pc_byte()) + self.y_index
|
||||||
|
|
||||||
def relative_mode(self):
|
def relative_mode(self):
|
||||||
pc = self.get_pc()
|
pc = self.get_pc()
|
||||||
return pc + 1 + signed(self.read_byte(pc))
|
return pc + 1 + signed(self.read_byte(pc))
|
||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
def update_nz(self, value):
|
def update_nz(self, value):
|
||||||
value = value % 0x100
|
value = value % 0x100
|
||||||
self.zero_flag = [0, 1][(value == 0)]
|
self.zero_flag = [0, 1][(value == 0)]
|
||||||
self.sign_flag = [0, 1][((value & 0x80) != 0)]
|
self.sign_flag = [0, 1][((value & 0x80) != 0)]
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def update_nzc(self, value):
|
def update_nzc(self, value):
|
||||||
self.carry_flag = [0, 1][(value > 0xFF)]
|
self.carry_flag = [0, 1][(value > 0xFF)]
|
||||||
return self.update_nz(value)
|
return self.update_nz(value)
|
||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
# LOAD / STORE
|
# LOAD / STORE
|
||||||
|
|
||||||
def LDA(self, operand_address):
|
def LDA(self, operand_address):
|
||||||
self.accumulator = self.update_nz(self.read_byte(operand_address))
|
self.accumulator = self.update_nz(self.read_byte(operand_address))
|
||||||
|
|
||||||
def LDX(self, operand_address):
|
def LDX(self, operand_address):
|
||||||
self.x_index = self.update_nz(self.read_byte(operand_address))
|
self.x_index = self.update_nz(self.read_byte(operand_address))
|
||||||
|
|
||||||
def LDY(self, operand_address):
|
def LDY(self, operand_address):
|
||||||
self.y_index = self.update_nz(self.read_byte(operand_address))
|
self.y_index = self.update_nz(self.read_byte(operand_address))
|
||||||
|
|
||||||
def STA(self, operand_address):
|
def STA(self, operand_address):
|
||||||
self.write_byte(operand_address, self.accumulator)
|
self.write_byte(operand_address, self.accumulator)
|
||||||
|
|
||||||
def STX(self, operand_address):
|
def STX(self, operand_address):
|
||||||
self.write_byte(operand_address, self.x_index)
|
self.write_byte(operand_address, self.x_index)
|
||||||
|
|
||||||
def STY(self, operand_address):
|
def STY(self, operand_address):
|
||||||
self.write_byte(operand_address, self.y_index)
|
self.write_byte(operand_address, self.y_index)
|
||||||
|
|
||||||
# TRANSFER
|
# TRANSFER
|
||||||
|
|
||||||
def TAX(self):
|
def TAX(self):
|
||||||
self.x_index = self.update_nz(self.accumulator)
|
self.x_index = self.update_nz(self.accumulator)
|
||||||
|
|
||||||
def TXA(self):
|
def TXA(self):
|
||||||
self.accumulator = self.update_nz(self.x_index)
|
self.accumulator = self.update_nz(self.x_index)
|
||||||
|
|
||||||
def TAY(self):
|
def TAY(self):
|
||||||
self.y_index = self.update_nz(self.accumulator)
|
self.y_index = self.update_nz(self.accumulator)
|
||||||
|
|
||||||
def TYA(self):
|
def TYA(self):
|
||||||
self.accumulator = self.update_nz(self.y_index)
|
self.accumulator = self.update_nz(self.y_index)
|
||||||
|
|
||||||
def TSX(self):
|
def TSX(self):
|
||||||
self.x_index = self.update_nz(self.stack_pointer)
|
self.x_index = self.update_nz(self.stack_pointer)
|
||||||
|
|
||||||
def TXS(self):
|
def TXS(self):
|
||||||
self.stack_pointer = self.x_index
|
self.stack_pointer = self.x_index
|
||||||
|
|
||||||
# SHIFTS / ROTATES
|
# SHIFTS / ROTATES
|
||||||
|
|
||||||
def ASL(self, operand_address=None):
|
def ASL(self, operand_address=None):
|
||||||
if operand_address is None:
|
if operand_address is None:
|
||||||
self.accumulator = self.update_nzc(self.accumulator << 1)
|
self.accumulator = self.update_nzc(self.accumulator << 1)
|
||||||
else:
|
else:
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
self.write_byte(operand_address, self.update_nzc(self.read_byte(operand_address) << 1))
|
self.write_byte(operand_address, self.update_nzc(self.read_byte(operand_address) << 1))
|
||||||
|
|
||||||
def ROL(self, operand_address=None):
|
def ROL(self, operand_address=None):
|
||||||
if operand_address is None:
|
if operand_address is None:
|
||||||
a = self.accumulator << 1
|
a = self.accumulator << 1
|
||||||
|
@ -926,7 +926,7 @@ class CPU:
|
||||||
if self.carry_flag:
|
if self.carry_flag:
|
||||||
m = m | 0x01
|
m = m | 0x01
|
||||||
self.write_byte(operand_address, self.update_nzc(m))
|
self.write_byte(operand_address, self.update_nzc(m))
|
||||||
|
|
||||||
def ROR(self, operand_address=None):
|
def ROR(self, operand_address=None):
|
||||||
if operand_address is None:
|
if operand_address is None:
|
||||||
if self.carry_flag:
|
if self.carry_flag:
|
||||||
|
@ -940,7 +940,7 @@ class CPU:
|
||||||
m = m | 0x100
|
m = m | 0x100
|
||||||
self.carry_flag = m % 2
|
self.carry_flag = m % 2
|
||||||
self.write_byte(operand_address, self.update_nz(m >> 1))
|
self.write_byte(operand_address, self.update_nz(m >> 1))
|
||||||
|
|
||||||
def LSR(self, operand_address=None):
|
def LSR(self, operand_address=None):
|
||||||
if operand_address is None:
|
if operand_address is None:
|
||||||
self.carry_flag = self.accumulator % 2
|
self.carry_flag = self.accumulator % 2
|
||||||
|
@ -949,224 +949,224 @@ class CPU:
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
self.carry_flag = self.read_byte(operand_address) % 2
|
self.carry_flag = self.read_byte(operand_address) % 2
|
||||||
self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) >> 1))
|
self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) >> 1))
|
||||||
|
|
||||||
# JUMPS / RETURNS
|
# JUMPS / RETURNS
|
||||||
|
|
||||||
def JMP(self, operand_address):
|
def JMP(self, operand_address):
|
||||||
self.cycles -= 1
|
self.cycles -= 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def JSR(self, operand_address):
|
def JSR(self, operand_address):
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
self.push_word(self.program_counter - 1)
|
self.push_word(self.program_counter - 1)
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def RTS(self):
|
def RTS(self):
|
||||||
self.cycles += 4
|
self.cycles += 4
|
||||||
self.program_counter = self.pull_word() + 1
|
self.program_counter = self.pull_word() + 1
|
||||||
|
|
||||||
# BRANCHES
|
# BRANCHES
|
||||||
|
|
||||||
def BCC(self, operand_address):
|
def BCC(self, operand_address):
|
||||||
if not self.carry_flag:
|
if not self.carry_flag:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def BCS(self, operand_address):
|
def BCS(self, operand_address):
|
||||||
if self.carry_flag:
|
if self.carry_flag:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def BEQ(self, operand_address):
|
def BEQ(self, operand_address):
|
||||||
if self.zero_flag:
|
if self.zero_flag:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def BNE(self, operand_address):
|
def BNE(self, operand_address):
|
||||||
if not self.zero_flag:
|
if not self.zero_flag:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def BMI(self, operand_address):
|
def BMI(self, operand_address):
|
||||||
if self.sign_flag:
|
if self.sign_flag:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def BPL(self, operand_address):
|
def BPL(self, operand_address):
|
||||||
if not self.sign_flag:
|
if not self.sign_flag:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def BVC(self, operand_address):
|
def BVC(self, operand_address):
|
||||||
if not self.overflow_flag:
|
if not self.overflow_flag:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
def BVS(self, operand_address):
|
def BVS(self, operand_address):
|
||||||
if self.overflow_flag:
|
if self.overflow_flag:
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.program_counter = operand_address
|
self.program_counter = operand_address
|
||||||
|
|
||||||
# SET / CLEAR FLAGS
|
# SET / CLEAR FLAGS
|
||||||
|
|
||||||
def CLC(self):
|
def CLC(self):
|
||||||
self.carry_flag = 0
|
self.carry_flag = 0
|
||||||
|
|
||||||
def CLD(self):
|
def CLD(self):
|
||||||
self.decimal_mode_flag = 0
|
self.decimal_mode_flag = 0
|
||||||
|
|
||||||
def CLI(self):
|
def CLI(self):
|
||||||
self.interrupt_disable_flag = 0
|
self.interrupt_disable_flag = 0
|
||||||
|
|
||||||
def CLV(self):
|
def CLV(self):
|
||||||
self.overflow_flag = 0
|
self.overflow_flag = 0
|
||||||
|
|
||||||
def SEC(self):
|
def SEC(self):
|
||||||
self.carry_flag = 1
|
self.carry_flag = 1
|
||||||
|
|
||||||
def SED(self):
|
def SED(self):
|
||||||
self.decimal_mode_flag = 1
|
self.decimal_mode_flag = 1
|
||||||
|
|
||||||
def SEI(self):
|
def SEI(self):
|
||||||
self.interrupt_disable_flag = 1
|
self.interrupt_disable_flag = 1
|
||||||
|
|
||||||
# INCREMENT / DECREMENT
|
# INCREMENT / DECREMENT
|
||||||
|
|
||||||
def DEC(self, operand_address):
|
def DEC(self, operand_address):
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) - 1))
|
self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) - 1))
|
||||||
|
|
||||||
def DEX(self):
|
def DEX(self):
|
||||||
self.x_index = self.update_nz(self.x_index - 1)
|
self.x_index = self.update_nz(self.x_index - 1)
|
||||||
|
|
||||||
def DEY(self):
|
def DEY(self):
|
||||||
self.y_index = self.update_nz(self.y_index - 1)
|
self.y_index = self.update_nz(self.y_index - 1)
|
||||||
|
|
||||||
def INC(self, operand_address):
|
def INC(self, operand_address):
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) + 1))
|
self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) + 1))
|
||||||
|
|
||||||
def INX(self):
|
def INX(self):
|
||||||
self.x_index = self.update_nz(self.x_index + 1)
|
self.x_index = self.update_nz(self.x_index + 1)
|
||||||
|
|
||||||
def INY(self):
|
def INY(self):
|
||||||
self.y_index = self.update_nz(self.y_index + 1)
|
self.y_index = self.update_nz(self.y_index + 1)
|
||||||
|
|
||||||
# PUSH / PULL
|
# PUSH / PULL
|
||||||
|
|
||||||
def PHA(self):
|
def PHA(self):
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.push_byte(self.accumulator)
|
self.push_byte(self.accumulator)
|
||||||
|
|
||||||
def PHP(self):
|
def PHP(self):
|
||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.push_byte(self.status_as_byte())
|
self.push_byte(self.status_as_byte())
|
||||||
|
|
||||||
def PLA(self):
|
def PLA(self):
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
self.accumulator = self.update_nz(self.pull_byte())
|
self.accumulator = self.update_nz(self.pull_byte())
|
||||||
|
|
||||||
def PLP(self):
|
def PLP(self):
|
||||||
self.cycles += 2
|
self.cycles += 2
|
||||||
self.status_from_byte(self.pull_byte())
|
self.status_from_byte(self.pull_byte())
|
||||||
|
|
||||||
# LOGIC
|
# LOGIC
|
||||||
|
|
||||||
def AND(self, operand_address):
|
def AND(self, operand_address):
|
||||||
self.accumulator = self.update_nz(self.accumulator & self.read_byte(operand_address))
|
self.accumulator = self.update_nz(self.accumulator & self.read_byte(operand_address))
|
||||||
|
|
||||||
def ORA(self, operand_address):
|
def ORA(self, operand_address):
|
||||||
self.accumulator = self.update_nz(self.accumulator | self.read_byte(operand_address))
|
self.accumulator = self.update_nz(self.accumulator | self.read_byte(operand_address))
|
||||||
|
|
||||||
def EOR(self, operand_address):
|
def EOR(self, operand_address):
|
||||||
self.accumulator = self.update_nz(self.accumulator ^ self.read_byte(operand_address))
|
self.accumulator = self.update_nz(self.accumulator ^ self.read_byte(operand_address))
|
||||||
|
|
||||||
# ARITHMETIC
|
# ARITHMETIC
|
||||||
|
|
||||||
def ADC(self, operand_address):
|
def ADC(self, operand_address):
|
||||||
# @@@ doesn't handle BCD yet
|
# @@@ doesn't handle BCD yet
|
||||||
assert not self.decimal_mode_flag
|
assert not self.decimal_mode_flag
|
||||||
|
|
||||||
a2 = self.accumulator
|
a2 = self.accumulator
|
||||||
a1 = signed(a2)
|
a1 = signed(a2)
|
||||||
m2 = self.read_byte(operand_address)
|
m2 = self.read_byte(operand_address)
|
||||||
m1 = signed(m2)
|
m1 = signed(m2)
|
||||||
|
|
||||||
# twos complement addition
|
# twos complement addition
|
||||||
result1 = a1 + m1 + self.carry_flag
|
result1 = a1 + m1 + self.carry_flag
|
||||||
|
|
||||||
# unsigned addition
|
# unsigned addition
|
||||||
result2 = a2 + m2 + self.carry_flag
|
result2 = a2 + m2 + self.carry_flag
|
||||||
|
|
||||||
self.accumulator = self.update_nzc(result2)
|
self.accumulator = self.update_nzc(result2)
|
||||||
|
|
||||||
# perhaps this could be calculated from result2 but result1 is more intuitive
|
# perhaps this could be calculated from result2 but result1 is more intuitive
|
||||||
self.overflow_flag = [0, 1][(result1 > 127) | (result1 < -128)]
|
self.overflow_flag = [0, 1][(result1 > 127) | (result1 < -128)]
|
||||||
|
|
||||||
def SBC(self, operand_address):
|
def SBC(self, operand_address):
|
||||||
# @@@ doesn't handle BCD yet
|
# @@@ doesn't handle BCD yet
|
||||||
assert not self.decimal_mode_flag
|
assert not self.decimal_mode_flag
|
||||||
|
|
||||||
a2 = self.accumulator
|
a2 = self.accumulator
|
||||||
a1 = signed(a2)
|
a1 = signed(a2)
|
||||||
m2 = self.read_byte(operand_address)
|
m2 = self.read_byte(operand_address)
|
||||||
m1 = signed(m2)
|
m1 = signed(m2)
|
||||||
|
|
||||||
# twos complement subtraction
|
# twos complement subtraction
|
||||||
result1 = a1 - m1 - [1, 0][self.carry_flag]
|
result1 = a1 - m1 - [1, 0][self.carry_flag]
|
||||||
|
|
||||||
# unsigned subtraction
|
# unsigned subtraction
|
||||||
result2 = a2 - m2 - [1, 0][self.carry_flag]
|
result2 = a2 - m2 - [1, 0][self.carry_flag]
|
||||||
|
|
||||||
self.accumulator = self.update_nz(result2)
|
self.accumulator = self.update_nz(result2)
|
||||||
self.carry_flag = [0, 1][(result2 >= 0)]
|
self.carry_flag = [0, 1][(result2 >= 0)]
|
||||||
|
|
||||||
# perhaps this could be calculated from result2 but result1 is more intuitive
|
# perhaps this could be calculated from result2 but result1 is more intuitive
|
||||||
self.overflow_flag = [0, 1][(result1 > 127) | (result1 < -128)]
|
self.overflow_flag = [0, 1][(result1 > 127) | (result1 < -128)]
|
||||||
|
|
||||||
# BIT
|
# BIT
|
||||||
|
|
||||||
def BIT(self, operand_address):
|
def BIT(self, operand_address):
|
||||||
value = self.read_byte(operand_address)
|
value = self.read_byte(operand_address)
|
||||||
self.sign_flag = ((value >> 7) % 2) # bit 7
|
self.sign_flag = ((value >> 7) % 2) # bit 7
|
||||||
self.overflow_flag = ((value >> 6) % 2) # bit 6
|
self.overflow_flag = ((value >> 6) % 2) # bit 6
|
||||||
self.zero_flag = [0, 1][((self.accumulator & value) == 0)]
|
self.zero_flag = [0, 1][((self.accumulator & value) == 0)]
|
||||||
|
|
||||||
# COMPARISON
|
# COMPARISON
|
||||||
|
|
||||||
def CMP(self, operand_address):
|
def CMP(self, operand_address):
|
||||||
result = self.accumulator - self.read_byte(operand_address)
|
result = self.accumulator - self.read_byte(operand_address)
|
||||||
self.carry_flag = [0, 1][(result >= 0)]
|
self.carry_flag = [0, 1][(result >= 0)]
|
||||||
self.update_nz(result)
|
self.update_nz(result)
|
||||||
|
|
||||||
def CPX(self, operand_address):
|
def CPX(self, operand_address):
|
||||||
result = self.x_index - self.read_byte(operand_address)
|
result = self.x_index - self.read_byte(operand_address)
|
||||||
self.carry_flag = [0, 1][(result >= 0)]
|
self.carry_flag = [0, 1][(result >= 0)]
|
||||||
self.update_nz(result)
|
self.update_nz(result)
|
||||||
|
|
||||||
def CPY(self, operand_address):
|
def CPY(self, operand_address):
|
||||||
result = self.y_index - self.read_byte(operand_address)
|
result = self.y_index - self.read_byte(operand_address)
|
||||||
self.carry_flag = [0, 1][(result >= 0)]
|
self.carry_flag = [0, 1][(result >= 0)]
|
||||||
self.update_nz(result)
|
self.update_nz(result)
|
||||||
|
|
||||||
# SYSTEM
|
# SYSTEM
|
||||||
|
|
||||||
def NOP(self):
|
def NOP(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def BRK(self):
|
def BRK(self):
|
||||||
self.cycles += 5
|
self.cycles += 5
|
||||||
self.push_word(self.program_counter + 1)
|
self.push_word(self.program_counter + 1)
|
||||||
self.push_byte(self.status_as_byte())
|
self.push_byte(self.status_as_byte())
|
||||||
self.program_counter = self.read_word(0xFFFE)
|
self.program_counter = self.read_word(0xFFFE)
|
||||||
self.break_flag = 1
|
self.break_flag = 1
|
||||||
|
|
||||||
def RTI(self):
|
def RTI(self):
|
||||||
self.cycles += 4
|
self.cycles += 4
|
||||||
self.status_from_byte(self.pull_byte())
|
self.status_from_byte(self.pull_byte())
|
||||||
self.program_counter = self.pull_word()
|
self.program_counter = self.pull_word()
|
||||||
|
|
||||||
|
|
||||||
# @@@ IRQ
|
# @@@ IRQ
|
||||||
# @@@ NMI
|
# @@@ NMI
|
||||||
|
|
||||||
|
@ -1225,6 +1225,6 @@ if __name__ == "__main__":
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
mem = Memory(options)
|
mem = Memory(options)
|
||||||
|
|
||||||
cpu = CPU(options, mem)
|
cpu = CPU(options, mem)
|
||||||
cpu.run(options.bus)
|
cpu.run(options.bus)
|
||||||
|
|
208
tests.py
208
tests.py
|
@ -3,16 +3,16 @@ from cpu6502 import Memory, CPU
|
||||||
|
|
||||||
|
|
||||||
class TestMemory(unittest.TestCase):
|
class TestMemory(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
|
|
||||||
def test_load(self):
|
def test_load(self):
|
||||||
self.memory.load(0x1000, [0x01, 0x02, 0x03])
|
self.memory.load(0x1000, [0x01, 0x02, 0x03])
|
||||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x01)
|
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x01)
|
||||||
self.assertEqual(self.memory.read_byte(None, 0x1001), 0x02)
|
self.assertEqual(self.memory.read_byte(None, 0x1001), 0x02)
|
||||||
self.assertEqual(self.memory.read_byte(None, 0x1002), 0x03)
|
self.assertEqual(self.memory.read_byte(None, 0x1002), 0x03)
|
||||||
|
|
||||||
def test_write(self):
|
def test_write(self):
|
||||||
self.memory.write_byte(None, 0x1000, 0x11)
|
self.memory.write_byte(None, 0x1000, 0x11)
|
||||||
self.memory.write_byte(None, 0x1001, 0x12)
|
self.memory.write_byte(None, 0x1001, 0x12)
|
||||||
|
@ -23,12 +23,12 @@ class TestMemory(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestLoadStoreOperations(unittest.TestCase):
|
class TestLoadStoreOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
self.memory.load(0x1000, [0x00, 0x01, 0x7F, 0x80, 0xFF])
|
self.memory.load(0x1000, [0x00, 0x01, 0x7F, 0x80, 0xFF])
|
||||||
|
|
||||||
def test_LDA(self):
|
def test_LDA(self):
|
||||||
self.cpu.LDA(0x1000)
|
self.cpu.LDA(0x1000)
|
||||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||||
|
@ -50,7 +50,7 @@ class TestLoadStoreOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0xFF)
|
self.assertEqual(self.cpu.accumulator, 0xFF)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
|
|
||||||
def test_LDX(self):
|
def test_LDX(self):
|
||||||
self.cpu.LDX(0x1000)
|
self.cpu.LDX(0x1000)
|
||||||
self.assertEqual(self.cpu.x_index, 0x00)
|
self.assertEqual(self.cpu.x_index, 0x00)
|
||||||
|
@ -72,7 +72,7 @@ class TestLoadStoreOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.x_index, 0xFF)
|
self.assertEqual(self.cpu.x_index, 0xFF)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
|
|
||||||
def test_LDY(self):
|
def test_LDY(self):
|
||||||
self.cpu.LDY(0x1000)
|
self.cpu.LDY(0x1000)
|
||||||
self.assertEqual(self.cpu.y_index, 0x00)
|
self.assertEqual(self.cpu.y_index, 0x00)
|
||||||
|
@ -94,17 +94,17 @@ class TestLoadStoreOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.y_index, 0xFF)
|
self.assertEqual(self.cpu.y_index, 0xFF)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
|
|
||||||
def test_STA(self):
|
def test_STA(self):
|
||||||
self.cpu.accumulator = 0x37
|
self.cpu.accumulator = 0x37
|
||||||
self.cpu.STA(0x2000)
|
self.cpu.STA(0x2000)
|
||||||
self.assertEqual(self.memory.read_byte(None, 0x2000), 0x37)
|
self.assertEqual(self.memory.read_byte(None, 0x2000), 0x37)
|
||||||
|
|
||||||
def test_STX(self):
|
def test_STX(self):
|
||||||
self.cpu.x_index = 0x38
|
self.cpu.x_index = 0x38
|
||||||
self.cpu.STX(0x2000)
|
self.cpu.STX(0x2000)
|
||||||
self.assertEqual(self.memory.read_byte(None, 0x2000), 0x38)
|
self.assertEqual(self.memory.read_byte(None, 0x2000), 0x38)
|
||||||
|
|
||||||
def test_STY(self):
|
def test_STY(self):
|
||||||
self.cpu.y_index = 0x39
|
self.cpu.y_index = 0x39
|
||||||
self.cpu.STY(0x2000)
|
self.cpu.STY(0x2000)
|
||||||
|
@ -112,11 +112,11 @@ class TestLoadStoreOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestRegisterTransferOperations(unittest.TestCase):
|
class TestRegisterTransferOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_TAX(self):
|
def test_TAX(self):
|
||||||
self.cpu.accumulator = 0x00
|
self.cpu.accumulator = 0x00
|
||||||
self.cpu.TAX()
|
self.cpu.TAX()
|
||||||
|
@ -133,7 +133,7 @@ class TestRegisterTransferOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.x_index, 0xFF)
|
self.assertEqual(self.cpu.x_index, 0xFF)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
|
|
||||||
def test_TAY(self):
|
def test_TAY(self):
|
||||||
self.cpu.accumulator = 0x00
|
self.cpu.accumulator = 0x00
|
||||||
self.cpu.TAY()
|
self.cpu.TAY()
|
||||||
|
@ -150,7 +150,7 @@ class TestRegisterTransferOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.y_index, 0xFF)
|
self.assertEqual(self.cpu.y_index, 0xFF)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
|
|
||||||
def test_TXA(self):
|
def test_TXA(self):
|
||||||
self.cpu.x_index = 0x00
|
self.cpu.x_index = 0x00
|
||||||
self.cpu.TXA()
|
self.cpu.TXA()
|
||||||
|
@ -167,7 +167,7 @@ class TestRegisterTransferOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0xFF)
|
self.assertEqual(self.cpu.accumulator, 0xFF)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
|
|
||||||
def test_TYA(self):
|
def test_TYA(self):
|
||||||
self.cpu.y_index = 0x00
|
self.cpu.y_index = 0x00
|
||||||
self.cpu.TYA()
|
self.cpu.TYA()
|
||||||
|
@ -187,22 +187,22 @@ class TestRegisterTransferOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestStackOperations(unittest.TestCase):
|
class TestStackOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_TSX(self):
|
def test_TSX(self):
|
||||||
s = self.cpu.stack_pointer
|
s = self.cpu.stack_pointer
|
||||||
self.cpu.TSX()
|
self.cpu.TSX()
|
||||||
self.assertEqual(self.cpu.x_index, s)
|
self.assertEqual(self.cpu.x_index, s)
|
||||||
# @@@ check NZ?
|
# @@@ check NZ?
|
||||||
|
|
||||||
def test_TXS(self):
|
def test_TXS(self):
|
||||||
x = self.cpu.x_index
|
x = self.cpu.x_index
|
||||||
self.cpu.TXS()
|
self.cpu.TXS()
|
||||||
self.assertEqual(self.cpu.stack_pointer, x)
|
self.assertEqual(self.cpu.stack_pointer, x)
|
||||||
|
|
||||||
def test_PHA_and_PLA(self):
|
def test_PHA_and_PLA(self):
|
||||||
self.cpu.accumulator = 0x00
|
self.cpu.accumulator = 0x00
|
||||||
self.cpu.PHA()
|
self.cpu.PHA()
|
||||||
|
@ -225,7 +225,7 @@ class TestStackOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
|
|
||||||
def test_PHP_and_PLP(self):
|
def test_PHP_and_PLP(self):
|
||||||
p = self.cpu.status_as_byte()
|
p = self.cpu.status_as_byte()
|
||||||
self.cpu.PHP()
|
self.cpu.PHP()
|
||||||
|
@ -235,11 +235,11 @@ class TestStackOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestLogicalOperations(unittest.TestCase):
|
class TestLogicalOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_AND(self):
|
def test_AND(self):
|
||||||
self.memory.write_byte(None, 0x1000, 0x37)
|
self.memory.write_byte(None, 0x1000, 0x37)
|
||||||
self.cpu.accumulator = 0x34
|
self.cpu.accumulator = 0x34
|
||||||
|
@ -252,7 +252,7 @@ class TestLogicalOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
|
|
||||||
def test_EOR(self):
|
def test_EOR(self):
|
||||||
self.memory.write_byte(None, 0x1000, 0x37)
|
self.memory.write_byte(None, 0x1000, 0x37)
|
||||||
self.cpu.accumulator = 0x34
|
self.cpu.accumulator = 0x34
|
||||||
|
@ -270,7 +270,7 @@ class TestLogicalOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
|
|
||||||
def test_ORA(self):
|
def test_ORA(self):
|
||||||
self.memory.write_byte(None, 0x1000, 0x37)
|
self.memory.write_byte(None, 0x1000, 0x37)
|
||||||
self.cpu.accumulator = 0x34
|
self.cpu.accumulator = 0x34
|
||||||
|
@ -288,7 +288,7 @@ class TestLogicalOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
|
|
||||||
def test_BIT(self):
|
def test_BIT(self):
|
||||||
self.memory.write_byte(None, 0x1000, 0x00)
|
self.memory.write_byte(None, 0x1000, 0x00)
|
||||||
self.cpu.accumulator = 0x00
|
self.cpu.accumulator = 0x00
|
||||||
|
@ -323,15 +323,15 @@ class TestLogicalOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestArithmeticOperations(unittest.TestCase):
|
class TestArithmeticOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_ADC_without_BCD(self):
|
def test_ADC_without_BCD(self):
|
||||||
|
|
||||||
## test cases from http://www.6502.org/tutorials/vflag.html
|
## test cases from http://www.6502.org/tutorials/vflag.html
|
||||||
|
|
||||||
# 1 + 1 = 2 (C = 0; V = 0)
|
# 1 + 1 = 2 (C = 0; V = 0)
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.accumulator = 0x01
|
self.cpu.accumulator = 0x01
|
||||||
|
@ -340,7 +340,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x02)
|
self.assertEqual(self.cpu.accumulator, 0x02)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 0)
|
self.assertEqual(self.cpu.overflow_flag, 0)
|
||||||
|
|
||||||
# 1 + -1 = 0 (C = 1; V = 0)
|
# 1 + -1 = 0 (C = 1; V = 0)
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.accumulator = 0x01
|
self.cpu.accumulator = 0x01
|
||||||
|
@ -349,7 +349,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 0)
|
self.assertEqual(self.cpu.overflow_flag, 0)
|
||||||
|
|
||||||
# 127 + 1 = 128 (C = 0; V = 1)
|
# 127 + 1 = 128 (C = 0; V = 1)
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.accumulator = 0x7F
|
self.cpu.accumulator = 0x7F
|
||||||
|
@ -358,7 +358,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x80) # @@@
|
self.assertEqual(self.cpu.accumulator, 0x80) # @@@
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 1)
|
self.assertEqual(self.cpu.overflow_flag, 1)
|
||||||
|
|
||||||
# -128 + -1 = -129 (C = 1; V = 1)
|
# -128 + -1 = -129 (C = 1; V = 1)
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.accumulator = 0x80
|
self.cpu.accumulator = 0x80
|
||||||
|
@ -367,7 +367,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x7F) # @@@
|
self.assertEqual(self.cpu.accumulator, 0x7F) # @@@
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 1)
|
self.assertEqual(self.cpu.overflow_flag, 1)
|
||||||
|
|
||||||
# 63 + 64 + 1 = 128 (C = 0; V = 1)
|
# 63 + 64 + 1 = 128 (C = 0; V = 1)
|
||||||
self.cpu.carry_flag = 1
|
self.cpu.carry_flag = 1
|
||||||
self.cpu.accumulator = 0x3F
|
self.cpu.accumulator = 0x3F
|
||||||
|
@ -376,7 +376,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x80)
|
self.assertEqual(self.cpu.accumulator, 0x80)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 1)
|
self.assertEqual(self.cpu.overflow_flag, 1)
|
||||||
|
|
||||||
def test_SBC_without_BCD(self):
|
def test_SBC_without_BCD(self):
|
||||||
self.cpu.accumulator = 0x02
|
self.cpu.accumulator = 0x02
|
||||||
self.memory.write_byte(None, 0x1000, 0x01)
|
self.memory.write_byte(None, 0x1000, 0x01)
|
||||||
|
@ -384,16 +384,16 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 0)
|
self.assertEqual(self.cpu.overflow_flag, 0)
|
||||||
|
|
||||||
self.cpu.accumulator = 0x01
|
self.cpu.accumulator = 0x01
|
||||||
self.memory.write_byte(None, 0x1000, 0x02)
|
self.memory.write_byte(None, 0x1000, 0x02)
|
||||||
self.cpu.SBC(0x1000)
|
self.cpu.SBC(0x1000)
|
||||||
self.assertEqual(self.cpu.accumulator, 0xFF)
|
self.assertEqual(self.cpu.accumulator, 0xFF)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 0) # @@@
|
self.assertEqual(self.cpu.overflow_flag, 0) # @@@
|
||||||
|
|
||||||
## test cases from http://www.6502.org/tutorials/vflag.html
|
## test cases from http://www.6502.org/tutorials/vflag.html
|
||||||
|
|
||||||
# 0 - 1 = -1 (V = 0)
|
# 0 - 1 = -1 (V = 0)
|
||||||
self.cpu.carry_flag = 1
|
self.cpu.carry_flag = 1
|
||||||
self.cpu.accumulator = 0x00
|
self.cpu.accumulator = 0x00
|
||||||
|
@ -402,7 +402,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0xFF)
|
self.assertEqual(self.cpu.accumulator, 0xFF)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 0) # @@@
|
self.assertEqual(self.cpu.overflow_flag, 0) # @@@
|
||||||
|
|
||||||
# -128 - 1 = -129 (V = 1)
|
# -128 - 1 = -129 (V = 1)
|
||||||
self.cpu.carry_flag = 1
|
self.cpu.carry_flag = 1
|
||||||
self.cpu.accumulator = 0x80
|
self.cpu.accumulator = 0x80
|
||||||
|
@ -411,7 +411,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x7F)
|
self.assertEqual(self.cpu.accumulator, 0x7F)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 1)
|
self.assertEqual(self.cpu.overflow_flag, 1)
|
||||||
|
|
||||||
# 127 - -1 = 128 (V = 1)
|
# 127 - -1 = 128 (V = 1)
|
||||||
self.cpu.carry_flag = 1
|
self.cpu.carry_flag = 1
|
||||||
self.cpu.accumulator = 0x7F
|
self.cpu.accumulator = 0x7F
|
||||||
|
@ -420,7 +420,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x80)
|
self.assertEqual(self.cpu.accumulator, 0x80)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 1)
|
self.assertEqual(self.cpu.overflow_flag, 1)
|
||||||
|
|
||||||
# -64 -64 -1 = -129 (V = 1)
|
# -64 -64 -1 = -129 (V = 1)
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.accumulator = 0xC0
|
self.cpu.accumulator = 0xC0
|
||||||
|
@ -429,9 +429,9 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.accumulator, 0x7F)
|
self.assertEqual(self.cpu.accumulator, 0x7F)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
self.assertEqual(self.cpu.overflow_flag, 1) # @@@
|
self.assertEqual(self.cpu.overflow_flag, 1) # @@@
|
||||||
|
|
||||||
## @@@ BCD versions still to do
|
## @@@ BCD versions still to do
|
||||||
|
|
||||||
def test_CMP(self):
|
def test_CMP(self):
|
||||||
self.cpu.accumulator = 0x0A
|
self.cpu.accumulator = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x09)
|
self.memory.write_byte(None, 0x1000, 0x09)
|
||||||
|
@ -439,35 +439,35 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.accumulator = 0x0A
|
self.cpu.accumulator = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x0B)
|
self.memory.write_byte(None, 0x1000, 0x0B)
|
||||||
self.cpu.CMP(0x1000)
|
self.cpu.CMP(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
|
|
||||||
self.cpu.accumulator = 0x0A
|
self.cpu.accumulator = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||||
self.cpu.CMP(0x1000)
|
self.cpu.CMP(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.accumulator = 0xA0
|
self.cpu.accumulator = 0xA0
|
||||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||||
self.cpu.CMP(0x1000)
|
self.cpu.CMP(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.accumulator = 0x0A
|
self.cpu.accumulator = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0xA0)
|
self.memory.write_byte(None, 0x1000, 0xA0)
|
||||||
self.cpu.CMP(0x1000)
|
self.cpu.CMP(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0) # @@@
|
self.assertEqual(self.cpu.sign_flag, 0) # @@@
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
|
|
||||||
def test_CPX(self):
|
def test_CPX(self):
|
||||||
self.cpu.x_index = 0x0A
|
self.cpu.x_index = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x09)
|
self.memory.write_byte(None, 0x1000, 0x09)
|
||||||
|
@ -475,35 +475,35 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.x_index = 0x0A
|
self.cpu.x_index = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x0B)
|
self.memory.write_byte(None, 0x1000, 0x0B)
|
||||||
self.cpu.CPX(0x1000)
|
self.cpu.CPX(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
|
|
||||||
self.cpu.x_index = 0x0A
|
self.cpu.x_index = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||||
self.cpu.CPX(0x1000)
|
self.cpu.CPX(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.x_index = 0xA0
|
self.cpu.x_index = 0xA0
|
||||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||||
self.cpu.CPX(0x1000)
|
self.cpu.CPX(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.x_index = 0x0A
|
self.cpu.x_index = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0xA0)
|
self.memory.write_byte(None, 0x1000, 0xA0)
|
||||||
self.cpu.CPX(0x1000)
|
self.cpu.CPX(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0) # @@@
|
self.assertEqual(self.cpu.sign_flag, 0) # @@@
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
|
|
||||||
def test_CPY(self):
|
def test_CPY(self):
|
||||||
self.cpu.y_index = 0x0A
|
self.cpu.y_index = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x09)
|
self.memory.write_byte(None, 0x1000, 0x09)
|
||||||
|
@ -511,28 +511,28 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.y_index = 0x0A
|
self.cpu.y_index = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x0B)
|
self.memory.write_byte(None, 0x1000, 0x0B)
|
||||||
self.cpu.CPY(0x1000)
|
self.cpu.CPY(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
|
|
||||||
self.cpu.y_index = 0x0A
|
self.cpu.y_index = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||||
self.cpu.CPY(0x1000)
|
self.cpu.CPY(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.y_index = 0xA0
|
self.cpu.y_index = 0xA0
|
||||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||||
self.cpu.CPY(0x1000)
|
self.cpu.CPY(0x1000)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
self.cpu.y_index = 0x0A
|
self.cpu.y_index = 0x0A
|
||||||
self.memory.write_byte(None, 0x1000, 0xA0)
|
self.memory.write_byte(None, 0x1000, 0xA0)
|
||||||
self.cpu.CPY(0x1000)
|
self.cpu.CPY(0x1000)
|
||||||
|
@ -542,11 +542,11 @@ class TestArithmeticOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestIncrementDecrementOperations(unittest.TestCase):
|
class TestIncrementDecrementOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_INC(self):
|
def test_INC(self):
|
||||||
self.memory.write_byte(None, 0x1000, 0x00)
|
self.memory.write_byte(None, 0x1000, 0x00)
|
||||||
self.cpu.INC(0x1000)
|
self.cpu.INC(0x1000)
|
||||||
|
@ -563,7 +563,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x00)
|
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x00)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
|
|
||||||
def test_INX(self):
|
def test_INX(self):
|
||||||
self.cpu.x_index = 0x00
|
self.cpu.x_index = 0x00
|
||||||
self.cpu.INX()
|
self.cpu.INX()
|
||||||
|
@ -580,7 +580,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.x_index, 0x00)
|
self.assertEqual(self.cpu.x_index, 0x00)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
|
|
||||||
def test_INY(self):
|
def test_INY(self):
|
||||||
self.cpu.y_index = 0x00
|
self.cpu.y_index = 0x00
|
||||||
self.cpu.INY()
|
self.cpu.INY()
|
||||||
|
@ -597,7 +597,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.y_index, 0x00)
|
self.assertEqual(self.cpu.y_index, 0x00)
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
|
|
||||||
def test_DEC(self):
|
def test_DEC(self):
|
||||||
self.memory.write_byte(None, 0x1000, 0x01)
|
self.memory.write_byte(None, 0x1000, 0x01)
|
||||||
self.cpu.DEC(0x1000)
|
self.cpu.DEC(0x1000)
|
||||||
|
@ -614,7 +614,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0xFF)
|
self.assertEqual(self.memory.read_byte(None, 0x1000), 0xFF)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
|
|
||||||
def test_DEX(self):
|
def test_DEX(self):
|
||||||
self.cpu.x_index = 0x01
|
self.cpu.x_index = 0x01
|
||||||
self.cpu.DEX()
|
self.cpu.DEX()
|
||||||
|
@ -631,7 +631,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.x_index, 0xFF)
|
self.assertEqual(self.cpu.x_index, 0xFF)
|
||||||
self.assertEqual(self.cpu.sign_flag, 1)
|
self.assertEqual(self.cpu.sign_flag, 1)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
|
|
||||||
def test_DEY(self):
|
def test_DEY(self):
|
||||||
self.cpu.y_index = 0x01
|
self.cpu.y_index = 0x01
|
||||||
self.cpu.DEY()
|
self.cpu.DEY()
|
||||||
|
@ -651,11 +651,11 @@ class TestIncrementDecrementOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestShiftOperations(unittest.TestCase):
|
class TestShiftOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_ASL(self):
|
def test_ASL(self):
|
||||||
self.cpu.accumulator = 0x01
|
self.cpu.accumulator = 0x01
|
||||||
self.cpu.ASL()
|
self.cpu.ASL()
|
||||||
|
@ -675,7 +675,7 @@ class TestShiftOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 1)
|
self.assertEqual(self.cpu.zero_flag, 1)
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
def test_LSR(self):
|
def test_LSR(self):
|
||||||
self.cpu.accumulator = 0x01
|
self.cpu.accumulator = 0x01
|
||||||
self.cpu.LSR()
|
self.cpu.LSR()
|
||||||
|
@ -695,7 +695,7 @@ class TestShiftOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0)
|
self.assertEqual(self.cpu.zero_flag, 0)
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
|
|
||||||
def test_ROL(self):
|
def test_ROL(self):
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.accumulator = 0x80
|
self.cpu.accumulator = 0x80
|
||||||
|
@ -725,7 +725,7 @@ class TestShiftOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.sign_flag, 0)
|
self.assertEqual(self.cpu.sign_flag, 0)
|
||||||
self.assertEqual(self.cpu.zero_flag, 0) # @@@
|
self.assertEqual(self.cpu.zero_flag, 0) # @@@
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
def test_ROR(self):
|
def test_ROR(self):
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.accumulator = 0x01
|
self.cpu.accumulator = 0x01
|
||||||
|
@ -758,29 +758,29 @@ class TestShiftOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestJumpCallOperations(unittest.TestCase):
|
class TestJumpCallOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_JMP(self):
|
def test_JMP(self):
|
||||||
self.cpu.JMP(0x1000)
|
self.cpu.JMP(0x1000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x1000)
|
self.assertEqual(self.cpu.program_counter, 0x1000)
|
||||||
|
|
||||||
def test_JSR(self):
|
def test_JSR(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.JSR(0x2000)
|
self.cpu.JSR(0x2000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x2000)
|
self.assertEqual(self.cpu.program_counter, 0x2000)
|
||||||
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 1), 0xFF)
|
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 1), 0xFF)
|
||||||
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 2), 0x0F)
|
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 2), 0x0F)
|
||||||
|
|
||||||
def test_RTS(self):
|
def test_RTS(self):
|
||||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFF, 0x12)
|
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFF, 0x12)
|
||||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFE, 0x33)
|
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFE, 0x33)
|
||||||
self.cpu.stack_pointer = 0xFD
|
self.cpu.stack_pointer = 0xFD
|
||||||
self.cpu.RTS()
|
self.cpu.RTS()
|
||||||
self.assertEqual(self.cpu.program_counter, 0x1234)
|
self.assertEqual(self.cpu.program_counter, 0x1234)
|
||||||
|
|
||||||
def test_JSR_and_RTS(self):
|
def test_JSR_and_RTS(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.JSR(0x2000)
|
self.cpu.JSR(0x2000)
|
||||||
|
@ -790,11 +790,11 @@ class TestJumpCallOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestBranchOperations(unittest.TestCase):
|
class TestBranchOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_BCC(self):
|
def test_BCC(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.carry_flag = 1
|
self.cpu.carry_flag = 1
|
||||||
|
@ -804,7 +804,7 @@ class TestBranchOperations(unittest.TestCase):
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.BCC(0x2000)
|
self.cpu.BCC(0x2000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x2000)
|
self.assertEqual(self.cpu.program_counter, 0x2000)
|
||||||
|
|
||||||
def test_BCS(self):
|
def test_BCS(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
|
@ -814,7 +814,7 @@ class TestBranchOperations(unittest.TestCase):
|
||||||
self.cpu.carry_flag = 1
|
self.cpu.carry_flag = 1
|
||||||
self.cpu.BCS(0x2000)
|
self.cpu.BCS(0x2000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x2000)
|
self.assertEqual(self.cpu.program_counter, 0x2000)
|
||||||
|
|
||||||
def test_BEQ(self):
|
def test_BEQ(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.zero_flag = 0
|
self.cpu.zero_flag = 0
|
||||||
|
@ -824,7 +824,7 @@ class TestBranchOperations(unittest.TestCase):
|
||||||
self.cpu.zero_flag = 1
|
self.cpu.zero_flag = 1
|
||||||
self.cpu.BEQ(0x2000)
|
self.cpu.BEQ(0x2000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x2000)
|
self.assertEqual(self.cpu.program_counter, 0x2000)
|
||||||
|
|
||||||
def test_BMI(self):
|
def test_BMI(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.sign_flag = 0
|
self.cpu.sign_flag = 0
|
||||||
|
@ -834,7 +834,7 @@ class TestBranchOperations(unittest.TestCase):
|
||||||
self.cpu.sign_flag = 1
|
self.cpu.sign_flag = 1
|
||||||
self.cpu.BMI(0x2000)
|
self.cpu.BMI(0x2000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x2000)
|
self.assertEqual(self.cpu.program_counter, 0x2000)
|
||||||
|
|
||||||
def test_BNE(self):
|
def test_BNE(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.zero_flag = 1
|
self.cpu.zero_flag = 1
|
||||||
|
@ -844,7 +844,7 @@ class TestBranchOperations(unittest.TestCase):
|
||||||
self.cpu.zero_flag = 0
|
self.cpu.zero_flag = 0
|
||||||
self.cpu.BNE(0x2000)
|
self.cpu.BNE(0x2000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x2000)
|
self.assertEqual(self.cpu.program_counter, 0x2000)
|
||||||
|
|
||||||
def test_BPL(self):
|
def test_BPL(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.sign_flag = 1
|
self.cpu.sign_flag = 1
|
||||||
|
@ -854,7 +854,7 @@ class TestBranchOperations(unittest.TestCase):
|
||||||
self.cpu.sign_flag = 0
|
self.cpu.sign_flag = 0
|
||||||
self.cpu.BPL(0x2000)
|
self.cpu.BPL(0x2000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x2000)
|
self.assertEqual(self.cpu.program_counter, 0x2000)
|
||||||
|
|
||||||
def test_BVC(self):
|
def test_BVC(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.overflow_flag = 1
|
self.cpu.overflow_flag = 1
|
||||||
|
@ -864,7 +864,7 @@ class TestBranchOperations(unittest.TestCase):
|
||||||
self.cpu.overflow_flag = 0
|
self.cpu.overflow_flag = 0
|
||||||
self.cpu.BVC(0x2000)
|
self.cpu.BVC(0x2000)
|
||||||
self.assertEqual(self.cpu.program_counter, 0x2000)
|
self.assertEqual(self.cpu.program_counter, 0x2000)
|
||||||
|
|
||||||
def test_BVS(self):
|
def test_BVS(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.cpu.overflow_flag = 0
|
self.cpu.overflow_flag = 0
|
||||||
|
@ -877,41 +877,41 @@ class TestBranchOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestStatusFlagOperations(unittest.TestCase):
|
class TestStatusFlagOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_CLC(self):
|
def test_CLC(self):
|
||||||
self.cpu.carry_flag = 1
|
self.cpu.carry_flag = 1
|
||||||
self.cpu.CLC()
|
self.cpu.CLC()
|
||||||
self.assertEqual(self.cpu.carry_flag, 0)
|
self.assertEqual(self.cpu.carry_flag, 0)
|
||||||
|
|
||||||
def test_CLD(self):
|
def test_CLD(self):
|
||||||
self.cpu.decimal_mode_flag = 1
|
self.cpu.decimal_mode_flag = 1
|
||||||
self.cpu.CLD()
|
self.cpu.CLD()
|
||||||
self.assertEqual(self.cpu.decimal_mode_flag, 0)
|
self.assertEqual(self.cpu.decimal_mode_flag, 0)
|
||||||
|
|
||||||
def test_CLI(self):
|
def test_CLI(self):
|
||||||
self.cpu.interrupt_disable_flag = 1
|
self.cpu.interrupt_disable_flag = 1
|
||||||
self.cpu.CLI()
|
self.cpu.CLI()
|
||||||
self.assertEqual(self.cpu.interrupt_disable_flag, 0)
|
self.assertEqual(self.cpu.interrupt_disable_flag, 0)
|
||||||
|
|
||||||
def test_CLV(self):
|
def test_CLV(self):
|
||||||
self.cpu.overflow_flag = 1
|
self.cpu.overflow_flag = 1
|
||||||
self.cpu.CLV()
|
self.cpu.CLV()
|
||||||
self.assertEqual(self.cpu.overflow_flag, 0)
|
self.assertEqual(self.cpu.overflow_flag, 0)
|
||||||
|
|
||||||
def test_SEC(self):
|
def test_SEC(self):
|
||||||
self.cpu.carry_flag = 0
|
self.cpu.carry_flag = 0
|
||||||
self.cpu.SEC()
|
self.cpu.SEC()
|
||||||
self.assertEqual(self.cpu.carry_flag, 1)
|
self.assertEqual(self.cpu.carry_flag, 1)
|
||||||
|
|
||||||
def test_SED(self):
|
def test_SED(self):
|
||||||
self.cpu.decimal_mode_flag = 0
|
self.cpu.decimal_mode_flag = 0
|
||||||
self.cpu.SED()
|
self.cpu.SED()
|
||||||
self.assertEqual(self.cpu.decimal_mode_flag, 1)
|
self.assertEqual(self.cpu.decimal_mode_flag, 1)
|
||||||
|
|
||||||
def test_SEI(self):
|
def test_SEI(self):
|
||||||
self.cpu.interrupt_disable_flag = 0
|
self.cpu.interrupt_disable_flag = 0
|
||||||
self.cpu.SEI()
|
self.cpu.SEI()
|
||||||
|
@ -919,11 +919,11 @@ class TestStatusFlagOperations(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestSystemFunctionOperations(unittest.TestCase):
|
class TestSystemFunctionOperations(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_BRK(self):
|
def test_BRK(self):
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
self.memory.rom.load(0xFFFE, [0x00, 0x20])
|
self.memory.rom.load(0xFFFE, [0x00, 0x20])
|
||||||
|
@ -934,7 +934,7 @@ class TestSystemFunctionOperations(unittest.TestCase):
|
||||||
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 1), status)
|
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 1), status)
|
||||||
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 2), 0x01)
|
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 2), 0x01)
|
||||||
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 3), 0x10)
|
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 3), 0x10)
|
||||||
|
|
||||||
def test_RTI(self):
|
def test_RTI(self):
|
||||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFF, 0x12)
|
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFF, 0x12)
|
||||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFE, 0x33)
|
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFE, 0x33)
|
||||||
|
@ -943,17 +943,17 @@ class TestSystemFunctionOperations(unittest.TestCase):
|
||||||
self.cpu.RTI()
|
self.cpu.RTI()
|
||||||
self.assertEqual(self.cpu.program_counter, 0x1233)
|
self.assertEqual(self.cpu.program_counter, 0x1233)
|
||||||
self.assertEqual(self.cpu.status_as_byte(), 0x20)
|
self.assertEqual(self.cpu.status_as_byte(), 0x20)
|
||||||
|
|
||||||
def test_NOP(self):
|
def test_NOP(self):
|
||||||
self.cpu.NOP()
|
self.cpu.NOP()
|
||||||
|
|
||||||
|
|
||||||
class Test6502Bugs(unittest.TestCase):
|
class Test6502Bugs(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.memory = Memory(use_bus=False)
|
self.memory = Memory(use_bus=False)
|
||||||
self.cpu = CPU(self.memory)
|
self.cpu = CPU(self.memory)
|
||||||
|
|
||||||
def test_zero_page_x(self):
|
def test_zero_page_x(self):
|
||||||
self.cpu.x_index = 0x01
|
self.cpu.x_index = 0x01
|
||||||
self.memory.load(0x1000, [0x00, 0x7F, 0xFF])
|
self.memory.load(0x1000, [0x00, 0x7F, 0xFF])
|
||||||
|
@ -961,7 +961,7 @@ class Test6502Bugs(unittest.TestCase):
|
||||||
self.assertEqual(self.cpu.zero_page_x_mode(), 0x01)
|
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(), 0x80)
|
||||||
self.assertEqual(self.cpu.zero_page_x_mode(), 0x00)
|
self.assertEqual(self.cpu.zero_page_x_mode(), 0x00)
|
||||||
|
|
||||||
def test_indirect(self):
|
def test_indirect(self):
|
||||||
self.memory.load(0x20, [0x00, 0x20])
|
self.memory.load(0x20, [0x00, 0x20])
|
||||||
self.memory.load(0x00, [0x12])
|
self.memory.load(0x00, [0x12])
|
||||||
|
@ -971,29 +971,29 @@ class Test6502Bugs(unittest.TestCase):
|
||||||
self.memory.load(0x2000, [0x05])
|
self.memory.load(0x2000, [0x05])
|
||||||
self.memory.load(0x1234, [0x05])
|
self.memory.load(0x1234, [0x05])
|
||||||
self.memory.load(0x2345, [0x00, 0xF0])
|
self.memory.load(0x2345, [0x00, 0xF0])
|
||||||
|
|
||||||
self.cpu.program_counter = 0x1000
|
self.cpu.program_counter = 0x1000
|
||||||
|
|
||||||
self.cpu.x_index = 0x00
|
self.cpu.x_index = 0x00
|
||||||
self.cpu.LDA(self.cpu.indirect_x_mode())
|
self.cpu.LDA(self.cpu.indirect_x_mode())
|
||||||
self.assertEqual(self.cpu.accumulator, 0x05)
|
self.assertEqual(self.cpu.accumulator, 0x05)
|
||||||
|
|
||||||
self.cpu.y_index = 0x00
|
self.cpu.y_index = 0x00
|
||||||
self.cpu.LDA(self.cpu.indirect_y_mode())
|
self.cpu.LDA(self.cpu.indirect_y_mode())
|
||||||
self.assertEqual(self.cpu.accumulator, 0x05)
|
self.assertEqual(self.cpu.accumulator, 0x05)
|
||||||
|
|
||||||
self.cpu.y_index = 0x00
|
self.cpu.y_index = 0x00
|
||||||
self.cpu.LDA(self.cpu.indirect_y_mode())
|
self.cpu.LDA(self.cpu.indirect_y_mode())
|
||||||
self.assertEqual(self.cpu.accumulator, 0x05)
|
self.assertEqual(self.cpu.accumulator, 0x05)
|
||||||
|
|
||||||
self.cpu.x_index = 0x00
|
self.cpu.x_index = 0x00
|
||||||
self.cpu.LDA(self.cpu.indirect_x_mode())
|
self.cpu.LDA(self.cpu.indirect_x_mode())
|
||||||
self.assertEqual(self.cpu.accumulator, 0x05)
|
self.assertEqual(self.cpu.accumulator, 0x05)
|
||||||
|
|
||||||
self.cpu.x_index = 0xFF
|
self.cpu.x_index = 0xFF
|
||||||
self.cpu.LDA(self.cpu.indirect_x_mode())
|
self.cpu.LDA(self.cpu.indirect_x_mode())
|
||||||
self.assertEqual(self.cpu.accumulator, 0x05)
|
self.assertEqual(self.cpu.accumulator, 0x05)
|
||||||
|
|
||||||
self.assertEqual(self.cpu.indirect_mode(), 0xF000)
|
self.assertEqual(self.cpu.indirect_mode(), 0xF000)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue