Skip to content

Commit 3581c83

Browse files
committed
Add the TraceHeader/TraceHeader2 configuration parameters for trace.py
1 parent 0cbc85a commit 3581c83

6 files changed

Lines changed: 143 additions & 8 deletions

File tree

skoolkit/config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2017-2025 Richard Dymond (rjdymond@gmail.com)
1+
# © 2017-2026 Richard Dymond (rjdymond@gmail.com)
22
#
33
# This file is part of SkoolKit.
44
#
@@ -142,6 +142,8 @@
142142
'Screen': (0, 'screen'),
143143
'ScreenFps': (50, ''),
144144
'ScreenScale': (2, ''),
145+
'TraceHeader': ('', ''),
146+
'TraceHeader2': ('', ''),
145147
'TraceLine': ("${pc:04X} {i}", ''),
146148
'TraceLine2': (
147149
"${pc:04X} {i:<15} "

skoolkit/trace.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def __init__(self, simulator, border, out7ffd, outfffd, ay, outfe, audio):
4949
self.audio_log = []
5050
self.keyboard = None
5151

52-
def run(self, start, stop, max_operations, max_tstates, interrupts, draw, exec_map, trace_line, prefix, byte_fmt, word_fmt):
52+
def run(self, start, stop, max_operations, max_tstates, interrupts, draw,
53+
exec_map, trace_header, trace_line, prefix, byte_fmt, word_fmt):
5354
simulator = self.simulator
5455
memory = simulator.memory
5556
registers = simulator.registers
@@ -64,6 +65,8 @@ def run(self, start, stop, max_operations, max_tstates, interrupts, draw, exec_m
6465
if trace_line:
6566
r = Registers(registers)
6667

68+
if trace_header:
69+
print(trace_header)
6770
if hasattr(simulator, 'trace'):
6871
if trace_line:
6972
df = lambda pc: disassemble(memory, pc, prefix, byte_fmt, word_fmt)[0]
@@ -288,9 +291,12 @@ def run(snafile, options, config):
288291
tracer = Tracer(simulator, border, out7ffd, outfffd, ay, outfe, audio)
289292
simulator.set_tracer(tracer)
290293
if options.verbose:
291-
s = (('', '2'), ('Decimal', 'Decimal2'))[options.decimal][min(options.verbose - 1, 1)]
292-
trace_line = config['TraceLine' + s].replace(r'\n', '\n')
294+
b = ('', 'Decimal')[options.decimal]
295+
s = ('', '2')[min(options.verbose - 1, 1)]
296+
trace_header = config['TraceHeader' + s].replace(r'\n', '\n')
297+
trace_line = config['TraceLine' + b + s].replace(r'\n', '\n')
293298
else:
299+
trace_header = None
294300
trace_line = None
295301
trace_operand = config['TraceOperand' + ('', 'Decimal')[options.decimal]]
296302
prefix, byte_fmt, word_fmt = (trace_operand + ',' * (2 - trace_operand.count(','))).split(',')[:3]
@@ -312,7 +318,8 @@ def run(snafile, options, config):
312318
exec_map = None
313319
begin = time.time()
314320
tracer.run(start, options.stop, options.max_operations, options.max_tstates,
315-
options.interrupts, draw, exec_map, trace_line, prefix, byte_fmt, word_fmt)
321+
options.interrupts, draw, exec_map, trace_header, trace_line,
322+
prefix, byte_fmt, word_fmt)
316323
rt = time.time() - begin
317324
if len(simulator.memory) == 65536:
318325
cpu_freq = CLOCK_SPEEDS[0]

sphinx/source/changelog.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Changelog
2525
in the ``TraceLine`` configuration parameter
2626
* Added support to :ref:`bin2sna.py` and :ref:`snapmod.py` for setting the
2727
MEMPTR register in SZX snapshots
28+
* Added the ``TraceHeader`` and ``TraceHeader2`` configuration parameters for
29+
:ref:`trace.py <trace-conf>` (to specify headers to print before a trace)
2830
* Added support to the :ref:`AUDIO` macro for keyword arguments
2931
* Added support to :ref:`rzxplay.py` for ignoring any snapshots after the first
3032
one (which is useful for playing some RZX files created by the Fuse emulator)

sphinx/source/commands.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2222,6 +2222,8 @@ configuration parameters are:
22222222
* ``ScreenFps`` - screen refresh rate in frames per second (default: ``50``);
22232223
if set to 0, `trace.py` runs at maximum speed
22242224
* ``ScreenScale`` - screen scale factor (default: ``2``)
2225+
* ``TraceHeader`` - the header to print when ``-v`` is used (default: None)
2226+
* ``TraceHeader2`` - the header to print when ``-vv`` is used (default: None)
22252227
* ``TraceLine`` - the format of each instruction line when ``-v`` is used
22262228
(default: ``${pc:04X} {i}``)
22272229
* ``TraceLine2`` - the format of each instruction line when ``-vv`` is used
@@ -2258,8 +2260,8 @@ The register name ``X`` in ``r[X]`` must be one of the following::
22582260

22592261
The names that begin with ``^`` denote the shadow registers.
22602262

2261-
Wherever ``\n`` appears in a ``TraceLine*`` parameter value, it is replaced by
2262-
a newline character.
2263+
Wherever ``\n`` appears in a ``TraceHeader*`` or ``TraceLine*`` parameter
2264+
value, it is replaced by a newline character.
22632265

22642266
Configuration parameters must appear in a ``[trace]`` section. For example,
22652267
to make `trace.py` write a timestamp for each instruction when ``-v`` is used,
@@ -2279,7 +2281,8 @@ Configuration parameters may also be set on the command line by using the
22792281
| | capturing AY audio; added support to the ``--reg`` option for |
22802282
| | setting the MEMPTR register; reads and writes the MEMPTR register |
22812283
| | in SZX snapshots; added support for the ``r[memptr]`` replacement |
2282-
| | field in the ``TraceLine*`` configuration parameters |
2284+
| | field in the ``TraceLine*`` configuration parameters; added the |
2285+
| | ``TraceHeader`` and ``TraceHeader2`` configuration parameters |
22832286
+---------+-------------------------------------------------------------------+
22842287
| 9.6 | Added the ``Screen`` configuration parameter |
22852288
+---------+-------------------------------------------------------------------+

sphinx/source/man/trace.py.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ configuration parameters are:
170170
:ScreenFps: Screen refresh rate in frames per second (default:``50``). If set
171171
to 0, ``trace.py`` runs at maximum speed.
172172
:ScreenScale: Screen scale factor (default: ``2``).
173+
:TraceHeader: The header to print when ``-v`` is used (default: None).
174+
:TraceHeader2: The header to print when ``-vv`` is used (default: None).
173175
:TraceLine: The format of each instruction line when ``-v`` is used
174176
(default: ``${pc:04X} {i}``).
175177
:TraceLine2: The format of each instruction line when ``-vv`` is used. Use

tests/test_trace.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1894,6 +1894,8 @@ def test_option_show_config(self):
18941894
"Screen=0\n"
18951895
"ScreenFps=50\n"
18961896
"ScreenScale=2\n"
1897+
"TraceHeader=\n"
1898+
"TraceHeader2=\n"
18971899
"TraceLine=${pc:04X} {i}\n"
18981900
"TraceLine2=${pc:04X} {i:<15} "
18991901
"A={r[a]:02X} F={r[f]:08b} BC={r[bc]:04X} DE={r[de]:04X} HL={r[hl]:04X} IX={r[ix]:04X} IY={r[iy]:04X}\\n "
@@ -1922,6 +1924,8 @@ def test_option_show_config_read_from_file(self):
19221924
Screen=0
19231925
ScreenFps=50
19241926
ScreenScale=2
1927+
TraceHeader=
1928+
TraceHeader2=
19251929
TraceLine=${pc:04X} {i}
19261930
TraceLine2=${pc:04x} {i:<15} A={r[a]:02X}
19271931
TraceLineDecimal={pc:05} {i}
@@ -2479,6 +2483,121 @@ def test_config_ScreenScale_set_on_command_line(self):
24792483
self.assertEqual(screen.scr[0], 16)
24802484
self.assertEqual(screen.frame, 1)
24812485

2486+
def test_config_TraceHeader_read_from_file(self):
2487+
ini = """
2488+
[trace]
2489+
TraceHeader=ADDR DISASSEMBLY
2490+
"""
2491+
self.write_text_file(dedent(ini).strip(), 'skoolkit.ini')
2492+
code = (
2493+
0x06, 0x02, # $8000 LD B,$02
2494+
0x0E, 0x03, # $8002 LD C,$03
2495+
)
2496+
binfile = self.write_bin_file(code, suffix='.bin')
2497+
start = 0x8000
2498+
stop = start + len(code)
2499+
output, error = self.run_trace(f'-n -o {start} -S {stop} -v {binfile}')
2500+
self.assertEqual(error, '')
2501+
exp_output = """
2502+
ADDR DISASSEMBLY
2503+
$8000 LD B,$02
2504+
$8002 LD C,$03
2505+
Stopped at $8004
2506+
"""
2507+
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
2508+
2509+
def test_config_TraceHeader_set_on_command_line(self):
2510+
code = (
2511+
0x06, 0x02, # $8000 LD B,$02
2512+
0x0E, 0x03, # $8002 LD C,$03
2513+
)
2514+
binfile = self.write_bin_file(code, suffix='.bin')
2515+
start = 0x8000
2516+
stop = start + len(code)
2517+
header = 'Addr Disassembly'
2518+
output, error = self.run_trace(('-n', '-I', f'TraceHeader={header}', '-o', str(start), '-S', str(stop), '-v', binfile))
2519+
self.assertEqual(error, '')
2520+
exp_output = """
2521+
Addr Disassembly
2522+
$8000 LD B,$02
2523+
$8002 LD C,$03
2524+
Stopped at $8004
2525+
"""
2526+
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
2527+
2528+
def test_config_TraceHeader_with_newline(self):
2529+
code = (
2530+
0x06, 0x02, # $8000 LD B,$02
2531+
0x0E, 0x03, # $8002 LD C,$03
2532+
)
2533+
binfile = self.write_bin_file(code, suffix='.bin')
2534+
start = 0x8000
2535+
stop = start + len(code)
2536+
header = r'Addr Disassembly\n==== ==========='
2537+
output, error = self.run_trace(('-n', '-I', f'TraceHeader={header}', '-o', str(start), '-S', str(stop), '-v', binfile))
2538+
self.assertEqual(error, '')
2539+
exp_output = """
2540+
Addr Disassembly
2541+
==== ===========
2542+
$8000 LD B,$02
2543+
$8002 LD C,$03
2544+
Stopped at $8004
2545+
"""
2546+
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
2547+
2548+
def test_config_TraceHeader2_read_from_file(self):
2549+
ini = """
2550+
[trace]
2551+
TraceHeader2=ADDR DISASSEMBLY REGISTERS
2552+
"""
2553+
self.write_text_file(dedent(ini).strip(), 'skoolkit.ini')
2554+
code = (0x3E, 0x01) # $8000 LD A,$01
2555+
binfile = self.write_bin_file(code, suffix='.bin')
2556+
start = 0x8000
2557+
stop = start + len(code)
2558+
output, error = self.run_trace(f'-n -o {start} -S {stop} -vv {binfile}')
2559+
self.assertEqual(error, '')
2560+
exp_output = """
2561+
ADDR DISASSEMBLY REGISTERS
2562+
$8000 LD A,$01 A=01 F=00000000 BC=0000 DE=0000 HL=0000 IX=0000 IY=5C3A
2563+
A'=00 F'=00000000 BC'=0000 DE'=0000 HL'=0000 SP=5C00 IR=3F01
2564+
Stopped at $8002
2565+
"""
2566+
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
2567+
2568+
def test_config_TraceHeader2_set_on_command_line(self):
2569+
code = (0x3E, 0x01) # $8000 LD A,$01
2570+
binfile = self.write_bin_file(code, suffix='.bin')
2571+
start = 0x8000
2572+
stop = start + len(code)
2573+
header = 'Addr Disassembly Registers'
2574+
output, error = self.run_trace(('-n', '-I', f'TraceHeader2={header}', '-o', str(start), '-S', str(stop), '-vv', binfile))
2575+
self.assertEqual(error, '')
2576+
exp_output = """
2577+
Addr Disassembly Registers
2578+
$8000 LD A,$01 A=01 F=00000000 BC=0000 DE=0000 HL=0000 IX=0000 IY=5C3A
2579+
A'=00 F'=00000000 BC'=0000 DE'=0000 HL'=0000 SP=5C00 IR=3F01
2580+
Stopped at $8002
2581+
"""
2582+
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
2583+
2584+
def test_config_TraceHeader2_with_newline(self):
2585+
code = (0x3E, 0x01) # $8000 LD A,$01
2586+
binfile = self.write_bin_file(code, suffix='.bin')
2587+
start = 0x8000
2588+
stop = start + len(code)
2589+
header = r'Addr Disassembly Registers\n==== =========== ========='
2590+
output, error = self.run_trace(('-n', '-I', f'TraceHeader2={header}', '-o', str(start), '-S', str(stop), '-vv', binfile))
2591+
self.assertEqual(error, '')
2592+
exp_output = """
2593+
Addr Disassembly Registers
2594+
==== =========== =========
2595+
$8000 LD A,$01 A=01 F=00000000 BC=0000 DE=0000 HL=0000 IX=0000 IY=5C3A
2596+
A'=00 F'=00000000 BC'=0000 DE'=0000 HL'=0000 SP=5C00 IR=3F01
2597+
Stopped at $8002
2598+
"""
2599+
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
2600+
24822601
def test_config_TraceLine_read_from_file(self):
24832602
ini = """
24842603
[trace]

0 commit comments

Comments
 (0)