From 03e3d240eab516abb95a866a96210bfb2b01a50a Mon Sep 17 00:00:00 2001 From: Richard Dymond Date: Fri, 7 Jul 2023 11:54:17 -0300 Subject: [PATCH] Enable get_snapshot() to retrieve all RAM from 128K snapshots --- skoolkit/snapshot.py | 33 ++++++++++++++++------------- tests/test_snapshot.py | 47 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/skoolkit/snapshot.py b/skoolkit/snapshot.py index fce5e985..f463e250 100644 --- a/skoolkit/snapshot.py +++ b/skoolkit/snapshot.py @@ -92,7 +92,7 @@ def get_snapshot(fname, page=None): ram = _read_z80(data, page) elif ext == '.szx': ram = _read_szx(data, page) - if len(ram) != 49152: + if len(ram) not in (49152, 131072): raise SnapshotError("RAM size is {0}".format(len(ram))) mem = [0] * 16384 mem.extend(ram) @@ -309,16 +309,15 @@ def _read_sna(data, page=None): if len(data) <= 49179 or page is None: return data[27:49179] paged_bank = data[49181] & 7 - banks = [5, 2, paged_bank] + pages = {5: data[27:16411], 2: data[16411:32795], paged_bank: data[32795:49179]} + offset = 49183 for i in range(8): - if i not in banks: - banks.append(i) - page_index = banks.index(page) - if page_index < 3: - index = 27 + page_index * 16384 - else: - index = 49183 + (page_index - 3) * 16384 - return data[27:32795] + data[index:index + 16384] + if i not in pages: + pages[i] = data[offset:offset + 16384] + offset += 16384 + if page >= 0: + return pages[5] + pages[2] + pages[page] + return pages[5] + pages[2] + pages[0] + pages[1] + pages[3] + pages[4] + pages[6] + pages[7] def _read_z80(data, page=None): if sum(data[6:8]) > 0: @@ -344,8 +343,11 @@ def _read_z80(data, page=None): banks = (5, 1, 2) # 48K else: if page is None: - page = data[35] & 7 - banks = (5, 2, page) # 128K + banks = (5, 2, data[35] & 7) + elif page < 0: + banks = (5, 2, 0, 1, 3, 4, 6, 7) + else: + banks = (5, 2, page) return _decompress(data[header_size:], banks, extension) def _read_szx(data, page=None): @@ -361,8 +363,11 @@ def _read_szx(data, page=None): specregs = _get_zxstblock(data, 8, 'SPCR')[1] if specregs is None: raise SnapshotError("SPECREGS (SPCR) block not found") - page = specregs[1] & 7 - banks = (5, 2, page) # 128K + banks = (5, 2, specregs[1] & 7) + elif page < 0: + banks = (5, 2, 0, 1, 3, 4, 6, 7) + else: + banks = (5, 2, page) pages = {} for bank in banks: pages[bank] = None diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 58f4a673..d5e841d7 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -3,20 +3,31 @@ class SnapshotTest(SkoolKitTestCase): def _check_ram(self, ram, exp_ram, model, out_7ffd, pages, page): - self.assertEqual(len(ram), 49152) if model == 0: # 16K + self.assertEqual(len(ram), 49152) self.assertEqual(ram[:16384], exp_ram[:16384]) self.assertEqual(ram[16384:], [0] * 32768) elif model == 1: # 48K + self.assertEqual(len(ram), 49152) self.assertEqual(ram, exp_ram) else: # 128K - self.assertEqual(ram[:32768], exp_ram[:32768]) if page is None: page = out_7ffd & 7 - self.assertEqual(ram[32768:], pages.get(page, exp_ram[32768:])) + if page >= 0: + self.assertEqual(len(ram), 49152) + self.assertEqual(ram[:32768], exp_ram[:32768]) + self.assertEqual(ram[32768:], pages.get(page, exp_ram[32768:])) + else: + self.assertEqual(len(ram), 0x20000) + self.assertEqual(ram[0x00000:0x0C000], exp_ram) + self.assertEqual(ram[0x0C000:0x10000], pages[1]) + self.assertEqual(ram[0x10000:0x14000], pages[3]) + self.assertEqual(ram[0x14000:0x18000], pages[4]) + self.assertEqual(ram[0x18000:0x1C000], pages[6]) + self.assertEqual(ram[0x1C000:0x20000], pages[7]) class ErrorTest(SnapshotTest): def test_unknown_file_type(self): @@ -92,6 +103,26 @@ def test_sna_128k_page_5(self): self.assertEqual(len(ram), 49152) self.assertEqual(ram, page5 + page2 + page5) + def test_sna_128k_all_pages(self): + header = [0] * 27 + pages = {p: [p] * 16384 for p in range(8)} + config = [0, 0] # PC + config.append(3) # Port 7ffd (page 3 mapped to 49152-65535) + config.append(0) # TR-DOS ROM not paged + sna = header + pages[5] + pages[2] + pages[3] + config + pages[0] + pages[1] + pages[4] + pages[6] + pages[7] + tmp_sna = self.write_bin_file(sna, suffix='.sna') + snapshot = get_snapshot(tmp_sna, -1) + ram = snapshot[16384:] + self.assertEqual(len(ram), 131072) + self.assertTrue(set(ram[0x00000:0x04000]), {5}) + self.assertTrue(set(ram[0x04000:0x08000]), {2}) + self.assertTrue(set(ram[0x08000:0x0C000]), {0}) + self.assertTrue(set(ram[0x0C000:0x10000]), {1}) + self.assertTrue(set(ram[0x10000:0x14000]), {3}) + self.assertTrue(set(ram[0x14000:0x18000]), {4}) + self.assertTrue(set(ram[0x18000:0x1C000]), {6}) + self.assertTrue(set(ram[0x1C000:0x20000]), {7}) + class Z80Test(SnapshotTest): def _test_z80(self, exp_ram, version, compress, machine_id=0, modify=False, out_7ffd=0, pages={}, page=None): model, tmp_z80 = self.write_z80(exp_ram, version, compress, machine_id, modify, out_7ffd, pages) @@ -146,6 +177,11 @@ def test_z80v3_128k_page_4(self): pages = {4: [(n + 249) & 255 for n in range(16384)]} self._test_z80(exp_ram, 3, False, machine_id=4, pages=pages, page=4) + def test_z80v3_128k_all_pages(self): + exp_ram = [(n + 37) & 255 for n in range(49152)] + pages = {p: [p] * 16384 for p in (1, 3, 4, 6, 7)} + self._test_z80(exp_ram, 3, False, machine_id=4, pages=pages, page=-1) + def test_z80v3_48k_compressed_block_ending_with_ED(self): exp_ram = [0] * 49152 exp_ram[16383] = 237 @@ -366,3 +402,8 @@ def test_szx_128k_page_1(self): exp_ram = [(n + 173) & 255 for n in range(49152)] pages = {1: [(n + 19) & 255 for n in range(16384)]} self._test_szx(exp_ram, False, machine_id=2, pages=pages, page=1) + + def test_szx_128k_all_pages(self): + exp_ram = [(n + 173) & 255 for n in range(49152)] + pages = {p: [p] * 16384 for p in (1, 3, 4, 6, 7)} + self._test_szx(exp_ram, False, machine_id=2, pages=pages, page=-1)