diff --git a/.github/workflows/building.yml b/.github/workflows/building.yml index 20e150c..8167204 100644 --- a/.github/workflows/building.yml +++ b/.github/workflows/building.yml @@ -30,7 +30,7 @@ jobs: - name: Install tools run: | sudo apt-get update - sudo apt-get install p7zip-full python -y + sudo apt-get install p7zip-full -y - name: Build & Package GodMode9i id: build run: | diff --git a/Makefile b/Makefile index 97a4dc1..814700e 100644 --- a/Makefile +++ b/Makefile @@ -24,14 +24,12 @@ dsi: $(TARGET).dsi $(TARGET).nds: arm7/$(TARGET).elf arm9/$(TARGET).elf ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf -d $(NITRODATA) \ -b icon.bmp "GodMode9i;Rocket Robz" \ - -z 80040000 -u 00030004 - python fix_ndsheader.py $(CURDIR)/$(TARGET).nds + -z 80040000 $(TARGET).dsi: arm7/$(TARGET).elf arm9/$(TARGET).elf ndstool -c $(TARGET).dsi -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf -d $(NITRODATA) \ -b icon.bmp "GodMode9i;Rocket Robz" \ -g HGMA 00 "GODMODE9I" -z 80040000 -u 00030004 - python fix_ndsheader.py $(CURDIR)/$(TARGET).dsi #--------------------------------------------------------------------------------- arm7/$(TARGET).elf: diff --git a/fix_ndsheader.py b/fix_ndsheader.py deleted file mode 100644 index 1676adc..0000000 --- a/fix_ndsheader.py +++ /dev/null @@ -1,505 +0,0 @@ -# -*- coding: utf8 -*- -# Patch an .nds (works with homebrew and ds demo only) to make it ready for make_cia -# -# 2016-02-28, Ahezard -# -# inspired by -# Apache Thunder .nds edited files and comments -# https://github.com/Relys/Project_CTR/blob/master/makerom/srl.h -# https://dsibrew.org/wiki/DSi_Cartridge_Header -# if the header size of the input nds file is 0x200 (homebrew) -# the header size of the output nds file will be patched to 0x4000 (normal ds/dsi header), 0x3E00 offset - -from struct import * -from collections import namedtuple -from collections import OrderedDict -from pprint import pprint -import os, sys -import binascii -import argparse - - -parser = argparse.ArgumentParser(description='Patch an nds in order to be ready cia conversion via make_cia --srl=.') -parser.add_argument('file', metavar='file.nds', help='nds file to patch') -parser.add_argument('--verbose', help='verbose mode', action="store_true") -parser.add_argument('--out', help='output file [optionnal]') -parser.add_argument('--read', help='print only the header content, do not patch', action="store_true") -parser.add_argument('--extract', help='extract the content of the rom : header.bin,arm9.bin,arm7.bin,icon.bin,arm9i.bin,arm7i.bin, do not patch', action="store_true") #Not yet implemented -parser.add_argument('--title', help='Game title') -parser.add_argument('--code', help='Game code') -parser.add_argument('--maker', help='Maker code') -parser.add_argument('--mode', help='target mode, default mode is ds [ds|dsi|dsinogba|nitrohax]') -parser.add_argument('--arm9', help='swap the ds arm9 binary by the one provided') -parser.add_argument('--arm7', help='swap the ds arm7 binary by the one provided') -parser.add_argument('--arm9EntryAddress', help='arm9 ram address of the binary provided') -parser.add_argument('--arm7EntryAddress', help='arm7 ram address of the binary provided') -parser.add_argument('--arm9i', help='add a dsi arm9i binary to the file, not needed for homebrew so far') -parser.add_argument('--arm7i', help='add a dsi arm7i binary to the file, not needed for homebrew so far') -parser.add_argument('--accessControl', help='access control field') -args = parser.parse_args() - -if args.mode is None: - args.mode = "dsi" - - -def getBytes(e): - if (sys.version_info.major == 2): - return bytes(e) - else: - try: - return e.encode('ascii') - except: - print("ERROR: {}".format(e)) -# -# CRC16 MODULE -# -# includes CRC16 and CRC16 MODBUS -# - -from ctypes import c_ushort - -# from https://github.com/cristianav/PyCRC/blob/master/demo.py -class CRC16(object): - crc16_tab = [] - - # The CRC's are computed using polynomials. Here is the most used - # coefficient for CRC16 - crc16_constant = 0xA001 # 40961 - - def __init__(self, modbus_flag=False): - # initialize the precalculated tables - if not len(self.crc16_tab): - self.init_crc16() - self.mdflag = bool(modbus_flag) - - def calculate(self, input_data=None): - try: - is_string = isinstance(input_data, str) - is_bytes = isinstance(input_data, (bytes, bytearray)) - - if not is_string and not is_bytes: - raise Exception("Please provide a string or a byte sequence " - "as argument for calculation.") - - crc_value = 0x0000 if not self.mdflag else 0xffff - - for c in input_data: - d = ord(c) if is_string else c - tmp = crc_value ^ d - rotated = crc_value >> 8 - crc_value = rotated ^ self.crc16_tab[(tmp & 0x00ff)] - - return crc_value - except Exception as e: - print("EXCEPTION(calculate): {}".format(e)) - - def init_crc16(self): - """The algorithm uses tables with precalculated values""" - for i in range(0, 256): - crc = c_ushort(i).value - for j in range(0, 8): - if crc & 0x0001: - crc = c_ushort(crc >> 1).value ^ self.crc16_constant - else: - crc = c_ushort(crc >> 1).value - self.crc16_tab.append(crc) - -def getSize(fileobject): - current = fileobject.tell() - fileobject.seek(0,2) # move the cursor to the end of the file - size = fileobject.tell() - fileobject.seek(current,0) - return size - -def skipUntilAddress(f_in,f_out, caddr, taddr): - chunk = f_in.read(taddr-caddr) - f_out.write(chunk) - -def writeBlankuntilAddress(f_out, caddr, taddr): - f_out.write(b"\x00"*(taddr-caddr)) - -fname=args.file - -if not args.read: - print("Patching file : "+fname) -else: - print("Reading header of file : "+fname) - -#offset of 0x4600 created - -# File size compute -file = open(fname, 'rb') -fsize=getSize(file) -file.close() - -#CRC header compute "CRC-16 (Modbus)" -file = open(fname, 'rb') -#0x15E from https://github.com/devkitPro/ndstool/ ... source/header.cpp -hdr = file.read(0x15E) -hdrCrc=CRC16(modbus_flag=True).calculate(hdr) -if args.verbose: - print("{:10s} {:20X}".format('HDR CRC-16 ModBus', hdrCrc)) -#print "origin header cr c"+hdr[0x15E:0x15F] -#filew = open(fname+".hdr", "wb") -#filew.write(hdr); -#filew.close() -file.close() - -if args.arm9 is not None: - arm9Fname=args.arm9 - arm9File = open(arm9Fname, 'rb') - arm9FileSize=getSize(arm9File) - dataArm9=arm9File.read(arm9FileSize) - arm9File.close() - -if args.arm7 is not None: - arm7Fname=args.arm7 - arm7File = open(arm7Fname, 'rb') - arm7FileSize=getSize(arm7File) - dataArm7=arm7File.read(arm7FileSize) - arm7File.close() - -filer = open(fname, 'rb') -data = filer.read(0x180) -caddr=0x180 - -#DS Data 180 bytes -SrlHeader = namedtuple('SrlHeader', - "gameTitle " - "gameCode " - "makerCode " - "unitCode " - "encryptionSeedSelect " - "deviceCapacity " - "reserved0 " - "dsiflags " - "romVersion " - "internalFlag " - "arm9RomOffset " - "arm9EntryAddress " - "arm9RamAddress " - "arm9Size " - "arm7RomOffset " - "arm7EntryAddress " - "arm7RamAddress " - "arm7Size " - "fntOffset " - "fntSize " - "fatOffset " - "fatSize " - "arm9OverlayOffset " - "arm9OverlaySize " - "arm7OverlayOffset " - "arm7OverlaySize " - "normalCardControlRegSettings " - "secureCardControlRegSettings " - "icon_bannerOffset " - "secureAreaCrc " - "secure_transfer_timeout " - "arm9Autoload " - "arm7Autoload " - "secureDisable " - "ntrRomSize " - "headerSize " - "reserved1 " - "nintendoLogo " - "nintendoLogoCrc " - "headerCrc " - "debugReserved ") -srlHeaderFormat='<12s4s2scbb7s2sbcIIIIIIIIIIIIIIIIIIIHHII8sII56s156s2sH32s' -srlHeader=SrlHeader._make(unpack_from(srlHeaderFormat, data)) -if args.verbose: - print("origin header crc "+hex(srlHeader.headerCrc)) - print("origin secure crc "+hex(srlHeader.secureAreaCrc)) - -#SecureArea CRC compute "CRC-16 (Modbus)" -file = open(fname, 'rb') -#0x15E from https://github.com/devkitPro/ndstool/ ... source/header.cpp -file.read(0x200) -sec = file.read(0x4000) -secCrc=CRC16(modbus_flag=True).calculate(sec) -if args.verbose: - print("{:10s} {:20X}".format('SEC CRC-16 ModBus', secCrc)) -file.close() - -if srlHeader.arm7EntryAddress>0x2400000 and not args.read and args.arm7 is None: - print("WARNING: .nds arm7EntryAddress greater than 0x2400000 will not boot as cia") - print("you need to recompile or swap the arm7 binary with a precompiled one with --arm7 and --arm7EntryAddress") - -if "dsi" in args.mode : - srlHeaderPatched=srlHeader._replace( - dsiflags= '\x01\x00', #disable modcrypt but enable twl - unitCode= '\x02', - ) - -srlHeaderPatchedNoStrings = [] -for e in list(srlHeaderPatched._asdict().values()): - if (isinstance(e, str)): - srlHeaderPatchedNoStrings.append(getBytes(e)) - else: - srlHeaderPatchedNoStrings.append(e) - -data1=pack(*[srlHeaderFormat]+srlHeaderPatchedNoStrings) -newHdrCrc=CRC16(modbus_flag=True).calculate(data1[0:0x15E]) -srlHeaderPatched=srlHeaderPatched._replace(headerCrc=newHdrCrc) - -if args.verbose: - print("new header crc "+hex(newHdrCrc)) -if not args.read : - if args.verbose: - pprint(dict(srlHeaderPatched._asdict())) -else: - pprint(dict(srlHeader._asdict())) - -srlHeaderPatchedNoStrings = [] -for e in list(srlHeaderPatched._asdict().values()): - if (isinstance(e, str)): - srlHeaderPatchedNoStrings.append(getBytes(e)) - else: - srlHeaderPatchedNoStrings.append(e) - -data1=pack(*[srlHeaderFormat]+srlHeaderPatchedNoStrings) - -arm9isize=0 -arm7isize=0 - -#TWL Only Data 384 bytes -SrlTwlExtHeader = namedtuple('SrlTwlExtHeader', - "MBK_1_5_Settings " - "MBK_6_8_Settings_ARM9 " - "MBK_6_8_Settings_ARM7 " - "global_MBK_9_Setting " - "regionFlags " - "accessControl " - "arm7ScfgExtMask " - "reserved_flags " - "arm9iRomOffset " - "reserved2 " - "arm9iLoadAddress " - "arm9iSize " - "arm7iRomOffset " - "struct_param_baseAddress " - "arm7iLoadAddress " - "arm7iSize " - "digest_ntrRegionOffset " - "digest_ntrRegionSize " - "digest_twlRegionOffset " - "digest_twlRegionSize " - "digestSectorHashtableOffset " - "digestSectorHashtableSize " - "digest_blockHashtableOffset " - "digest_blockHashtableSize " - "digestSectorSize " - "digest_blockSectorcount " - "iconSize " #usually 0x23C0 or 2112 in homebrew - "unknown1 " - "twlRomSize " - "unknown2 " - "modcryptArea1Offset " - "modcryptArea1Size " - "modcryptArea2Offset " - "modcryptArea2Size " - "title_id " - "pubSaveDataSize " - "privSaveDataSize " - "reserved4 " - "parentalControl ") -srlTwlExtHeaderFormat="<20s12s12s4s4sIIII4sIIIIIIIIIIIIIIIII4sI12sIIII8sII176s16s" -if srlHeader.headerSize<0x300: - #homebrew - srlTwlExtHeader=SrlTwlExtHeader._make(unpack_from(srlTwlExtHeaderFormat, "\x00" * (0x300-0x180))) -else: - data = filer.read(0x300-0x180) - srlTwlExtHeader=SrlTwlExtHeader._make(unpack_from(srlTwlExtHeaderFormat, data)) - caddr=0x300 - -#pprint(dict(srlTwlExtHeader._asdict())) - -if not args.read: - # Fix srlTwlExtHeader - if "dsi" in args.mode: - arm7iRomOffset=srlHeaderPatched.arm7RomOffset - arm9iRomOffset=srlHeaderPatched.arm9RomOffset - arm7isize=srlHeaderPatched.arm7Size - arm9isize=srlHeaderPatched.arm9Size - totaldsisize=0 - arm7iname = None - arm9iname = None - - if args.arm9i is not None: - arm9iname = args.arm9i - tmp = open(arm9iname, "rb") - arm9isize = getSize(args.arm9i) - arm9iRomOffset=srlHeaderPatched.ntrRomSize - if args.verbose: - print("arm9isize : "+hex(arm9isize)) - print("arm9ioffset : "+hex(srlHeaderPatched.ntrRomSize)) - tmp.close() - totaldsisize=arm9isize - - if args.arm7i is not None: - arm7iname = args.arm7i - tmp = open(arm7iname, "rb") - arm7isize = getSize(args.arm7i) - arm7iRomOffset=srlHeaderPatched.ntrRomSize+arm9isize - if args.verbose: - print("arm7isize : "+hex(arm7isize)) - print("arm9ioffset : "+hex(srlHeaderPatched.ntrRomSize+arm9isize)) - tmp.close() - totaldsisize=arm9isize+arm7isize - - - - srlTwlExtHeader=srlTwlExtHeader._replace( - accessControl= 0x00000138, - arm7ScfgExtMask= 0x80040000, - reserved_flags= 0x01000000 - ) - - if args.accessControl is not None: - srlTwlExtHeader=srlTwlExtHeader._replace( - accessControl= int(args.accessControl,0), - ) - -if args.verbose or args.read: - pprint(dict(srlTwlExtHeader._asdict())) - -srlTwlExtHeaderNoStrings = [] -for e in list(srlTwlExtHeader._asdict().values()): - if (isinstance(e, str)): - srlTwlExtHeaderNoStrings.append(getBytes(e)) - else: - srlTwlExtHeaderNoStrings.append(e) - -data2=pack(*[srlTwlExtHeaderFormat]+srlTwlExtHeaderNoStrings) - -#TWL and Signed NTR 3328 bytes -SrlSignedHeader = namedtuple('SrlSignedHeader', - "arm9WithSecAreaSha1Hmac " - "arm7Sha1Hmac " - "digestMasterSha1Hmac " - "bannerSha1Hmac " - "arm9iSha1Hmac " - "arm7iSha1Hmac " - "reserved5 " - "arm9Sha1Hmac " - "reserved6 " - "reserved7 " - "signature " - ) -srlSignedHeaderFormat="<20s20s20s20s20s20s40s20s2636s384s128s" -if srlHeader.headerSize<0x1100: - #homebrew - srlSignedHeader=SrlSignedHeader._make(unpack_from(srlSignedHeaderFormat, "\x00" * (3328))) -else: - data = filer.read(3328) - srlSignedHeader=SrlSignedHeader._make(unpack_from(srlSignedHeaderFormat, data)) - caddr=0x300+3328 - filer.read(0x4000-caddr) - caddr=0x4000 - -#pprint(dict(srlSignedHeader._asdict())) - -# Fix srlSignedHeader -if not args.read: - srlSignedHeader=srlSignedHeader._replace( - arm7Sha1Hmac= b'\xff'*20, - arm9WithSecAreaSha1Hmac= b'\xff'*20, - bannerSha1Hmac= b'\xff'*20, - signature= b'\xff'*128 - ) - if "dsi" in args.mode : - srlSignedHeader=srlSignedHeader._replace( - arm7Sha1Hmac= b'\xff'*20, - arm7iSha1Hmac= b'\xff'*20, - arm9Sha1Hmac= b'\xff'*20, - arm9WithSecAreaSha1Hmac= b'\xff'*20, - arm9iSha1Hmac= b'\xff'*20, - bannerSha1Hmac= b'\xff'*20, - digestMasterSha1Hmac= b'\xff'*20, - signature= b'\xff'*128 - ) -if args.verbose or args.read: - pprint(dict(srlSignedHeader._asdict())) - -srlSignedHeaderNoStrings = [] -for e in list(srlSignedHeader._asdict().values()): - if (isinstance(e, str)): - srlSignedHeaderNoStrings.append(getBytes(e)) - else: - srlSignedHeaderNoStrings.append(e) - -data3=pack(*[srlSignedHeaderFormat]+srlSignedHeaderNoStrings) - -# ARM9 footer -# from https://github.com/devkitPro/ndstool/ ... source/header.cpp -# ARM9 footer size = 3*4 -ARM9Footer = namedtuple('ARM9Footer', - "nitrocode " #0xDEC00621 - "versionInfo " - "reserved " - ) -ARM9FooterFormat="