# Path: skoolkit/snapshot.py
# def get_snapshot(fname, page=None):
#     """
#     Read a snapshot file and produce a 65536-element list of byte values.
# 
#     :param fname: The snapshot filename.
#     :param page: The page number to map to addresses 49152-65535 (C000-FFFF).
#                  This is relevant only when reading a 128K snapshot file.
#     :return: A 65536-element list of byte values.
#     """
#     if not can_read(fname):
#         raise SnapshotError("{}: Unknown file type".format(fname))
#     data = read_bin_file(fname)
#     ext = fname[-4:].lower()
#     if ext == '.sna':
#         ram = _read_sna(data, page)
#     elif ext == '.z80':
#         ram = _read_z80(data, page)
#     elif ext == '.szx':
#         ram = _read_szx(data, page)
#     if len(ram) != 49152:
#         raise SnapshotError("RAM size is {0}".format(len(ram)))
#     mem = [0] * 16384
#     mem.extend(ram)
#     return mem
# 
# def make_z80_ram_block(data, page):
#     block = []
#     prev_b = None
#     count = 0
#     for b in data:
#         if b == prev_b or prev_b is None:
#             prev_b = b
#             if count < 255:
#                 count += 1
#                 continue
#         if count > 4 or (count > 1 and prev_b == 237):
#             block.extend((237, 237, count, prev_b))
#         elif prev_b == 237:
#             block.extend((237, b))
#             prev_b = None
#             count = 0
#             continue
#         else:
#             block.extend((prev_b,) * count)
#         prev_b = b
#         count = 1
#     if count > 4 or (count > 1 and prev_b == 237):
#         block.extend((237, 237, count, prev_b))
#     else:
#         block.extend((prev_b,) * count)
#     length = len(block)
#     return [length % 256, length // 256, page] + block
# 
# class SnapshotError(SkoolKitError):
#     """Raised when an error occurs while reading a snapshot file."""


from skoolkittest import SkoolKitTestCase
from skoolkit.snapshot import get_snapshot, make_z80_ram_block, SnapshotError

    def test_z80v3_128k(self):
        exp_ram = [(n + 37) & 255 for n in range(49152)]
        self._test_z80(exp_ram, 3, False, machine_id=4)

    def test_z80v3_128k_page_4(self):
        exp_ram = [(n + 37) & 255 for n in range(49152)]
        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_bad_z80(self):
        header = [0] * 30
        header[6] = 255 # Set PC > 0 to indicate a v1 Z80 snapshot
        header[12] |= 32 # Signal that the RAM data block is compressed
        z80 = header + [255] # Good byte to start with
        z80 += [237, 237, 0, 11] # Bad block of length 0
        z80 += [0, 237, 237, 0] # Terminator
        z80_file = self.write_bin_file(z80, suffix='.z80')
        with self.assertRaisesRegex(SnapshotError, 'Found ED ED 00 0B'):
            get_snapshot(z80_file)

class Z80CompressionTest(SkoolKitTestCase):
    def test_single_ED_followed_by_five_identical_values(self):
        data = [237, 1, 1, 1, 1, 1]
        block = make_z80_ram_block(data, 0)
        exp_data = [len(data), 0, 0] + data
        self.assertEqual(exp_data, block)

    def test_single_ED_followed_by_six_identical_values(self):
        data = [237, 2, 2, 2, 2, 2, 2]

# Path: skoolkit/snapshot.py
# def get_snapshot(fname, page=None):
#     """
#     Read a snapshot file and produce a 65536-element list of byte values.
# 
#     :param fname: The snapshot filename.
#     :param page: The page number to map to addresses 49152-65535 (C000-FFFF).
#                  This is relevant only when reading a 128K snapshot file.
#     :return: A 65536-element list of byte values.
#     """
#     if not can_read(fname):
#         raise SnapshotError("{}: Unknown file type".format(fname))
#     data = read_bin_file(fname)
#     ext = fname[-4:].lower()
#     if ext == '.sna':
#         ram = _read_sna(data, page)
#     elif ext == '.z80':
#         ram = _read_z80(data, page)
#     elif ext == '.szx':
#         ram = _read_szx(data, page)
#     if len(ram) != 49152:
#         raise SnapshotError("RAM size is {0}".format(len(ram)))
#     mem = [0] * 16384
#     mem.extend(ram)
#     return mem
# 
# def make_z80_ram_block(data, page):
#     block = []
#     prev_b = None
#     count = 0
#     for b in data:
#         if b == prev_b or prev_b is None:
#             prev_b = b
#             if count < 255:
#                 count += 1
#                 continue
#         if count > 4 or (count > 1 and prev_b == 237):
#             block.extend((237, 237, count, prev_b))
#         elif prev_b == 237:
#             block.extend((237, b))
#             prev_b = None
#             count = 0
#             continue
#         else:
#             block.extend((prev_b,) * count)
#         prev_b = b
#         count = 1
#     if count > 4 or (count > 1 and prev_b == 237):
#         block.extend((237, 237, count, prev_b))
#     else:
#         block.extend((prev_b,) * count)
#     length = len(block)
#     return [length % 256, length // 256, page] + block
# 
# class SnapshotError(SkoolKitError):
#     """Raised when an error occurs while reading a snapshot file."""


# Path: tests/test_snapshot.py
from skoolkittest import SkoolKitTestCase
from skoolkit.snapshot import get_snapshot, make_z80_ram_block, SnapshotError


    def test_z80v3_128k(self):
        exp_ram = [(n + 37) & 255 for n in range(49152)]
        self._test_z80(exp_ram, 3, False, machine_id=4)

    def test_z80v3_128k_page_4(self):
        exp_ram = [(n + 37) & 255 for n in range(49152)]
        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_bad_z80(self):
        header = [0] * 30
        header[6] = 255 # Set PC > 0 to indicate a v1 Z80 snapshot
        header[12] |= 32 # Signal that the RAM data block is compressed
        z80 = header + [255] # Good byte to start with
        z80 += [237, 237, 0, 11] # Bad block of length 0
        z80 += [0, 237, 237, 0] # Terminator
        z80_file = self.write_bin_file(z80, suffix='.z80')
        with self.assertRaisesRegex(SnapshotError, 'Found ED ED 00 0B'):
            get_snapshot(z80_file)

class Z80CompressionTest(SkoolKitTestCase):
    def test_single_ED_followed_by_five_identical_values(self):
        data = [237, 1, 1, 1, 1, 1]
        block = make_z80_ram_block(data, 0)
        exp_data = [len(data), 0, 0] + data
        self.assertEqual(exp_data, block)

    def test_single_ED_followed_by_six_identical_values(self):
        data = [237, 2, 2, 2, 2, 2, 2]

        block = make_z80_ram_block(data, 0)