Last active
August 29, 2015 14:14
-
-
Save swarzesherz/651f69b2e8e5c370a0f4 to your computer and use it in GitHub Desktop.
3DSFAT16tool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# version 1.0 | |
import os | |
import sys | |
import argparse | |
import math | |
import numpy | |
if not sys.version_info[:2] == (2, 7): | |
print '*****\n!!!!!Warning - Only tested with Python 2.7!!!!!\n*****\n' | |
parser = argparse.ArgumentParser() | |
parser.add_argument('nand_file', action='store', help='NAND file (must exist for dumping and injecting)') | |
parser.add_argument('fat16_file', action='store', help='FAT16 file (only should exist for injecting, fat16 file will be written/overwrite when dumping)') | |
parser.add_argument('fat16_xorpad', action='store', help='FAT16 xorpad file') | |
choose = parser.add_mutually_exclusive_group() | |
choose.add_argument('-d', action='store_true', default=False, dest='dump', help='Dump FAT16 from NAND file') | |
choose.add_argument('-i', action='store_true', default=False, dest='inject', help='Inject FAT16 into NAND file') | |
parser.add_argument('-n3ds', action='store_true', default=False, dest='n3ds', help='Use for N3DS NAND dumps') | |
parser.add_argument('-lowmem', action='store_true', default=False, dest='lowmem', help='Use if you have low RAM available') | |
arguments = parser.parse_args() | |
#https://stackoverflow.com/questions/5734691/fastest-bitwise-xor-between-two-multibyte-binary-data-variables | |
def xor(data, key): | |
import numpy, math | |
# key multiplication in order to match the data length | |
key = (key*int(math.ceil(float(len(data))/float(len(key)))))[:len(data)] | |
# Select the type size in bytes | |
for i in (8,4,2,1): | |
if not len(data) % i: break | |
if i == 8: dt = numpy.dtype('<Q8'); | |
elif i == 4: dt = numpy.dtype('<L4'); | |
elif i == 2: dt = numpy.dtype('<H2'); | |
else: dt = numpy.dtype('B'); | |
return numpy.bitwise_xor(numpy.fromstring(key, dtype=dt), numpy.fromstring(data, dtype=dt)).tostring() | |
if (arguments.dump is arguments.inject): | |
print 'Please choose -d or -i to dump or inject the fat16 partition' | |
exit(0) | |
print '*******\n3DSFAT16tool\n*******\n' | |
start = 0x0B930000 | |
size = 0x2F3E3600 | |
chunksize = 0x3200000 #10MB(0XA00000) RAM usage ~77.531MiB, 25MB(0X1900000) RAM usage ~77.531MiB, 50MB(0X3200000) RAM usage ~364.840MiB | |
fsOffset = 0x2CA00 | |
if(arguments.n3ds): | |
size = 0x41D2D200 | |
fsOffset = 0x2AE00 | |
if not os.path.isfile(arguments.nand_file): | |
print 'NAND file cannot be found' | |
exit(0) | |
if (arguments.inject): | |
if not os.path.isfile(arguments.fat16_file): | |
print 'FAT16 file cannot be found' | |
exit(0) | |
with open(arguments.fat16_file, 'rb') as r, open(arguments.nand_file, 'rb+') as w, open(arguments.fat16_xorpad, 'rb') as x: | |
print 'Injecting... please wait' | |
if arguments.lowmem: | |
for i in range(0, size, chunksize): | |
w.seek(start+fsOffset+i) | |
x.seek(fsOffset+i) | |
chunksize = size % chunksize if size < chunksize else chunksize | |
fat16 = r.read(chunksize) | |
xorpad = x.read(chunksize) | |
w.write(xor(fat16, xorpad)) | |
size -= chunksize | |
else: | |
w.seek(start+fsOffset) | |
x.seek(fsOffset) | |
fat16 = r.read(size) | |
xorpad = x.read(size) | |
w.write(xor(fat16, xorpad)) | |
if (arguments.dump): | |
if os.path.isfile(arguments.fat16_file): | |
print 'FAT16 with this name and path already exists, file will be overwritten' | |
with open(arguments.nand_file, 'rb') as r, open(arguments.fat16_file, 'wb') as w, open(arguments.fat16_xorpad, 'rb') as x: | |
print 'Dumping... please wait' | |
if arguments.lowmem: | |
for i in range(0, size, chunksize): | |
r.seek(start+fsOffset+i) | |
x.seek(fsOffset+i) | |
chunksize = size % chunksize if size < chunksize else chunksize | |
fat16 = r.read(chunksize) | |
xorpad = x.read(chunksize) | |
w.write(xor(fat16, xorpad)) | |
size -= chunksize | |
else: | |
r.seek(start+fsOffset) | |
x.seek(fsOffset) | |
fat16 = r.read(size) | |
xorpad = x.read(size) | |
w.write(xor(fat16, xorpad)) | |
print '' | |
print 'Finished' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
works fine with python 3.4. you just need to install numpy and convert the print statements to print functions.