From 5dd6e9f95a37a3a17ede913377b18913fcdd5f71 Mon Sep 17 00:00:00 2001 From: Mike Naberezny Date: Tue, 18 Aug 2009 23:12:55 -0700 Subject: [PATCH] Added a new interactive assembly mode to the monitor. --- CHANGES.txt | 6 ++++ src/py65/monitor.py | 65 +++++++++++++++++++++++++++++++++- src/py65/tests/test_monitor.py | 8 ----- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index db50006..f0e365a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -19,6 +19,12 @@ Next Release - Applied patch from Ed Spittles to change the CMP algorithm so that it no longer fails Rob Finch's test suite. Closes #8. + - Added a new interactive assembly mode to the monitor. Entering the + the assemble command with a statement such as "a c000 lda #0" works + as before. Entering "a c000" will start the interactive assembler + at that address. Entering "a" alone will start it at the current + program counter. + 0.6 (2009-08-11) - Added monitor shortcut "a" for "assemble". diff --git a/src/py65/monitor.py b/src/py65/monitor.py index b652006..6283ad7 100644 --- a/src/py65/monitor.py +++ b/src/py65/monitor.py @@ -11,6 +11,7 @@ from py65.devices.mpu65c02 import MPU as CMOS65C02 from py65.disassembler import Disassembler from py65.assembler import Assembler from py65.utils.addressing import AddressParser +from py65.utils.console import getch from py65.utils.console import getch_noblock from py65.utils.conversions import itoa from py65.memory import ObservableMemory @@ -83,6 +84,9 @@ class Monitor(cmd.Cmd): if (not quoted) and (line[pos] == ';'): line = line[:pos] break + + if line == 'a': + line = 'assemble' return line @@ -169,7 +173,7 @@ class Monitor(cmd.Cmd): def do_assemble(self, args): split = args.split(None, 1) if len(split) != 2: - return self.help_assemble() + return self._interactive_assemble(args) start, statement = split try: @@ -190,6 +194,65 @@ class Monitor(cmd.Cmd): self._output("assemble
") self._output("Assemble a statement at the address.") + def _interactive_assemble(self, args): + if args == '': + start = self._mpu.pc + else: + try: + start = self._address_parser.number(args) + except KeyError: + self._output("Bad label: %s" % start) + return + + assembling = True + + while assembling: + collecting_line = True + line = '' + prompt = "\r$%04x " % (start) + + self.stdout.write(prompt) + + while collecting_line: + char = getch(self.stdin) + if char in ("\n", "\r"): + break + elif ord(char) in (0x7f, 0x08): # backspace + if len(line) > 0: + line = line[:-1] + self.stdout.write("\r%s\r%s%s" % \ + (' ' * (len(prompt+line) +5), prompt, line)) + elif ord(char) == 0x1b: # escape + pass + else: + line += char + self.stdout.write(char) + + if not line: + self.stdout.write("\n") + return + + bytes = self._assembler.assemble(line) + if bytes is None: + self._output("Assemble failed: %s\n" % line) + return + + end = start + len(bytes) + self._mpu.memory[start:end] = bytes + + bytes, disasm = self._disassembler.instruction_at(start) + + mem = '' + for byte in self._mpu.memory[start:start+bytes]: + mem += '%02x ' % byte + + self.stdout.write("\r" + (' ' * (len(prompt+line) + 5) )) + line = "\r$%04x %-10s%s\n" % (start, mem, disasm) + self.stdout.write(line) + + start += bytes + + def do_disassemble(self, args): start, end = self._address_parser.range(args) if start == end: diff --git a/src/py65/tests/test_monitor.py b/src/py65/tests/test_monitor.py index c60bfe3..68f97b1 100644 --- a/src/py65/tests/test_monitor.py +++ b/src/py65/tests/test_monitor.py @@ -9,14 +9,6 @@ class MonitorTests(unittest.TestCase): # assemble - def test_do_assemble_shows_help_for_invalid_args(self): - stdout = StringIO() - mon = Monitor(stdout=stdout) - mon.do_assemble('c000') - - out = stdout.getvalue() - self.assertTrue(out.startswith("assemble
")) - def test_do_assemble_assembles_valid_statement(self): stdout = StringIO() mon = Monitor(stdout=stdout)