Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

yaml-ify map metadata & iQue pm_map #1145

Merged
merged 4 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion tools/build/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ def write_ninja_rules(
ninja.rule(
"pack_title_data",
description="pack_title_data $out",
command=f"$python {BUILD_TOOLS}/mapfs/pack_title_data.py $out $in",
command=f"$python {BUILD_TOOLS}/mapfs/pack_title_data.py $version $out $in",
)

ninja.rule("map_header", command=f"$python {BUILD_TOOLS}/mapfs/map_header.py $in > $out")
Expand Down Expand Up @@ -944,6 +944,9 @@ def build(
"img_flags": "",
},
)
elif path.suffixes[-2:] == [".raw", ".dat"]:
compress = False
bin_path = path
elif name == "title_data":
compress = True

Expand Down
32 changes: 26 additions & 6 deletions tools/build/mapfs/combine.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ def get_version_date(version):
return "Map Ver.00/07/05 19:13"
elif version == "pal":
return "Map Ver.01/03/23 16:30"
elif version == "ique":
return "Map Ver.04/05/18 13:41"
else:
return "Map Ver.??/??/?? ??:??"


def build_mapfs(out_bin, assets, version):
def build_mapfs(out_bin, assets, version, pre_write_assets):
# 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.
Expand All @@ -41,6 +43,9 @@ def build_mapfs(out_bin, assets, version):
decompressed_size = decompressed.stat().st_size
size = next_multiple(compressed.stat().st_size, 2) if compressed.exists() else decompressed_size

if version == "ique" and decompressed.stem == "title_data":
size = compressed.stat().st_size

# print(f"{name} {offset:08X} {size:08X} {decompressed_size:08X}")

# write all previously-written names; required to match
Expand All @@ -52,10 +57,18 @@ def build_mapfs(out_bin, assets, version):
f.seek(toc_entry_pos + 0x10)
f.write(struct.pack(">III", offset, size, decompressed_size))

# initial data to be overwritten back, provided by .raw.dat files
pre_write_bytes = b""
if pre_write_assets.get(decompressed.stem):
with open(pre_write_assets[decompressed.stem], "rb") as pwf:
pre_write_bytes = pwf.read()
f.seek(0x20 + next_data_pos)
f.write(pre_write_bytes)

# write data.
f.seek(0x20 + next_data_pos)
f.write(compressed.read_bytes() if compressed.exists() else decompressed.read_bytes())
next_data_pos += size
next_data_pos += max(len(pre_write_bytes), size)

asset_idx += 1

Expand All @@ -77,9 +90,16 @@ def build_mapfs(out_bin, assets, version):
out = argv.pop(0)

assets = []
pre_write_assets = {}

for path in argv:
path = Path(path)
if path.suffixes[-2:] == [".raw", ".dat"]:
pre_write_assets[path.with_suffix("").stem] = path
else:
assets.append(path)

# pairs
for i in range(0, len(argv), 2):
assets.append((Path(argv[i]), Path(argv[i + 1])))
# turn them into pairs
assets = list(zip(assets[::2], assets[1::2]))

build_mapfs(out, assets, version)
build_mapfs(out, assets, version, pre_write_assets)
62 changes: 24 additions & 38 deletions tools/build/mapfs/pack_title_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,37 @@

if __name__ == "__main__":
argv.pop(0) # python3

if len(argv) > 4:
out, img1, img2, img3, img2_pal = argv
version = argv.pop(0)
out = argv.pop(0)
imgs = argv

imgs_bytes = []
for img in imgs:
with open(img, "rb") as f:
imgs_bytes.append(f.read())

if version == "jp":
# copyright, copyright pal, press start, logo
write_order = (1, 3, 2, 0)
elif version == "ique":
# press start, copyright, logo
write_order = (2, 1, 0)
else:
out, img1, img2, img3 = argv
img2_pal = None

with open(img1, "rb") as f:
img1 = f.read()

with open(img2, "rb") as f:
img2 = f.read()

with open(img3, "rb") as f:
img3 = f.read()

if img2_pal:
with open(img2_pal, "rb") as f:
img2_pal = f.read()
# copyright, press start, logo
write_order = (1, 2, 0)

with open(out, "wb") as f:
f.seek(0x10)

pos2 = f.tell()
f.write(img2)

if img2_pal:
pos2_pal = f.tell()
f.write(img2_pal)
else:
pos2_pal = None

pos3 = f.tell()
f.write(img3)

pos1 = f.tell()
f.write(img1)
imgs_pos = [0] * len(imgs)
for i in write_order:
imgs_pos[i] = f.tell()
f.write(imgs_bytes[i])

if img2_pal:
if version == "jp":
# jp padding?
f.write(b"\x00" * 0x10)

f.seek(0)
f.write(pos1.to_bytes(4, byteorder="big"))
f.write(pos2.to_bytes(4, byteorder="big"))
f.write(pos3.to_bytes(4, byteorder="big"))
if pos2_pal:
f.write(pos2_pal.to_bytes(4, byteorder="big"))
for pos in imgs_pos:
f.write(pos.to_bytes(4, byteorder="big"))
Loading
Loading