mirror of
https://github.com/pmret/papermario.git
synced 2024-11-09 20:42:41 +01:00
8837fbdf65
* WIP work on sprites (sprite_stuff.py) * cleanup of various stuff * separate compiler installation into separate script * wipz * more * renames, bugfixes * more * very grood * cleanin * goods and services * oopth * oopth2 * Parse palette data from xml * more work * more wipperz * more * it working * git subrepo pull --force tools/splat subrepo: subdir: "tools/splat" merged: "e72a868f9f" upstream: origin: "https://github.com/ethteck/splat.git" branch: "master" commit: "e72a868f9f" git-subrepo: version: "0.4.5" origin: "https://github.com/ingydotnet/git-subrepo" commit: "aa416e4" * fix symbol_addrs for new splat * upd8s * Use generated header, other versions, fixes * fixes & formatting * wip fusing npc + player extraction & cleanup * remove npc_files * buildin * fix some bugs * Cleanup, yay0s separately * cleen * cleanup * Respect stack during build * jp spritz * dun * fix c files --------- Co-authored-by: pixel-stuck <mathmcclintic@gmail.com>
82 lines
2.6 KiB
Python
Executable File
82 lines
2.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
from sys import argv
|
|
from pathlib import Path
|
|
import struct
|
|
|
|
def next_multiple(pos, multiple):
|
|
return pos + pos % multiple
|
|
|
|
def get_version_date(version):
|
|
if version == "us":
|
|
return "Map Ver.00/11/07 15:36"
|
|
elif version == "jp":
|
|
return "Map Ver.00/07/05 19:13"
|
|
elif version == "pal":
|
|
return "Map Ver.01/03/23 16:30"
|
|
else:
|
|
return "Map Ver.??/??/?? ??:??"
|
|
|
|
def build_mapfs(out_bin, assets, version):
|
|
# every TOC entry's name field has data after the null terminator made up from all the previous name fields.
|
|
# we probably don't have to do this for the game to read the data properly (it doesn't read past the null terminator
|
|
# of `string`), but the original devs' equivalent of this script had this bug so we need to replicate it to match.
|
|
|
|
with open(out_bin, "wb") as f:
|
|
f.write(get_version_date(version).encode("ascii"))
|
|
|
|
next_data_pos = (len(assets) + 1) * 0x1C
|
|
|
|
asset_idx = 0
|
|
lastname = ""
|
|
for decompressed, compressed in assets:
|
|
toc_entry_pos = 0x20 + asset_idx * 0x1C
|
|
|
|
# data for TOC entry
|
|
name = decompressed.stem + "\0"
|
|
offset = next_data_pos
|
|
decompressed_size = decompressed.stat().st_size
|
|
size = next_multiple(compressed.stat().st_size, 2) if compressed.exists() else decompressed_size
|
|
|
|
#print(f"{name} {offset:08X} {size:08X} {decompressed_size:08X}")
|
|
|
|
# write all previously-written names; required to match
|
|
lastname = name + lastname[len(name):]
|
|
f.seek(toc_entry_pos)
|
|
f.write(lastname.encode('ascii'))
|
|
|
|
# write TOC entry.
|
|
f.seek(toc_entry_pos + 0x10)
|
|
f.write(struct.pack(">III", offset, size, decompressed_size))
|
|
|
|
# write data.
|
|
f.seek(0x20 + next_data_pos)
|
|
f.write(compressed.read_bytes() if compressed.exists() else decompressed.read_bytes())
|
|
next_data_pos += size
|
|
|
|
asset_idx += 1
|
|
|
|
# end_data
|
|
toc_entry_pos = 0x20 + asset_idx * 0x1C
|
|
|
|
last_name_entry = "end_data\0"
|
|
f.seek(toc_entry_pos)
|
|
lastname = last_name_entry + lastname[len(last_name_entry):]
|
|
f.write(lastname.encode('ascii'))
|
|
|
|
f.seek(toc_entry_pos + 0x18)
|
|
f.write((0x903F0000).to_bytes(4, byteorder="big")) # TODO: figure out purpose
|
|
|
|
if __name__ == "__main__":
|
|
argv.pop(0) # python3
|
|
version = argv.pop(0)
|
|
out = argv.pop(0)
|
|
|
|
assets = []
|
|
|
|
# pairs
|
|
for i in range(0, len(argv), 2):
|
|
assets.append((Path(argv[i]), Path(argv[i+1])))
|
|
|
|
build_mapfs(out, assets, version)
|