Merge branch 'master' into timer

This commit is contained in:
James Tauber 2012-04-18 07:28:59 -04:00
commit 0c29d5a27d
6 changed files with 715 additions and 247 deletions

3
README
View File

@ -31,4 +31,5 @@ runs all the programs I've tried so far.
The only I/O supported is the keyboard and screen but 40-column text, LORES The only I/O supported is the keyboard and screen but 40-column text, LORES
and HIRES graphics are all supported. and HIRES graphics are all supported.
ApplePy currently requires Pygame. ApplePy currently requires Pygame (although there is a minimal applepy_curses.py
that uses curses to display text mode only).

View File

@ -5,10 +5,13 @@
import numpy import numpy
import pygame import pygame
import select
import socket
import struct import struct
import subprocess import subprocess
import sys import sys
import time import time
import wave
class Display: class Display:
@ -106,6 +109,10 @@ class Display:
self.flash_time = time.time() self.flash_time = time.time()
self.flash_on = False self.flash_on = False
self.flash_chars = [[0] * 0x400] * 2 self.flash_chars = [[0] * 0x400] * 2
self.page = 1
self.text = True
self.colour = False
self.chargen = [] self.chargen = []
for c in self.characters: for c in self.characters:
@ -288,12 +295,33 @@ class Speaker:
self.play() self.play()
class Cassette:
def __init__(self, fn):
wav = wave.open(fn, "r")
self.raw = wav.readframes(wav.getnframes())
self.start_cycle = 0
self.start_offset = 0
for i, b in enumerate(self.raw):
if ord(b) > 0xA0:
self.start_offset = i
break
def read_byte(self, cycle):
if self.start_cycle == 0:
self.start_cycle = cycle
offset = self.start_offset + (cycle - self.start_cycle) * 22000 / 1000000
return ord(self.raw[offset]) if offset < len(self.raw) else 0x80
class SoftSwitches: class SoftSwitches:
def __init__(self, display, speaker): 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
def read_byte(self, cycle, address): def read_byte(self, cycle, address):
assert 0xC000 <= address <= 0xCFFF assert 0xC000 <= address <= 0xCFFF
@ -320,6 +348,9 @@ class SoftSwitches:
self.display.lores() self.display.lores()
elif address == 0xC057: elif address == 0xC057:
self.display.hires() self.display.hires()
elif address == 0xC060:
if self.cassette:
return self.cassette.read_byte(cycle)
else: else:
pass # print "%04X" % address pass # print "%04X" % address
return 0x00 return 0x00
@ -327,25 +358,36 @@ class SoftSwitches:
class Apple2: class Apple2:
def __init__(self, options, display, speaker): def __init__(self, options, display, speaker, cassette):
self.display = display self.display = display
self.speaker = speaker self.speaker = speaker
self.softswitches = SoftSwitches(display, speaker) self.softswitches = SoftSwitches(display, speaker, cassette)
listener = socket.socket()
listener.bind(("127.0.0.1", 0))
listener.listen(0)
args = [ args = [
sys.executable, sys.executable,
"cpu6502.py", "cpu6502.py",
"--bus", str(listener.getsockname()[1]),
"--rom", options.rom, "--rom", options.rom,
] ]
if options.ram: if options.ram:
args.extend([ args.extend([
"--ram", options.ram, "--ram", options.ram,
]) ])
self.core = subprocess.Popen( if options.pc is not None:
args=args, args.extend([
stdin=subprocess.PIPE, "--pc", str(options.pc),
stdout=subprocess.PIPE, ])
) self.core = subprocess.Popen(args)
rs, _, _ = select.select([listener], [], [], 2)
if not rs:
print >>sys.stderr, "CPU module did not start"
sys.exit(1)
self.cpu, _ = listener.accept()
def run(self): def run(self):
update_cycle = 0 update_cycle = 0
@ -354,11 +396,12 @@ class Apple2:
quit = False quit = False
while not quit: while not quit:
op = self.core.stdout.read(8) op = self.cpu.recv(8)
if len(op) == 0:
break
cycle, rw, addr, val = struct.unpack("<IBHB", op) cycle, rw, addr, val = struct.unpack("<IBHB", op)
if rw == 0: if rw == 0:
self.core.stdin.write(chr(self.softswitches.read_byte(cycle, addr))) self.cpu.send(chr(self.softswitches.read_byte(cycle, addr)))
self.core.stdin.flush()
elif rw == 1: elif rw == 1:
self.display.update(addr, val) self.display.update(addr, val)
else: else:
@ -397,8 +440,10 @@ def usage():
print >>sys.stderr print >>sys.stderr
print >>sys.stderr, "Usage: applepy.py [options]" print >>sys.stderr, "Usage: applepy.py [options]"
print >>sys.stderr print >>sys.stderr
print >>sys.stderr, " -c, --cassette Cassette wav file to load"
print >>sys.stderr, " -R, --rom ROM file to use (default A2ROM.BIN)" print >>sys.stderr, " -R, --rom ROM file to use (default A2ROM.BIN)"
print >>sys.stderr, " -r, --ram RAM file to load (default none)" print >>sys.stderr, " -r, --ram RAM file to load (default none)"
print >>sys.stderr, " -p, --pc Initial PC value"
print >>sys.stderr, " -q, --quiet Quiet mode, no sounds (default sounds)" print >>sys.stderr, " -q, --quiet Quiet mode, no sounds (default sounds)"
sys.exit(1) sys.exit(1)
@ -406,20 +451,28 @@ def usage():
def get_options(): def get_options():
class Options: class Options:
def __init__(self): def __init__(self):
self.cassette = None
self.rom = "A2ROM.BIN" self.rom = "A2ROM.BIN"
self.ram = None self.ram = None
self.pc = None
self.quiet = False self.quiet = False
options = Options() options = Options()
a = 1 a = 1
while a < len(sys.argv): while a < len(sys.argv):
if sys.argv[a].startswith("-"): if sys.argv[a].startswith("-"):
if sys.argv[a] in ("-R", "--rom"): if sys.argv[a] in ("-c", "--cassette"):
a += 1
options.cassette = sys.argv[a]
elif sys.argv[a] in ("-R", "--rom"):
a += 1 a += 1
options.rom = sys.argv[a] options.rom = sys.argv[a]
elif sys.argv[a] in ("-r", "--ram"): elif sys.argv[a] in ("-r", "--ram"):
a += 1 a += 1
options.ram = sys.argv[a] options.ram = sys.argv[a]
elif sys.argv[a] in ("-p", "--pc"):
a += 1
options.pc = int(sys.argv[a])
elif sys.argv[a] in ("-q", "--quiet"): elif sys.argv[a] in ("-q", "--quiet"):
options.quiet = True options.quiet = True
else: else:
@ -435,6 +488,7 @@ if __name__ == "__main__":
options = get_options() options = get_options()
display = Display() display = Display()
speaker = None if options.quiet else Speaker() speaker = None if options.quiet else Speaker()
cassette = Cassette(options.cassette) if options.cassette else None
apple = Apple2(options, display, speaker) apple = Apple2(options, display, speaker, cassette)
apple.run() apple.run()

