def read_art(art_name): check_ext(art_name, '.ART') verbose = 0 parts = read_madspack(art_name) save_madspack(art_name, parts) # parts[0] -- dimensions + palette # parts[1] -- image data # header h = Header() h.width = read_uint16(parts[0]) h.height = read_uint16(parts[0]) save_header(art_name, h) # palette pal = read_palette_rex(parts[0]) export_palette(pal, art_name) # image -- read indexed image img = Image.new('P', (h.width, h.height)) attach_palette(img, pal) pix = img.load() for j in range(h.height): for i in range(h.width): ind = read_uint8(parts[1]) pix[i, j] = ind save_image(art_name, img)
def read_pik(pik_name): check_ext(pik_name, '.PIK') parts = read_madspack(pik_name) assert len(parts) >= 3 save_madspack(pik_name, parts) h = read_pik_header(parts[0]) pal = read_palette_col(parts[2]) img = read_pik_image(parts[1], h, pal) save_image(pik_name, img)
def read_cnv(cnv_name): check_ext(cnv_name, '.CNV') parts = read_madspack(cnv_name) assert len(parts) == 7 save_madspack(cnv_name, parts) h = read_cnv_header(cnv_name) save_cnv_header(cnv_name, h) msgs = read_cnv_messages(cnv_name, h.msg_count) save_cnv_messages(cnv_name, msgs)
def read_aa(aa_name): assert aa_name.endswith('.AA') parts = read_madspack(aa_name) assert len(parts) >= 1 save_madspack(aa_name, parts) h = read_aa_header(aa_name) save_aa_header(aa_name, h) if len(parts) > 1: msgs = read_aa_messages(aa_name, h.msg_count) save_aa_messages(aa_name, msgs)
def read_aa(aa_name): check_ext(aa_name, '.AA') parts = read_madspack(aa_name) assert len(parts) >= 1 save_madspack(aa_name, parts) h = read_aa_header(aa_name) save_aa_header(aa_name, h) if len(parts) > 1: msgs = read_aa_messages(aa_name, h.msg_count) save_aa_messages(aa_name, msgs)
def read_ss(f, ss_name): """ SS file is a MADSPACK file with 4 parts: * part 0 header mode -- part3 encoding 0 -- linemode 1 -- FAB and linemode count -- number of sprites size -- size of part3 * part 1 is composed of tile_headers, there can be many tiles in one file ntiles = len(part2) / 0x00000010 * part 2 palette * part 3 image data, may contain many tiles Tiles are compressed with linemode|command encoding. Colors are stored in indexed mode. Each pixel line begins with linemode. Linemodes/commands: lm cm description ------------------------------------------------------------------------ 255 fill rest of the line with bg color and read linemode 252 stop 254 pixel mode 254 255 fill rest of the line with bg color and read linemode 254 254 len col produce len * [col] pixels, read command 254 col produce [col] pixel, read command 253 multiple pixels mode 253 255 fill rest of the line with bg color and read linemode 253 len col produce len * [col] pixels, read command """ verbose = 0 parts = read_madspack(f) save_madspack(ss_name, parts) ss_header = read_ss_header(parts[0]) # save header save_ss_header(ss_name, ss_header) if verbose: print("nsprites=", ss_header.nsprites) sprite_headers = [] for i in range(ss_header.nsprites): sprite_header = read_sprite_header(parts[1]) sprite_headers.append(sprite_header) # save header sprite_name = '{}.{:03}'.format(ss_name, i) save_sprite_header(sprite_name, sprite_header) pal = read_pallete(parts[2]) sprites = [] for i, sprite_header in enumerate(sprite_headers): sprite = read_sprite(sprite_header, parts[3], pal, mode = ss_header.mode) sprites.append(sprite) # save sprite sprite_name = '{}.{:03}'.format(ss_name, i) save_sprite(sprite_name, sprite) return sprites
def read_ff(ff_name): """ FF file: 1 part MADSPACK header max_height: 1 byte max_width: 1 byte glyphs widths: 128 bytes glyphs offsets: 2 x 128 byte glyphs ... """ check_ext(ff_name, '.FF') parts = read_madspack(ff_name) save_madspack(ff_name, parts) f = parts[0] # Header h = Record() h.max_height = read_uint8(f) h.max_width = read_uint8(f) # glyphs width in pixels # glyph height is max_height # null has width 0 h.char_widths = [0] + [read_uint8(f) for _ in range(127)] read_uint8(f) # alignment to 128 # space occupied by glyph is # math.ceil((glyph_width * max_height) / 4.0) # or is is rounded per line ? # offsets inside section h.char_offsets = [2 + 128 + 256] + [read_uint16(f) for _ in range(127)] read_uint16(f) # alignment assert f.tell() == 2 + 128 + 256 save_ff_header(ff_name, h) # Glyphs f.seek(h.char_offsets[1]) for ch in range(1,128): width = h.char_widths[ch] height = h.max_height offset = h.char_offsets[ch] assert f.tell() == offset if width == 0: continue img = Image.new("P", (width,height)) attach_palette(img, pal) y = 0 while y < height: x = 0 while 1: byte = read_uint8(f) col = (byte & 0b11000000) >> 6 img.putpixel((x,y), col) x += 1 if x == width: break col = (byte & 0b00110000) >> 4 img.putpixel((x,y), col) x += 1 if x == width: break col = (byte & 0b00001100) >> 2 img.putpixel((x,y), col) x += 1 if x == width: break col = (byte & 0b00000011) >> 0 img.putpixel((x,y), col) x += 1 if x == width: break y += 1 oname = "{}.{:03}.png".format(ff_name, ch) img.save(oname) output(oname)
def read_ff(ff_name): pal = [(0,0,0,0),(0,255,0,255),(0,127,0,255),(0,63,0,255)] parts = read_madspack(ff_name) save_madspack(ff_name, parts) f = parts[0] f.seek(0) h = Record() h.max_height = read_uint8(f) h.max_width = read_uint8(f) # glyphs width in pixels # glyph height is max_height # null has width 0 h.char_widths = [0] + read_bytes(f, 127) read_uint8(f) # alignment to 128 # space occupied by glyph is # math.ceil((glyph_width * max_height) / 4.0) # or is is rounded per line ? # offsets inside section h.char_offsets = [2 + 128 + 256] + [read_uint16(f) for _ in range(127)] read_uint16(f) # alignment assert f.tell() == 2 + 128 + 256 save_ff_header(ff_name, h) # load glyphs for ch in range(1,128): width = h.char_widths[ch] height = h.max_height if width == 0: continue img = Image.new("RGBA", (width,height)) y = 0 while y < height: x = 0 while 1: byte = read_uint8(f) col = pal[(byte & 0b11000000) >> 6] img.putpixel((x,y), col) x += 1 if x == width: break col = pal[(byte & 0b00110000) >> 4] img.putpixel((x,y), col) x += 1 if x == width: break col = pal[(byte & 0b00001100) >> 2] img.putpixel((x,y), col) x += 1 if x == width: break col = pal[(byte & 0b00000011) >> 0] img.putpixel((x,y), col) x += 1 if x == width: break y += 1 oname = "{}.{:03}.png".format(ff_name, ch) img.save(oname) output(oname)
def call(fmt,cmd,path): odd = os.getcwd() ndd,arg1 = os.path.split(path) common.g_curr_dir = ndd if ndd: os.chdir(ndd) try: if cmd not in ['pack','unpack']: print('invalid command; use "pack" or "unpack"') sys.exit(1) if fmt == 'dat': if cmd == 'unpack': read_messagesdat(open(arg1, 'rb'), arg1) elif cmd == 'pack': write_messagesdat(open(arg1, 'wb'), arg1) elif fmt == 'hag': if cmd == 'unpack': read_madsconcat(open(arg1, 'rb'), arg1) elif cmd == 'pack': write_madsconcat(arg1) elif fmt == 'ss': if cmd == 'unpack': read_ss(open(arg1, 'rb'), arg1) elif cmd == 'pack': write_ss(arg1) else: print(usage) sys.exit(1) elif fmt == 'fab': if cmd == 'unpack': read_fab_unrestricted(arg1) elif cmd == 'pack': print("fab compression? what for?") # write_fab_unrestricted(arg1) else: print(usage) sys.exit(1) elif fmt == 'madspack': if cmd == 'unpack': save_madspack(arg1, read_madspack(open(arg1, 'rb'))) elif cmd == 'pack': write_madspack(arg1, load_madspack(arg1)) else: print(usage) sys.exit(1) elif fmt == 'aa': if cmd == 'unpack': read_aa(arg1) elif cmd == 'pack': write_aa(arg1) else: print(usage) sys.exit(1) elif fmt == 'ff': if cmd == 'unpack': read_ff(arg1) elif cmd == 'pack': write_ff(arg1) else: print(usage) sys.exit(1) else: raise External('invalid format specification') finally: os.chdir(odd) common.g_curr_dir = ''