From 6d975faa6c5097e339962006a6000c45e7546d27 Mon Sep 17 00:00:00 2001 From: Richard Dymond Date: Mon, 19 Feb 2024 11:05:34 -0400 Subject: [PATCH] Add support to rzxplay.py for RZX files recorded in +2 mode --- skoolkit/pagingtracer.py | 4 ++-- skoolkit/rzxplay.py | 20 ++++++-------------- skoolkit/simulator.py | 6 +++--- skoolkit/snapshot.py | 29 +++++++++++++++++++++++++++-- tests/test_rzxplay.py | 10 +++++----- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/skoolkit/pagingtracer.py b/skoolkit/pagingtracer.py index d6e40c96..3de10cd0 100644 --- a/skoolkit/pagingtracer.py +++ b/skoolkit/pagingtracer.py @@ -17,9 +17,9 @@ from skoolkit import ROM128, read_bin_file class Memory: - def __init__(self, banks=None, out7ffd=0): + def __init__(self, banks=None, out7ffd=0, roms=None): self.banks = banks or tuple([0] * 16384 for b in range(8)) - self.roms = tuple(read_bin_file(r) for r in ROM128) + self.roms = tuple(read_bin_file(r) for r in roms or ROM128) self.memory = [None, self.banks[5], self.banks[2], None] self.out7ffd(out7ffd) diff --git a/skoolkit/rzxplay.py b/skoolkit/rzxplay.py index 1bfa79e3..d8417a27 100644 --- a/skoolkit/rzxplay.py +++ b/skoolkit/rzxplay.py @@ -260,29 +260,21 @@ def draw(screen, memory, frame, pixel_rects, cell_rects, prev_scr): # pragma: no def check_supported(snapshot, options): if options.force: return + if snapshot.rom is None: + return 'Unsupported machine type' if snapshot.type == 'Z80': header = snapshot.header - if len(header) == 30: - # Version 1 - return - if header[37] & 128: - return 'Unsupported machine type' - machine_id = header[34] - if len(header) == 55: + if len(header) == 55 and header[34] not in (0, 3): # Version 2 - if machine_id not in (0, 3): - return 'Unsupported machine type' - # Version 3 - elif machine_id not in (0, 4): + return 'Unsupported machine type' + if len(header) > 55 and header[34] not in (0, 4): + # Version 3 return 'Unsupported machine type' elif snapshot.type == 'SZX': supported_blocks = {'AY', 'CRTR', 'KEYB', 'JOY', 'RAMP', 'SPCR', 'TAPE', 'Z80R'} unsupported_blocks = set(b[0] for b in snapshot.tail) - supported_blocks if unsupported_blocks: return 'Unsupported block(s) ({}) in SZX snapshot'.format(', '.join(unsupported_blocks)) - machine_id = snapshot.header[6] - if machine_id > 2: - return 'Unsupported machine type' def process_block(block, options, context): if block is None: diff --git a/skoolkit/simulator.py b/skoolkit/simulator.py index 569d194a..8a4b2cd0 100644 --- a/skoolkit/simulator.py +++ b/skoolkit/simulator.py @@ -16,7 +16,7 @@ from functools import partial -from skoolkit import ROM48, read_bin_file +from skoolkit import read_bin_file from skoolkit.pagingtracer import Memory JR_OFFSETS = tuple(j + 2 if j < 128 else j - 254 for j in range(256)) @@ -150,10 +150,10 @@ def from_snapshot(cls, snapshot, registers=None, config=None, rom_file=None): ram = snapshot.ram(-1) if len(ram) == 0x20000: banks = [ram[a:a + 0x4000] for a in range(0, 0x20000, 0x4000)] - s_memory = Memory(banks, snapshot.out7ffd) + s_memory = Memory(banks, snapshot.out7ffd, snapshot.rom) else: s_memory = [0] * 16384 + ram - rom = read_bin_file(rom_file or ROM48) + rom = read_bin_file(rom_file or snapshot.rom) s_memory[:len(rom)] = rom s_registers = { 'A': snapshot.a, diff --git a/skoolkit/snapshot.py b/skoolkit/snapshot.py index b92229f3..d500c318 100644 --- a/skoolkit/snapshot.py +++ b/skoolkit/snapshot.py @@ -17,7 +17,7 @@ import textwrap import zlib -from skoolkit import SkoolKitError, get_dword, get_word, get_int_param, parse_int, read_bin_file +from skoolkit import ROM48, ROM128, ROM_PLUS2, SkoolKitError, get_dword, get_word, get_int_param, parse_int, read_bin_file from skoolkit.components import get_snapshot_reader, get_value FRAME_DURATIONS = (69888, 70908) @@ -159,6 +159,7 @@ def __init__(self): self.outfffd = 0 self.ay = (0,) * 16 self.outfe = 0 + self.rom = None @classmethod def get(cls, sfile, ext=None): @@ -218,6 +219,7 @@ def __init__(self, sna_data): if self.sp >= 16384: self.pc = get_word(self.tail, self.sp - 16384) page = 0 + self.rom = ROM48 else: self.pc = get_word(self.tail, 49152) self.out7ffd = self.tail[49154] @@ -226,6 +228,7 @@ def __init__(self, sna_data): for i in sorted(set(range(8)) - {5, 2, page}): banks[i] = self.tail[offset:offset + 16384] offset += 16384 + self.rom = ROM128 banks[5] = self.tail[:0x4000] banks[2] = self.tail[0x4000:0x8000] banks[page] = self.tail[0x8000:0xC000] @@ -262,6 +265,13 @@ def _read(self, szx_data): if len(data) < 8 or data[:4] != b'ZXST': raise SnapshotError('Invalid SZX file') self.header = data[:8] + machine_id = self.header[6] + if machine_id < 2: + self.rom = ROM48 + elif machine_id == 2: + self.rom = ROM128 + elif machine_id == 3: + self.rom = ROM_PLUS2 page = 0 i = 8 while i + 8 <= len(data): @@ -453,6 +463,7 @@ def _read(self, z80_data): banks[5] = ram[0x0000:0x4000] banks[2] = ram[0x4000:0x8000] banks[0] = ram[0x8000:0xC000] + self.rom = ROM48 else: page = None i = 32 + data[30] @@ -461,6 +472,7 @@ def _read(self, z80_data): self.out7ffd = self.header[35] self.outfffd = self.header[38] self.ay = tuple(self.header[39:55]) + machine_id = (self.header[34], self.header[37] // 128) if i > 55: # Version 3 frame_duration = FRAME_DURATIONS[self.header[34] > 3] @@ -468,7 +480,20 @@ def _read(self, z80_data): t1 = (self.header[55] + 256 * self.header[56]) % qframe_duration t2 = (2 - self.header[57]) % 4 self.tstates = frame_duration - 1 - t2 * qframe_duration - t1 - if (i == 55 and data[34] > 2) or (i > 55 and data[34] > 3): + m48_ids = (0, 1, 3) + m128_ids = (4, 5, 6) + else: + # Version 2 + m48_ids = (0, 1) + m128_ids = (3, 4) + if machine_id[0] in m48_ids: + self.rom = ROM48 + elif machine_id[0] in m128_ids: + if machine_id[1] == 1: + self.rom = ROM_PLUS2 + else: + self.rom = ROM128 + if (i == 55 and machine_id[0] > 2) or (i > 55 and machine_id[0] > 3): page = data[35] % 8 # 128K while i < len(data): length = data[i] + 256 * data[i + 1] diff --git a/tests/test_rzxplay.py b/tests/test_rzxplay.py index c2082767..49646810 100644 --- a/tests/test_rzxplay.py +++ b/tests/test_rzxplay.py @@ -517,17 +517,17 @@ def test_szx_unsupported_block(self): ram[pc - 0x4000:pc - 0x4000 + len(code)] = code registers = [0] * 37 registers[22:24] = (pc % 256, pc // 256) - if1 = [0] * 19 - if1[:3] = [ord(c) for c in 'IF1'] - if1[4] = 11 # Block size - szxdata = self.write_szx(ram, machine_id=4, registers=registers, blocks=[if1], ret_data=True) + covx = [0] * 12 + covx[:4] = [ord(c) for c in 'COVX'] + covx[4] = 4 # Block size + szxdata = self.write_szx(ram, machine_id=3, registers=registers, blocks=[covx], ret_data=True) rzx = RZX() frames = [(1, 1, [191])] rzx.add_snapshot(szxdata, 'szx', frames) rzxfile = self.write_rzx_file(rzx) with self.assertRaises(SkoolKitError) as cm: self.run_rzxplay(f'--no-screen {rzxfile}') - self.assertEqual(cm.exception.args[0], 'Unsupported block(s) (IF1) in SZX snapshot') + self.assertEqual(cm.exception.args[0], 'Unsupported block(s) (COVX) in SZX snapshot') def test_szx_unsupported_machine(self): ram = [0] * 0xC000