From 126dd239c09c3c7caf61b78666a3aad19797a472 Mon Sep 17 00:00:00 2001 From: Richard Dymond Date: Mon, 10 Jul 2023 17:19:29 -0300 Subject: [PATCH] Replace the --dump option of trace.py with a positional argument --- skoolkit/trace.py | 10 +-- sphinx/source/commands.rst | 6 +- sphinx/source/man/trace.py.rst | 8 +-- sphinx/source/migration.rst | 8 +++ tests/test_trace.py | 122 ++++++++++++++++----------------- 5 files changed, 80 insertions(+), 74 deletions(-) diff --git a/skoolkit/trace.py b/skoolkit/trace.py index 894ae700..b45a1773 100644 --- a/skoolkit/trace.py +++ b/skoolkit/trace.py @@ -284,16 +284,18 @@ def run(snafile, options): f'tstates={r[T]}' ) write_z80v3(options.dump, ram, registers, state) - print(f'Z80 snapshot dumped to {options.dump}') + print(f'Wrote {options.dump}') def main(args): parser = argparse.ArgumentParser( - usage='trace.py [options] FILE', + usage='trace.py [options] FILE [file.z80]', description="Trace Z80 machine code execution. " - "FILE may be a binary (raw memory) file, a SNA, SZX or Z80 snapshot, or '.' for no snapshot.", + "FILE may be a binary (raw memory) file, a SNA, SZX or Z80 snapshot, or '.' for no snapshot. " + "If 'file.z80' is given, a Z80 snapshot is written after execution has completed.", add_help=False ) parser.add_argument('snafile', help=argparse.SUPPRESS, nargs='?') + parser.add_argument('dump', help=argparse.SUPPRESS, nargs='?') group = parser.add_argument_group('Options') group.add_argument('--audio', action='store_true', help="Show audio delays.") @@ -301,8 +303,6 @@ def main(args): help="Show decimal values in verbose mode.") group.add_argument('--depth', type=int, default=2, help='Simplify audio delays to this depth (default: 2).') - group.add_argument('--dump', metavar='FILE', - help='Dump a Z80 snapshot to this file after execution.') group.add_argument('-i', '--interrupts', action='store_true', help='Execute interrupt routines.') group.add_argument('--max-operations', metavar='MAX', type=int, default=0, diff --git a/sphinx/source/commands.rst b/sphinx/source/commands.rst index 55fcb97b..d19b33e9 100644 --- a/sphinx/source/commands.rst +++ b/sphinx/source/commands.rst @@ -1707,16 +1707,16 @@ For example:: To list the options supported by `trace.py`, run it with no arguments:: - usage: trace.py [options] FILE + usage: trace.py [options] FILE [file.z80] Trace Z80 machine code execution. FILE may be a binary (raw memory) file, a - SNA, SZX or Z80 snapshot, or '.' for no snapshot. + SNA, SZX or Z80 snapshot, or '.' for no snapshot. If 'file.z80' is given, a + Z80 snapshot is written after execution has completed. Options: --audio Show audio delays. --depth DEPTH Simplify audio delays to this depth (default: 2). -D, --decimal Show decimal values in verbose mode. - --dump FILE Dump a Z80 snapshot to this file after execution. -i, --interrupts Execute interrupt routines. --max-operations MAX Maximum number of instructions to execute. --max-tstates MAX Maximum number of T-states to run for. diff --git a/sphinx/source/man/trace.py.rst b/sphinx/source/man/trace.py.rst index 7aa57d76..b580cade 100644 --- a/sphinx/source/man/trace.py.rst +++ b/sphinx/source/man/trace.py.rst @@ -6,13 +6,14 @@ trace.py SYNOPSIS ======== -``trace.py`` [options] FILE +``trace.py`` [options] FILE [file.z80] DESCRIPTION =========== ``trace.py`` simulates the execution of machine code in a 48K binary (raw memory) file or a SNA, SZX or Z80 snapshot. If FILE is '.', no snapshot is -loaded, and the RAM is left blank (all zeroes). +loaded, and the RAM is left blank (all zeroes). If 'file.z80' is given, a Z80 +snapshot is written after execution has completed. OPTIONS ======= @@ -29,9 +30,6 @@ OPTIONS -D, --decimal Show decimal values in verbose (``-v``, ``-vv``) mode. ---dump `FILE` - Dump a Z80 snapshot to this file after execution. - -i, --interrupts Execute interrupt routines. diff --git a/sphinx/source/migration.rst b/sphinx/source/migration.rst index c2aa9c83..52576246 100644 --- a/sphinx/source/migration.rst +++ b/sphinx/source/migration.rst @@ -34,3 +34,11 @@ In SkoolKit 8, :ref:`tap2sna.py` would refuse to overwrite an existing snapshot unless the ``--force`` option was given. In SkoolKit 9, `tap2sna.py` will overwrite an existing snapshot by default, and the ``--force`` option is no longer supported. + +trace.py +-------- +In SkoolKit 8, :ref:`trace.py` had a ``--dump`` option for specifying an output +Z80 snapshot file. In SkoolKit 9, this option has been removed; instead the +output filename may be specified after the input filename. For example:: + + $ trace.py --stop 32768 in.z80 out.z80 diff --git a/tests/test_trace.py b/tests/test_trace.py index d84a96e3..02110551 100644 --- a/tests/test_trace.py +++ b/tests/test_trace.py @@ -363,64 +363,6 @@ def test_option_depth_3(self): """ self.assertEqual(dedent(exp_output).strip(), output.rstrip()) - @patch.object(trace, 'write_z80v3', mock_write_z80v3) - def test_option_dump(self): - data = [ - 0x37, # $8000 SCF - 0x9F, # $8001 SBC A,A - 0xF3, # $8002 DI - 0xED, 0x5E, # $8003 IM 2 - 0xED, 0x47, # $8005 LD I,A - 0xED, 0x4F, # $8007 LD R,A - 0x08, # $8009 EX AF,AF' - 0x3E, 0x01, # $800A LD A,$01 - 0xA7, # $800C AND A - 0xD3, 0xFE, # $800D OUT ($FE),A - 0x01, 0x88, 0x10, # $800F LD BC,$1088 - 0x11, 0xB8, 0x53, # $8012 LD DE,$53B8 - 0x21, 0x57, 0x63, # $8015 LD HL,$6357 - 0xD9, # $8018 EXX - 0x01, 0x27, 0xEF, # $8019 LD BC,$EF27 - 0x11, 0xF8, 0x13, # $801C LD DE,$13F8 - 0x01, 0x77, 0x7D, # $801F LD BC,$7D77 - 0x31, 0xE9, 0xBE, # $8022 LD SP,$BEE9 - 0xDD, 0x21, 0x72, 0x0D, # $8025 LD IX,$0D72 - 0xFD, 0x21, 0x2E, 0x27, # $8029 LD IY,$272E - ] - infile = self.write_bin_file(data, suffix='.bin') - outfile = os.path.join(self.make_directory(), 'dump.z80') - start = 32768 - stop = start + len(data) - output, error = self.run_trace(f'-o {start} -S {stop} --dump {outfile} {infile}') - exp_output = f""" - Stopped at ${stop:04X} - Z80 snapshot dumped to {outfile} - """ - exp_reg = ( - 'a=1', - 'f=16', - 'bc=32119', - 'de=5112', - 'hl=0', - 'ix=3442', - 'iy=10030', - 'sp=48873', - 'i=255', - 'r=143', - '^a=255', - '^f=187', - '^bc=4232', - '^de=21432', - '^hl=25431', - f'pc={stop}' - ) - exp_state = ('border=1', 'iff=0', 'im=2', 'tstates=166') - self.assertEqual(dedent(exp_output).strip(), output.rstrip()) - self.assertEqual(z80fname, outfile) - self.assertEqual(data, snapshot[start:stop]) - self.assertEqual(exp_reg, z80reg) - self.assertEqual(exp_state, z80state) - def test_option_interrupts_mode_0(self): data = [ 0xED, 0x46, # $8000 IM 0 @@ -667,7 +609,7 @@ def test_option_interrupts_with_djnz(self): ram[start - 0x4000:start - 0x4000 + len(data)] = data registers = {'PC': start, 'iff2': 1, 'im': 1, 'tstates': 69805} z80file = self.write_z80_file(None, ram, registers=registers) - output, error = self.run_trace(f'--interrupts -S {stop} --dump {outfile} -v {z80file}') + output, error = self.run_trace(f'--interrupts -S {stop} -v {z80file} {outfile}') self.assertEqual(error, '') self.assertEqual(snapshot[0xc001], 2) # DJNZ interrupted when B=2 @@ -692,7 +634,7 @@ def test_option_interrupts_with_ldir(self): ram[start - 0x4000:start - 0x4000 + len(data)] = data registers = {'PC': start, 'iff2': 1, 'im': 1, 'tstates': 69805} z80file = self.write_z80_file(None, ram, registers=registers) - output, error = self.run_trace(f'--interrupts -S {stop} --dump {outfile} -v {z80file}') + output, error = self.run_trace(f'--interrupts -S {stop} -v {z80file} {outfile}') self.assertEqual(error, '') self.assertEqual(snapshot[0xc000], 2) # LDIR interrupted when BC=2 @@ -717,7 +659,7 @@ def test_option_interrupts_with_lddr(self): ram[start - 0x4000:start - 0x4000 + len(data)] = data registers = {'PC': start, 'iff2': 1, 'im': 1, 'tstates': 69805} z80file = self.write_z80_file(None, ram, registers=registers) - output, error = self.run_trace(f'--interrupts -S {stop} --dump {outfile} -v {z80file}') + output, error = self.run_trace(f'--interrupts -S {stop} -v {z80file} {outfile}') self.assertEqual(error, '') self.assertEqual(snapshot[0xc000], 2) # LDDR interrupted when BC=2 @@ -1001,3 +943,61 @@ def test_invalid_register_value(self): with self.assertRaises(SkoolKitError) as cm: self.run_trace(f'-o {addr} --reg A=x {binfile}') self.assertEqual(cm.exception.args[0], 'Cannot parse register value: A=x') + + @patch.object(trace, 'write_z80v3', mock_write_z80v3) + def test_write_z80(self): + data = [ + 0x37, # $8000 SCF + 0x9F, # $8001 SBC A,A + 0xF3, # $8002 DI + 0xED, 0x5E, # $8003 IM 2 + 0xED, 0x47, # $8005 LD I,A + 0xED, 0x4F, # $8007 LD R,A + 0x08, # $8009 EX AF,AF' + 0x3E, 0x01, # $800A LD A,$01 + 0xA7, # $800C AND A + 0xD3, 0xFE, # $800D OUT ($FE),A + 0x01, 0x88, 0x10, # $800F LD BC,$1088 + 0x11, 0xB8, 0x53, # $8012 LD DE,$53B8 + 0x21, 0x57, 0x63, # $8015 LD HL,$6357 + 0xD9, # $8018 EXX + 0x01, 0x27, 0xEF, # $8019 LD BC,$EF27 + 0x11, 0xF8, 0x13, # $801C LD DE,$13F8 + 0x01, 0x77, 0x7D, # $801F LD BC,$7D77 + 0x31, 0xE9, 0xBE, # $8022 LD SP,$BEE9 + 0xDD, 0x21, 0x72, 0x0D, # $8025 LD IX,$0D72 + 0xFD, 0x21, 0x2E, 0x27, # $8029 LD IY,$272E + ] + infile = self.write_bin_file(data, suffix='.bin') + outfile = os.path.join(self.make_directory(), 'out.z80') + start = 32768 + stop = start + len(data) + output, error = self.run_trace(f'-o {start} -S {stop} {infile} {outfile}') + exp_output = f""" + Stopped at ${stop:04X} + Wrote {outfile} + """ + exp_reg = ( + 'a=1', + 'f=16', + 'bc=32119', + 'de=5112', + 'hl=0', + 'ix=3442', + 'iy=10030', + 'sp=48873', + 'i=255', + 'r=143', + '^a=255', + '^f=187', + '^bc=4232', + '^de=21432', + '^hl=25431', + f'pc={stop}' + ) + exp_state = ('border=1', 'iff=0', 'im=2', 'tstates=166') + self.assertEqual(dedent(exp_output).strip(), output.rstrip()) + self.assertEqual(z80fname, outfile) + self.assertEqual(data, snapshot[start:stop]) + self.assertEqual(exp_reg, z80reg) + self.assertEqual(exp_state, z80state)