def main(argv=None): argv = argv or sys.argv if len(argv) > 1 and argv[0] == '--help': print("usage: sav2sb53.py infile.sav outfile.pb53\n" "Packs a savtool background in PB53 format.") return if len(argv) != 3: print("sav2sb53.py: wrong number of arguments; try sav2sb53.py --help", file=sys.stderr) sys.exit(1) _, infilename, outfilename = argv with open(infilename, 'rb') as infp: data = infp.read(8192) namdata = data[6144:7168] num_tiles = 1 + max(namdata[:960]) chrdata = data[0:16 * num_tiles] paldata = data[-256:-240] outdata = [ bytearray([num_tiles & 0xFF]), pb53.pb53(chrdata)[0], pb53.pb53(namdata)[0], paldata ] with open(outfilename, 'wb') as outfp: outfp.writelines(outdata)
def main(argv=None): argv = argv or sys.argv if len(argv) > 1 and argv[1] == '--help': print( "usage: sav2sb53.py infile.sav outfile.pb53\n" "Packs a savtool background: tile count, PB53 tile data, PB53 nametable,\n" "16-entry palette") return if len(argv) != 3: print("sav2sb53.py: wrong number of arguments; try sav2sb53.py --help", file=sys.stderr) sys.exit(1) _, infilename, outfilename = argv with open(infilename, 'rb') as infp: data = infp.read(8192) namdata = data[6144:7168] num_tiles = 1 + max(namdata[:960]) chrdata = data[0:16 * num_tiles] paldata = data[-256:-240] outdata = [ bytearray([num_tiles & 0xFF]), pb53.pb53(chrdata)[0], pb53.pb53(namdata)[0], paldata ] with open(outfilename, 'wb') as outfp: outfp.writelines(outdata)
def main(argv=None): args = parse_argv(argv or sys.argv) blanktile = b"".join((b"\xff" if args.blank_color & b else b"\x00") * 8 for b in [0x01, 0x02]) with open(args.savfile, "rb") as infp: tiledata = infp.read(4096) infp.read(2048) nt = infp.read(960) attrs = infp.read(64) infp.read(768) palette = infp.read(16) tiledata = [tiledata[16 * i:16 * i + 16] for i in nt] nt = None tiledata, r = crop_blank_tiles(tiledata, 32, blanktile) tiles_per_row = r[2] - r[0] tiledata, nt = uniq_on_grid(tiledata, tiles_per_row, args.x_grid, args.y_grid, blanktile=blanktile, verbose=args.verbose) # Crop the leading blank tile assert tiledata[0] == blanktile del tiledata[0] # Now compress everything ctiles, _ = pb53.pb53(b''.join(tiledata)) cnt = iu53_compress_nt(nt) start_tile = args.start_tile if start_tile is None: start_tile = len(args.x_grid) * len(args.y_grid) if args.verbose: print("starting tile number set to %d" % start_tile) if args.verbose: print("cropped to rect: (%d, %d)-(%d, %d)" % r) print("%s: %d bytes of pattern and %d bytes of map" % (args.savfile, len(ctiles), len(cnt))) out = iu53_decompress_nt(cnt, len(nt)) print("Match" if nt == out else "Decompression mismatch") ntaddr = 0x2000 + r[1] * 32 + r[0] if args.with_attrs: ntaddr += 0x8000 if args.with_palette: ntaddr += 0x4000 out = bytearray([start_tile, len(tiledata)]) out.extend(ctiles) out.extend( (ntaddr & 0xFF, (ntaddr >> 8) & 0xFF, tiles_per_row, r[3] - r[1])) out.extend(cnt) if args.with_attrs: cattrs, _ = pb53.pb53(attrs) out.extend(cattrs) if args.with_palette: out.extend(palette) if args.verbose: print(len(out), "total bytes") with open(args.iu53file, "wb") as outfp: outfp.write(out)
def bmptowidesb53(infilename, palette, outfilename): im = Image.open(infilename) if im.size[0] != 512: raise ValueError("Image width is %d pixels (expected 512)" % im.size[0]) if im.size[1] != 240: raise ValueError("Image height is %d pixels (expected 240)" % im.size[0]) # Quantize picture to palette palette = b''.join(palette[0:1] + palette[i + 1:i + 4] for i in range(0, 16, 4)) palettes = [[tuple(savtool.bisqpal[r]) for r in palette[i:i + 4]] for i in range(0, 16, 4)] imf, attrs = savtool.colorround(im, palettes) # Convert to unique tiles chrdata = pilbmp2nes.pilbmp2chr(imf, 8, 8) chrdata, linear_namdata = chnutils.dedupe_chr(chrdata) print("%d distinct tiles" % len(chrdata)) # Split into separate 32x32 nametables nametables = [[ linear_namdata[i:i + 32] for i in range(x, len(linear_namdata), im.size[0] // 8) ] for x in range(0, im.size[0] // 8, 32)] nametables = [bytes(b for row in nt for b in row) for nt in nametables] # Pack attributes into bytes if len(attrs) % 2: attrs.append([0] * len(attrs[0])) attrs = [[lc | (rc << 2) for lc, rc in zip(row[0::2], row[1::2])] for row in attrs] attrs = [[tc | (bc << 4) for (tc, bc) in zip(t, b)] for (t, b) in zip(attrs[0::2], attrs[1::2])] # Split into separate 32x32 nametables attrs = [ bytes(b for row in attrs for b in row[i:i + 8]) for i in range(0, len(attrs[0]), 8) ] print([len(x) for x in attrs]) outdata = [ bytearray([len(chrdata) & 0xFF]), pb53(b''.join(chrdata), copyprev=False)[0] ] outdata.extend( pb53(nt + at, copyprev=False)[0] for nt, at in zip(nametables, attrs)) outdata.append(palette) with open(outfilename, 'wb') as outfp: outfp.writelines(outdata)
def bmptowidesb53(infilename, palette, outfilename): im = Image.open(infilename) if im.size[0] != 512: raise ValueError("Image width is %d pixels (expected 512)" % im.size[0]) if im.size[1] != 240: raise ValueError("Image height is %d pixels (expected 240)" % im.size[0]) # Quantize picture to palette palette = b''.join(palette[0:1] + palette[i + 1:i + 4] for i in range(0, 16, 4)) palettes = [[tuple(savtool.bisqpal[r]) for r in palette[i:i + 4]] for i in range(0, 16, 4)] imf, attrs = savtool.colorround(im, palettes) # Convert to unique tiles chrdata = pilbmp2nes.pilbmp2chr(imf, 8, 8) chrdata, linear_namdata = chnutils.dedupe_chr(chrdata) print("%d distinct tiles" % len(chrdata)) # Split into separate 32x32 nametables nametables = [[linear_namdata[i:i + 32] for i in range(x, len(linear_namdata), im.size[0] // 8)] for x in range(0, im.size[0] // 8, 32)] nametables = [bytes(b for row in nt for b in row) for nt in nametables] # Pack attributes into bytes if len(attrs) % 2: attrs.append([0] * len(attrs[0])) attrs = [[lc | (rc << 2) for lc, rc in zip(row[0::2], row[1::2])] for row in attrs] attrs = [[tc | (bc << 4) for (tc, bc) in zip(t, b)] for (t, b) in zip(attrs[0::2], attrs[1::2])] # Split into separate 32x32 nametables attrs = [bytes(b for row in attrs for b in row[i:i + 8]) for i in range(0, len(attrs[0]), 8)] print([len(x) for x in attrs]) outdata = [ bytearray([len(chrdata) & 0xFF]), pb53(b''.join(chrdata), copyprev=False)[0] ] outdata.extend(pb53(nt + at, copyprev=False)[0] for nt, at in zip(nametables, attrs)) outdata.append(palette) with open(outfilename, 'wb') as outfp: outfp.writelines(outdata)
def main(argv=None): argv = argv or sys.argv specfilename = argv[1] imname = argv[2] outfilename = argv[3] lines = load_spec_file(specfilename) coords = [] for line in lines: coord = [x.strip() for x in line.split(',')] if len(coord) != 2 or not all(x.isdigit() for x in coord): print("%s is not coords" % line, sys.stderr) continue coords.append(tuple(int(x) for x in coord)) im = Image.open(imname) if im.mode != 'P': print("mkspritemap.py: %s must be indexed" % imname, file=sys.stderr)) sys.exit(1) overdraw = [0]*im.size[1] alltiles = [] out = array.array('B', [len(coords)]) for left, top in coords: out.extend((left, top)) for y in xrange(top, top + 8): overdraw[y] += 1 tdata = pilbmp2chr(im.crop((left, top, left+8, top+8))) alltiles.extend(tdata) compressed = pb53.pb53(''.join(alltiles))[0] out.fromstring(compressed) print("Num tiles: %d; max overdraw: %d; data size: %d bytes" % (len(alltiles), max(overdraw), len(compressed)))