Skip to content

Commit

Permalink
Add support to rzxplay.py for RZX files recorded in +2 mode
Browse files Browse the repository at this point in the history
  • Loading branch information
skoolkid committed Feb 19, 2024
1 parent 2f07c13 commit 6d975fa
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 26 deletions.
4 changes: 2 additions & 2 deletions skoolkit/pagingtracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
20 changes: 6 additions & 14 deletions skoolkit/rzxplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 3 additions & 3 deletions skoolkit/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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,
Expand Down
29 changes: 27 additions & 2 deletions skoolkit/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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]
Expand All @@ -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]
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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]
Expand All @@ -461,14 +472,28 @@ 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]
qframe_duration = frame_duration // 4
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]
Expand Down
10 changes: 5 additions & 5 deletions tests/test_rzxplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 6d975fa

Please sign in to comment.