-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a TDXT extractor and partial updater.
- Loading branch information
1 parent
379d746
commit 3a1ebf3
Showing
5 changed files
with
133 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#! /usr/bin/env python3 | ||
import argparse | ||
import io | ||
import json | ||
import math | ||
import os | ||
import os.path | ||
import sys | ||
import textwrap | ||
from PIL import Image, ImageDraw | ||
from typing import Any, Dict, List, Optional, Tuple, TypeVar | ||
|
||
from bemani.format import TDXT | ||
|
||
|
||
def extract_texture( | ||
fname: str, | ||
output_fname: Optional[str], | ||
) -> int: | ||
with open(fname, "rb") as bfp: | ||
tdxt = TDXT.fromBytes(bfp.read()) | ||
|
||
if output_fname is None: | ||
output_fname = os.path.splitext(os.path.abspath(fname))[0] + ".png" | ||
|
||
if not output_fname.lower().endswith(".png"): | ||
raise Exception("Invalid output file format!") | ||
|
||
# Actually place the files down. | ||
output_dir = os.path.dirname(os.path.abspath(output_fname)) | ||
os.makedirs(output_dir, exist_ok=True) | ||
|
||
print(f"Extracting texture from {os.path.abspath(fname)} to {os.path.abspath(output_fname)}") | ||
with open(output_fname, "wb") as bfp: | ||
tdxt.img.save(bfp, format="PNG") | ||
|
||
return 0 | ||
|
||
|
||
def update_texture( | ||
fname: str, | ||
input_fname: str, | ||
) -> int: | ||
with open(fname, "rb") as bfp: | ||
tdxt = TDXT.fromBytes(bfp.read()) | ||
|
||
if not input_fname.lower().endswith(".png"): | ||
raise Exception("Invalid output file format!") | ||
|
||
with open(input_fname, "rb") as bfp: | ||
img = Image.open(io.BytesIO(bfp.read())) | ||
|
||
tdxt.img = img | ||
|
||
print(f"Updating texture in {os.path.abspath(fname)} from {os.path.abspath(input_fname)}") | ||
with open(fname, "wb") as bfp: | ||
bfp.write(tdxt.toBytes()) | ||
|
||
return 0 | ||
|
||
|
||
def main() -> int: | ||
parser = argparse.ArgumentParser( | ||
description="Konami TDXT graphic file unpacker/repacker." | ||
) | ||
subparsers = parser.add_subparsers(help="Action to take", dest="action") | ||
|
||
unpack_parser = subparsers.add_parser( | ||
"unpack", | ||
help="Unpack texture data into a PNG file.", | ||
) | ||
unpack_parser.add_argument( | ||
"infile", | ||
metavar="INFILE", | ||
help="The TDXT container to unpack the texture from.", | ||
) | ||
unpack_parser.add_argument( | ||
"outfile", | ||
metavar="OUTFILE", | ||
nargs="?", | ||
default=None, | ||
help="The PNG file to unpack the texture to.", | ||
) | ||
|
||
update_parser = subparsers.add_parser( | ||
"update", | ||
help="Update texture data from a PNG file.", | ||
) | ||
update_parser.add_argument( | ||
"outfile", | ||
metavar="OUTFILE", | ||
help="The TDXT container to update the texture to, must already exist.", | ||
) | ||
update_parser.add_argument( | ||
"infile", | ||
metavar="INFILE", | ||
help="The PNG file to update the texture from.", | ||
) | ||
|
||
args = parser.parse_args() | ||
|
||
if args.action == "unpack": | ||
return extract_texture( | ||
args.infile, | ||
args.outfile, | ||
) | ||
elif args.action == "update": | ||
return update_texture( | ||
args.outfile, | ||
args.infile, | ||
) | ||
else: | ||
raise Exception(f"Invalid action {args.action}!") | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#! /usr/bin/env python3 | ||
if __name__ == "__main__": | ||
import os | ||
path = os.path.abspath(os.path.dirname(__file__)) | ||
name = os.path.basename(__file__) | ||
|
||
import sys | ||
sys.path.append(path) | ||
os.environ["SQLALCHEMY_SILENCE_UBER_WARNING"] = "1" | ||
|
||
import runpy | ||
runpy.run_module(f"bemani.utils.{name}", run_name="__main__") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ declare -a arr=( | |
"scheduler" | ||
"services" | ||
"struct" | ||
"tdxtutils" | ||
"trafficgen" | ||
"twodxutils" | ||
) | ||
|