Include ROM utilities from Grid SRAM dumper project.

This commit is contained in:
Jennifer Taylor 2021-06-27 17:21:40 +00:00
parent 9715e3b747
commit 2b5ddaee7b
3 changed files with 171 additions and 0 deletions

View File

@ -52,3 +52,9 @@ A patch with multiple offsets, and helpful author descriptions for each section:
# This part of the patch fixes sound playback issues.
256: 33 -> 44
```
## splitrom
Utility for combining/splitting/byteswapping ROM files. Run it like `./splitrom --help`
to see generic help and what commands are available, and like `./splitrom <command> --help`
for a specific command's help.

View File

@ -261,3 +261,38 @@ class BinaryDiff:
# Now, get the maximum byte we need to apply this patch.
return max([offset for offset, _, _ in differences]) + 1 if differences else 0
class ByteUtil:
@staticmethod
def byteswap(data: bytes) -> bytes:
even = [d for d in data[::2]]
odd = [d for d in data[1::2]]
chunks = [bytes([odd[i], even[i]]) for i in range(len(even))]
return b''.join(chunks)
@staticmethod
def wordswap(data: bytes) -> bytes:
one = [d for d in data[::4]]
two = [d for d in data[1::4]]
three = [d for d in data[2::4]]
four = [d for d in data[3::4]]
chunks = [
bytes([four[i], three[i], two[i], one[i]])
for i in range(len(one))
]
return b''.join(chunks)
@staticmethod
def combine16bithalves(upper: bytes, lower: bytes) -> bytes:
chunks = [
b''.join([upper[i:(i+2)], lower[i:(i+2)]])
for i in range(0, len(upper), 2)
]
return b''.join(chunks)
@staticmethod
def combine8bithalves(upper: bytes, lower: bytes) -> bytes:
chunks = [bytes([upper[i], lower[i]]) for i in range(len(upper))]
return b''.join(chunks)

130
splitrom Executable file
View File

@ -0,0 +1,130 @@
#! /usr/bin/env python3
import argparse
import os
import sys
from arcadeutils.binary import ByteUtil
def main() -> int:
parser = argparse.ArgumentParser("ROM manipulation utilities.")
subparsers = parser.add_subparsers(
dest="action",
help="Action to perform.",
)
byteswap = subparsers.add_parser(
"byteswap",
help="Swap every byte pair of a 16bit rom.",
)
byteswap.add_argument(
"old",
metavar="OLD",
type=str,
help="Old rom file to byteswap.",
)
byteswap.add_argument(
"new",
metavar="NEW",
type=str,
help="New rom file to write after byteswapping.",
)
wordswap = subparsers.add_parser(
"wordswap",
help="Swap every 32bit value in a 32bit rom.",
)
wordswap.add_argument(
"old",
metavar="OLD",
type=str,
help="Old rom file to wordswap.",
)
wordswap.add_argument(
"new",
metavar="NEW",
type=str,
help="New rom file to write after wordswapping.",
)
combine8 = subparsers.add_parser(
"combine8",
help="Combine two 8bit roms to one 16bit rom.",
)
combine8.add_argument(
"upper",
metavar="UPPER",
type=str,
help="Upper half of rom file.",
)
combine8.add_argument(
"lower",
metavar="LOWER",
type=str,
help="Lower half of rom file.",
)
combine8.add_argument(
"combined",
metavar="COMBINED",
type=str,
help="Combined output file.",
)
combine16 = subparsers.add_parser(
"combine16",
help="Combine two 16bit roms to one 32bit rom.",
)
combine16.add_argument(
"upper",
metavar="UPPER",
type=str,
help="Upper half of rom file.",
)
combine16.add_argument(
"lower",
metavar="LOWER",
type=str,
help="Lower half of rom file.",
)
combine16.add_argument(
"combined",
metavar="COMBINED",
type=str,
help="Combined output file.",
)
args = parser.parse_args()
if args.action == "combine8":
with open(args.upper, "rb") as fp:
upper = fp.read()
with open(args.lower, "rb") as fp:
lower = fp.read()
with open(args.combined, "wb") as fp:
fp.write(ByteUtil.combine8bithalves(upper, lower))
elif args.action == "combine16":
with open(args.upper, "rb") as fp:
upper = fp.read()
with open(args.lower, "rb") as fp:
lower = fp.read()
with open(args.combined, "wb") as fp:
fp.write(ByteUtil.combine16bithalves(upper, lower))
elif args.action == "byteswap":
with open(args.old, "rb") as fp:
old = fp.read()
with open(args.new, "wb") as fp:
fp.write(ByteUtil.byteswap(old))
elif args.action == "wordswap":
with open(args.old, "rb") as fp:
old = fp.read()
with open(args.new, "wb") as fp:
fp.write(ByteUtil.wordswap(old))
else:
print(f"Please specify a valid command!{os.linesep}", file=sys.stderr)
parser.print_help()
return 1
return 0
if __name__ == "__main__":
sys.exit(main())