Skip to content

Instantly share code, notes, and snippets.

@heisvoid
Created July 20, 2019 10:50
Show Gist options
  • Save heisvoid/a4b72220cc5babdd12e9d3e0558882af to your computer and use it in GitHub Desktop.
Save heisvoid/a4b72220cc5babdd12e9d3e0558882af to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
# Extract sprites
import argparse
import struct
import os
# mode 13h resolution
MONITOR_WIDTH = 320
MONITOR_HEIGHT = 200
# bright pink
SPRITE_BACKGROUND = (255, 0, 255)
parser = argparse.ArgumentParser(description='Extract sprites.')
parser.add_argument('-p', required=True, help='palette file', dest='pal')
parser.add_argument('-f', required=True, help='compressed sprites file',
dest='spr')
args = parser.parse_args()
# read palette
pal = []
with open(args.pal, 'rb') as f:
for i in range(256):
buf = f.read(3)
buf = struct.unpack('<BBB', buf)
pal.append((buf[0], buf[1], buf[2]))
# extract sprites
with open(args.spr, 'rb') as f:
f.seek(0, os.SEEK_END)
file_len = f.tell()
f.seek(0, os.SEEK_SET)
# header
f.seek(0x42, os.SEEK_SET)
# maybe, number of sprites.
buf = f.read(2)
buf = struct.unpack('<H', buf)
num = buf[0]
# zero padding
f.seek(60, os.SEEK_CUR)
for n in range(num):
buf = f.read(4)
buf = struct.unpack('<I', buf)
length = buf[0]
# width
buf = f.read(2)
buf = struct.unpack('<H', buf)
width = buf[0]
# height
buf = f.read(2)
buf = struct.unpack('<H', buf)
height = buf[0]
assert MONITOR_WIDTH >= width
assert MONITOR_HEIGHT >= height
assert (width * height + 4) == length
# unknown
f.read(4)
f.read(2)
f.read(2)
f.read(16)
f.read(2)
f.read(2)
# reset monitor
monitor = range(width * height)
monitor = []
for i in range(width * height):
monitor.append(SPRITE_BACKGROUND)
# draw a sprite on monitor
for idx in range(width * height):
assert f.tell() < file_len
buf = f.read(1)
buf = struct.unpack('<B', buf)
pal_idx = buf[0]
if 0xff != pal_idx: # maybe, 0xff means 'Not painted'.
monitor[idx] = pal[pal_idx]
# write a sprite to file
out_name = os.path.basename(args.spr)
out_name = out_name + '.%05d' % n + '.ppm'
with open(out_name, 'w') as out:
out.write('P3\n')
out.write('%d %d\n' % (width, height))
out.write('255\n')
for h in range(height):
for w in range(width):
rgb = monitor[width * h + w]
out.write('%d %d %d\n' % (rgb[0], rgb[1], rgb[2]))
assert f.tell() == file_len
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment