# fuse-3ds
fuse-3ds is the best and most efficient way to extract data for Nintendo 3DS games and NANDs. It works by presenting a virtual filesystem with the contents of your games, NAND, or SD card contents, and you can browse and copy out just the files that you need.

Windows, macOS, and Linux are supported.

<p align="center"><img src="https://github.com/ihaveamac/fuse-3ds/raw/master/resources/ciamount-mac.png" width="882"></p>

## Example uses
* Mount a NAND backup and browse CTRNAND, TWLNAND, and others, and write back to them without having to extract and decrypt them first.
* Browse decrypted SD card contents. Dump installed games and saves, or copy contents between two system's SD contents.
* Extract a game's files out of a CIA, CCI (".3ds"), NCCH, RomFS, raw CDN contents, just by mounting them and browsing its files. Or use the virtual decrypted file and start playing the game in [Citra](https://citra-emu.org) right away.

## Setup
The ARM9 bootROM is required. You can dump it using boot9strap, which can be set up by [3DS Hacks Guide](https://3ds.hacks.guide). It is checked in order of:
* `BOOT9_PATH` environment variable (if set)
* `%APPDATA%\3ds\boot9.bin` (Windows-specific)
* `~/Library/Application Support/3ds/boot9.bin` (macOS-specific)
* `~/.3ds/boot9.bin`
* `~/3ds/boot9.bin`

`boot9_prot.bin` can also be used in all of these locations.

"`~`" means the user's home directory. "`~/3ds`" would mean `/Users/username/3ds` on macOS and `C:\Users\username\3ds` on Windows.

CCI, CDN, CIA, and NCCH mounting will need [SeedDB](https://github.com/ihaveamac/3DS-rom-tools/wiki/SeedDB-list) for mounting NCCH containers.  
SeedDB is checked in order of:
* `SEEDDB_PATH` environment variable (if set)
* `%APPDATA%\3ds\seeddb.bin` (Windows-specific)
* `~/Library/Application Support/3ds/seeddb.bin` (macOS-specific)
* `~/.3ds/seeddb.bin`
* `~/3ds/seeddb.bin`

It can also be provided with the `--seeddb` argument.

Python 3.6.1+ and pycryptodomex are required. appJar is required for the GUI.
* fusepy is pre-included until the [main fusepy repository](https://github.com/fusepy/fusepy) has full Windows support.

### Windows
Windows 7 or later is required.

A standalone executable with a GUI is available for use. You can get a single executable for download from [GitHub](https://github.com/ihaveamac/fuse-3ds/releases) or the [GBAtemp Download Center](https://gbatemp.net/download/fuse-3ds.34706/) A window will appear allowing you to choose mount options easily.

Python does not have to be installed, but [WinFsp](http://www.secfs.net/winfsp/download/) is still required.

<p align="center"><img src="https://github.com/ihaveamac/fuse-3ds/raw/master/resources/mainwindow-win.png"></p>

#### Install with existing Python
* Install the latest version of [Python 3](https://www.python.org/downloads/). The x86-64 version is preferred on 64-bit Windows.
* Install the latest version of [WinFsp](http://www.secfs.net/winfsp/download/).
* Install fuse-3ds with `py -3 -m pip install --upgrade https://github.com/ihaveamac/fuse-3ds/archive/master.zip`.
  * With GUI support: `py -3 -m pip install --upgrade https://github.com/ihaveamac/fuse-3ds/archive/master.zip#egg=fuse-3ds[gui]`

### macOS
Versions of macOS supported by Apple are highly recommended. Mac OS X Snow Leopard is the lowest version that should work.

* Install the latest version of Python 3. The recommended way is [Homebrew](https://brew.sh). You can also use an installer from [python.org](https://www.python.org/downloads/) or a tool like [pyenv](https://github.com/pyenv/pyenv).
* Install the latest version of [FUSE for macOS](https://github.com/osxfuse/osxfuse/releases/latest).
* Install fuse-3ds with `python3 -m pip install --upgrade https://github.com/ihaveamac/fuse-3ds/archive/master.zip`.
  * With GUI support: `python3 -m pip install --upgrade https://github.com/ihaveamac/fuse-3ds/archive/master.zip#egg=fuse-3ds[gui]`

### Linux
* Recent distributions should have Python 3.6.1 or later pre-installed, or included in its repositories. If not, you can use an extra repository (e.g. [deadsnakes's PPA](https://launchpad.net/%7Edeadsnakes/+archive/ubuntu/ppa) for Ubuntu), [build from source](https://www.python.org/downloads/source/), or use a tool like [pyenv](https://github.com/pyenv/pyenv).
* Most distributions should have fuse enabled/installed by default. Use your package manager if it isn't.
* Install fuse-3ds with `python3 -m pip install --upgrade --user https://github.com/ihaveamac/fuse-3ds/archive/master.zip`.
  * `--user` is not needed if you are using a virtual environment.
  * With GUI support: `python3 -m pip install --upgrade --user https://github.com/ihaveamac/fuse-3ds/archive/master.zip#egg=fuse-3ds[gui]`

## Usage
### Graphical user interface
A GUI can be used, if fuse-3ds was installed with GUI support, by specifying the type to be `gui` (e.g. Windows: `py -3 -mfuse3ds gui`, \*nix: `python3 -mfuse3ds gui`). The GUI controls mounting and unmounting.

### Command line
The main way to run a mount script after installing is using "`mount_<type>`" (e.g. `mount_cci game.3ds mountpoint`). Use `-h` to view arguments for a script.

If it doesn't work, the other way is to use `<python-cmd> -mfuse3ds <type>` (e.g. Windows: `py -3 -mfuse3ds cci game.3ds mountpoint`, \*nix: `python3 -mfuse3ds cci game.3ds mountpoint`).

Windows users can use a drive letter like `F:` as a mountpoint, or use `*` and a drive letter will be automatically chosen.

#### Unmounting
* Windows: Press <kbd>Ctrl</kbd> + <kbd>C</kbd> in the command prompt/PowerShell window.
* macOS: Two methods:
  * Right-click on the mount and choose "Eject “_drive name_”".
  * Run from terminal: `diskutil unmount /path/to/mount`
* Linux: Run from terminal: `fusermount -u /path/to/mount`

### Examples
* Mount a 3DS game card dump:  
  `mount_cci game.3ds mountpoint`
* Mount contents downloaded from CDN:  
  `mount_cdn cdn_directory mountpoint`
* Mount CDN contents with a specific decrypted titlekey:  
  `mount_cdn --dec-key 3E3E6769742E696F2F76416A65423C3C cdn_directory mountpoint`
* Mount a CIA:  
  `mount_cia game.cia mountpoint`
* Mount an ExeFS:  
  `mount_exefs exefs.bin mountpoint`
* Mount a NAND backup with `essential.exefs` embedded:    
  `mount_nand nand.bin mountpoint`
* Mount a NAND backup with an OTP file (Counter is automatically generated):  
  `mount_nand --otp otp.bin nand.bin mountpoint`
* Mount a NAND backup with OTP and CID files:  
  `mount_nand --otp otp.bin --cid nand_cid.bin nand.bin mountpoint`
* Mount a NAND backup with OTP file and a CID hexstring:  
  `mount_nand --otp otp.bin --cid 7468616E6B7334636865636B696E6721 nand.bin mountpoint`
* Mount a DSi NAND backup (Counter is automatically generated):  
  `mount_nanddsi --console-id 4E696E74656E646F nand_dsi.bin mountpoint`
* Mount a DSi NAND backup with a Console ID hexstring and specified CID hexstring:  
  `mount_nanddsi --console-id 4E696E74656E646F --cid 576879446F657344536945786973743F nand_dsi.bin mountpoint`
* Mount a DSi NAND backup with a Console ID file and specified CID file:  
  `mount_nanddsi --console-id ConsoleID.bin --cid CID.bin nand_dsi.bin mountpoint`
* Mount an NCCH container (.app, .cxi, .cfa, .ncch):  
  `mount_ncch content.cxi mountpoint`
* Mount a RomFS:  
  `mount_romfs romfs.bin mountpoint`
* Mount a `Nintendo 3DS` directory from an SD card:  
  `mount_sd --movable movable.sed "/path/to/Nintendo 3DS" mountpoint`
* Mount a Nintendo DS ROM image (NDS/SRL, `mount_nds` also works):  
  `mount_srl game.nds`
* Mount a 3DSX homebrew application:  
  `mount_threedsx boot.3dsx mountpoint`
* Mount an entire `title` directory (like one from a NAND backup, or in an SD card mount):  
  `mount_titledir title mountpoint`

## Useful tools
* wwylele's [3ds-save-tool](https://github.com/wwylele/3ds-save-tool) can be used to extract game saves and extra data (DISA and DIFF, respectively).
* [OSFMount](https://www.osforensics.com/tools/mount-disk-images.html) for Windows can mount FAT12/FAT16 partitions in NAND backups.

# License/Credits
`fuse3ds` is under the MIT license. fusepy is under the ISC license ([taken from `setup.py`](https://github.com/fusepy/fusepy/blob/b5f87a1855119d55c755c2c4c8b1da346365629d/setup.py)).

Special thanks to @Stary2001 for help with NAND crypto (especially TWL), and @d0k3 for SD crypto.

OTP code is from [Stary2001/3ds_tools](https://github.com/Stary2001/3ds_tools/blob/10b74fee927f66865b97fd73b3e7392e81a3099f/three_ds/aesengine.py), and is under the MIT license.
