Esempio n. 1
0
 def test_unknown_file_type(self):
     file_type = 'tzx'
     snapshot_file = self.write_bin_file(suffix='.{0}'.format(file_type))
     with self.assertRaisesRegex(
             SnapshotError,
             "{}: Unknown file type '{}'".format(snapshot_file, file_type)):
         get_snapshot(snapshot_file)
Esempio n. 2
0
def main(args):
    parser = argparse.ArgumentParser(
        usage='bin2tap.py [options] FILE [file.tap]',
        description="Convert a binary (raw memory) file or a SNA, SZX or Z80 snapshot into a TAP file. "
                    "FILE may be a regular file, or '-' to read a binary file from standard input.",
        add_help=False
    )
    parser.add_argument('infile', help=argparse.SUPPRESS, nargs='?')
    parser.add_argument('outfile', help=argparse.SUPPRESS, nargs='?')
    group = parser.add_argument_group('Options')
    group.add_argument('-c', '--clear', dest='clear', metavar='N', type=int,
                       help="Use a 'CLEAR N' command in the BASIC loader and leave the stack pointer alone")
    group.add_argument('-e', '--end', dest='end', metavar='ADDR', type=int, default=65536,
                       help="Set the end address when reading a snapshot")
    group.add_argument('-o', '--org', dest='org', metavar='ORG', type=int,
                       help="Set the origin address (default: 16384 for a snapshot, otherwise 65536 minus the length of FILE)")
    group.add_argument('-p', '--stack', dest='stack', metavar='STACK', type=int,
                       help="Set the stack pointer (default: ORG)")
    group.add_argument('-s', '--start', dest='start', metavar='START', type=int,
                       help="Set the start address to JP to (default: ORG)")
    group.add_argument('-S', '--screen', dest='screen', metavar='FILE',
                       help="Add a loading screen to the TAP file; FILE may be a snapshot or a 6912-byte SCR file")
    group.add_argument('-t', '--tapfile', dest='tapfile', metavar='TAPFILE',
                       help="Set the TAP filename")
    group.add_argument('-V', '--version', action='version', version='SkoolKit {}'.format(VERSION),
                       help='Show SkoolKit version number and exit')

    namespace, unknown_args = parser.parse_known_args(args)
    infile = namespace.infile
    if unknown_args or infile is None:
        parser.exit(2, parser.format_help())
    if infile.lower().endswith(('.sna', '.szx', '.z80')):
        org = namespace.org or 16384
        if org >= namespace.end:
            raise SkoolKitError('End address must be greater than {}'.format(org))
        ram = get_snapshot(infile)[org:namespace.end]
    else:
        ram = read_bin_file(infile, 49152)
        if len(ram) == 0:
            raise SkoolKitError('{} is empty'.format(infile))
        org = namespace.org or 65536 - len(ram)
    clear = namespace.clear
    start = namespace.start or org
    stack = namespace.stack or org
    tapfile = namespace.outfile or namespace.tapfile
    if tapfile is None:
        if infile.lower().endswith(('.bin', '.sna', '.szx', '.z80')):
            prefix = infile[:-4]
        elif infile == '-':
            prefix = 'program'
        else:
            prefix = infile
        tapfile = prefix + ".tap"
    scr = namespace.screen
    if scr is not None:
        if scr.lower().endswith(('.sna', '.szx', '.z80')):
            scr = get_snapshot(scr)[16384:23296]
        else:
            scr = read_bin_file(scr, 6912)
    run(ram, clear, org, start, stack, tapfile, scr)
Esempio n. 3
0
 def test_szx_128k_no_specregs(self):
     szx = self._get_szx_header(2, specregs=False)
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     try:
         get_snapshot(tmp_szx)
     except SnapshotError as e:
         self.assertEqual(e.args[0], "SPECREGS (SPCR) block not found")
Esempio n. 4
0
 def test_szx_128k_no_specregs(self):
     szx = self._get_szx_header(2, specregs=False)
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     try:
         get_snapshot(tmp_szx)
     except SnapshotError as e:
         self.assertEqual(e.args[0], "SPECREGS (SPCR) block not found")
Esempio n. 5
0
 def test_szx_48k_missing_page(self):
     szx = self._get_szx_header()
     szx.extend(self._get_zxstrampage(5, True, [0] * 16384))
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     try:
         get_snapshot(tmp_szx)
     except SnapshotError as e:
         self.assertEqual(e.args[0], "Page 2 not found")
Esempio n. 6
0
 def test_szx_48k_missing_page(self):
     szx = self._get_szx_header()
     szx.extend(self._get_zxstrampage(5, True, [0] * 16384))
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     try:
         get_snapshot(tmp_szx)
     except SnapshotError as e:
         self.assertEqual(e.args[0], "Page 2 not found")
Esempio n. 7
0
 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.assertRaisesRegexp(SnapshotError, 'Found ED ED 00 0B'):
         get_snapshot(z80_file)
Esempio n. 8
0
 def test_szx_48k_bad_page_size(self):
     szx = self._get_szx_header()
     ram = [0, 0, 0] # Bad page size (3 != 16384)
     page = 5
     szx.extend(self._get_zxstrampage(page, False, ram))
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     try:
         get_snapshot(tmp_szx)
     except SnapshotError as e:
         self.assertEqual(e.args[0], "Page {0} is {1} bytes (should be 16384)".format(5, len(ram)))
Esempio n. 9
0
 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)
Esempio n. 10
0
 def test_szx_48k_bad_page_size(self):
     szx = self._get_szx_header()
     ram = [0, 0, 0] # Bad page size (3 != 16384)
     page = 5
     szx.extend(self._get_zxstrampage(page, False, ram))
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     try:
         get_snapshot(tmp_szx)
     except SnapshotError as e:
         self.assertEqual(e.args[0], "Page {0} is {1} bytes (should be 16384)".format(5, len(ram)))
Esempio n. 11
0
 def test_szx_48k_bad_zlib_block(self):
     szx = self._get_szx_header()
     szx.extend((82, 65, 77, 80)) # RAMP
     ram = (1, 2, 3, 4, 5, 6, 7, 8) # Invalid zlib block
     size = len(ram) + 3
     szx.extend((size % 256, size // 256, 0, 0))
     szx.extend((1, 0)) # Compressed
     page = 5
     szx.append(page)
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     try:
         get_snapshot(tmp_szx)
     except SnapshotError as e:
         self.assertTrue(e.args[0].startswith("Error while decompressing page {0}:".format(page)))
Esempio n. 12
0
 def test_szx_48k_bad_zlib_block(self):
     szx = self._get_szx_header()
     szx.extend((82, 65, 77, 80)) # RAMP
     ram = (1, 2, 3, 4, 5, 6, 7, 8) # Invalid zlib block
     size = len(ram) + 3
     szx.extend((size % 256, size // 256, 0, 0))
     szx.extend((1, 0)) # Compressed
     page = 5
     szx.append(page)
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     try:
         get_snapshot(tmp_szx)
     except SnapshotError as e:
         self.assertTrue(e.args[0].startswith("Error while decompressing page {0}:".format(page)))
Esempio n. 13
0
    def _check_z80(self,
                   z80file,
                   data,
                   org=None,
                   sp=None,
                   pc=None,
                   border=7,
                   iff=1,
                   im=1):
        with open(z80file, 'rb') as f:
            z80h = f.read(34)
        if org is None:
            org = 65536 - len(data)
        if sp is None:
            sp = org
        if pc is None:
            pc = org

        self.assertEqual((z80h[12] >> 1) & 7, border)  # BORDER
        self.assertEqual(z80h[27], iff)  # IFF1
        self.assertEqual(z80h[28], iff)  # IFF2
        self.assertEqual(z80h[29] & 3, im)  # Interrupt mode

        self.assertEqual(z80h[8] + 256 * z80h[9], sp)  # SP
        self.assertEqual(z80h[10], 63)  # I
        self.assertEqual(z80h[23] + 256 * z80h[24], 23610)  # IY
        self.assertEqual(z80h[32] + 256 * z80h[33], pc)  # PC

        snapshot = get_snapshot(z80file)
        self.assertEqual(data, snapshot[org:org + len(data)])
Esempio n. 14
0
def run(snafile, imgfname, options):
    snapshot = get_snapshot(snafile)
    skool = BackToSkool(snapshot)
    width = 192
    eric = 210
    for address in options.mutable:
        skool.alter_skool_udgs(address)
    x = y = 0
    height = 21
    skool.hide_chars()

    if options.blackboard:
        bb = BLACKBOARDS[options.blackboard]
        width, height, x, y = bb['geometry']
        eric_x, eric_y = bb['location']
        skool.place_char(eric, eric_x, eric_y, 0)
    elif options.geometry:
        wh, xy = options.geometry.split('+', 1)
        width, height = [int(n) for n in wh.split('x')]
        x, y = [int(n) for n in xy.split('+')]

    for spec in options.text:
        board_id, sep, text = spec.partition(':')
        if sep:
            bb = BLACKBOARDS[board_id]
            skool.write(bb['tiles'], text)

    for spec in options.place_char:
        values = []
        for n in spec.split(','):
            try:
                values.append(int(n))
            except ValueError:
                values.append(None)
        skool.place_char(*values[:4])

    for spec in options.pokes:
        addr, val = spec.split(',', 1)
        step = 1
        if '-' in addr:
            addr1, addr2 = addr.split('-', 1)
            addr1 = int(addr1)
            if '-' in addr2:
                addr2, step = [int(i) for i in addr2.split('-', 1)]
            else:
                addr2 = int(addr2)
        else:
            addr1 = int(addr)
            addr2 = addr1
        addr2 += 1
        value = int(val)
        for a in range(addr1, addr2, step):
            snapshot[a] = value

    udg_array = skool.get_skool_udgs(x, y, width, height)
    frame = Frame(udg_array, options.scale)
    image_writer = ImageWriter()
    image_format = 'gif' if imgfname.lower()[-4:] == '.gif' else 'png'
    with open(imgfname, "wb") as f:
        image_writer.write_image([frame], f, image_format)
Esempio n. 15
0
 def _test_z80(self,
               options,
               header,
               exp_header=None,
               ram=None,
               exp_ram=None,
               version=3,
               compress=False):
     if exp_header is None:
         exp_header = header
     if ram is None:
         ram = [0] * 49152
     if exp_ram is None:
         exp_ram = ram
     infile = self.write_z80_file(header, ram, version, compress)
     outfile = '{}-out.z80'.format(infile[:-4])
     self.tempfiles.append(outfile)
     output, error = self.run_snapmod('{} {} {}'.format(
         options, infile, outfile))
     self.assertEqual([], output)
     self.assertEqual(error, '')
     z80_header = list(read_bin_file(outfile, len(exp_header)))
     self.assertEqual(exp_header, z80_header)
     z80_ram = get_snapshot(outfile)[16384:]
     self.assertEqual(exp_ram, z80_ram)
Esempio n. 16
0
def run(infile, outfile, options):
    x, y = [int(c) for c in options.xy.split(',', 1)]
    w, h = [int(c) for c in options.wh.split(',', 1)]
    w = min(32 - x, w)
    h = min(24 - y, h)

    if infile[-4:].lower() == '.scr':
        with open(infile, 'rb') as f:
            scr = bytearray(f.read(6912))
        snapshot = [0] * 65536
        snapshot[16384:16384 + len(scr)] = scr
    else:
        snapshot = get_snapshot(infile)

    for spec in options.pokes:
        poke(snapshot, spec)

    scr = snapshot[16384:23296]

    if options.invert:
        for i in range(6144, 6912):
            if scr[i] & 128:
                df = 2048 * (i // 256 - 24) + i % 256
                for j in range(df, df + 2048, 256):
                    scr[j] ^= 255
                scr[i] -= 128

    scrshot = _get_screenshot(scr, x, y, w, h, options.flip)
    _write_image(scrshot, outfile, options.scale, options.animated)
Esempio n. 17
0
def _find_text(infile, text):
    size = len(text)
    byte_values = [ord(c) for c in text]
    snapshot = get_snapshot(infile)
    for a in range(16384, 65536 - size + 1):
        if snapshot[a:a + size] == byte_values:
            print("{0}-{1} {0:04X}-{1:04X}: {2}".format(a, a + size - 1, text))
Esempio n. 18
0
def run(infile, outfile, options):
    x, y = options.origin
    w = min(32 - x, options.size[0])
    h = min(24 - y, options.size[1])

    if infile[-4:].lower() == '.scr':
        scr = read_bin_file(infile, 6912)
        snapshot = [0] * 65536
        snapshot[16384:16384 + len(scr)] = scr
    else:
        snapshot = get_snapshot(infile)

    for spec in options.pokes:
        poke(snapshot, spec)

    scrshot = _get_screenshot(snapshot[16384:23296], x, y, w, h)

    if options.invert:
        for row in scrshot:
            for udg in row:
                if udg.attr & 128:
                    udg.data = [b^255 for b in udg.data]
                    udg.attr &= 127

    flip_udgs(scrshot, options.flip)
    rotate_udgs(scrshot, options.rotate)

    _write_image(scrshot, outfile, options.scale, options.animated)
Esempio n. 19
0
def _read_z80(z80file):
    data = read_bin_file(z80file)
    if get_word(data, 6) > 0:
        header = data[:30]
    else:
        header_len = 32 + get_word(data, 30)
        header = data[:header_len]
    return list(header), get_snapshot(z80file)
Esempio n. 20
0
def _read_z80(z80file):
    data = read_bin_file(z80file)
    if get_word(data, 6) > 0:
        header = data[:30]
    else:
        header_len = 32 + get_word(data, 30)
        header = data[:header_len]
    return list(header), get_snapshot(z80file)
Esempio n. 21
0
def run(snafile, imgfname, options):
    snapshot = get_snapshot(snafile)
    game = ContactSamCruise(snapshot)
    x = y = 0
    width, height = 256, 42
    game.hide_chars()
    game.reset_fuses()
    game.switch_lights_on()
    game.raise_blinds()
    game.close_doors()
    game.adjust_rope(options.rope)

    if options.geometry:
        wh, xy = options.geometry.split('+', 1)
        width, height = [int(n) for n in wh.split('x')]
        x, y = [int(n) for n in xy.split('+')]

    for spec in options.place_char:
        values = []
        index = 0
        for n in spec.split(','):
            if not values and '.' in n:
                n, i = n.split('.', 1)
                try:
                    index = int(i)
                except:
                    pass
            try:
                values.append(int(n))
            except ValueError:
                values.append(None)
        game.place_char(*values[:5], index=index)

    for spec in options.pokes:
        addr, val = spec.split(',', 1)
        step = 1
        if '-' in addr:
            addr1, addr2 = addr.split('-', 1)
            addr1 = int(addr1)
            if '-' in addr2:
                addr2, step = [int(i) for i in addr2.split('-', 1)]
            else:
                addr2 = int(addr2)
        else:
            addr1 = int(addr)
            addr2 = addr1
        addr2 += 1
        value = int(val)
        for a in range(addr1, addr2, step):
            snapshot[a] = value

    udg_array = game.get_play_area_udgs(x, y, width, height)
    frame = Frame(udg_array, options.scale)
    image_writer = ImageWriter()
    image_format = 'gif' if imgfname.lower()[-4:] == '.gif' else 'png'
    with open(imgfname, "wb") as f:
        image_writer.write_image([frame], f, image_format)
Esempio n. 22
0
 def test_sna_48k(self):
     header = [0] * 27
     exp_ram = [(n + 23) & 255 for n in range(49152)]
     sna = header + exp_ram
     tmp_sna = self.write_bin_file(sna, suffix='.sna')
     snapshot = get_snapshot(tmp_sna)
     ram = snapshot[16384:]
     self.assertEqual(len(ram), 49152)
     self.assertEqual(ram, exp_ram)
Esempio n. 23
0
 def test_sna_48k(self):
     header = [0] * 27
     exp_ram = [(n + 23) & 255 for n in range(49152)]
     sna = header + exp_ram
     tmp_sna = self.write_bin_file(sna, suffix='.sna')
     snapshot = get_snapshot(tmp_sna)
     ram = snapshot[16384:]
     self.assertEqual(len(ram), 49152)
     self.assertEqual(ram, exp_ram)
Esempio n. 24
0
def run(infile, outfile, options):
    if options.binary or options.org is not None:
        snapshot = read_bin_file(infile, 49152)
        if options.org is None:
            org = 65536 - len(snapshot)
        else:
            org = options.org
        snapshot = [0] * org + list(snapshot) + [0] * (65536 - org -
                                                       len(snapshot))
    elif infile[-4:].lower() == '.scr':
        scr = read_bin_file(infile, 6912)
        snapshot = [0] * 65536
        snapshot[16384:16384 + len(scr)] = scr
    elif infile[-4:].lower() in ('.sna', '.szx', '.z80'):
        snapshot = get_snapshot(infile)
    else:
        try:
            snapshot = BinWriter(infile, fix_mode=options.fix_mode).snapshot
        except SkoolKitError:
            raise
        except:
            raise SkoolKitError(
                'Unable to parse {} as a skool file'.format(infile))

    for spec in options.moves:
        move(snapshot, spec)
    for spec in options.pokes:
        poke(snapshot, spec)

    if options.macro is not None:
        match = re.match('(#?)(FONT|SCR|UDG|UDGARRAY)([^A-Z]|$)',
                         options.macro)
        if match:
            macro = match.group(2)
            try:
                frame = MACROS[macro](snapshot, options.macro[match.end(2):])
            except skoolmacro.MacroParsingError as e:
                raise SkoolKitError('Invalid #{} macro: {}'.format(
                    macro, e.args[0]))
        else:
            raise SkoolKitError('Macro must be #FONT, #SCR, #UDG or #UDGARRAY')
    else:
        (x, y), (w, h) = options.origin, options.size
        frame = Frame(scr_udgs(snapshot, x, y, w, h), options.scale)

    if options.invert:
        for row in frame.udgs:
            for udg in row:
                if udg.attr & 128:
                    udg.data = [b ^ 255 for b in udg.data]
                    udg.attr &= 127

    flip_udgs(frame.udgs, options.flip)
    rotate_udgs(frame.udgs, options.rotate)

    _write_image(frame, outfile, options.animated)
Esempio n. 25
0
def run(subcommand):
    func = functions[subcommand][0]
    if not os.path.isdir(BUILD_DIR):
        os.mkdir(BUILD_DIR)
    if not os.path.isfile(MM_Z80):
        tap2sna.main(('-d', BUILD_DIR, '@{}/manic_miner.t2s'.format(MANICMINER_HOME)))
    ctlfile = '{}/{}.ctl'.format(BUILD_DIR, subcommand)
    with open(ctlfile, 'wt') as f:
        f.write(func(get_snapshot(MM_Z80)))
    sna2skool.main(('-c', ctlfile, MM_Z80))
Esempio n. 26
0
def main(args):
    parser = argparse.ArgumentParser(
        usage='snapinfo.py [options] file',
        description="Analyse an SNA, SZX or Z80 snapshot.",
        add_help=False
    )
    parser.add_argument('infile', help=argparse.SUPPRESS, nargs='?')
    group = parser.add_argument_group('Options')
    group.add_argument('-b', '--basic', action='store_true',
                       help='List the BASIC program.')
    group.add_argument('-f', '--find', metavar='A[,B...[-M[-N]]]',
                       help='Search for the byte sequence A,B... with distance ranging from M to N (default=1) between bytes.')
    group.add_argument('-p', '--peek', metavar='A[-B[-C]]', action='append',
                       help='Show the contents of addresses A TO B STEP C. This option may be used multiple times.')
    group.add_argument('-t', '--find-text', dest='text', metavar='TEXT',
                       help='Search for a text string.')
    group.add_argument('-T', '--find-tile', dest='tile', metavar='X,Y[-M[-N]]',
                       help='Search for the graphic data of the tile at (X,Y) with distance ranging from M to N (default=1) between bytes.')
    group.add_argument('-v', '--variables', action='store_true',
                       help='List variables.')
    group.add_argument('-V', '--version', action='version', version='SkoolKit {}'.format(VERSION),
                       help='Show SkoolKit version number and exit.')
    group.add_argument('-w', '--word', metavar='A[-B[-C]]', action='append',
                       help='Show the words at addresses A TO B STEP C. This option may be used multiple times.')
    namespace, unknown_args = parser.parse_known_args(args)
    if unknown_args or namespace.infile is None:
        parser.exit(2, parser.format_help())
    infile = namespace.infile
    snapshot_type = infile[-4:].lower()
    if snapshot_type not in ('.sna', '.szx', '.z80'):
        raise SkoolKitError('Unrecognised snapshot type')

    if any((namespace.find, namespace.tile, namespace.text, namespace.peek, namespace.word, namespace.basic, namespace.variables)):
        snapshot = get_snapshot(infile)
        if namespace.find:
            _find(snapshot, namespace.find)
        elif namespace.tile:
            _find_tile(snapshot, namespace.tile)
        elif namespace.text:
            _find_text(snapshot, namespace.text)
        elif namespace.peek:
            _peek(snapshot, namespace.peek)
        elif namespace.word:
            _word(snapshot, namespace.word)
        else:
            if namespace.basic:
                print(BasicLister().list_basic(snapshot))
            if namespace.variables:
                print(VariableLister().list_variables(snapshot))
    elif snapshot_type == '.sna':
        _analyse_sna(infile)
    elif snapshot_type == '.z80':
        _analyse_z80(infile)
    else:
        _analyse_szx(infile)
Esempio n. 27
0
def main(args):
    parser = argparse.ArgumentParser(
        usage='snapinfo.py [options] file',
        description="Analyse an SNA, SZX or Z80 snapshot.",
        add_help=False
    )
    parser.add_argument('infile', help=argparse.SUPPRESS, nargs='?')
    group = parser.add_argument_group('Options')
    group.add_argument('-b', '--basic', action='store_true',
                       help='List the BASIC program.')
    group.add_argument('-f', '--find', metavar='A[,B...[-M[-N]]]',
                       help='Search for the byte sequence A,B... with distance ranging from M to N (default=1) between bytes.')
    group.add_argument('-p', '--peek', metavar='A[-B[-C]]', action='append',
                       help='Show the contents of addresses A TO B STEP C. This option may be used multiple times.')
    group.add_argument('-t', '--find-text', dest='text', metavar='TEXT',
                       help='Search for a text string.')
    group.add_argument('-T', '--find-tile', dest='tile', metavar='X,Y[-M[-N]]',
                       help='Search for the graphic data of the tile at (X,Y) with distance ranging from M to N (default=1) between bytes.')
    group.add_argument('-v', '--variables', action='store_true',
                       help='List variables.')
    group.add_argument('-V', '--version', action='version', version='SkoolKit {}'.format(VERSION),
                       help='Show SkoolKit version number and exit.')
    group.add_argument('-w', '--word', metavar='A[-B[-C]]', action='append',
                       help='Show the words at addresses A TO B STEP C. This option may be used multiple times.')
    namespace, unknown_args = parser.parse_known_args(args)
    if unknown_args or namespace.infile is None:
        parser.exit(2, parser.format_help())
    infile = namespace.infile
    snapshot_type = infile[-4:].lower()
    if snapshot_type not in ('.sna', '.szx', '.z80'):
        raise SkoolKitError('Unrecognised snapshot type')

    if any((namespace.find, namespace.tile, namespace.text, namespace.peek, namespace.word, namespace.basic, namespace.variables)):
        snapshot = get_snapshot(infile)
        if namespace.find:
            _find(snapshot, namespace.find)
        elif namespace.tile:
            _find_tile(snapshot, namespace.tile)
        elif namespace.text:
            _find_text(snapshot, namespace.text)
        elif namespace.peek:
            _peek(snapshot, namespace.peek)
        elif namespace.word:
            _word(snapshot, namespace.word)
        else:
            if namespace.basic:
                print(BasicLister().list_basic(snapshot))
            if namespace.variables:
                print(VariableLister().list_variables(snapshot))
    elif snapshot_type == '.sna':
        _analyse_sna(infile)
    elif snapshot_type == '.z80':
        _analyse_z80(infile)
    else:
        _analyse_szx(infile)
Esempio n. 28
0
def run(subcommand):
    func = functions[subcommand][0]
    if not os.path.isdir(BUILD_DIR):
        os.mkdir(BUILD_DIR)
    if not os.path.isfile(MM_Z80):
        tap2sna.main(
            ('-d', BUILD_DIR, '@{}/manic_miner.t2s'.format(MANICMINER_HOME)))
    ctlfile = '{}/{}.ctl'.format(BUILD_DIR, subcommand)
    with open(ctlfile, 'wt') as f:
        f.write(func(get_snapshot(MM_Z80)))
    sna2skool.main(('-c', ctlfile, MM_Z80))
Esempio n. 29
0
 def _test_szx(self,
               exp_ram,
               compress,
               machine_id=1,
               ch7ffd=0,
               pages={},
               page=None):
     tmp_szx = self.write_szx(exp_ram, compress, machine_id, ch7ffd, pages)
     snapshot = get_snapshot(tmp_szx, page)
     self._check_ram(snapshot[16384:], exp_ram, machine_id, ch7ffd, pages,
                     page)
Esempio n. 30
0
def find(infile, byte_seq):
    step = 1
    if '-' in byte_seq:
        byte_seq, step = byte_seq.split('-', 1)
        step = get_int_param(step)
    byte_values = [get_int_param(i) for i in byte_seq.split(',')]
    offset = step * len(byte_values)
    snapshot = get_snapshot(infile)
    for a in range(16384, 65537 - offset):
        if snapshot[a:a + offset:step] == byte_values:
            print("{}-{}-{}: {}".format(a, a + offset - step, step, byte_seq))
Esempio n. 31
0
 def test_tap_file_in_zip_archive(self):
     data = [1]
     block = create_tap_data_block(data)
     tap_name = 'game.tap'
     zip_fname = self._write_tap([block], zip_archive=True, tap_name=tap_name)
     z80file = self.write_bin_file(suffix='.z80')
     start = 16385
     output, error = self.run_tap2sna('--force --ram load=1,{} {} {}'.format(start, zip_fname, z80file))
     self.assertEqual(output, 'Extracting {}\nWriting {}\n'.format(tap_name, z80file))
     self.assertEqual(error, '')
     snapshot = get_snapshot(z80file)
     self.assertEqual(data, snapshot[start:start + len(data)])
Esempio n. 32
0
 def test_tap_file_in_zip_archive(self):
     data = [1]
     block = create_tap_data_block(data)
     tap_name = 'game.tap'
     zip_fname = self._write_tap([block], zip_archive=True, tap_name=tap_name)
     z80file = self.write_bin_file(suffix='.z80')
     start = 16385
     output, error = self.run_tap2sna('--force --ram load=1,{} {} {}'.format(start, zip_fname, z80file))
     self.assertEqual(output, 'Extracting {}\nWriting {}\n'.format(tap_name, z80file))
     self.assertEqual(error, '')
     snapshot = get_snapshot(z80file)
     self.assertEqual(data, snapshot[start:start + len(data)])
Esempio n. 33
0
    def test_standard_load_ignores_headerless_block(self):
        code_start = 16384
        code_header = self._create_tap_bytes_header_block(code_start)
        code = [2]
        blocks = [code_header, self._create_tap_data_block(code)]
        blocks.append(self._create_tap_data_block([23]))

        tapfile = self._write_tap(blocks)
        z80file = self.write_bin_file(suffix='.z80')
        output, error = self.run_tap2sna('--force {} {}'.format(tapfile, z80file))
        self.assertEqual(error, '')
        snapshot = get_snapshot(z80file)
        self.assertEqual(snapshot[code_start:code_start + len(code)], code)
Esempio n. 34
0
def peek(infile, addr_range):
    step = 1
    if '-' in addr_range:
        addr1, addr2 = addr_range.split('-', 1)
        addr1 = get_int_param(addr1)
        if '-' in addr2:
            addr2, step = [get_int_param(i) for i in addr2.split('-', 1)]
        else:
            addr2 = get_int_param(addr2)
    else:
        addr1 = addr2 = get_int_param(addr_range)
    snapshot = get_snapshot(infile)
    for a in range(addr1, addr2 + 1, step):
        print('{}: {}'.format(a, snapshot[a]))
Esempio n. 35
0
def run(imgfname, options):
    snapshot = get_snapshot('{}/build/jet_set_willy.z80'.format(JETSETWILLY_HOME))
    _do_pokes(options.pokes, snapshot)
    jsw = JetSetWilly(snapshot)
    udg_array = _place_willy(jsw, options.room, options.willy)
    if options.geometry:
        wh, xy = options.geometry.split('+', 1)
        width, height = [int(n) for n in wh.split('x')]
        x, y = [int(n) for n in xy.split('+')]
        udg_array = [row[x:x + width] for row in udg_array[y:y + height]]
    frame = Frame(udg_array, options.scale)
    image_writer = ImageWriter()
    with open(imgfname, "wb") as f:
        image_writer.write_image([frame], f)
Esempio n. 36
0
 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)
     snapshot = get_snapshot(tmp_z80, page)
     self._check_ram(snapshot[16384:], exp_ram, model, out_7ffd, pages,
                     page)
Esempio n. 37
0
 def _get_snapshot(self, start=16384, data=None, options='', load_options=None, blocks=None, tzx=False):
     if blocks is None:
         blocks = [create_tap_data_block(data)]
     if tzx:
         tape_file = self._write_tzx(blocks)
     else:
         tape_file = self._write_tap(blocks)
     z80file = self.write_bin_file(suffix='.z80')
     if load_options is None:
         load_options = '--ram load=1,{}'.format(start)
     output, error = self.run_tap2sna('--force {} {} {} {}'.format(load_options, options, tape_file, z80file))
     self.assertEqual(output, 'Writing {}\n'.format(z80file))
     self.assertEqual(error, '')
     return get_snapshot(z80file)
Esempio n. 38
0
def run(imgfname, options):
    snapshot = get_snapshot('{}/build/manic_miner.z80'.format(MANICMINER_HOME))
    _do_pokes(options.pokes, snapshot)
    mm = ManicMiner(snapshot)
    udg_array = _place_willy(mm, options.cavern, options.willy)
    if options.geometry:
        wh, xy = options.geometry.split('+', 1)
        width, height = [int(n) for n in wh.split('x')]
        x, y = [int(n) for n in xy.split('+')]
        udg_array = [row[x:x + width] for row in udg_array[y:y + height]]
    frame = Frame(udg_array, options.scale)
    image_writer = ImageWriter()
    with open(imgfname, "wb") as f:
        image_writer.write_image([frame], f)
Esempio n. 39
0
 def _get_snapshot(self, start=16384, data=None, options='', load_options=None, blocks=None, tzx=False):
     if blocks is None:
         blocks = [create_tap_data_block(data)]
     if tzx:
         tape_file = self._write_tzx(blocks)
     else:
         tape_file = self._write_tap(blocks)
     z80file = self.write_bin_file(suffix='.z80')
     if load_options is None:
         load_options = '--ram load=1,{}'.format(start)
     output, error = self.run_tap2sna('--force {} {} {} {}'.format(load_options, options, tape_file, z80file))
     self.assertEqual(output, 'Writing {}\n'.format(z80file))
     self.assertEqual(error, '')
     return get_snapshot(z80file)
Esempio n. 40
0
def _find(infile, byte_seq):
    step = 1
    if '-' in byte_seq:
        byte_seq, step = byte_seq.split('-', 1)
        step = get_int_param(step)
    try:
        byte_values = [get_int_param(i) for i in byte_seq.split(',')]
    except ValueError:
        raise SkoolKitError('Invalid byte sequence: {}'.format(byte_seq))
    offset = step * len(byte_values)
    snapshot = get_snapshot(infile)
    for a in range(16384, 65537 - offset):
        if snapshot[a:a + offset:step] == byte_values:
            print("{0}-{1}-{2} {0:04X}-{1:04X}-{2:X}: {3}".format(a, a + offset - step, step, byte_seq))
Esempio n. 41
0
    def test_standard_load_ignores_truncated_header_block(self):
        code_start = 30000
        code = [2, 3, 4]
        length = len(code)
        blocks = [
            create_tap_header_block(start=code_start)[:-1],
            create_tap_data_block(code),
        ]

        tapfile = self._write_tap(blocks)
        z80file = self.write_bin_file(suffix='.z80')
        output, error = self.run_tap2sna('--force {} {}'.format(tapfile, z80file))
        self.assertEqual(error, '')
        snapshot = get_snapshot(z80file)
        self.assertEqual([0] * length, snapshot[code_start:code_start + length])
Esempio n. 42
0
 def _test_z80(self, options, header, exp_header, ram=None, exp_ram=None, version=3, compress=False):
     if ram is None:
         ram = [0] * 49152
     if exp_ram is None:
         exp_ram = ram
     infile = self.write_z80_file(header, ram, version, compress)
     outfile = '{}-out.z80'.format(infile[:-4])
     self.tempfiles.append(outfile)
     output, error = self.run_snapmod('{} {} {}'.format(options, infile, outfile))
     self.assertEqual(output, '')
     self.assertEqual(error, '')
     z80_header = list(read_bin_file(outfile, len(exp_header)))
     self.assertEqual(exp_header, z80_header)
     z80_ram = get_snapshot(outfile)[16384:]
     self.assertEqual(exp_ram, z80_ram)
Esempio n. 43
0
    def test_standard_load_ignores_headerless_block(self):
        code_start = 16384
        code = [2]
        blocks = [
            create_tap_header_block(start=code_start),
            create_tap_data_block(code),
            create_tap_data_block([23])
        ]

        tapfile = self._write_tap(blocks)
        z80file = self.write_bin_file(suffix='.z80')
        output, error = self.run_tap2sna('--force {} {}'.format(tapfile, z80file))
        self.assertEqual(error, '')
        snapshot = get_snapshot(z80file)
        self.assertEqual(code, snapshot[code_start:code_start + len(code)])
Esempio n. 44
0
    def test_standard_load_ignores_truncated_header_block(self):
        code_start = 30000
        code = [2, 3, 4]
        length = len(code)
        blocks = [
            create_tap_header_block(start=code_start)[:-1],
            create_tap_data_block(code),
        ]

        tapfile = self._write_tap(blocks)
        z80file = self.write_bin_file(suffix='.z80')
        output, error = self.run_tap2sna('--force {} {}'.format(tapfile, z80file))
        self.assertEqual(error, '')
        snapshot = get_snapshot(z80file)
        self.assertEqual([0] * length, snapshot[code_start:code_start + length])
Esempio n. 45
0
def run(imgfname, options):
    snapshot = get_snapshot('{}/build/manic_miner.z80'.format(MANICMINER_HOME))
    _do_pokes(options.pokes, snapshot)
    mm = ManicMiner(snapshot)
    udg_array = _place_willy(mm, options.cavern, options.willy)
    if options.geometry:
        wh, xy = options.geometry.split('+', 1)
        width, height = [int(n) for n in wh.split('x')]
        x, y = [int(n) for n in xy.split('+')]
        udg_array = [row[x:x + width] for row in udg_array[y:y + height]]
    frame = Frame(udg_array, options.scale)
    image_format = 'gif' if imgfname.lower()[-4:] == '.gif' else 'png'
    image_writer = ImageWriter()
    with open(imgfname, "wb") as f:
        image_writer.write_image([frame], f, image_format)
Esempio n. 46
0
def run(subcommand):
    func = functions[subcommand][0]
    if not os.path.isdir(BUILD_DIR):
        os.mkdir(BUILD_DIR)
    if not os.path.isfile(MM_Z80):
        tap2sna.main(("-d", BUILD_DIR, "@{}/manic_miner.t2s".format(MANICMINER_HOME)))
    ctlfile = "{}/{}.ctl".format(BUILD_DIR, subcommand)
    with open(ctlfile, "wt") as f:
        f.write(func(get_snapshot(MM_Z80)))
    stdout = sys.stdout
    sys.stdout = StringIO()
    sna2skool.main(("-c", ctlfile, MM_Z80))
    skool = sys.stdout.getvalue()
    sys.stdout = stdout
    for line in skool.split("\n")[2:-1]:
        print(line)
Esempio n. 47
0
def run(subcommand):
    func = functions[subcommand][0]
    if not os.path.isdir(BUILD_DIR):
        os.mkdir(BUILD_DIR)
    if not os.path.isfile(MM_Z80):
        tap2sna.main(
            ('-d', BUILD_DIR, '@{}/manic_miner.t2s'.format(MANICMINER_HOME)))
    ctlfile = '{}/{}.ctl'.format(BUILD_DIR, subcommand)
    with open(ctlfile, 'wt') as f:
        f.write(func(get_snapshot(MM_Z80)))
    stdout = sys.stdout
    sys.stdout = StringIO()
    sna2skool.main(('-c', ctlfile, MM_Z80))
    skool = sys.stdout.getvalue()
    sys.stdout = stdout
    for line in skool.split('\n')[2:-1]:
        print(line)
Esempio n. 48
0
def _peek(infile, specs):
    addr_ranges = []
    for addr_range in specs:
        try:
            values = [get_int_param(i) for i in addr_range.split('-', 2)]
        except ValueError:
            raise SkoolKitError('Invalid address range: {}'.format(addr_range))
        addr_ranges.append(values + [values[0], 1][len(values) - 1:])
    snapshot = get_snapshot(infile)
    for addr1, addr2, step in addr_ranges:
        for a in range(addr1, addr2 + 1, step):
            value = snapshot[a]
            if 32 <= value <= 126:
                char = chr(value)
            else:
                char = ''
            print('{0:>5} {0:04X}: {1:>3}  {1:02X}  {1:08b}  {2}'.format(a, value, char))
Esempio n. 49
0
    def test_standard_load_from_tap_file(self):
        basic_data = [1, 2, 3]
        code_start = 32768
        code = [4, 5]
        blocks = [
            create_tap_header_block(data_type=0),
            create_tap_data_block(basic_data),
            create_tap_header_block(start=code_start),
            create_tap_data_block(code)
        ]

        tapfile = self._write_tap(blocks)
        z80file = self.write_bin_file(suffix='.z80')
        output, error = self.run_tap2sna('--force {} {}'.format(tapfile, z80file))
        self.assertEqual(error, '')
        snapshot = get_snapshot(z80file)
        self.assertEqual(basic_data, snapshot[23755:23755 + len(basic_data)])
        self.assertEqual(code, snapshot[code_start:code_start + len(code)])
Esempio n. 50
0
    def test_standard_load_from_tap_file(self):
        basic_data = [1, 2, 3]
        code_start = 32768
        code = [4, 5]
        blocks = [
            create_tap_header_block(data_type=0),
            create_tap_data_block(basic_data),
            create_tap_header_block(start=code_start),
            create_tap_data_block(code)
        ]

        tapfile = self._write_tap(blocks)
        z80file = self.write_bin_file(suffix='.z80')
        output, error = self.run_tap2sna('--force {} {}'.format(tapfile, z80file))
        self.assertEqual(error, '')
        snapshot = get_snapshot(z80file)
        self.assertEqual(basic_data, snapshot[23755:23755 + len(basic_data)])
        self.assertEqual(code, snapshot[code_start:code_start + len(code)])
Esempio n. 51
0
    def test_standard_load_from_tzx_file(self):
        basic_data = [6, 7]
        code_start = 49152
        code = [8, 9, 10]
        blocks = [
            [48, 3, 65, 66, 67], # Text description block (0x30): ABC
            create_tzx_header_block(data_type=0),
            create_tzx_data_block(basic_data),
            create_tzx_header_block(start=code_start),
            create_tzx_data_block(code)
        ]

        tzxfile = self._write_tzx(blocks)
        z80file = self.write_bin_file(suffix='.z80')
        output, error = self.run_tap2sna('--force {} {}'.format(tzxfile, z80file))
        self.assertEqual(error, '')
        snapshot = get_snapshot(z80file)
        self.assertEqual(basic_data, snapshot[23755:23755 + len(basic_data)])
        self.assertEqual(code, snapshot[code_start:code_start + len(code)])
Esempio n. 52
0
 def test_sna_128k_page_5(self):
     header = [0] * 27
     page5 = [(n + 37) & 255 for n in range(16384)]
     page2 = [(n + 19) & 255 for n in range(16384)]
     page3 = [(n + 203) & 255 for n in range(16384)]
     page0 = [(n + 197) & 255 for n in range(16384)]
     page1 = [(n + 117) & 255 for n in range(16384)]
     page4 = [(n + 5) & 255 for n in range(16384)]
     page6 = [(n + 23) & 255 for n in range(16384)]
     page7 = [(n + 41) & 255 for n in range(16384)]
     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 + page5 + page2 + page3 + config + page0 + page1 + page4 + page6 + page7
     tmp_sna = self.write_bin_file(sna, suffix='.sna')
     snapshot = get_snapshot(tmp_sna, 5)
     ram = snapshot[16384:]
     self.assertEqual(len(ram), 49152)
     self.assertEqual(ram, page5 + page2 + page5)
Esempio n. 53
0
    def test_standard_load_from_tzx_file(self):
        basic_data = [6, 7]
        code_start = 49152
        code = [8, 9, 10]
        blocks = [
            [48, 3, 65, 66, 67], # Text description block (0x30): ABC
            create_tzx_header_block(data_type=0),
            create_tzx_data_block(basic_data),
            create_tzx_header_block(start=code_start),
            create_tzx_data_block(code)
        ]

        tzxfile = self._write_tzx(blocks)
        z80file = self.write_bin_file(suffix='.z80')
        output, error = self.run_tap2sna('--force {} {}'.format(tzxfile, z80file))
        self.assertEqual(error, '')
        snapshot = get_snapshot(z80file)
        self.assertEqual(basic_data, snapshot[23755:23755 + len(basic_data)])
        self.assertEqual(code, snapshot[code_start:code_start + len(code)])
Esempio n. 54
0
 def test_sna_128k_page_5(self):
     header = [0] * 27
     page5 = [(n + 37) & 255 for n in range(16384)]
     page2 = [(n + 19) & 255 for n in range(16384)]
     page3 = [(n + 203) & 255 for n in range(16384)]
     page0 = [(n + 197) & 255 for n in range(16384)]
     page1 = [(n + 117) & 255 for n in range(16384)]
     page4 = [(n + 5) & 255 for n in range(16384)]
     page6 = [(n + 23) & 255 for n in range(16384)]
     page7 = [(n + 41) & 255 for n in range(16384)]
     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 + page5 + page2 + page3 + config + page0 + page1 + page4 + page6 + page7
     tmp_sna = self.write_bin_file(sna, suffix='.sna')
     snapshot = get_snapshot(tmp_sna, 5)
     ram = snapshot[16384:]
     self.assertEqual(len(ram), 49152)
     self.assertEqual(ram, page5 + page2 + page5)
Esempio n. 55
0
def run(snafile, options):
    # Read the snapshot file
    if snafile[-4:].lower() in ('.sna', '.szx', '.z80'):
        snapshot = get_snapshot(snafile, options.page)
        start = max(START, options.start)
    else:
        ram = read_bin_file(snafile)
        if options.org is None:
            org = 65536 - len(ram)
        else:
            org = options.org
        snapshot = [0] * org
        snapshot.extend(ram)
        start = max(org, options.start)
    end = min(options.end, len(snapshot))

    # Pad out the end of the snapshot to avoid disassembly errors when an
    # instruction crosses the 64K boundary
    snapshot += [0] * (65539 - len(snapshot))

    if options.sftfile:
        # Use a skool file template
        info('Using skool file template: {}'.format(options.sftfile))
        writer = SftParser(snapshot, options.sftfile, options.zfill, options.asm_hex, options.asm_lower)
        writer.write_skool(options.start, options.end)
        return

    if options.genctlfile:
        # Generate a control file
        ctls = generate_ctls(snapshot, start, end, options.code_map)
        write_ctl(options.genctlfile, ctls, options.ctl_hex)
        ctl_parser = CtlParser(ctls)
    elif options.ctlfile:
        # Use a control file
        info('Using control file: {}'.format(options.ctlfile))
        ctl_parser = CtlParser()
        ctl_parser.parse_ctl(options.ctlfile, options.start, options.end)
    else:
        ctl_parser = CtlParser({start: 'c', end: 'i'})
    writer = SkoolWriter(snapshot, ctl_parser, options)
    writer.write_skool(options.write_refs, options.text)
Esempio n. 56
0
 def _test_szx(self, exp_ram, compress, machine_id=1, ch7ffd=0, pages={}, page=None):
     szx = self._get_szx_header(machine_id, ch7ffd)
     rampages = {5: self._get_zxstrampage(5, compress, exp_ram[:16384])}
     if machine_id >= 1:
         # 48K and 128K
         rampages[2] = self._get_zxstrampage(2, compress, exp_ram[16384:32768])
         if machine_id == 1:
             # 48K
             rampages[0] = self._get_zxstrampage(0, compress, exp_ram[32768:])
         else:
             # 128K
             rampages[ch7ffd & 7] = self._get_zxstrampage(ch7ffd & 7, compress, exp_ram[32768:])
             for bank, data in pages.items():
                 rampages[bank] = self._get_zxstrampage(bank, compress, data)
             for bank in set(range(8)) - set(rampages.keys()):
                 rampages[bank] = self._get_zxstrampage(bank, compress, [0] * 16384)
     for rampage in rampages.values():
         szx.extend(rampage)
     tmp_szx = self.write_bin_file(szx, suffix='.szx')
     snapshot = get_snapshot(tmp_szx, page)
     self._check_ram(snapshot[16384:], exp_ram, machine_id, ch7ffd, pages, page)
Esempio n. 57
0
def main(args):
    parser = argparse.ArgumentParser(
        usage='snapinfo.py [options] file',
        description="Analyse an SNA, SZX or Z80 snapshot.",
        add_help=False
    )
    parser.add_argument('infile', help=argparse.SUPPRESS, nargs='?')
    group = parser.add_argument_group('Options')
    group.add_argument('-b', '--basic', action='store_true',
                       help='List the BASIC program')
    group.add_argument('-f', '--find', metavar='A[,B...[-N]]',
                       help='Search for the byte sequence A,B... with distance N (default=1) between bytes')
    group.add_argument('-p', '--peek', metavar='A[-B[-C]]', action='append',
                       help='Show the contents of addresses A TO B STEP C; this option may be used multiple times')
    group.add_argument('-t', '--find-text', dest='text', metavar='TEXT',
                       help='Search for a text string')
    group.add_argument('-V', '--version', action='version', version='SkoolKit {}'.format(VERSION),
                       help='Show SkoolKit version number and exit')
    namespace, unknown_args = parser.parse_known_args(args)
    if unknown_args or namespace.infile is None:
        parser.exit(2, parser.format_help())
    infile = namespace.infile
    snapshot_type = infile[-4:].lower()
    if snapshot_type not in ('.sna', '.szx', '.z80'):
        raise SkoolKitError('Unrecognised snapshot type')

    if namespace.find is not None:
        _find(infile, namespace.find)
    elif namespace.text is not None:
        _find_text(infile, namespace.text)
    elif namespace.peek is not None:
        _peek(infile, namespace.peek)
    elif namespace.basic:
        print(BasicLister().list_basic(get_snapshot(infile)))
    elif snapshot_type == '.sna':
        _analyse_sna(infile)
    elif snapshot_type == '.z80':
        _analyse_z80(infile)
    else:
        _analyse_szx(infile)
Esempio n. 58
0
def run(snafile, options, config):
    # Read the snapshot file
    if snafile[-4:].lower() in ('.sna', '.szx', '.z80'):
        snapshot = get_snapshot(snafile, options.page)
        start = max(START, options.start)
    else:
        ram = read_bin_file(snafile, 65536)
        if options.org is None:
            org = 65536 - len(ram)
        else:
            org = options.org
        snapshot = [0] * org
        snapshot.extend(ram)
        start = max(org, options.start)
    end = min(options.end, len(snapshot))

    snapshot += [0] * (65536 - len(snapshot))

    if options.sftfile:
        # Use a skool file template
        info('Using skool file template: {}'.format(options.sftfile))
        writer = SftParser(snapshot, options.sftfile, options.zfill,
                           options.base == 16, options.case == 1)
        writer.write_skool(options.start, options.end)
        return

    if options.genctlfile:
        # Generate a control file
        ctls = generate_ctls(snapshot, start, end, options.code_map)
        write_ctl(options.genctlfile, ctls, options.ctl_hex)
        ctl_parser = CtlParser(ctls)
    elif options.ctlfile:
        # Use a control file
        info('Using control file: {}'.format(options.ctlfile))
        ctl_parser = CtlParser()
        ctl_parser.parse_ctl(options.ctlfile, options.start, options.end)
    else:
        ctl_parser = CtlParser({start: 'c', end: 'i'})
    writer = SkoolWriter(snapshot, ctl_parser, options, config)
    writer.write_skool(options.write_refs, options.text)
Esempio n. 59
0
 def test_bad_ram_size(self):
     ram_size = 3
     with self.assertRaisesRegex(SnapshotError,
                                 'RAM size is {}'.format(ram_size)):
         get_snapshot(
             self.write_bin_file([0] * (27 + ram_size), suffix='.sna'))
Esempio n. 60
0
def main(args):
    parser = argparse.ArgumentParser(
        usage='bin2tap.py [options] FILE [file.tap]',
        description=
        "Convert a binary (raw memory) file or a SNA, SZX or Z80 snapshot into a TAP file. "
        "FILE may be a regular file, or '-' to read a binary file from standard input.",
        add_help=False)
    parser.add_argument('infile', help=argparse.SUPPRESS, nargs='?')
    parser.add_argument('outfile', help=argparse.SUPPRESS, nargs='?')
    group = parser.add_argument_group('Options')
    group.add_argument(
        '-c',
        '--clear',
        dest='clear',
        metavar='N',
        type=integer,
        help=
        "Use a 'CLEAR N' command in the BASIC loader and leave the stack pointer alone."
    )
    group.add_argument('-e',
                       '--end',
                       dest='end',
                       metavar='ADDR',
                       type=integer,
                       default=65536,
                       help="Set the end address when reading a snapshot.")
    group.add_argument(
        '-o',
        '--org',
        dest='org',
        metavar='ORG',
        type=integer,
        help=
        "Set the origin address (default: 16384 for a snapshot, otherwise 65536 minus the length of FILE)."
    )
    group.add_argument('-p',
                       '--stack',
                       dest='stack',
                       metavar='STACK',
                       type=integer,
                       help="Set the stack pointer (default: ORG).")
    group.add_argument('-s',
                       '--start',
                       dest='start',
                       metavar='START',
                       type=integer,
                       help="Set the start address to JP to (default: ORG).")
    group.add_argument(
        '-S',
        '--screen',
        dest='screen',
        metavar='FILE',
        help=
        "Add a loading screen to the TAP file. FILE may be a snapshot or a 6912-byte SCR file."
    )
    group.add_argument('-V',
                       '--version',
                       action='version',
                       version='SkoolKit {}'.format(VERSION),
                       help='Show SkoolKit version number and exit.')

    namespace, unknown_args = parser.parse_known_args(args)
    infile = namespace.infile
    if unknown_args or infile is None:
        parser.exit(2, parser.format_help())
    if infile.lower().endswith(('.sna', '.szx', '.z80')):
        org = namespace.org or 16384
        if org >= namespace.end:
            raise SkoolKitError(
                'End address must be greater than {}'.format(org))
        ram = get_snapshot(infile)[org:namespace.end]
    else:
        ram = read_bin_file(infile, 49152)
        if len(ram) == 0:
            raise SkoolKitError('{} is empty'.format(infile))
        org = namespace.org or 65536 - len(ram)
    clear = namespace.clear
    start = namespace.start or org
    stack = namespace.stack or org
    tapfile = namespace.outfile
    if tapfile is None:
        if infile.lower().endswith(('.bin', '.sna', '.szx', '.z80')):
            prefix = infile[:-4]
        elif infile == '-':
            prefix = 'program'
        else:
            prefix = infile
        tapfile = prefix + ".tap"
    scr = namespace.screen
    if scr is not None:
        if scr.lower().endswith(('.sna', '.szx', '.z80')):
            scr = get_snapshot(scr)[16384:23296]
        else:
            scr = read_bin_file(scr, 6912)
    run(ram, clear, org, start, stack, tapfile, scr)