Skip to content

Commit

Permalink
Add the --tape-start and --tape-stop options to tapinfo.py
Browse files Browse the repository at this point in the history
  • Loading branch information
skoolkid committed Jun 26, 2024
1 parent 5de2cdd commit 59706d1
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 8 deletions.
10 changes: 7 additions & 3 deletions skoolkit/tapinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ def main(args):
help='List the BASIC program in block N loaded at address A (default 23755).')
group.add_argument('-d', '--data', action='store_true',
help='Show the entire contents of header and data blocks.')
group.add_argument('--tape-start', metavar='BLOCK', type=int, default=1,
help="Start at this tape block number.")
group.add_argument('--tape-stop', metavar='BLOCK', type=int, default=0,
help="Stop at this tape block number.")
group.add_argument('-V', '--version', action='version', version='SkoolKit {}'.format(VERSION),
help='Show SkoolKit version number and exit.')
namespace, unknown_args = parser.parse_known_args(args)
Expand All @@ -128,11 +132,11 @@ def main(args):
text_reader = TextReader()
tape_type = namespace.infile.lower()[-4:]
if tape_type == '.pzx':
tape = parse_pzx(namespace.infile)
tape = parse_pzx(namespace.infile, namespace.tape_start, namespace.tape_stop)
elif tape_type == '.tap':
tape = parse_tap(namespace.infile)
tape = parse_tap(namespace.infile, namespace.tape_start, namespace.tape_stop)
elif tape_type == '.tzx':
tape = parse_tzx(namespace.infile)
tape = parse_tzx(namespace.infile, namespace.tape_start, namespace.tape_stop)
else:
raise SkoolKitError('Unrecognised tape type')
_analyse_tape(tape, basic_block, text_reader, namespace.data)
6 changes: 4 additions & 2 deletions sphinx/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ Changelog
sequences to disassemble)
* Added the :ref:`bytes` directive (for specifying the byte values to which an
instruction should assemble)
* Added the ``--tape-start`` and ``--tape-stop`` options to :ref:`tapinfo.py`
(for specifying the block numbers at which to start or stop showing info)
* :ref:`tapinfo.py` now shows info for TZX block type 0x18 (CSW recording) and
also recognises the deprecated TZX block types 0x16, 0x17, 0x34 and 0x40
* The ``--find``, ``--find-text`` and ``--find-tile`` options of
:ref:`snapinfo.py` now search all RAM banks in a 128K snapshot by default
* Added support for path ID replacement fields in the ``destDir`` parameter of
items in the :ref:`resources` section
* :ref:`tapinfo.py` now shows info for TZX block type 0x18 (CSW recording) and
also recognises the deprecated TZX block types 0x16, 0x17, 0x34 and 0x40
* Fixed the bug that prevents the ``--reg`` option of :ref:`trace.py` from
accepting hexadecimal values prefixed by '0x'

Expand Down
9 changes: 6 additions & 3 deletions sphinx/source/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1943,14 +1943,17 @@ To list the options supported by `tapinfo.py`, run it with no arguments::
List the BASIC program in block N loaded at address A
(default 23755).
-d, --data Show the entire contents of header and data blocks.
--tape-start BLOCK Start at this tape block number.
--tape-stop BLOCK Stop at this tape block number.
-V, --version Show SkoolKit version number and exit.

+---------+-------------------------------------------------------------------+
| Version | Changes |
+=========+===================================================================+
| 9.3 | Added support for PZX files; shows info for TZX block type 0x18 |
| | (CSW recording); recognises deprecated TZX block types 0x16, |
| | 0x17, 0x34 and 0x40 |
| 9.3 | Added support for PZX files; added the ``--tape-start`` and |
| | ``--tape-stop`` options; shows info for TZX block type 0x18 (CSW |
| | recording); recognises deprecated TZX block types 0x16, 0x17, |
| | 0x34 and 0x40 |
+---------+-------------------------------------------------------------------+
| 9.2 | Shows info for TZX block type 0x15 (direct recording) |
+---------+-------------------------------------------------------------------+
Expand Down
6 changes: 6 additions & 0 deletions sphinx/source/man/tapinfo.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ OPTIONS
-d, --data
Show the entire contents of header and data blocks.

--tape-start `BLOCK`
Start at this tape block number.

--tape-stop `BLOCK`
Stop at this tape block number.

-V, --version
Show the SkoolKit version number and exit.

Expand Down
235 changes: 235 additions & 0 deletions tests/test_tapinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,241 @@ def test_option_data_with_tzx_file(self):
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_option_tape_start_with_pzx_file(self):
pzx = PZX()
pzx.add_puls()
pzx.add_data(create_header_block('test_start', 32768, 3))
pzx.add_puls()
pzx.add_data(create_data_block([1, 2, 3]))
pzx.add_puls()
pzx.add_data(create_data_block([4, 5, 6]))
pzxfile = self.write_bin_file(pzx.data, suffix='.pzx')
output, error = self.run_tapinfo(f'--tape-start 4 {pzxfile}')
self.assertEqual(error, '')
exp_output = """
4: Pulse sequence
3223 x 2168 T-states
1 x 667 T-states
1 x 735 T-states
5: Data block
Bits: 40 (5 bytes)
Initial pulse level: 1
0-bit pulse sequence: 855, 855 (T-states)
1-bit pulse sequence: 1710, 1710 (T-states)
Tail pulse: 945 T-states
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
6: Pulse sequence
3223 x 2168 T-states
1 x 667 T-states
1 x 735 T-states
7: Data block
Bits: 40 (5 bytes)
Initial pulse level: 1
0-bit pulse sequence: 855, 855 (T-states)
1-bit pulse sequence: 1710, 1710 (T-states)
Tail pulse: 945 T-states
Type: Data block
Length: 5
Data: 255, 4, 5, 6, 248
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_option_tape_stop_with_pzx_file(self):
pzx = PZX()
pzx.add_puls()
pzx.add_data(create_header_block('test__stop', 32768, 3))
pzx.add_puls()
pzx.add_data(create_data_block([1, 2, 3]))
pzx.add_puls()
pzx.add_data(create_data_block([4, 5, 6]))
pzxfile = self.write_bin_file(pzx.data, suffix='.pzx')
output, error = self.run_tapinfo(f'--tape-stop 6 {pzxfile}')
self.assertEqual(error, '')
exp_output = """
1: PZX header block
Version: 1.0
2: Pulse sequence
3223 x 2168 T-states
1 x 667 T-states
1 x 735 T-states
3: Data block
Bits: 152 (19 bytes)
Initial pulse level: 1
0-bit pulse sequence: 855, 855 (T-states)
1-bit pulse sequence: 1710, 1710 (T-states)
Tail pulse: 945 T-states
Type: Header block
Bytes: test__stop
CODE: 32768,3
Length: 19
Data: 0, 3, 116, 101, 115, 116, 95 ... 3, 0, 0, 128, 0, 0, 142
4: Pulse sequence
3223 x 2168 T-states
1 x 667 T-states
1 x 735 T-states
5: Data block
Bits: 40 (5 bytes)
Initial pulse level: 1
0-bit pulse sequence: 855, 855 (T-states)
1-bit pulse sequence: 1710, 1710 (T-states)
Tail pulse: 945 T-states
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_options_tape_start_and_tape_stop_with_pzx_file(self):
pzx = PZX()
pzx.add_puls()
pzx.add_data(create_header_block('test__both', 32768, 3))
pzx.add_puls()
pzx.add_data(create_data_block([1, 2, 3]))
pzx.add_puls()
pzx.add_data(create_data_block([4, 5, 6]))
pzxfile = self.write_bin_file(pzx.data, suffix='.pzx')
output, error = self.run_tapinfo(f'--tape-start 4 --tape-stop 6 {pzxfile}')
self.assertEqual(error, '')
exp_output = """
4: Pulse sequence
3223 x 2168 T-states
1 x 667 T-states
1 x 735 T-states
5: Data block
Bits: 40 (5 bytes)
Initial pulse level: 1
0-bit pulse sequence: 855, 855 (T-states)
1-bit pulse sequence: 1710, 1710 (T-states)
Tail pulse: 945 T-states
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_option_tape_start_with_tap_file(self):
tap_data = create_tap_header_block('test_start', 32768, 3)
tap_data.extend(create_tap_data_block([1, 2, 3]))
tap_data.extend(create_tap_data_block([4, 5, 6]))
tapfile = self.write_bin_file(tap_data, suffix='.tap')
output, error = self.run_tapinfo(f'--tape-start 2 {tapfile}')
self.assertEqual(error, '')
exp_output = """
2:
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
3:
Type: Data block
Length: 5
Data: 255, 4, 5, 6, 248
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_option_tape_stop_with_tap_file(self):
tap_data = create_tap_header_block('test__stop', 32768, 3)
tap_data.extend(create_tap_data_block([1, 2, 3]))
tap_data.extend(create_tap_data_block([4, 5, 6]))
tapfile = self.write_bin_file(tap_data, suffix='.tap')
output, error = self.run_tapinfo(f'--tape-stop 3 {tapfile}')
self.assertEqual(error, '')
exp_output = """
1:
Type: Header block
Bytes: test__stop
CODE: 32768,3
Length: 19
Data: 0, 3, 116, 101, 115, 116, 95 ... 3, 0, 0, 128, 0, 0, 142
2:
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_options_tape_start_and_tape_stop_with_tap_file(self):
tap_data = create_tap_header_block('test__both', 32768, 3)
tap_data.extend(create_tap_data_block([1, 2, 3]))
tap_data.extend(create_tap_data_block([4, 5, 6]))
tapfile = self.write_bin_file(tap_data, suffix='.tap')
output, error = self.run_tapinfo(f'--tape-start 2 --tape-stop 3 {tapfile}')
self.assertEqual(error, '')
exp_output = """
2:
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_option_tape_start_with_tzx_file(self):
tzxfile = self._write_tzx((
create_tzx_header_block('test_start', 32768, 3),
create_tzx_data_block([1, 2, 3]),
create_tzx_data_block([4, 5, 6])
))
output, error = self.run_tapinfo(f'--tape-start 2 {tzxfile}')
self.assertEqual(error, '')
exp_output = """
Version: 1.20
2: Standard speed data (0x10)
Pause: 0ms
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
3: Standard speed data (0x10)
Pause: 0ms
Type: Data block
Length: 5
Data: 255, 4, 5, 6, 248
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_option_tape_stop_with_tzx_file(self):
tzxfile = self._write_tzx((
create_tzx_header_block('test__stop', 32768, 3),
create_tzx_data_block([1, 2, 3]),
create_tzx_data_block([4, 5, 6])
))
output, error = self.run_tapinfo(f'--tape-stop 3 {tzxfile}')
self.assertEqual(error, '')
exp_output = """
Version: 1.20
1: Standard speed data (0x10)
Pause: 0ms
Type: Header block
Bytes: test__stop
CODE: 32768,3
Length: 19
Data: 0, 3, 116, 101, 115, 116, 95 ... 3, 0, 0, 128, 0, 0, 142
2: Standard speed data (0x10)
Pause: 0ms
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_options_tape_start_and_tape_stop_with_tzx_file(self):
tzxfile = self._write_tzx((
create_tzx_header_block('test__both', 32768, 3),
create_tzx_data_block([1, 2, 3]),
create_tzx_data_block([4, 5, 6])
))
output, error = self.run_tapinfo(f'--tape-start 2 --tape-stop 3 {tzxfile}')
self.assertEqual(error, '')
exp_output = """
Version: 1.20
2: Standard speed data (0x10)
Pause: 0ms
Type: Data block
Length: 5
Data: 255, 1, 2, 3, 255
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

def test_option_V(self):
for option in ('-V', '--version'):
output, error = self.run_tapinfo(option, catch_exit=0)
Expand Down

0 comments on commit 59706d1

Please sign in to comment.