- Joined
- Jan 25, 2024
- Messages
- 11,610
- Points
- 38
- Age
- 39
- Location
- USA
- Website
- gameparadise.org
- Credits
- 192,434
Wrote this up pretty quickly to help people having issues with using hactool. [Also I realize I put this in the wrong section... If a mod would move it that would be cool... I wasn't paying attention when I posted]
Requirements
Note that YMMV.
DOWNLOAD: https://mega.nz/#!Y6ByFbxI!3-whFid8d0UwMuDMEqrwM879d33SRZ9-GOuHwlpCkZU
FAQ (But you just posted ... Yeah but I know you are going to ask)
Q: I'm getting a Python not found error
A: Install python and make sure it is in your PATH variable. Google is your friend
Q: WhErE Do I GEt KEYS.dat
A: Find it yourself or follow the tutorial in the tutorials section
Q: Why isn't there a romfs.bin or romfs.romfs?!?
A: Folder works too
Q: Do I need to edit NPDM?
A: Nope.
Q: Game X doesnt work for Game Y!?!
A: Go check the tutorial mentioned above for a list of working redirects.
Q: WHERES THE DOWNLOAD
A: ... Read up.
Q: Why not Python 3?
A:
Changelog
V1.0.2 -- Made the files extract into game folders (same name as .xci) for use with Game Redirector (PyNX)
V1.0.1 -- Added notifications, changed the NPDM writing to not use hardcoded offsets
V1.0.0 -- Rough script. Needs cleaned and organized but seems to work as a POC for now.
Requirements
- Windows OS
- Python 2.7
- Tkinter (Python library, google it)
- hactool
- keys.dat
- Put the python file, hactool, and your keys.dat (don't ask me for it) in the same directory.
- Run 'python xci_to_lfs.py' in cmd or powershell (while in the file directory)
- Use the GUI to set your TitleID and pick your XCI
- Wait a minute. I didn't put anything in the script to notify you when its done. For a 2GB game it takes about a minute. YMMV. The last thing it does is delete the tmp folder, so when its gone you are good to go.
- Copy the Atmosphere folder to the root of your SD Card
- Follow the rest of the tutorial found in the tutorials section [How to use LayeredFS for Backup Loading] (Can't post links)
Note that YMMV.
DOWNLOAD: https://mega.nz/#!Y6ByFbxI!3-whFid8d0UwMuDMEqrwM879d33SRZ9-GOuHwlpCkZU
FAQ (But you just posted ... Yeah but I know you are going to ask)
Q: I'm getting a Python not found error
A: Install python and make sure it is in your PATH variable. Google is your friend
Q: WhErE Do I GEt KEYS.dat
A: Find it yourself or follow the tutorial in the tutorials section
Q: Why isn't there a romfs.bin or romfs.romfs?!?
A: Folder works too
Q: Do I need to edit NPDM?
A: Nope.
Q: Game X doesnt work for Game Y!?!
A: Go check the tutorial mentioned above for a list of working redirects.
Q: WHERES THE DOWNLOAD
A: ... Read up.
Q: Why not Python 3?
A:
Python:
import sys, os
from binascii import hexlify as hx, unhexlify as uhx
from struct import pack as pk, unpack as upk
hactoolPath =
# directory = input("Input directory? ")
directory = os.path.dirname(__file__)
for root, dirs, items in os.walk(directory):
for item in items:
if item.endswith(".xci"):
# TID to write
newTID = input("New TID to write in " + item + "? ")
outputFolder = root + "\\atmosphere\\titles\\" + newTID
os.makedirs(outputFolder, exist_ok=True)
# Extract the secure partition
filePath = os.path.join(root, item)
commandLine = hactoolPath + " -t xci " + filePath + " --securedir=" + outputFolder + " 1>nul 2>nul"
print("Extracting " + filePath + "...")
os.system(commandLine)
# Find the biggest nca
biggestSize = 0
biggestNCA = ""
for file in os.listdir(outputFolder):
if file.endswith(".nca"):
size = os.path.getsize(os.path.join(outputFolder, file))
if size > biggestSize:
biggestSize = size
biggestNCA = file
# Decrypt it
filePath = os.path.join(outputFolder, biggestNCA)
commandLine = hactoolPath + " " + filePath + " --exefsdir=" + outputFolder + "\\exefs --romfs=" + outputFolder + "\\romfs.bin 1>nul 2>nul"
print("Decrypting " + filePath + "...")
os.system(commandLine)
# Delete NCAs
print("Deleting NCA files...")
for file in os.listdir(outputFolder):
if file.endswith(".nca"):
os.remove(os.path.join(outputFolder, file))
# Patch main.npdm
with open(outputFolder + "\\exefs\\main.npdm", "rb+") as npdm:
# Pack TID
newTID = pk("<Q", int(newTID, 16))
# TID offset & length
hexa = bytearray(npdm.read())
TIDoffset = hexa.find(b"ACI0") + 0x10
TIDlength = 0x8
# Replace TID
print("Writing new TID...")
hexa[TIDoffset:TIDoffset+TIDlength] = newTID
npdm.seek(0)
npdm.write(hexa)
print("Done\n")
Changelog
V1.0.2 -- Made the files extract into game folders (same name as .xci) for use with Game Redirector (PyNX)
V1.0.1 -- Added notifications, changed the NPDM writing to not use hardcoded offsets
V1.0.0 -- Rough script. Needs cleaned and organized but seems to work as a POC for now.