Skip to content

Instantly share code, notes, and snippets.

@Xzonn
Last active February 14, 2022 03:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xzonn/aa4ffdfc89ea416108e8348f2506ad99 to your computer and use it in GitHub Desktop.
Save Xzonn/aa4ffdfc89ea416108e8348f2506ad99 to your computer and use it in GitHub Desktop.
btxt exporter for "Metroid Dread"
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import os
import re
import struct
import sys
def export_btxt(bin):
magic = bin[0x00 : 0x04]
assert magic == b'BTXT'
_, __ = struct.unpack("<2H", bin[0x04: 0x08])
assert _ == 1 and __ == 10
keys = []
values = []
pos = 0x08
while pos < len(bin):
key = ""
c = bin[pos]
while c:
key += chr(c)
pos += 1
c = bin[pos]
keys.append(key)
value = ""
pos += 1
c, = struct.unpack("<H", bin[pos : pos + 2])
while c:
value += chr(c)
pos += 2
c, = struct.unpack("<H", bin[pos : pos + 2])
pos += 2
values.append(value)
data = dict(zip(keys, values))
return data
def parse_path(path, root = ""):
path = path.replace("\\", "/")
root = root.replace("\\", "/")
if path.startswith(root):
path = path[len(root) : ]
path = re.sub(r"^(\.*/)+", "", path)
return path
if __name__ == "__main__":
args = sys.argv
if len(args) > 1:
root = args[1]
else:
root = "./"
if len(args) > 2:
export = args[2]
else:
export = "../export.txt"
ext = ".txt"
w = os.walk(root)
g = open(export, "w", -1, "utf-8")
for root, dirs, files in w:
for file in files:
if file.endswith(ext):
path = os.path.join(root, file)
with open(path, "rb") as f:
txts = export_btxt(f.read())
g.write(f"{parse_path(path, root)}\n")
for k, v in txts.items():
v = v.replace("\\", "\\\\").replace("\t", "\\t").replace("\n", "\\n")
g.write(f"{k}\t{v}\n")
g.flush()
g.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment