mirror of
https://gist.github.com/62c524587539f11b49316929264a530a.git
synced 2025-06-18 14:55:39 -04:00
102 lines
3.4 KiB
Python
102 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
|
|
# Requirements:
|
|
# pip3 install libscrc
|
|
|
|
"""
|
|
title copier © 2022 Pk11
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the “Software”), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
"""
|
|
|
|
import argparse
|
|
import struct
|
|
|
|
from libscrc import modbus
|
|
|
|
parser = argparse.ArgumentParser(description="Copies a title into any blank titles in a DS ROM")
|
|
parser.add_argument("input", metavar="in.nds", type=str, help="input ROM")
|
|
parser.add_argument("output", metavar="out.nds", type=str, help="output ROM")
|
|
parser.add_argument("-l", "--language", metavar="1", default=1, type=int, help="language (0-7)")
|
|
# 0=Japanese, 1=English, 2=French, 3=German, 4=Italian, 5=Spanish, 6=Chinese, 7=Korean
|
|
|
|
args = parser.parse_args()
|
|
|
|
languages = ("Japanese", "English", "French", "German", "Italian", "Spanish", "Chinese", "Korean")
|
|
|
|
if args.input == args.output:
|
|
print("Please use a different output path")
|
|
exit()
|
|
|
|
with open(args.output, "wb+") as out:
|
|
print("Copying file...")
|
|
with open(args.input, "rb") as rom:
|
|
out.write(rom.read())
|
|
|
|
# Get banner
|
|
out.seek(0x68)
|
|
bannerAddr = struct.unpack("<I", out.read(4))[0]
|
|
out.seek(bannerAddr)
|
|
bannerVer = struct.unpack("<H", out.read(2))[0]
|
|
print("Banner version: 0x%04X" % bannerVer)
|
|
|
|
# Check that language is supported
|
|
if(args.language < 0 or args.language > 5 + ((bannerVer & 3) - 1)):
|
|
print("Error: Invalid language")
|
|
exit()
|
|
|
|
# Copy title to any blank ones
|
|
out.seek(bannerAddr)
|
|
bannerData = out.read(0x23C0 if (bannerVer & 0x100) else (0x840 + ((bannerVer & 3) - 1) * 0x100))
|
|
title = bannerData[0x240 + (args.language * 0x100):0x340 + (args.language * 0x100)]
|
|
for i in range(6 + ((bannerVer & 3) - 1)):
|
|
if bannerData[0x240 + (i * 0x100)] in (0x00, 0x0A):
|
|
print("Copying %s title to %s..." % (languages[args.language], languages[i]))
|
|
out.seek(bannerAddr + 0x240 + (i * 0x100))
|
|
out.write(title)
|
|
|
|
# Update CRCs
|
|
out.seek(bannerAddr)
|
|
bannerData = out.read(0x23C0 if (bannerVer & 0x100) else (0x840 + ((bannerVer & 3) - 1) * 0x100))
|
|
print("Updating CRCs...")
|
|
out.seek(bannerAddr + 2)
|
|
|
|
# Base banner
|
|
crc = modbus(bannerData[0x20:0x840])
|
|
print("0x%04X" % crc)
|
|
out.write(struct.pack("<H", crc))
|
|
|
|
# Chinese
|
|
if((bannerVer & 3) >= 2):
|
|
crc = modbus(bannerData[0x20:0x940])
|
|
print("0x%04X" % crc)
|
|
out.write(struct.pack("<H", crc))
|
|
|
|
# Korean
|
|
if((bannerVer & 3) >= 3):
|
|
crc = modbus(bannerData[0x20:0xA40])
|
|
print("0x%04X" % crc)
|
|
out.write(struct.pack("<H", crc))
|
|
|
|
# DSi
|
|
if(bannerVer & 0x100):
|
|
crc = modbus(bannerData[0x1240:])
|
|
print("0x%04X" % crc)
|
|
out.write(struct.pack("<H", crc))
|