View File

@ -4,6 +4,7 @@
import curses import curses
import socket
import struct import struct
import subprocess import subprocess
import sys import sys
@ -55,20 +56,29 @@ def write(win, addr, val):
def run(win): def run(win):
global kbd global kbd
p = subprocess.Popen(
args=[sys.executable, "cpu6502.py"], listener = socket.socket()
stdin=subprocess.PIPE, listener.bind(("127.0.0.1", 0))
stdout=subprocess.PIPE, listener.listen(0)
)
args = [
sys.executable,
"cpu6502.py",
"--bus", str(listener.getsockname()[1]),
"--rom", options.rom,
]
p = subprocess.Popen(args)
cpu, _ = listener.accept()
win.clear() win.clear()
curses.noecho() curses.noecho()
win.nodelay(True) win.nodelay(True)
while True: while True:
op = p.stdout.read(8) op = cpu.recv(8)
cycle, rw, addr, val = struct.unpack("<IBHB", op) cycle, rw, addr, val = struct.unpack("<IBHB", op)
if rw == 0: if rw == 0:
p.stdin.write(chr(read(addr, val))) cpu.send(chr(read(addr, val)))
p.stdin.flush()
elif rw == 1: elif rw == 1:
write(win, addr, val) write(win, addr, val)
else: else:
@ -85,7 +95,39 @@ def run(win):
pass pass
except TypeError: except TypeError:
pass pass
def usage():
print >>sys.stderr, "ApplePy - an Apple ][ emulator in Python"
print >>sys.stderr, "James Tauber / http://jtauber.com/"
print >>sys.stderr
print >>sys.stderr, "Usage: applepy_curses.py [options]"
print >>sys.stderr
print >>sys.stderr, " -R, --rom ROM file to use (default A2ROM.BIN)"
sys.exit(1)
def get_options():
class Options:
def __init__(self):
self.rom = "A2ROM.BIN"
options = Options()
a = 1
while a < len(sys.argv):
if sys.argv[a].startswith("-"):
if sys.argv[a] in ("-R", "--rom"):
a += 1
options.rom = sys.argv[a]
else:
usage()
else:
usage()
a += 1
return options
if __name__ == "__main__": if __name__ == "__main__":
options = get_options()
curses.wrapper(run) curses.wrapper(run)

157
control.py Normal file
View File

@ -0,0 +1,157 @@
import json
import readline
import sys
import urllib
URL_PREFIX = "http://localhost:6502"
def get(url):
return json.loads(urllib.urlopen(URL_PREFIX + url).read())
def post(url, data=None):
return urllib.urlopen(URL_PREFIX + url, json.dumps(data) if data is not None else "")
def value(s):
if s.startswith("$"):
return int(s[1:], 16)
if s.startswith("0x"):
return int(s[2:], 16)
return int(s)
def format_disassemble(dis):
r = "%04X- " % dis["address"]
for i in range(3):
if i < len(dis["bytes"]):
r += "%02X " % dis["bytes"][i]
else:
r += " "
r += " %s" % dis["mnemonic"]
if "operand" in dis:
r += " %-10s" % dis["operand"]
if "memory" in dis:
r += "[%04X] = %0*X" % tuple(dis["memory"])
return r
def cmd_disassemble(a):
"""Disassemble"""
if len(a) > 1:
addr = value(a[1])
else:
status = get("/status")
addr = status["program_counter"]
disasm = get("/disassemble/%d" % addr)
for d in disasm:
print format_disassemble(d)
def cmd_dump(a):
"""Dump memory"""
start = value(a[1])
if len(a) > 2:
end = value(a[2])
else:
end = start + 15
data = get("/memory/%d-%d" % (start, end))
addr = start & ~0xF
while addr <= end:
s = "%04X-" % addr
for i in range(16):
if start <= addr + i <= end:
s += " %02X" % data[addr + i - start]
else:
s += " "
s += " "
for i in range(16):
if start <= addr + i <= end:
c = data[addr + i - start]
# adjust for apple character set
c &= 0x3f
if c < 0x20:
c += 0x40
if 0x20 <= c < 0x7f:
s += chr(c)
else:
s += "."
else:
s += " "
print s
addr += 16
def cmd_help(a):
"""Help commands"""
if len(a) > 1:
f = Commands.get(a[1])
if f is not None:
print f.__doc__
else:
print "Unknown command:", a[1]
else:
print "Commands:"
for c in sorted(Commands):
print " ", c
def cmd_peek(a):
"""Peek memory location"""
addr = value(a[1])
dump = get("/memory/%d" % addr)
print "%04X: %02X" % (addr, dump[0])
def cmd_poke(a):
"""Poke memory location"""
addr = value(a[1])
val = value(a[2])
post("/memory/%d" % addr, [val])
def cmd_status(a):
"""CPU status"""
status = get("/status")
print "A=%02X X=%02X Y=%02X S=%02X PC=%04X F=%c%c0%c%c%c%c%c" % (
status["accumulator"],
status["x_index"],
status["y_index"],
status["stack_pointer"],
status["program_counter"],
"N" if status["sign_flag"] else "n",
"V" if status["overflow_flag"] else "v",
"B" if status["break_flag"] else "b",
"D" if status["decimal_mode_flag"] else "d",
"I" if status["interrupt_disable_flag"] else "i",
"Z" if status["zero_flag"] else "z",
"C" if status["carry_flag"] else "c",
)
disasm = get("/disassemble/%d" % status["program_counter"])
print format_disassemble(disasm[0])
def cmd_quit(a):
"""Quit"""
sys.exit(0)
def cmd_reset(a):
"""Reset"""
post("/reset")
Commands = {
"disassemble": cmd_disassemble,
"dump": cmd_dump,
"help": cmd_help,
"peek": cmd_peek,
"poke": cmd_poke,
"status": cmd_status,
"quit": cmd_quit,
"reset": cmd_reset,
}
def main():
print "ApplePy control console"
while True:
s = raw_input("6502> ")
a = s.strip().split()
f = Commands.get(a[0])
if f is not None:
f(a)
else:
print "Unknown command:", s
if __name__ == "__main__":
main()

