fortunes_foundation/seed_compressor/parse_cart.py

103 lines
2.9 KiB
Python

SECTIONS = ("PREHEADER", "__lua__", "__gfx__", "__gff__", "__label__", "__map__", "__sfx__", "__music__")
class Pico8Cart(object):
def __init__(self, sections):
self._sections = sections
@classmethod
def load(cls, fname):
sections = {}
with open(fname, "rt") as f:
section_name = "PREHEADER"
section_text = []
def add_section():
sections[section_name] = "\n".join(section_text)
section_text.clear()
for line in f:
line = line.rstrip("\r\n")
if line in SECTIONS:
add_section()
section_name = line
else:
section_text.append(line)
add_section()
return Pico8Cart(sections)
def touch(self, section, cb):
self._sections[section] = touch(section, self._sections.get(section), cb)
def save(self, fname):
with open(fname, "wt") as f:
for s in SECTIONS:
val = self._sections.get(s)
val = canonize(s, val)
if val:
if s != "PREHEADER":
f.write(f"{s}\n")
f.write(f"{val}\n")
def canonize(section, val):
return touch(section, val, lambda _: ())
def touch(section, val, cb):
if section in ("__gfx__", "__map__"):
if val is None:
val = ""
length = 0x2000 if section == "__gfx__" else 0x1000
row_width=128 if section=="__gfx__" else 256
msb_first = section == "__map__"
memory = from_binary(val, length, msb_first)
cb(memory)
return to_binary(memory, length, msb_first, row_width)
return val
def from_binary(pico_data: str, length: int, msb_first: bool):
hex_data = "".join(pico_data.split("\n"))
byte_values = []
for i in range(0,len(hex_data),2):
x0 = int(hex_data[i],16)
x1 = int(hex_data[i+1],16)
byte_values.append(
(x0 << 4) + x1
if msb_first else
(x1 << 4) + x0
)
assert(len(byte_values) <= length)
byte_values = (byte_values + [0] * length)[:length]
return bytearray(byte_values)
def to_binary(memory: bytearray, length: int, msb_first: bool, row_width: int):
assert(len(memory) == length)
HEX_CHARS = "0123456789abcdef"
chars = []
for i in range(length):
byte = memory[i]
msb = (byte & 0xf0) >> 4
lsb = byte & 0x0f
if msb_first:
chars.append(HEX_CHARS[msb])
chars.append(HEX_CHARS[lsb])
else:
chars.append(HEX_CHARS[lsb])
chars.append(HEX_CHARS[msb])
lines = []
for i in range(0, len(chars), row_width):
lines.append("".join(chars[i:i+row_width]))
zeroes = "0" * row_width
while lines and lines[-1] == zeroes:
lines.pop()
return "\n".join(lines)