Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Switch RomFS (IStorage) -> Files
from struct import unpack as up
import sys, os
dirs, files = None, None
def read_at(fp, off, len):
def read_u8(fp, off):
return up('<B', read_at(fp, off, 1))[0]
def read_u16(fp, off):
return up('<H', read_at(fp, off, 2))[0]
def read_u32(fp, off):
return up('<I', read_at(fp, off, 4))[0]
def read_u64(fp, off):
return up('<Q', read_at(fp, off, 8))[0]
def read_filename(fp, off, l):
if l == 0:
return ''
s = read_at(fp, off, l)
if '\0' in s:
s = s[:s.index('\0')]
return s
def dump_file(name, offset, size):
global archive, out_dir
path = os.path.join(out_dir, name[1:])
print 'Dumping %s (%012X-%012X) to %s...' % (name, offset, offset+size, path)
with open(path, 'wb') as f:
ofs = 0
sz = 0x800000
while ofs < size:
if size - ofs < sz:
sz = size - ofs
ofs += sz
print 'Dumped!'
def parse_file(off, path = ''):
global archive, dirs_off, files_off, fdata_off
sibling = 0
while sibling != 0xFFFFFFFF: + off)
(parent, sibling, ofs, size, hsh, namelen) = up('<IIQQII',
name = read_filename(archive, files_off + off + 0x20, namelen)
filepath = '%s%s' % (path, name)
dump_file(filepath, fdata_off+ofs, size)
off = sibling
def parse_dir(off, path = ''):
global archive, dirs_off, files_off, fdata_off, out_dir + off)
(sibling, child, file, hsh, namelen) = up('<IIIII',
name = read_filename(archive, dirs_off + off + 0x14, namelen)
if path:
newpath = '%s%s/' % (path, name)
newpath = '%s/' % name
dirp = os.path.dirname(os.path.join(out_dir, newpath[1:])).replace('/', os.path.sep)
if not os.path.exists(dirp):
if file != 0xFFFFFFFF:
parse_file(file, newpath)
if sibling != 0xFFFFFFFF:
parse_dir(sibling, path)
if child != 0xFFFFFFFF:
parse_dir(child, newpath)
def main(argc, argv):
if argc != 3:
print 'Usage: %s in_file out_dir' % argv[0]
global archive, dirs_off, files_off, fdata_off
archive = open(argv[1], 'rb')
if read_u64(archive, 0) != 0x50:
print 'Error: Invalid archive.'
dirs_off = read_u64(archive, 0x18)+4
files_off = read_u64(archive, 0x38)
fdata_off = read_u64(archive, 0x48)
print 'Directory Metadata at %08X' % dirs_off
print 'File Metadata at %08X' % files_off
print 'Failed to open %s.' % argv[1]
global out_dir
out_dir = argv[2]
if __name__ == '__main__':
main(len(sys.argv), sys.argv)

This comment has been minimized.

Copy link

wumd-ar commented Jul 22, 2017

Thanks a lot for this.
I installed Python 3.6 and did this in Windows' CMD:

cd /d "d:\switchdump" XXX_romfs.istorage targetfolder

But then I got this error:

  File "D:\switchdump\", line 33
    print 'Dumping %s (%012X-%012X) to %s...' % (name, offset, offset+size, path
SyntaxError: invalid syntax

I would be grateful for any help to get this to run at all.


This comment has been minimized.

Copy link

jakibaki commented Jul 22, 2017

This is python2 code.

Print statements without () are not valid in python3.


This comment has been minimized.

Copy link

TabuuForteAkugun commented Jan 16, 2018

So this script can't get the RomFS from XCI files that are now showing up. Shame...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.