View File

@ -3,10 +3,18 @@
# originally written 2001, updated 2011 # originally written 2001, updated 2011
import BaseHTTPServer
import json
import re
import select
import socket
import struct import struct
import sys import sys
bus = None # socket for bus I/O
def signed(x): def signed(x):
if x > 0x7F: if x > 0x7F:
x = x - 0x100 x = x - 0x100
@ -25,7 +33,7 @@ class ROM:
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) 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)
@ -42,8 +50,8 @@ class RAM(ROM):
class Memory: class Memory:
def __init__(self, options=None, use_stdio=True): def __init__(self, options=None, use_bus=True):
self.use_stdio = use_stdio self.use_bus = use_bus
self.rom = ROM(0xD000, 0x3000) self.rom = ROM(0xD000, 0x3000)
if options: if options:
@ -82,26 +90,24 @@ class Memory:
self.bus_write(cycle, address, value) self.bus_write(cycle, address, value)
def bus_read(self, cycle, address): def bus_read(self, cycle, address):
if not self.use_stdio: if not self.use_bus:
return 0 return 0
op = struct.pack("<IBHB", cycle, 0, address, 0) op = struct.pack("<IBHB", cycle, 0, address, 0)
try: try:
sys.stdout.write(op) bus.send(op)
sys.stdout.flush() b = bus.recv(1)
except IOError: if len(b) == 0:
sys.exit(0)
return ord(b)
except socket.error:
sys.exit(0) sys.exit(0)
b = sys.stdin.read(1)
if len(b) == 0:
sys.exit(0)
return ord(b)
def bus_write(self, cycle, address, value): def bus_write(self, cycle, address, value):
if not self.use_stdio: if not self.use_bus:
return return
op = struct.pack("<IBHB", cycle, 1, address, value) op = struct.pack("<IBHB", cycle, 1, address, value)
try: try:
sys.stdout.write(op) bus.send(op)
sys.stdout.flush()
except IOError: except IOError:
sys.exit(0) sys.exit(0)
@ -114,214 +120,384 @@ class Disassemble:
self.setup_ops() self.setup_ops()
def setup_ops(self): def setup_ops(self):
self.ops = [None] * 0x100 self.ops = [(1, "???")] * 0x100
self.ops[0x00] = ("BRK", ) self.ops[0x00] = (1, "BRK", )
self.ops[0x01] = ("ORA", self.indirect_x_mode) self.ops[0x01] = (2, "ORA", self.indirect_x_mode)
self.ops[0x05] = ("ORA", self.zero_page_mode) self.ops[0x05] = (2, "ORA", self.zero_page_mode)
self.ops[0x06] = ("ASL", self.zero_page_mode) self.ops[0x06] = (2, "ASL", self.zero_page_mode)
self.ops[0x08] = ("PHP", ) self.ops[0x08] = (1, "PHP", )
self.ops[0x09] = ("ORA", self.immediate_mode) self.ops[0x09] = (2, "ORA", self.immediate_mode)
self.ops[0x0A] = ("ASL", ) self.ops[0x0A] = (1, "ASL", )
self.ops[0x0D] = ("ORA", self.absolute_mode) self.ops[0x0D] = (3, "ORA", self.absolute_mode)
self.ops[0x0E] = ("ASL", self.absolute_mode) self.ops[0x0E] = (3, "ASL", self.absolute_mode)
self.ops[0x10] = ("BPL", self.relative_mode) self.ops[0x10] = (2, "BPL", self.relative_mode)
self.ops[0x11] = ("ORA", self.indirect_y_mode) self.ops[0x11] = (2, "ORA", self.indirect_y_mode)
self.ops[0x15] = ("ORA", self.zero_page_x_mode) self.ops[0x15] = (2, "ORA", self.zero_page_x_mode)
self.ops[0x16] = ("ASL", self.zero_page_x_mode) self.ops[0x16] = (2, "ASL", self.zero_page_x_mode)
self.ops[0x18] = ("CLC", ) self.ops[0x18] = (1, "CLC", )
self.ops[0x19] = ("ORA", self.absolute_y_mode) self.ops[0x19] = (3, "ORA", self.absolute_y_mode)
self.ops[0x1D] = ("ORA", self.absolute_x_mode) self.ops[0x1D] = (3, "ORA", self.absolute_x_mode)
self.ops[0x1E] = ("ASL", self.absolute_x_mode) self.ops[0x1E] = (3, "ASL", self.absolute_x_mode)
self.ops[0x20] = ("JSR", self.absolute_mode) self.ops[0x20] = (3, "JSR", self.absolute_mode)
self.ops[0x21] = ("AND", self.indirect_x_mode) self.ops[0x21] = (2, "AND", self.indirect_x_mode)
self.ops[0x24] = ("BIT", self.zero_page_mode) self.ops[0x24] = (2, "BIT", self.zero_page_mode)
self.ops[0x25] = ("AND", self.zero_page_mode) self.ops[0x25] = (2, "AND", self.zero_page_mode)
self.ops[0x26] = ("ROL", self.zero_page_mode) self.ops[0x26] = (2, "ROL", self.zero_page_mode)
self.ops[0x28] = ("PLP", ) self.ops[0x28] = (1, "PLP", )
self.ops[0x29] = ("AND", self.immediate_mode) self.ops[0x29] = (2, "AND", self.immediate_mode)
self.ops[0x2A] = ("ROL", ) self.ops[0x2A] = (1, "ROL", )
self.ops[0x2C] = ("BIT", self.absolute_mode) self.ops[0x2C] = (3, "BIT", self.absolute_mode)
self.ops[0x2D] = ("AND", self.absolute_mode) self.ops[0x2D] = (3, "AND", self.absolute_mode)
self.ops[0x2E] = ("ROL", self.absolute_mode) self.ops[0x2E] = (3, "ROL", self.absolute_mode)
self.ops[0x30] = ("BMI", self.relative_mode) self.ops[0x30] = (2, "BMI", self.relative_mode)
self.ops[0x31] = ("AND", self.indirect_y_mode) self.ops[0x31] = (2, "AND", self.indirect_y_mode)
self.ops[0x35] = ("AND", self.zero_page_x_mode) self.ops[0x35] = (2, "AND", self.zero_page_x_mode)
self.ops[0x36] = ("ROL", self.zero_page_x_mode) self.ops[0x36] = (2, "ROL", self.zero_page_x_mode)
self.ops[0x38] = ("SEC", ) self.ops[0x38] = (1, "SEC", )
self.ops[0x39] = ("AND", self.absolute_y_mode) self.ops[0x39] = (3, "AND", self.absolute_y_mode)
self.ops[0x3D] = ("AND", self.absolute_x_mode) self.ops[0x3D] = (3, "AND", self.absolute_x_mode)
self.ops[0x3E] = ("ROL", self.absolute_x_mode) self.ops[0x3E] = (3, "ROL", self.absolute_x_mode)
self.ops[0x40] = ("RTI", ) self.ops[0x40] = (1, "RTI", )
self.ops[0x41] = ("EOR", self.indirect_x_mode) self.ops[0x41] = (2, "EOR", self.indirect_x_mode)
self.ops[0x45] = ("EOR", self.zero_page_mode) self.ops[0x45] = (2, "EOR", self.zero_page_mode)
self.ops[0x46] = ("LSR", self.zero_page_mode) self.ops[0x46] = (2, "LSR", self.zero_page_mode)
self.ops[0x48] = ("PHA", ) self.ops[0x48] = (1, "PHA", )
self.ops[0x49] = ("EOR", self.immediate_mode) self.ops[0x49] = (2, "EOR", self.immediate_mode)
self.ops[0x4A] = ("LSR", ) self.ops[0x4A] = (1, "LSR", )
self.ops[0x4C] = ("JMP", self.absolute_mode) self.ops[0x4C] = (3, "JMP", self.absolute_mode)
self.ops[0x4D] = ("EOR", self.absolute_mode) self.ops[0x4D] = (3, "EOR", self.absolute_mode)
self.ops[0x4E] = ("LSR", self.absolute_mode) self.ops[0x4E] = (3, "LSR", self.absolute_mode)
self.ops[0x50] = ("BVC", self.relative_mode) self.ops[0x50] = (2, "BVC", self.relative_mode)
self.ops[0x51] = ("EOR", self.indirect_y_mode) self.ops[0x51] = (2, "EOR", self.indirect_y_mode)
self.ops[0x55] = ("EOR", self.zero_page_x_mode) self.ops[0x55] = (2, "EOR", self.zero_page_x_mode)
self.ops[0x56] = ("LSR", self.zero_page_x_mode) self.ops[0x56] = (2, "LSR", self.zero_page_x_mode)
self.ops[0x58] = ("CLI", ) self.ops[0x58] = (1, "CLI", )
self.ops[0x59] = ("EOR", self.absolute_y_mode) self.ops[0x59] = (3, "EOR", self.absolute_y_mode)
self.ops[0x5D] = ("EOR", self.absolute_x_mode) self.ops[0x5D] = (3, "EOR", self.absolute_x_mode)
self.ops[0x5E] = ("LSR", self.absolute_x_mode) self.ops[0x5E] = (3, "LSR", self.absolute_x_mode)
self.ops[0x60] = ("RTS", ) self.ops[0x60] = (1, "RTS", )
self.ops[0x61] = ("ADC", self.indirect_x_mode) self.ops[0x61] = (2, "ADC", self.indirect_x_mode)
self.ops[0x65] = ("ADC", self.zero_page_mode) self.ops[0x65] = (2, "ADC", self.zero_page_mode)
self.ops[0x66] = ("ROR", self.zero_page_mode) self.ops[0x66] = (2, "ROR", self.zero_page_mode)
self.ops[0x68] = ("PLA", ) self.ops[0x68] = (1, "PLA", )
self.ops[0x69] = ("ADC", self.immediate_mode) self.ops[0x69] = (2, "ADC", self.immediate_mode)
self.ops[0x6A] = ("ROR", ) self.ops[0x6A] = (1, "ROR", )
self.ops[0x6C] = ("JMP", self.indirect_mode) self.ops[0x6C] = (3, "JMP", self.indirect_mode)
self.ops[0x6D] = ("ADC", self.absolute_mode) self.ops[0x6D] = (3, "ADC", self.absolute_mode)
self.ops[0x6E] = ("ROR", self.absolute_mode) self.ops[0x6E] = (3, "ROR", self.absolute_mode)
self.ops[0x70] = ("BVS", self.relative_mode) self.ops[0x70] = (2, "BVS", self.relative_mode)
self.ops[0x71] = ("ADC", self.indirect_y_mode) self.ops[0x71] = (2, "ADC", self.indirect_y_mode)
self.ops[0x75] = ("ADC", self.zero_page_x_mode) self.ops[0x75] = (2, "ADC", self.zero_page_x_mode)
self.ops[0x76] = ("ROR", self.zero_page_x_mode) self.ops[0x76] = (2, "ROR", self.zero_page_x_mode)
self.ops[0x78] = ("SEI", ) self.ops[0x78] = (1, "SEI", )
self.ops[0x79] = ("ADC", self.absolute_y_mode) self.ops[0x79] = (3, "ADC", self.absolute_y_mode)
self.ops[0x7D] = ("ADC", self.absolute_x_mode) self.ops[0x7D] = (3, "ADC", self.absolute_x_mode)
self.ops[0x7E] = ("ROR", self.absolute_x_mode) self.ops[0x7E] = (3, "ROR", self.absolute_x_mode)
self.ops[0x81] = ("STA", self.indirect_x_mode) self.ops[0x81] = (2, "STA", self.indirect_x_mode)
self.ops[0x84] = ("STY", self.zero_page_mode) self.ops[0x84] = (2, "STY", self.zero_page_mode)
self.ops[0x85] = ("STA", self.zero_page_mode) self.ops[0x85] = (2, "STA", self.zero_page_mode)
self.ops[0x86] = ("STX", self.zero_page_mode) self.ops[0x86] = (2, "STX", self.zero_page_mode)
self.ops[0x88] = ("DEY", ) self.ops[0x88] = (1, "DEY", )
self.ops[0x8A] = ("TXA", ) self.ops[0x8A] = (1, "TXA", )
self.ops[0x8C] = ("STY", self.absolute_mode) self.ops[0x8C] = (3, "STY", self.absolute_mode)
self.ops[0x8D] = ("STA", self.absolute_mode) self.ops[0x8D] = (3, "STA", self.absolute_mode)
self.ops[0x8E] = ("STX", self.absolute_mode) self.ops[0x8E] = (3, "STX", self.absolute_mode)
self.ops[0x90] = ("BCC", self.relative_mode) self.ops[0x90] = (2, "BCC", self.relative_mode)
self.ops[0x91] = ("STA", self.indirect_y_mode) self.ops[0x91] = (2, "STA", self.indirect_y_mode)
self.ops[0x94] = ("STY", self.zero_page_x_mode) self.ops[0x94] = (2, "STY", self.zero_page_x_mode)
self.ops[0x95] = ("STA", self.zero_page_x_mode) self.ops[0x95] = (2, "STA", self.zero_page_x_mode)
self.ops[0x96] = ("STX", self.zero_page_y_mode) self.ops[0x96] = (2, "STX", self.zero_page_y_mode)
self.ops[0x98] = ("TYA", ) self.ops[0x98] = (1, "TYA", )
self.ops[0x99] = ("STA", self.absolute_y_mode) self.ops[0x99] = (3, "STA", self.absolute_y_mode)
self.ops[0x9A] = ("TXS", ) self.ops[0x9A] = (1, "TXS", )
self.ops[0x9D] = ("STA", self.absolute_x_mode) self.ops[0x9D] = (3, "STA", self.absolute_x_mode)
self.ops[0xA0] = ("LDY", self.immediate_mode) self.ops[0xA0] = (2, "LDY", self.immediate_mode)
self.ops[0xA1] = ("LDA", self.indirect_x_mode) self.ops[0xA1] = (2, "LDA", self.indirect_x_mode)
self.ops[0xA2] = ("LDX", self.immediate_mode) self.ops[0xA2] = (2, "LDX", self.immediate_mode)
self.ops[0xA4] = ("LDY", self.zero_page_mode) self.ops[0xA4] = (2, "LDY", self.zero_page_mode)
self.ops[0xA5] = ("LDA", self.zero_page_mode) self.ops[0xA5] = (2, "LDA", self.zero_page_mode)
self.ops[0xA6] = ("LDX", self.zero_page_mode) self.ops[0xA6] = (2, "LDX", self.zero_page_mode)
self.ops[0xA8] = ("TAY", ) self.ops[0xA8] = (1, "TAY", )
self.ops[0xA9] = ("LDA", self.immediate_mode) self.ops[0xA9] = (2, "LDA", self.immediate_mode)
self.ops[0xAA] = ("TAX", ) self.ops[0xAA] = (1, "TAX", )
self.ops[0xAC] = ("LDY", self.absolute_mode) self.ops[0xAC] = (3, "LDY", self.absolute_mode)
self.ops[0xAD] = ("LDA", self.absolute_mode) self.ops[0xAD] = (3, "LDA", self.absolute_mode)
self.ops[0xAE] = ("LDX", self.absolute_mode) self.ops[0xAE] = (3, "LDX", self.absolute_mode)
self.ops[0xB0] = ("BCS", self.relative_mode) self.ops[0xB0] = (2, "BCS", self.relative_mode)
self.ops[0xB1] = ("LDA", self.indirect_y_mode) self.ops[0xB1] = (2, "LDA", self.indirect_y_mode)
self.ops[0xB4] = ("LDY", self.zero_page_x_mode) self.ops[0xB4] = (2, "LDY", self.zero_page_x_mode)
self.ops[0xB5] = ("LDA", self.zero_page_x_mode) self.ops[0xB5] = (2, "LDA", self.zero_page_x_mode)
self.ops[0xB6] = ("LDX", self.zero_page_y_mode) self.ops[0xB6] = (2, "LDX", self.zero_page_y_mode)
self.ops[0xB8] = ("CLV", ) self.ops[0xB8] = (1, "CLV", )
self.ops[0xB9] = ("LDA", self.absolute_y_mode) self.ops[0xB9] = (3, "LDA", self.absolute_y_mode)
self.ops[0xBA] = ("TSX", ) self.ops[0xBA] = (1, "TSX", )
self.ops[0xBC] = ("LDY", self.absolute_x_mode) self.ops[0xBC] = (3, "LDY", self.absolute_x_mode)
self.ops[0xBD] = ("LDA", self.absolute_x_mode) self.ops[0xBD] = (3, "LDA", self.absolute_x_mode)
self.ops[0xBE] = ("LDX", self.absolute_y_mode) self.ops[0xBE] = (3, "LDX", self.absolute_y_mode)
self.ops[0xC0] = ("CPY", self.immediate_mode) self.ops[0xC0] = (2, "CPY", self.immediate_mode)
self.ops[0xC1] = ("CMP", self.indirect_x_mode) self.ops[0xC1] = (2, "CMP", self.indirect_x_mode)
self.ops[0xC4] = ("CPY", self.zero_page_mode) self.ops[0xC4] = (2, "CPY", self.zero_page_mode)
self.ops[0xC5] = ("CMP", self.zero_page_mode) self.ops[0xC5] = (2, "CMP", self.zero_page_mode)
self.ops[0xC6] = ("DEC", self.zero_page_mode) self.ops[0xC6] = (2, "DEC", self.zero_page_mode)
self.ops[0xC8] = ("INY", ) self.ops[0xC8] = (1, "INY", )
self.ops[0xC9] = ("CMP", self.immediate_mode) self.ops[0xC9] = (2, "CMP", self.immediate_mode)
self.ops[0xCA] = ("DEX", ) self.ops[0xCA] = (1, "DEX", )
self.ops[0xCC] = ("CPY", self.absolute_mode) self.ops[0xCC] = (3, "CPY", self.absolute_mode)
self.ops[0xCD] = ("CMP", self.absolute_mode) self.ops[0xCD] = (3, "CMP", self.absolute_mode)
self.ops[0xCE] = ("DEC", self.absolute_mode) self.ops[0xCE] = (3, "DEC", self.absolute_mode)
self.ops[0xD0] = ("BNE", self.relative_mode) self.ops[0xD0] = (2, "BNE", self.relative_mode)
self.ops[0xD1] = ("CMP", self.indirect_y_mode) self.ops[0xD1] = (2, "CMP", self.indirect_y_mode)
self.ops[0xD5] = ("CMP", self.zero_page_x_mode) self.ops[0xD5] = (2, "CMP", self.zero_page_x_mode)
self.ops[0xD6] = ("DEC", self.zero_page_x_mode) self.ops[0xD6] = (2, "DEC", self.zero_page_x_mode)
self.ops[0xD8] = ("CLD", ) self.ops[0xD8] = (1, "CLD", )
self.ops[0xD9] = ("CMP", self.absolute_y_mode) self.ops[0xD9] = (3, "CMP", self.absolute_y_mode)
self.ops[0xDD] = ("CMP", self.absolute_x_mode) self.ops[0xDD] = (3, "CMP", self.absolute_x_mode)
self.ops[0xDE] = ("DEC", self.absolute_x_mode) self.ops[0xDE] = (3, "DEC", self.absolute_x_mode)
self.ops[0xE0] = ("CPX", self.immediate_mode) self.ops[0xE0] = (2, "CPX", self.immediate_mode)
self.ops[0xE1] = ("SBC", self.indirect_x_mode) self.ops[0xE1] = (2, "SBC", self.indirect_x_mode)
self.ops[0xE4] = ("CPX", self.zero_page_mode) self.ops[0xE4] = (2, "CPX", self.zero_page_mode)
self.ops[0xE5] = ("SBC", self.zero_page_mode) self.ops[0xE5] = (2, "SBC", self.zero_page_mode)
self.ops[0xE6] = ("INC", self.zero_page_mode) self.ops[0xE6] = (2, "INC", self.zero_page_mode)
self.ops[0xE8] = ("INX", ) self.ops[0xE8] = (1, "INX", )
self.ops[0xE9] = ("SBC", self.immediate_mode) self.ops[0xE9] = (2, "SBC", self.immediate_mode)
self.ops[0xEA] = ("NOP", ) self.ops[0xEA] = (1, "NOP", )
self.ops[0xEC] = ("CPX", self.absolute_mode) self.ops[0xEC] = (3, "CPX", self.absolute_mode)
self.ops[0xED] = ("SBC", self.absolute_mode) self.ops[0xED] = (3, "SBC", self.absolute_mode)
self.ops[0xEE] = ("INC", self.absolute_mode) self.ops[0xEE] = (3, "INC", self.absolute_mode)
self.ops[0xF0] = ("BEQ", self.relative_mode) self.ops[0xF0] = (2, "BEQ", self.relative_mode)
self.ops[0xF1] = ("SBC", self.indirect_y_mode) self.ops[0xF1] = (2, "SBC", self.indirect_y_mode)
self.ops[0xF5] = ("SBC", self.zero_page_x_mode) self.ops[0xF5] = (2, "SBC", self.zero_page_x_mode)
self.ops[0xF6] = ("INC", self.zero_page_x_mode) self.ops[0xF6] = (2, "INC", self.zero_page_x_mode)
self.ops[0xF8] = ("SED", ) self.ops[0xF8] = (1, "SED", )
self.ops[0xF9] = ("SBC", self.absolute_y_mode) self.ops[0xF9] = (3, "SBC", self.absolute_y_mode)
self.ops[0xFD] = ("SBC", self.absolute_x_mode) self.ops[0xFD] = (3, "SBC", self.absolute_x_mode)
self.ops[0xFE] = ("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.memory.read_word(pc + 1) a = self.cpu.read_word(pc + 1)
return "$%04X [%04X] = %02X" % (a, a, self.memory.read_word(a)) return {
"operand": "$%04X" % a,
"memory": [a, 2, self.cpu.read_word(a)],
}
def absolute_x_mode(self, pc): def absolute_x_mode(self, pc):
a = self.memory.read_word(pc + 1) a = self.cpu.read_word(pc + 1)
e = a + self.cpu.x_index e = a + self.cpu.x_index
return "$%04X,X [%04X] = %02X" % (a, e, self.memory.read_byte(e)) return {
"operand": "$%04X,X" % a,
"memory": [e, 1, self.cpu.read_byte(e)],
}
def absolute_y_mode(self, pc): def absolute_y_mode(self, pc):
a = self.memory.read_word(pc + 1) a = self.cpu.read_word(pc + 1)
e = a + self.cpu.y_index e = a + self.cpu.y_index
return "$%04X,Y [%04X] = %02X" % (a, e, self.memory.read_byte(e)) return {
"operand": "$%04X,Y" % a,
"memory": [e, 1, self.cpu.read_byte(e)],
}
def immediate_mode(self, pc): def immediate_mode(self, pc):
return "#$%02X" % (self.memory.read_byte(pc + 1)) return {
"operand": "#$%02X" % (self.cpu.read_byte(pc + 1)),
}
def indirect_mode(self, pc): def indirect_mode(self, pc):
a = self.memory.read_word(pc + 1) a = self.cpu.read_word(pc + 1)
return "($%04X) [%04X] = %02X" % (a, a, self.memory.read_word(a)) return {
"operand": "($%04X)" % a,
"memory": [a, 2, self.cpu.read_word(a)],
}
def indirect_x_mode(self, pc): def indirect_x_mode(self, pc):
z = self.memory.read_byte(pc + 1) z = self.cpu.read_byte(pc + 1)
a = self.memory.read_word((z + self.cpu.x_index) % 0x100) a = self.cpu.read_word((z + self.cpu.x_index) % 0x100)
return "($%02X,X) [%04X] = %02X" % (z, a, self.memory.read_byte(a)) return {
"operand": "($%02X,X)" % z,
"memory": [a, 1, self.cpu.read_byte(a)],
}
def indirect_y_mode(self, pc): def indirect_y_mode(self, pc):
z = self.memory.read_byte(pc + 1) z = self.cpu.read_byte(pc + 1)
a = self.memory.read_word(z) + self.cpu.y_index a = self.cpu.read_word(z) + self.cpu.y_index
return "($%02X),Y [%04X] = %02X" % (z, a, self.memory.read_byte(a)) return {
"operand": "($%02X),Y" % z,
"memory": [a, 1, self.cpu.read_byte(a)],
}
def relative_mode(self, pc): def relative_mode(self, pc):
return "$%04X" % (pc + signed(self.memory.read_byte(pc + 1) + 2)) return {
"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.memory.read_byte(pc + 1) a = self.cpu.read_byte(pc + 1)
return "$%02X [%04X] = %02X" % (a, a, self.memory.read_byte(a)) return {
"operand": "$%02X" % 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.memory.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
return "$%02X,X [%04X] = %02X" % (z, a, self.memory.read_byte(a)) return {
"operand": "$%02X,X" % z,
"memory": [a, 1, self.cpu.read_byte(a)],
}
def zero_page_y_mode(self, pc): def zero_page_y_mode(self, pc):
z = self.memory.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
return "$%02X,Y [%04X] = %02X" % (z, a, self.memory.read_byte(a)) return {
"operand": "$%02X,Y" % z,
"memory": [a, 1, self.cpu.read_byte(a)],
}
def disasm(self, pc): def disasm(self, pc):
op = self.memory.read_byte(pc) op = self.cpu.read_byte(pc)
info = self.ops[op] info = self.ops[op]
s = "%02X %s" % (pc, info[0]) r = {
if len(info) > 1: "address": pc,
s += " " + info[1](pc) "bytes": [self.cpu.read_byte(pc + i) for i in range(info[0])],
return s "mnemonic": info[1],
}
if len(info) > 2:
r.update(info[2](pc))
return r, info[0]
class ControlHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def __init__(self, request, client_address, server, cpu):
self.cpu = cpu
self.disassemble = Disassemble(self.cpu, self.cpu.memory)
self.get_urls = {
r"/disassemble/(\d+)$": self.get_disassemble,
r"/memory/(\d+)(-(\d+))?$": self.get_memory,
r"/memory/(\d+)(-(\d+))?/raw$": self.get_memory_raw,
r"/status$": self.get_status,
}
self.post_urls = {
r"/memory/(\d+)(-(\d+))?$": self.post_memory,
r"/memory/(\d+)(-(\d+))?/raw$": self.post_memory_raw,
r"/quit$": self.post_quit,
r"/reset$": self.post_reset,
}
BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request, client_address, server)
def log_request(self, code, size=0):
pass
def dispatch(self, urls):
for r, f in urls.items():
m = re.match(r, self.path)
if m is not None:
f(m)
break
else:
self.send_response(404)
self.end_headers()
def response(self, s):
self.send_response(200)
self.send_header("Content-Length", str(len(s)))
self.end_headers()
self.wfile.write(s)
def do_GET(self):
self.dispatch(self.get_urls)
def do_POST(self):
self.dispatch(self.post_urls)
def get_disassemble(self, m):
addr = int(m.group(1))
r = []
n = 20
while n > 0:
dis, length = self.disassemble.disasm(addr)
r.append(dis)
addr += length
n -= 1
self.response(json.dumps(r))
def get_memory_raw(self, m):
addr = int(m.group(1))
e = m.group(3)
if e is not None:
end = int(e)
else:
end = addr
self.response("".join([chr(self.cpu.read_byte(x)) for x in range(addr, end + 1)]))
def get_memory(self, m):
addr = int(m.group(1))
e = m.group(3)
if e is not None:
end = int(e)
else:
end = addr
self.response(json.dumps(list(map(self.cpu.read_byte, range(addr, end + 1)))))
def get_status(self, m):
self.response(json.dumps(dict((x, getattr(self.cpu, x)) for x in (
"accumulator",
"x_index",
"y_index",
"stack_pointer",
"program_counter",
"sign_flag",
"overflow_flag",
"break_flag",
"decimal_mode_flag",
"interrupt_disable_flag",
"zero_flag",
"carry_flag",
))))
def post_memory(self, m):
addr = int(m.group(1))
e = m.group(3)
if e is not None:
end = int(e)
else:
end = addr
data = json.loads(self.rfile.read(int(self.headers["Content-Length"])))
for i, a in enumerate(range(addr, end + 1)):
self.cpu.write_byte(a, data[i])
self.response("")
def post_memory_raw(self, m):
addr = int(m.group(1))
e = m.group(3)
if e is not None:
end = int(e)
else:
end = addr
data = self.rfile.read(int(self.headers["Content-Length"]))
for i, a in enumerate(range(addr, end + 1)):
self.cpu.write_byte(a, data[i])
self.response("")
def post_quit(self, m):
self.cpu.quit = True
self.response("")
def post_reset(self, m):
self.cpu.reset()
self.cpu.running = True
self.response("")
class ControlHandlerFactory:
def __init__(self, cpu):
self.cpu = cpu
def __call__(self, request, client_address, server):
return ControlHandler(request, client_address, server, self.cpu)
class CPU: class CPU:
@ -329,9 +505,10 @@ class CPU:
STACK_PAGE = 0x100 STACK_PAGE = 0x100
RESET_VECTOR = 0xFFFC RESET_VECTOR = 0xFFFC
def __init__(self, memory): def __init__(self, options, memory):
self.memory = memory self.memory = memory
self.disassemble = Disassemble(self, memory)
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
@ -351,6 +528,10 @@ class CPU:
self.setup_ops() self.setup_ops()
self.reset() self.reset()
if options.pc is not None:
self.program_counter = options.pc
self.running = True
self.quit = False
def setup_ops(self): def setup_ops(self):
self.ops = [None] * 0x100 self.ops = [None] * 0x100
@ -509,18 +690,41 @@ class CPU:
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): def run(self, bus_port):
while True: global bus
self.cycles += 2 # all instructions take this as a minimum bus = socket.socket()
op = self.read_pc_byte() bus.connect(("127.0.0.1", bus_port))
func = self.ops[op]
if func is None: while not self.quit:
print "UNKNOWN OP"
print hex(self.program_counter - 1) timeout = 0
print hex(op) if not self.running:
break timeout = 1
else: # Currently this handler blocks from the moment
self.ops[op]() # a connection is accepted until the response
# is sent. TODO: use an async HTTP server that
# handles input data asynchronously.
sockets = [self.control_server]
rs, _, _ = select.select(sockets, [], [], timeout)
for s in rs:
if s is self.control_server:
self.control_server._handle_request_noblock()
else:
pass
count = 1000
while count > 0 and self.running:
self.cycles += 2 # all instructions take this as a minimum
op = self.read_pc_byte()
func = self.ops[op]
if func is None:
print "UNKNOWN OP"
print hex(self.program_counter - 1)
print hex(op)
break
else:
self.ops[op]()
count -= 1
def test_run(self, start, end): def test_run(self, start, end):
self.program_counter = start self.program_counter = start
@ -973,6 +1177,8 @@ def usage():
print >>sys.stderr print >>sys.stderr
print >>sys.stderr, "Usage: cpu6502.py [options]" print >>sys.stderr, "Usage: cpu6502.py [options]"
print >>sys.stderr print >>sys.stderr
print >>sys.stderr, " -b, --bus Bus port number"
print >>sys.stderr, " -p, --pc Initial PC value"
print >>sys.stderr, " -R, --rom ROM file to use (default A2ROM.BIN)" print >>sys.stderr, " -R, --rom ROM file to use (default A2ROM.BIN)"
print >>sys.stderr, " -r, --ram RAM file to load (default none)" print >>sys.stderr, " -r, --ram RAM file to load (default none)"
sys.exit(1) sys.exit(1)
@ -983,12 +1189,20 @@ def get_options():
def __init__(self): def __init__(self):
self.rom = "A2ROM.BIN" self.rom = "A2ROM.BIN"
self.ram = None self.ram = None
self.bus = None
self.pc = None
options = Options() options = Options()
a = 1 a = 1
while a < len(sys.argv): while a < len(sys.argv):
if sys.argv[a].startswith("-"): if sys.argv[a].startswith("-"):
if sys.argv[a] in ("-R", "--rom"): if sys.argv[a] in ("-b", "--bus"):
a += 1
options.bus = int(sys.argv[a])
elif sys.argv[a] in ("-p", "--pc"):
a += 1
options.pc = int(sys.argv[a])
elif sys.argv[a] in ("-R", "--rom"):
a += 1 a += 1
options.rom = sys.argv[a] options.rom = sys.argv[a]
elif sys.argv[a] in ("-r", "--ram"): elif sys.argv[a] in ("-r", "--ram"):
@ -1004,13 +1218,13 @@ def get_options():
if __name__ == "__main__": if __name__ == "__main__":
if sys.stdout.isatty(): options = get_options()
if options.bus is None:
print "ApplePy cpu core" print "ApplePy cpu core"
print "Run applepy.py instead" print "Run applepy.py instead"
sys.exit(0) sys.exit(0)
options = get_options()
mem = Memory(options) mem = Memory(options)
cpu = CPU(mem) cpu = CPU(options, mem)
cpu.run() cpu.run(options.bus)

View File

@ -5,7 +5,7 @@ from cpu6502 import Memory, CPU
class TestMemory(unittest.TestCase): class TestMemory(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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])
@ -25,7 +25,7 @@ class TestMemory(unittest.TestCase):
class TestLoadStoreOperations(unittest.TestCase): class TestLoadStoreOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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])
@ -114,7 +114,7 @@ class TestLoadStoreOperations(unittest.TestCase):
class TestRegisterTransferOperations(unittest.TestCase): class TestRegisterTransferOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -189,7 +189,7 @@ class TestRegisterTransferOperations(unittest.TestCase):
class TestStackOperations(unittest.TestCase): class TestStackOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -237,7 +237,7 @@ class TestStackOperations(unittest.TestCase):
class TestLogicalOperations(unittest.TestCase): class TestLogicalOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -325,7 +325,7 @@ class TestLogicalOperations(unittest.TestCase):
class TestArithmeticOperations(unittest.TestCase): class TestArithmeticOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -544,7 +544,7 @@ class TestArithmeticOperations(unittest.TestCase):
class TestIncrementDecrementOperations(unittest.TestCase): class TestIncrementDecrementOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -653,7 +653,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
class TestShiftOperations(unittest.TestCase): class TestShiftOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -760,7 +760,7 @@ class TestShiftOperations(unittest.TestCase):
class TestJumpCallOperations(unittest.TestCase): class TestJumpCallOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -792,7 +792,7 @@ class TestJumpCallOperations(unittest.TestCase):
class TestBranchOperations(unittest.TestCase): class TestBranchOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -879,7 +879,7 @@ class TestBranchOperations(unittest.TestCase):
class TestStatusFlagOperations(unittest.TestCase): class TestStatusFlagOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -921,7 +921,7 @@ class TestStatusFlagOperations(unittest.TestCase):
class TestSystemFunctionOperations(unittest.TestCase): class TestSystemFunctionOperations(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):
@ -951,7 +951,7 @@ class TestSystemFunctionOperations(unittest.TestCase):
class Test6502Bugs(unittest.TestCase): class Test6502Bugs(unittest.TestCase):
def setUp(self): def setUp(self):
self.memory = Memory(use_stdio=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):