1
0
mirror of https://github.com/mnaberez/py65.git synced 2024-06-06 20:29:34 +00:00

Added a new interactive assembly mode to the monitor.

This commit is contained in:
Mike Naberezny 2009-08-18 23:12:55 -07:00
parent b122a60ddf
commit 5dd6e9f95a
3 changed files with 70 additions and 9 deletions

View File

@ -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".

View File

@ -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 <address> <statement>")
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:

View File

@ -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 <address>"))
def test_do_assemble_assembles_valid_statement(self):
stdout = StringIO()
mon = Monitor(stdout=stdout)