sdfs - SD card filesystem

The sd module enables reading and writing of Nintendo 3DS SD card encrypted digital content. This is the “Nintendo 3DS” folder on an SD card and includes application data, save data, and extdata.

Directory hierarchy

  • Nintendo 3DS

    • <id0>

      • <id1>

        • backup

        • dbs

        • extdata

        • title

        • Nintendo DSiWare

Getting started

There are two or three steps to get access to the filesystem inside id1. First you create an SDRoot object pointing at a “Nintendo 3DS” folder. Then, if you wish, you can select an id1 directory to use. Then use open_id1() to open the filesystem it and receive an SDFS object.

from pyctr.type.sdfs import SDRoot, SDFS

root = SDRoot('/Volumes/GM9SD/Nintendo 3DS',
              sd_key_file='movable.sed')
# at this point check root.id1s if you wish, and then pass it to open_id1
# or don't, and it will select the first one it finds
fs = root.open_id1()
with fs.open('/dbs/title.db') as f:
    f.read()

You can also use the SDRoot to open titles. It also accepts an id1 or will use the first one by default.

title = sd.open_title('0004000000169800')
with title.contents[0].romfs.open('/file.bin') as f:
    f.read()

SDRoot objects

class pyctr.type.sdfs.SDRoot(path, *, crypto=None, dev=False, sd_key_file=None, sd_key=None)[source]

Opens an ID0 folder inside a “Nintendo 3DS” folder.

Parameters:
  • path – Path to the Nintendo 3DS folder.

  • crypto – A custom crypto.CryptoEngine object to be used. Defaults to None, which causes a new one to be created.

  • dev – Use devunit keys.

  • sd_key_file – Path to a movable.sed file to load the SD KeyY from.

  • sd_key – SD KeyY to use. Has priority over sd_key_file if both are specified.

open_id1(id1=None)[source]

Opens the filesystem inside an ID1 directory.

if no ID1 is specified, the first one in id1s is used.

Parameters:

id1 (Optional[str]) – ID1 directory to use.

Returns:

SD filesystem.

Return type:

SDFS

Raises:

fs.errors.ResourceNotFound – If the ID1 directory doesn’t exist.

open_title(title_id, *, case_insensitive=False, seed=None, load_contents=True)[source]

Open a title’s contents for reading.

In the case where a title’s directory has multiple tmd files, the one with the smallest number in the filename is used.

Parameters:
  • title_id (str) – Title ID to open.

  • case_insensitive (bool) – Use case-insensitive paths for the RomFS of each NCCH container.

  • seed (bytes) – Seed to use. This is a quick way to add a seed using add_seed().

  • load_contents (bool) – Load each partition with NCCHReader.

Return type:

SDTitleReader

Raises:

MissingTitleError – If the title could not be found.

SDFS objects

These are created by SDRoot and usually shouldn’t be created manually.

These inherit fs.base.FS and so generally the same methods work.

class pyctr.type.sdfs.SDFS(parent_fs, path, *, crypto)[source]

Enables access to an SD card filesystem inside Nintendo 3DS/id0/id1.

Currently, files inside the “Nintendo 3DS” directory cannot be read.

Parameters:
  • parent_fs (FS) – The filesystem containing the contents of “Nintendo 3DS”.

  • path (str) – The path to the id1 folder.

  • crypto (CryptoEngine) – The CryptoEngine object to be used.