Skip to content

Commit

Permalink
Enable get_snapshot() to retrieve all RAM from 128K snapshots
Browse files Browse the repository at this point in the history
  • Loading branch information
skoolkid committed Jul 7, 2023
1 parent 094d492 commit 03e3d24
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
33 changes: 19 additions & 14 deletions skoolkit/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand All @@ -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):
Expand All @@ -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
Expand Down
47 changes: 44 additions & 3 deletions tests/test_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

0 comments on commit 03e3d24

Please sign in to comment.