Skip to content

Instantly share code, notes, and snippets.

@drdaxxy
Last active November 5, 2016 21:59
Show Gist options
  • Save drdaxxy/f25678ffb03c4cb25e4488d94bbf8abe to your computer and use it in GitHub Desktop.
Save drdaxxy/f25678ffb03c4cb25e4488d94bbf8abe to your computer and use it in GitHub Desktop.
MAGES. engine sprite definition (.LAY) decoder. I didn't write this.
#!/usr/bin/env python3
# unlay: represent LAY file in a human readable form.
# Author: Nimms <nimms@ya.ru>
# edited by DrDaxxy to support little endian files (Windows builds)
import sys
import struct
import codecs
# endianness, depends on target platform (> = big, < = little)
BYTE_ORDER = '<'
if len(sys.argv) == 1:
print("Usage: unlay file", file=sys.stderr)
exit(1)
with open(sys.argv[1], 'rb') as f:
# uint32: count of states
states_count = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
print(states_count)
# uint32: count of coordinates records
coord_records_count = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
print(coord_records_count)
print()
i = 0
# State record.
# The "state" is a series of blocks combined in one image, think about it as
# a frame of an animated image.
while i < states_count:
# uint32: state ID (printed as HEX for readability)
state_raw = bytearray(f.read(4))
if BYTE_ORDER == '<':
state_raw.reverse()
state = codecs.encode(state_raw, 'hex').decode('ascii')
# uint32: starting record number
start = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
# uint32: count of records to read
count = struct.unpack(BYTE_ORDER + 'I', f.read(4))[0]
print(state, start, count)
i += 1
print()
i = 0
# Coordinates record.
# Contains positions of a block in the source image and on the screen where
# it will be displayed (relative to its center).
while i < coord_records_count:
# float32: block position on the screen, X
x1 = struct.unpack(BYTE_ORDER + 'f', f.read(4))[0] + 1
# float32: block position on the screen, Y
y1 = struct.unpack(BYTE_ORDER + 'f', f.read(4))[0] + 1
# float32: block position in the image, X
x2 = struct.unpack(BYTE_ORDER + 'f', f.read(4))[0] - 1
# float32: block position in the image, Y
y2 = struct.unpack(BYTE_ORDER + 'f', f.read(4))[0] - 1
print(x1, y1, x2, y2)
i += 1
i = 0
# Every block also has a corresponding value which is somehow used by the
# game engine.
# Looks like it determines whether the block has translucent pixels.
# For the sake of simplicity, let's call this value "opacity".
while i < coord_records_count:
# bool: opacity
is_opaque = struct.unpack(BYTE_ORDER + 'b', f.read(1))[0]
print(is_opaque, end=' ')
i += 1
print()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment