Package: pyctr
PyCTRPython library to interact with Nintendo 3DS files.The API is not yet stable. If you decide to use this, you should stick to a specific version on pypi, or store a copy locally, until it is stable.Documentation is being updated over time and is published onRead the Docs. Most classes and functions have docstrings.Support is provided onGitHub Discussionsor Discord (info,invite link).Supported typesApplication metadata and containersCDN contents ("tmd" next to other contents)CTR Cart Image (".3ds", ".cci")CTR Importable Archive (".cia")NCCH (".cxi", ".cfa", ".ncch", ".app")Title Metadata ("*.tmd")SMDH icon ("*.smdh", "icon.bin")Application contentsExecutable Filesystem (".exefs", "exefs.bin")Read-only Filesystem (".romfs", "romfs.bin")User filesNAND ("nand.bin")SD card filesystem ("Nintendo 3DS" directory)DISA (save) and DIFF (extdata) containersNOT the Inner Fat yet! This is for the wrappers around them.Licensepyctris under the MIT license.Note: this is for the 0.7 branch, which split from master once the 0.7.0 release was made. For 0.8 or newer, please look at the other branches.v0.7.5 - February 28, 2024Attempt to load from "Crypto" module if "Cryptodome" fails. This is for cases where on pycryptodome is available and not pycryptodomex.v0.7.4 - February 16, 2024Fix setting CTRNANDNew Y incorrectly (the fixed key was being overwritten by the incorrect key from Boot9)v0.7.3 - January 2, 2024Always set fixed keys regardless of boot9 (in particular: TWLNAND Y, CTRNANDNew Y, ZeroKey N, FixedSystemKey N)v0.7.2 - November 27, 2023Fix setting TWLNAND key for dev consoles (thanks to @xprism1 for assistance)v0.7.1 - September 15, 2023ChangelogBackportCryptoEngine._format_stateandCryptoEngine._print_statefrom 0.8Fix pycryptodomex version specifier (should be >=3.9,<4)v0.7.0 - September 3, 2023HighlightsPython 3.8 or later is now required, up from 3.6.1.A newpyctr.type.configpackage withsaveandblocksmodules was added. These allow for reading theconfig savegame, both to read the raw blocks, and to parse the data into a usable format.A newnandmodule with theNANDclass is added to read and write to NAND images. This only provides raw access (for FAT32, trynathanhi/pyfatfs).RomFSReaderinitialization performance was improved, especially with RomFS files containing large amounts of files or directories.Documentation is being added and improved over time. Check it onRead the
Docs.ChangelogAdd the modulepyctr.type.configsavewith the classConfigSaveReader(module name changed in a future commit)Implementto_bytesandremove_blockinConfigSaveReaderSplitpyctr.type.configsaveinto two packages:pyctr.type.config.blocksandpyctr.type.config.saveNewConfigSaveBlockParserclass with 3 methods:get_username,get_user_time_offset, andget_system_model(plus convenience functionsloadandfrom_fileso aConfigSaveParserdoesn't need to be manually created)New enum:SystemModelBothConfigSaveReaderandConfigSaveBlockParserare importable frompyctr.type.configAddflushtoSubsectionIOOptimizeCTRFileIOto re-use existing cipher object when possible (seeking invalidates the current one)OptimizeRomFSReaderby reading entire directory and file metadata at once before traversing, significantly reducing the amount of read calls to the underlying fileOptimizeRomFSReaderto reduce the read calls for the header (once for raw lv3, twice for IVFC)Check for unformatted saves inDISA(the first 0x20 bytes are all NULL and the rest is garbage)Removecrypto_method == 0check for NCCH files usingfixed_crypto_keyAddnandmodule withNANDclass, to read and write to a NAND imageAdd__slots__to a bunch of classes (CCIReader,CDNReader,CIAReader,ExeFSReader,NAND,NCCHReader,RomFSReader,SDFilesystem,SDTitleReader,SMDH,ConfigSaveReader,TypeReaderBase,TypeReaderCryptoBase)Update copyright yearVarious documentation and type hint changesAdd newFilePathandFilePathOrObjecttypesAdd__slots__toSubsectionIOandSplitFileMergerAdd some tests forromfsandsmdhLoad all boot9 keys inCryptoEngine.setup_keys_from_boot9Moved package metadata tosetup.cfgFix setting fixed keys inCryptoEngineand add debug logging to key settingSeparate NCSD header loading fromNANDto a separate classNANDNCSDHeaderRefactor thenandmodule andNANDclass:Add support for virtual sections (things that are not NCSD partitions)Renameopen_ncsd_partitiontooprn_raw_sectionAdd custom section IDs that always point to the correct partition, regardless of its physical locationAdd custom section ID for GodMode9 bonus volumeAdd documentation files created with sphinx-autodocSwitch Sphinx theme to rtd, add example-cia, add info to index pageMove RomFS header loading inRomFSReaderto a newRomFSLv3HeaderclassMany different documentation changes or additionsRequire Python 3.8Create new and update documentation pages -example-nandandpyctr.type.nandFixclosefdbeing default to True always inNANDCreate documentation page forpyctr.type.sdCreate documentation page forpyctr.fileioCreate documentation page forpyctr.utilFixes toConfigSaveReader:data_offsetis not hardcoded to0x41E4, it's based on the amount of data from the blocksCFG adds data to save from end to start when the block data is > 4 bytes, so now we are replicating this behavior and generating a properdata_offsetand data sorting when usingto_bytesAdded sanity checks while parsing a config saveset_blockpreviously didn't allowedNonein flags despite being stated to default to0xENew attribute for SMDH:SMDH.region_lockout, with a new NamedTupleSMDHRegionLockoutNew attribute for CCIReader:CCIReader.cart_region, with a new EnumCCICartRegionConfigSaveReader.set_blockwill now check Block IDs, flags, and sizes against a known list of blocksPassingstrict=Truetoset_blockwill bypass thisKNOWN_BLOCKSinpyctr.type.config.savewas changed to have values be dicts with "flags" and "size" keys (instead of plain tuples)Switchget_*andset_*to getters and setters in `pyctr.type.config.blockse.g.usernameinstead ofget_usernameandset_usernameAdd newfrom_bytesand__bytes__methods toAppTitleto load title structures (and modifySMDHto use this now)v0.6.0 - January 26, 2022HighlightsPillow is now an optional dependency. It is available through the extra featureimages. This means to usepyctr[images]when adding tosetup.py,requirements.txt, orpip install.SMDH icon data is stored into an array like[[(1, 2, 3), (4, 5, 6), ...]]. It can be used with other libraries like the pure-python pypng, for example:frompyctr.type.ciaimportCIAReaderfromitertoolsimportchainimportpngmy_cia=CIAReader('game.cia')# pypng expects an array like [[1, 2, 3, 4, 5, 6, ...]] so we need to flatten the inner listsimg=png.from_array((chain.from_iterable(x)forxinmy_cia.contents[0].exefs.icon.icon_large_array),'RGB',{'width':48,'height':48})img.save('icon.png')ChangelogMove around object attribute initialization in cci, cdn, cia, and sdtitle, to prevent extra exceptions if an error is raised earlyUseopen_raw_sectioninternally when initializing aCIAReaderobject, instead of manually seeking and readingMake Pillow an optional dependency and make SMDH load icon data into an array (useful for other libraries like pypng)New functions insmdh:rgb565_to_rgb888_tuple,load_tiled_rgb565_to_array,rgb888_array_to_imageInit arguments forSMDHwere changed to accept icon data arrays instead of PillowImageobjectsPillow is added toextras_requireunder the featureimagesDocumentation tweaks tosmdhRemove unused import inciav0.5.1 - June 28, 2021Fix arbitrary reads in the first 0x10 block ofCBCFileIOv0.5.0 - June 26, 2021HighlightsA newsdtitlemodule withSDTitleReaderis added to read titles installed on an SD card. When used directly, it works with contents that are not SD encrypted. To open a title on a 3DS SD card that is SD encrypted, a new method is added tosd.SDFilesystem:open_title.SMDH icons are now loaded usingPillow.SMDH flags are now loaded.The ExeFS in NCCH contents is now fully decrypted properly. This means there is no longer garbage at the last block of the.codesection for titles that use extra NCCH keys. This was achieved by rewriting the ExeFS section to concatenate multiple file-like objects that use different keyslots with a new class,SplitFileMerger.ChangelogAdd_raise_if_file_closed_generictopyctr.commonAddSplitFileMergertopyctr.fileioto merge multiple file-like objects into one (currently no support for writing)Support closing all subfiles inSplitFileMergerRewrite ExeFS handling inNCCHReaderto useSplitFileMergerto merge multipleSubsectionIOfiles to handle the parts that use different encryption, and updateFullDecryptedto use it when reading ExeFSAddfrom_bytesclassmethod toNCCHFlagsAlways use the internal ExeFS file object when reading it for FullDecryptedAdd docstrings toNCCHFlagsAdd dependency onPillow>=8.2Load SMDH icons using Pillow/PIL, stored in new attributes in theSMDHclass:icon_small,icon_largeLoad SMDH flags into a newSMDHFlagsclassAddisfileandisdirmethods toSDFilesystem, convert path to string insd.normalize_sd_pathto make it easier to use anyos.PathLikeobject (e.g.pathlib.PurePosixPath)Addsdtitlemodule withSDTitleReaderclass, to read titles installed to the SD card inside "Nintendo 3DS"Addopen_titlemethod toSDFilesystemto open a title usingSDTitleReader, and a newMissingTitleErrorexceptionUpdate type hints insdv0.4.7 - April 20, 2021Use absolute paths inCDNReaderUse absolute paths inSDFilesystemMakeSubsectionIOobjects hashable (if the underlying file object is)Make sure two differentCTRFileIO,TWLCTRFileIO, andCBCFileIOreturn different hashes, even with the same reader + key + iv/counterAddTWLCTRFileIOtocrypto.engine.__all__Use afrozenseton a closedCDNReaderobject's internal open files setDon't set__del__directly tocloseinTypeReaderBase, in casecloseis overriddenAuto-close opened files based on a reader when the reader closes (applies toCCIReader,CIAReader,ExeFSReader,NCCHReader, andRomFSReader)Add new pseudo-keyslotNCCHExtraKeyto store the second keyslot data for NCCH contentsThis is important because there exist titles that use Original NCCH but with a seed. Before this change, the key in theNCCHkeyslot would be overwritten, causing everything but the special regions (ExeFS .code and RomFS) to be improperly decrypted.UseNCCHExtraKeyfor the second keyslot instead of the actual keyslot inNCCHReaderSet_open_filesbefore opening the file inTypeReaderBaseto prevent an additional error if opening the file failsDon't set KeyX and KeyY separately if fixed crypto key is used without an extra crypto methodFix sections inCCIReadernot opening, raising an errorv0.4.6 - March 1, 2021Add pycryptodomex version requiremenet range (>=3.9,<4)Fix using bytes file paths forCDNReaderandSDFilesystemSupport auto-closing underlying file forCTRFileIOandCBCFileIOMakeCTRFileIOandCBCFileIOobjects hashable (if the underlying file object is)UpdateCDNReaderto re-open files instead of using shared file objects, and internally open all files throughCDNReader.open_raw_section(fixes #6)Store encrypted and decrypted OTP inCryptoEngineasotp_encandotp_dec, and addotp_keys_setto check if an OTP was setVerify OTP magic after decryption inCryptoEngine.setup_keys_from_otpMakeCryptoEngine.otp_device_idrequire OTP (raising an exception instead of returning None)AddTWLCTRFileIOas a subclass ofCTRFileIOwhich handles the special read/write crypto specific to TWLNANDv0.4.5 - October 24, 2020Fix loading RomFS from a filename inRomFSReaderFix loading ExeFS from a filename inExeFSReaderv0.4.4 - September 20, 2020Support loading a decrypted titlekey forCDNReaderRemove unusedsectionsattribute fromCDNReaderAddavailable_sectionstoCDNReaderto provide a list of sections available in the titleAdd__author__,__copyright__,__license__,__version__, andversion_infotopyctr.__init__v0.4.3 - July 28, 2020Fix endianness issue when converting aTitleMetadataReaderobject tobytesv0.4.2 - July 28, 2020Don't assume a Cygwin environment is WindowsChange keyslot for New 3DS key sector keys from 0x11 to 0x43This adds a new Keyslot enum item:Keyslot.New3DSKeySectorDocument more methods in pyctr.crypto.engineAdd newfileio.CloseWrapperclass to provide access to a file object while preventing closing it directlyUseCloseWrapperinCDNReader.open_raw_sectionv0.4.1 - July 11, 2020Support NCCH contents with fixed crypto key (zerokey and fixed system key)CryptoEngine adds these to fake keyslots 0x41 and 0x42 respectively.Fixed setting up keyslot 0x11, used for decrypting the New 3DS key sectorv0.4.0 - July 10, 2020Add DISA/DIFF reading and writing underpyctr.type.saveThis does NOT include Inner FAT support yet.This can read and write to IVFC level 4. For now, external tools can be used to read or write to the Inner FAT.Add CDN reading underpyctr.type.cdnAdd more docstrings to various modulesAdd seed parameters to ncch, cia, and cdnRenameKeyslot.UDSLocalWANtoKeyslot.UDSLocalWLANMany other internal changes done months agov0.3.1 - April 8, 2020Fixsetup.pynot including subpackagesv0.3.0 - April 8, 2020Document more classes, methods, and attributesAdd apyctr.crypto.seeddbmodule for central SeedDB managementLoading SeedDB inNCCHReaderis now removedAdd newTypeReaderBaseandTypeReaderCryptoBasefor reader types that use a single fileFixPathLikeerror inNCCHReaderandRomFSReaderChanged type ofpartition_idandprogram_idinNCCHReadertostrSome other changes. I'll get better at documenting this!v0.2.1 - April 3, 2020Remove debug print inSDFilesystem.openv0.2.0 - April 3, 2020Add the modulepyctr.type.sdwith the classSDFilesystemAdd docstrings topyctr.cryptoAllowos.PathLike,str, andbytesas file paths in most methodsAllow Windows-style paths inCryptoEngine.sd_path_to_ivv0.1.0 - January 27, 2020Initial standalone release. All previous commits are in theninfsrepo.The MIT License (MIT)Copyright (c) 2017-2023 Ian BurgwinPermission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.