haroohie-club / NitroPacker

A utility for (un)packing NDS ROMs as well as patching their ARM9 and overlays
GNU General Public License v3.0
15 stars 2 forks source link

NitroPacker

NitroPacker is an open source, cross-platform utility for packing and unpacking Nintendo DS ROMs. It also can apply ASM hacks to both ARM9 and overlay files.

Authors

This code was written primarily by Ermelber and Gericom. Jonko has ported it to .NET 8.0 and made modifications to make it cross-platform.

Prerequisites

Packing and Unpacking

The primary purpose of NitroPacker is to pack and unpack NDS ROMs.

Unpacking

To unpack a ROM with NitroPacker, run the following command:

NitroPacker unpack -r PATH/TO/ROM.nds -o PATH/TO/UNPACK/DIRECTORY -p PROJECT_NAME

Replace the capitalized arguments with:

This command will unpack all the game's files and place them in the specified directory. The ROM's file system will go in the data subdirectory, while any overlays present will be placed in the overlay subdirectory. The main ARM9 and ARM7 binaries will be placed in the root directory. Additionally, the created project file contains a bunch of metadata about the ROM, such as the ROM header, the overlay table, and the banner.

In order to disassemble or patch arm9.bin, you'll need it to be decompressed. If the arm9 binary is compressed, you can append the -d flag to the above command to decompress it, e.g.

NitroPacker unpack -r PATH/TO/ROM.nds -o PATH/TO/UNPACK/DIRECTORY -p PROJECT_NAME -d

Packing

NitroPacker can only pack a directory that was previously unpacked with NitroPacker (or something structured exactly like that). To pack a ROM, run the following command:

NitroPacker pack -p PATH/TO/PROJECT_FILE.xml -r PATH/TO/OUTPUT_ROM.nds

The project file is expected to be in a directory with ARM9 and ARM7 binaries as well as the data and overlay subdirectories mentioned previously. If the ARM9 binary was decompressed previously, you will need to add -c in order to compress it at this stage.

ASM Hacks

NitroPacker can also be used as a powerful tool to apply assembly hacks, but this functionality is a bit more complicated.

Install Prerequisites

As mentioned above, NitroPacker relies on other programs to help with the assembling your hacks, namely, devkitARM and Make. DevkitARM is distributed by devkitPro and can be downloaded from their website. They have a graphical installer for Windows (for which you need only select the NDS workloads) and a package manager for Mac/Linux (for which you can run the command dkp-pacman -S nds-dev to install devkitARM).

On Linux distros, Make can be installed from the package manager (e.g. sudo apt install make). On macOS, you can use brew. On Windows, the easiest way to install it is with Chocolatey, where the command is choco install make.

If either of these options presents a challenge for you or doesn't work for some reason, you can instead opt to use the alternate method of assembling the code in Docker containers. After installing Docker Desktop or the Docker engine, ensure the engine is running. Then, when calling NitroPacker, ensure you pass -d followed by the Docker tag you want to use. If you're not sure which one to use, we recommend trying 20230526 as that is the most recent tag as of this publishing (when the samples were last updated). If you want to use newer features or need later bugfixes, choose latest or a later tag. See devkitpro/devkitarm on DockerHub for more details.

Directory Structure

You will need to move the unpacked arm9.bin to a different directory with a specific structure:

This directory structure should be copied from the asm_sample directory in this repo. A fully fleshed-out example can be found in the ChokuretsuTranslationBuild repository.

Additionally, prior to assembling the ARM9, you will need to find the arena lo offset. This value can be found by searching for 0x37F8000 in the ROM. IDA or Ghidra should be used to search for this value. Once you find it, you'll want to go back a few values until you see an offset that has a value between 0x20C0000 and 0x20F0000 – the offset (not the value) is the arena lo offset. It will most likely be followed by two subroutines that look like:

MOV             R0, R0,LSL#2
ADD             R0, R0, #0x2700000
ADD             R0, R0, #0xFF000
STR             R1, [R0,#0xDC4]
BX              LR

...

MOV             R0, R0,LSL#2
ADD             R0, R0, #0x2700000
ADD             R0, R0, #0xFF000
STR             R1, [R0,#0xDA0]
BX              LR

Finally, source files may have any valid ARM assembly. To hook into a function and create a branch link to your code, the following format should be used:

ahook_02061344:
   CODE_HERE
   bx lr

This method will replace the instruction at 0x02061344 with a BL to your code.

Once this directory has been constructed, source files have been created, the arena lo offset determined, and the ARM9 has been copied in, the following commands may be used:

Assemble ARM9

To assemble the hacked ARM9, run the following command:

NitroPacker patch-arm9 -i PATH/TO/SRC/DIRECTORY -o PATH/TO/OUTPUT/DIRECTORY -p PROJECT_FILE -a ARENA_LO_OFFSET [-d DOCKER_TAG]

The project file you need to supply is the one created by unpacking the ROM with NitroPacker. The project file is only needed for determining the ARM9's RAM address; if you would rather specify this address manually, you may use -r RAM_ADDRESS instead.

This will assemble the hacks and append them to arm9.bin, then copy the ARM9 to the output directory (which should be the directory you will then run the pack command on).

Note: To be able to use the patch-arm9 command, the arm9.bin must be decompressed. See the Unpacking section for more information on how to do this.

Assemble Overlays

To patch the overlays, run the following command:

NitroPacker patch-overlays -i PATH/TO/ORIGINAL/OVERLAY/DIRECTORY -o PATH/TO/PATCHED/OVERLAY/DIRECTORY -s PATH/TO/OVERLAY/SOURCE -r PATH/TO/PROJECT/FILE [-d DOCKER_TAG]