Tyulis / 3DSkit

A multi-purpose and pluggable program to extract and repack files found in 3DS (and some other Nintendo consoles) games
GNU General Public License v3.0
65 stars 11 forks source link
extract formats-decoding game-editing nintendo-hacking pack

3DSkit

3DSkit is a tool to extract and repack many files formats found on the NDS, DSi, 3DS, Wii U and Switch.

What does 3DSkit do?

3DSkit can:

Installation

Actually, some 3DSkit modules are based on libkit. This is a "virtual" module, which can be either c3DSkit, a C extension, or py3DSkit, its equivalent in pure Python. This means that you can use 3DSkit directly as is, without any setup: all 3DSkit modules can work without c3DSkit.

However, some formats are VERY, very slow to process in pure Python: for example, textures, fonts, audio... So if you can, build c3DSkit, that computes them much faster (sometimes 10000 times or more).

To install c3DSkit, just go into the c3DSkit directory and run python3 setup.py install. You need a working C compiler and the Python includes (that should be included in your python installation) When you update it, it may be required to remove the build/ directory. If you don't have the admin rights, try python3 setup.py install --user.

How to use

 usage: 3DSkit.py [-h] [-v] [-V] [-q] [-x | -p | -D | -C | -g PLUGIN] [-d]
    [-f FORMAT] [-l | -b] [-o OUT] [-c COMPRESSION]
    [--ckit | --pykit] [-O OPTIONS]
    [files [files ...]]

 Positional arguments:
 files                 Name of the file to convert or to pack into an archive

 Optional arguments:
 -h, --help            show this help message and exit
 -v, --verbose         Increases the verbosity of 3DSkit
 -V, --debug           Debugging mode, turns every 3DSkit error into Python
                       exceptions (only useful for debugging)
 -q, --quiet           Run without any terminal output
 -x, --extract         Extract files contained in the archive / decompress
                       the file if necessary and convert it to a readable
                       format. On a directory, recursively extracts all
                       contained files
 -p, --pack            Pack files into an archive, or convert it to a console
                       format
 -D, --decompress      Decompress the input files
 -C, --compress        Compress the input file
 -g PLUGIN, --plugin PLUGIN
                       Run a plugin
 -d, --dir             Use a directory to pack an archive. The root will be
                       the directory. Very recommended.
 -f FORMAT, --format FORMAT
                       Format to repack, or input format (to extract. See the
                       formats section of the help for more infos)
 -l, --little          Little endian (for 3DS / NDS files), default
 -b, --big             Big endian (for WiiU files)
 -o OUT, --out OUT     Output file name (only for repacking). If not given,
                       the output file name will be automatically determined
 -c COMPRESSION, --compression COMPRESSION
                       Output compression type
 --ckit                Force use of c3DSkit as libkit
 --pykit               Force use of py3DSkit as libkit
 -O OPTIONS, --options OPTIONS
                       Format-specific options, see below for details

Examples

Extract a DARC archive:

python3 3DSkit.py -x archive.darc

Recursively extract all the contents of a directory:

python3 3DSkit.py -x my-directory/

Extract a 3DS ROM (NCCH) without doing hash checks

python3 3DSkit.py -x -O dochecks=false my_ncch_partition.cxi

Convert a BFLIM image in verbose mode:

python3 3DSkit.py -xv myTexture.bflim

Convert into a BFLYT file with a custom output name:

python3 3DSkit.py -pf BFLYT -o myLayout.bflyt a-layout.tflyt

Pack a folder into a version 6 GARC archive in verbose mode

python3 3DSkit.py -pdvf GARC -O version=6 any-directory

Pack three files into an SARC file and compress it in LZ11

python3 3DSkit.py -pf SARC -c LZ11 file1 file2 file3

Pack a BFLIM texture for the WiiU (big endian):

python3 3DSkit.py -pbf BFLIM my_texture.png

Pack two BCSTM respectively with one and two tracks, the second with a loop.

python3 3DSkit.py -pf BCSTM -o oneTrackTest.bcstm track1.wav
python3 3DSkit.py -pf BCSTM -o twoTracksExample.bcstm -O loop=100000-2100000 track1.wav track2.wav

Compress a DARC file without any console output and with a specific output file name

python3 3DSkit.py -Cqc LZ11 -o archive_LZ.darc archive.darc

Decompress the previous DARC file

python3 3DSkit.py -D archive_LZ.darc

Format-specific options

Specify these options with the -O option. You can specify them with -O option1=value1 -O option2=value2 ...

Extraction options:

Packing options:

Supported formats

Info on the table:

Crosses:

Output: Output format of the unpacker. As explained previously, modules which use libkit may be very slow in pure Python and much faster if you have c3DSkit installed

Format X P R Extensions Output Uses libkit
ALYT x x .alyt files
BCGRP x .bcgrp files
BCSAR e .bcsar files
BCSTM x x .bcstm WAV Yes
BCWAR x .bcwar files
BCWAV x .bcwav WAV Yes
BFFNT p .bffnt PNG+JSON Yes
BFLAN p .bflan JSON
BFLIM x x .bflim PNG Yes
BFLYT x x .bflyt JSON
BNTX x p .bntx PNG+JSON Yes
CBMD e .bnr banner[.bin] files
DARC x e .arc .bcma (...) files
GARC x x .garc (none) files
GFA x .gfa files
mini x x .mini .bl .wd (none) files
MSBT x .msbt TX
NARC p .narc files
NCCH x .app .cxi .cfa sections
NDS x .nds files
SARC x x .sarc .arc .szs files

There is also:

Compressions:

Compression D C Extensions Uses libkit
LZ10 x x (none) .cmp .l *_LZ.bin .LZ
LZ11 x x (none) .cmp .l *_LZ.bin .LZ Yes
LZH8 x .cx
Yaz0 x .szs
ETC1 x Texture compression in BFLIM

Dependencies

To access all 3DSkit functionalities, you need:

Pillow is only needed for textures and images (BFLIM, BFFNT). If you don't have it, other modules will work as well.

Contributing

Before submitting an issue, take a look at the program's help (-H option), your problem may have an easy fix, or already explained there. Don't forget to check if the issue has already been reported, or fixed (check also in the closed issues tab). Check if you have the latest commit. After all that, if you've actually found a new issue, you should state: