mirror of
https://github.com/mnaberez/py65.git
synced 2025-04-05 13:37:09 +00:00
Fix --rom, add tests for argv. Closes #41
This commit is contained in:
parent
88ae860720
commit
6e21008b89
@ -42,21 +42,39 @@ class Monitor(cmd.Cmd):
|
||||
Microprocessors = {'6502': NMOS6502, '65C02': CMOS65C02,
|
||||
'65Org16': V65Org16}
|
||||
|
||||
def __init__(self, mpu_type=NMOS6502, completekey='tab', stdin=None,
|
||||
stdout=None, argv=None, memory=None, putc_addr=0xF001, getc_addr=0xF004):
|
||||
def __init__(self, argv=None, stdin=None, stdout=None,
|
||||
mpu_type=NMOS6502, memory=None,
|
||||
putc_addr=0xF001, getc_addr=0xF004):
|
||||
self.mpu_type = mpu_type
|
||||
self.memory = memory
|
||||
self.putc_addr = putc_addr
|
||||
self.getc_addr = getc_addr
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
self._breakpoints = []
|
||||
self._width = 78
|
||||
self.prompt = "."
|
||||
self._add_shortcuts()
|
||||
cmd.Cmd.__init__(self, completekey, stdin, stdout)
|
||||
self._parse_args(argv)
|
||||
self._reset(self.mpu_type,self.getc_addr,self.putc_addr)
|
||||
cmd.Cmd.__init__(self, stdin=stdin, stdout=stdout)
|
||||
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
load, rom, goto = self._parse_args(argv)
|
||||
|
||||
self._reset(self.mpu_type, self.getc_addr, self.putc_addr)
|
||||
|
||||
if load is not None:
|
||||
self.do_load(load)
|
||||
|
||||
if goto is not None:
|
||||
self.do_goto(goto)
|
||||
|
||||
if rom is not None:
|
||||
# load a ROM and run from the reset vector
|
||||
self.do_load("%r top" % rom)
|
||||
physMask = self._mpu.memory.physMask
|
||||
reset = self._mpu.RESET & physMask
|
||||
dest = self._mpu.memory[reset] + \
|
||||
(self._mpu.memory[reset + 1] << self.byteWidth)
|
||||
self.do_goto("$%x" % dest)
|
||||
|
||||
def _parse_args(self, argv):
|
||||
try:
|
||||
@ -68,10 +86,7 @@ class Monitor(cmd.Cmd):
|
||||
self._usage()
|
||||
self._exit(1)
|
||||
|
||||
load = None
|
||||
rom = None
|
||||
goto = None
|
||||
mpu = None
|
||||
load, rom, goto = None, None, None
|
||||
|
||||
for opt, value in options:
|
||||
if opt in ('-i', '--input'):
|
||||
@ -80,6 +95,19 @@ class Monitor(cmd.Cmd):
|
||||
if opt in ('-o', '--output'):
|
||||
self.putc_addr = int(value, 16)
|
||||
|
||||
if opt in ('-m', '--mpu'):
|
||||
mpu_type = self._get_mpu(value)
|
||||
if mpu_type is None:
|
||||
mpus = sorted(self.Microprocessors.keys())
|
||||
msg = "Fatal: no such MPU. Available MPUs: %s"
|
||||
self._output(msg % ', '.join(mpus))
|
||||
sys.exit(1)
|
||||
self.mpu_type = mpu_type
|
||||
|
||||
if opt in ("-h", "--help"):
|
||||
self._usage()
|
||||
self._exit(0)
|
||||
|
||||
if opt in ('-l', '--load'):
|
||||
load = value
|
||||
|
||||
@ -89,42 +117,7 @@ class Monitor(cmd.Cmd):
|
||||
if opt in ('-g', '--goto'):
|
||||
goto = value
|
||||
|
||||
if opt in ('-m', '--mpu'):
|
||||
mpu = value
|
||||
|
||||
elif opt in ("-h", "--help"):
|
||||
self._usage()
|
||||
self._exit(0)
|
||||
|
||||
if (mpu is not None) or (rom is not None):
|
||||
if mpu is None:
|
||||
mpu = "6502"
|
||||
if self._get_mpu(mpu) is None:
|
||||
mpus = list(self.Microprocessors.keys())
|
||||
mpus.sort()
|
||||
msg = "Fatal: no such MPU. Available MPUs: %s"
|
||||
self._output(msg % ', '.join(mpus))
|
||||
sys.exit(1)
|
||||
self.mpu_type = self._get_mpu(mpu)
|
||||
|
||||
if load is not None:
|
||||
cmd = "load %s" % load
|
||||
self.onecmd(cmd)
|
||||
|
||||
if goto is not None:
|
||||
cmd = "goto %s" % goto
|
||||
self.onecmd(cmd)
|
||||
|
||||
if rom is not None:
|
||||
# load a ROM and run from the reset vector
|
||||
cmd = "load '%s' top" % rom
|
||||
self.onecmd(cmd)
|
||||
physMask = self._mpu.memory.physMask
|
||||
reset = self._mpu.RESET & physMask
|
||||
dest = self._mpu.memory[reset] + \
|
||||
(self._mpu.memory[reset + 1] << self.byteWidth)
|
||||
cmd = "goto %08x" % dest
|
||||
self.onecmd(cmd)
|
||||
return load, rom, goto
|
||||
|
||||
def _usage(self):
|
||||
usage = __doc__ % sys.argv[0]
|
||||
@ -148,7 +141,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
return result
|
||||
|
||||
def _reset(self, mpu_type,getc_addr=0xF004,putc_addr=0xF001):
|
||||
def _reset(self, mpu_type, getc_addr=0xF004, putc_addr=0xF001):
|
||||
self._mpu = mpu_type(memory=self.memory)
|
||||
self.addrWidth = self._mpu.ADDR_WIDTH
|
||||
self.byteWidth = self._mpu.BYTE_WIDTH
|
||||
@ -157,7 +150,7 @@ class Monitor(cmd.Cmd):
|
||||
self.addrMask = self._mpu.addrMask
|
||||
self.byteMask = self._mpu.byteMask
|
||||
if getc_addr and putc_addr:
|
||||
self._install_mpu_observers(getc_addr,putc_addr)
|
||||
self._install_mpu_observers(getc_addr, putc_addr)
|
||||
self._address_parser = AddressParser()
|
||||
self._disassembler = Disassembler(self._mpu, self._address_parser)
|
||||
self._assembler = Assembler(self._mpu, self._address_parser)
|
||||
@ -230,7 +223,7 @@ class Monitor(cmd.Cmd):
|
||||
break
|
||||
return mpu
|
||||
|
||||
def _install_mpu_observers(self,getc_addr,putc_addr):
|
||||
def _install_mpu_observers(self, getc_addr, putc_addr):
|
||||
def putc(address, value):
|
||||
try:
|
||||
self.stdout.write(chr(value))
|
||||
|
@ -1156,6 +1156,95 @@ class MonitorTests(unittest.TestCase):
|
||||
out = stdout.getvalue()
|
||||
self.assertTrue(out.startswith('0008: 00 00 ff 00 00'), "monitor must see pre-initialized memory")
|
||||
|
||||
# command line options
|
||||
|
||||
def test_argv_mpu(self):
|
||||
argv = ['py65mon', '--mpu', '65c02']
|
||||
stdout = StringIO()
|
||||
mon = Monitor(argv=argv, stdout=stdout)
|
||||
self.assertEqual('65C02', mon._mpu.name)
|
||||
|
||||
def test_argv_mpu_invalid(self):
|
||||
argv = ['py65mon', '--mpu', 'bad']
|
||||
stdout = StringIO()
|
||||
try:
|
||||
Monitor(argv=argv, stdout=stdout)
|
||||
except SystemExit as exc:
|
||||
self.assertEqual(1, exc.code)
|
||||
self.assertTrue("Fatal: no such MPU." in stdout.getvalue())
|
||||
|
||||
def test_argv_goto(self):
|
||||
argv = ['py65mon', '--goto', 'c000']
|
||||
stdout = StringIO()
|
||||
memory = bytearray(0x10000)
|
||||
memory[0xc000] = 0xea # c000 nop
|
||||
memory[0xc001] = 0xea # c001 nop
|
||||
memory[0xc002] = 0x00 # c002 brk
|
||||
mon = Monitor(argv=argv, stdout=stdout, memory=memory)
|
||||
self.assertEqual(0xc002, mon._mpu.pc)
|
||||
|
||||
def test_argv_load(self):
|
||||
with tempfile.NamedTemporaryFile('wb+') as f:
|
||||
data = bytearray([0xab, 0xcd])
|
||||
f.write(data)
|
||||
f.flush()
|
||||
|
||||
argv = ['py65mon', '--load', f.name]
|
||||
stdout = StringIO()
|
||||
mon = Monitor(argv=argv, stdout=stdout)
|
||||
self.assertEqual(list(data), mon._mpu.memory[:len(data)])
|
||||
|
||||
def test_argv_rom(self):
|
||||
with tempfile.NamedTemporaryFile('wb+') as f:
|
||||
rom = bytearray(4096)
|
||||
rom[0] = 0xea # f000 nop
|
||||
rom[1] = 0xea # f001 nop
|
||||
rom[2] = 0x00 # f002 brk
|
||||
rom[-2] = 0xf000 & 0xff # fffc reset vector low
|
||||
rom[-3] = 0xf000 >> 8 # fffd reset vector high
|
||||
f.write(rom)
|
||||
f.flush()
|
||||
|
||||
argv = ['py65mon', '--rom', f.name]
|
||||
stdout = StringIO()
|
||||
mon = Monitor(argv=argv, stdout=stdout)
|
||||
self.assertEqual(list(rom), mon._mpu.memory[-len(rom):])
|
||||
self.assertEqual(0xf002, mon._mpu.pc)
|
||||
|
||||
def test_argv_input(self):
|
||||
argv = ['py65mon', '--input', 'abcd']
|
||||
stdout = StringIO()
|
||||
mon = Monitor(argv=argv, stdout=stdout)
|
||||
read_subscribers = mon._mpu.memory._read_subscribers
|
||||
self.assertEqual(1, len(read_subscribers))
|
||||
self.assertTrue('getc' in repr(read_subscribers[0xabcd]))
|
||||
|
||||
def test_argv_output(self):
|
||||
argv = ['py65mon', '--output', 'dcba']
|
||||
stdout = StringIO()
|
||||
mon = Monitor(argv=argv, stdout=stdout)
|
||||
write_subscribers = mon._mpu.memory._write_subscribers
|
||||
self.assertEqual(1, len(write_subscribers))
|
||||
self.assertTrue('putc' in repr(write_subscribers[0xdcba]))
|
||||
|
||||
def test_argv_combination_rom_mpu(self):
|
||||
with tempfile.NamedTemporaryFile('wb+') as f:
|
||||
rom = bytearray(4096)
|
||||
rom[0] = 0xea # f000 nop
|
||||
rom[1] = 0xea # f001 nop
|
||||
rom[2] = 0x00 # f002 brk
|
||||
rom[-2] = 0xf000 & 0xff # fffc reset vector low
|
||||
rom[-3] = 0xf000 >> 8 # fffd reset vector high
|
||||
f.write(rom)
|
||||
f.flush()
|
||||
|
||||
argv = ['py65mon', '--rom', f.name, '--mpu', '65c02',]
|
||||
stdout = StringIO()
|
||||
mon = Monitor(argv=argv, stdout=stdout)
|
||||
self.assertEqual('65C02', mon._mpu.name)
|
||||
self.assertEqual(list(rom), mon._mpu.memory[-len(rom):])
|
||||
self.assertEqual(0xf002, mon._mpu.pc)
|
||||
|
||||
def test_suite():
|
||||
return unittest.findTestCases(sys.modules[__name__])
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user