From cd692af6f33d24a117bd0ad5db0011db63b13366 Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Thu, 18 Aug 2011 20:39:28 +1200 Subject: [PATCH 1/5] use sockets for comms instead of stdio --- applepy.py | 19 +++++++++++-------- cpu6502.py | 36 +++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/applepy.py b/applepy.py index 5052474..e7feeb1 100644 --- a/applepy.py +++ b/applepy.py @@ -5,6 +5,7 @@ import numpy import pygame +import socket import struct import subprocess import sys @@ -357,30 +358,32 @@ class Apple2: self.speaker = speaker self.softswitches = SoftSwitches(display, speaker, cassette) + listener = socket.socket() + listener.bind(("127.0.0.1", 0)) + listener.listen(0) + args = [ sys.executable, "cpu6502.py", + "--ui", str(listener.getsockname()[1]), "--rom", options.rom, ] if options.ram: args.extend([ "--ram", options.ram, ]) - self.core = subprocess.Popen( - args=args, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - ) + self.core = subprocess.Popen(args) + + self.cpu, _ = listener.accept() def run(self): update_cycle = 0 quit = False while not quit: - op = self.core.stdout.read(8) + op = self.cpu.recv(8) cycle, rw, addr, val = struct.unpack(" 0x7F: x = x - 0x100 @@ -86,22 +90,20 @@ class Memory: return 0 op = struct.pack(">sys.stderr 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, " -u, --ui UI socket" sys.exit(1) @@ -983,6 +989,7 @@ def get_options(): def __init__(self): self.rom = "A2ROM.BIN" self.ram = None + self.ui = None options = Options() a = 1 @@ -994,6 +1001,9 @@ def get_options(): elif sys.argv[a] in ("-r", "--ram"): a += 1 options.ram = sys.argv[a] + elif sys.argv[a] in ("-u", "--ui"): + a += 1 + options.ui = int(sys.argv[a]) else: usage() else: @@ -1004,13 +1014,13 @@ def get_options(): if __name__ == "__main__": - if sys.stdout.isatty(): + options = get_options() + if options.ui is None: print "ApplePy cpu core" print "Run applepy.py instead" sys.exit(0) - options = get_options() mem = Memory(options) cpu = CPU(mem) - cpu.run() + cpu.run(options.ui) From dcc8e9d8ce6c0cfe5be6a007c1dcdc0e56dce056 Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Thu, 18 Aug 2011 21:14:49 +1200 Subject: [PATCH 2/5] update curses UI for socket comms --- applepy_curses.py | 58 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/applepy_curses.py b/applepy_curses.py index 8b234e6..b85b779 100644 --- a/applepy_curses.py +++ b/applepy_curses.py @@ -4,6 +4,7 @@ import curses +import socket import struct import subprocess import sys @@ -55,20 +56,29 @@ def write(win, addr, val): def run(win): global kbd - p = subprocess.Popen( - args=[sys.executable, "cpu6502.py"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - ) + + listener = socket.socket() + listener.bind(("127.0.0.1", 0)) + listener.listen(0) + + args = [ + sys.executable, + "cpu6502.py", + "--ui", str(listener.getsockname()[1]), + "--rom", options.rom, + ] + + p = subprocess.Popen(args) + cpu, _ = listener.accept() + win.clear() curses.noecho() win.nodelay(True) while True: - op = p.stdout.read(8) + op = cpu.recv(8) cycle, rw, addr, val = struct.unpack(">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__": + options = get_options() curses.wrapper(run) From 15e174c02a2037b8434d06cf102ecd9060b8bab6 Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Fri, 19 Aug 2011 20:30:55 +1200 Subject: [PATCH 3/5] rename --ui switch to --bus --- applepy.py | 2 +- applepy_curses.py | 2 +- cpu6502.py | 40 ++++++++++++++++++++-------------------- tests.py | 26 +++++++++++++------------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/applepy.py b/applepy.py index e7feeb1..cebe0c0 100644 --- a/applepy.py +++ b/applepy.py @@ -365,7 +365,7 @@ class Apple2: args = [ sys.executable, "cpu6502.py", - "--ui", str(listener.getsockname()[1]), + "--bus", str(listener.getsockname()[1]), "--rom", options.rom, ] if options.ram: diff --git a/applepy_curses.py b/applepy_curses.py index b85b779..a232c40 100644 --- a/applepy_curses.py +++ b/applepy_curses.py @@ -64,7 +64,7 @@ def run(win): args = [ sys.executable, "cpu6502.py", - "--ui", str(listener.getsockname()[1]), + "--bus", str(listener.getsockname()[1]), "--rom", options.rom, ] diff --git a/cpu6502.py b/cpu6502.py index f397aa6..e48b0c7 100644 --- a/cpu6502.py +++ b/cpu6502.py @@ -8,7 +8,7 @@ import struct import sys -ui = None +bus = None # socket for bus I/O def signed(x): @@ -46,8 +46,8 @@ class RAM(ROM): class Memory: - def __init__(self, options=None, use_stdio=True): - self.use_stdio = use_stdio + def __init__(self, options=None, use_bus=True): + self.use_bus = use_bus self.rom = ROM(0xD000, 0x3000) if options: @@ -86,12 +86,12 @@ class Memory: self.bus_write(cycle, address, value) def bus_read(self, cycle, address): - if not self.use_stdio: + if not self.use_bus: return 0 op = struct.pack(">sys.stderr print >>sys.stderr, "Usage: cpu6502.py [options]" print >>sys.stderr + print >>sys.stderr, " -b, --bus Bus port number" 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, " -u, --ui UI socket" sys.exit(1) @@ -989,21 +989,21 @@ def get_options(): def __init__(self): self.rom = "A2ROM.BIN" self.ram = None - self.ui = None + self.bus = None options = Options() a = 1 while a < len(sys.argv): 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 ("-R", "--rom"): a += 1 options.rom = sys.argv[a] elif sys.argv[a] in ("-r", "--ram"): a += 1 options.ram = sys.argv[a] - elif sys.argv[a] in ("-u", "--ui"): - a += 1 - options.ui = int(sys.argv[a]) else: usage() else: @@ -1015,7 +1015,7 @@ def get_options(): if __name__ == "__main__": options = get_options() - if options.ui is None: + if options.bus is None: print "ApplePy cpu core" print "Run applepy.py instead" sys.exit(0) @@ -1023,4 +1023,4 @@ if __name__ == "__main__": mem = Memory(options) cpu = CPU(mem) - cpu.run(options.ui) + cpu.run(options.bus) diff --git a/tests.py b/tests.py index 3d8dedd..6a5d606 100644 --- a/tests.py +++ b/tests.py @@ -5,7 +5,7 @@ from cpu6502 import Memory, CPU class TestMemory(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) def test_load(self): self.memory.load(0x1000, [0x01, 0x02, 0x03]) @@ -25,7 +25,7 @@ class TestMemory(unittest.TestCase): class TestLoadStoreOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) self.memory.load(0x1000, [0x00, 0x01, 0x7F, 0x80, 0xFF]) @@ -114,7 +114,7 @@ class TestLoadStoreOperations(unittest.TestCase): class TestRegisterTransferOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_TAX(self): @@ -189,7 +189,7 @@ class TestRegisterTransferOperations(unittest.TestCase): class TestStackOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_TSX(self): @@ -237,7 +237,7 @@ class TestStackOperations(unittest.TestCase): class TestLogicalOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_AND(self): @@ -325,7 +325,7 @@ class TestLogicalOperations(unittest.TestCase): class TestArithmeticOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_ADC_without_BCD(self): @@ -544,7 +544,7 @@ class TestArithmeticOperations(unittest.TestCase): class TestIncrementDecrementOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_INC(self): @@ -653,7 +653,7 @@ class TestIncrementDecrementOperations(unittest.TestCase): class TestShiftOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_ASL(self): @@ -760,7 +760,7 @@ class TestShiftOperations(unittest.TestCase): class TestJumpCallOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_JMP(self): @@ -792,7 +792,7 @@ class TestJumpCallOperations(unittest.TestCase): class TestBranchOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_BCC(self): @@ -879,7 +879,7 @@ class TestBranchOperations(unittest.TestCase): class TestStatusFlagOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_CLC(self): @@ -921,7 +921,7 @@ class TestStatusFlagOperations(unittest.TestCase): class TestSystemFunctionOperations(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_BRK(self): @@ -951,7 +951,7 @@ class TestSystemFunctionOperations(unittest.TestCase): class Test6502Bugs(unittest.TestCase): def setUp(self): - self.memory = Memory(use_stdio=False) + self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) def test_zero_page_x(self): From 9f09818aa03362431add8770593236892cd02a65 Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Fri, 19 Aug 2011 21:07:19 +1200 Subject: [PATCH 4/5] abandon startup if cpu module does not start --- applepy.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/applepy.py b/applepy.py index cebe0c0..2c35ca5 100644 --- a/applepy.py +++ b/applepy.py @@ -5,6 +5,7 @@ import numpy import pygame +import select import socket import struct import subprocess @@ -374,6 +375,10 @@ class Apple2: ]) 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): From a673f8a4d4b80933a2bc0694cc10b95a8c52a680 Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Fri, 19 Aug 2011 21:43:12 +1200 Subject: [PATCH 5/5] graceful shutdown if cpu core exits --- applepy.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/applepy.py b/applepy.py index 2c35ca5..71e0aef 100644 --- a/applepy.py +++ b/applepy.py @@ -386,6 +386,8 @@ class Apple2: quit = False while not quit: op = self.cpu.recv(8) + if len(op) == 0: + break cycle, rw, addr, val = struct.unpack("