def rebuild_nsp(ifolder, ofolder, buffer=65536, delta=False, xml_gen=False, export='nsp'): extlist = ['nsp', 'nsz'] files = listmanager.folder_to_list(ifolder, extlist) from Fs import Nsp import decompressor total = len(files) for filepath in files: if filepath.endswith('nsp'): basename = os.path.basename(os.path.abspath(filepath)) endfile = os.path.join(ofolder, basename) print('Processing: ' + filepath) f = Nsp(filepath) f.rebuild(buffer, endfile, delta, False, xml_gen) f.flush() f.close() elif filepath.endswith('nsz'): basename = os.path.basename(os.path.abspath(filepath)) endname = basename[:-1] + 'p' endname = os.path.join(ofolder, endname) decompressor.decompress_nsz(filepath, endname, buffer, delta, xml_gen) total -= 1 print("**********************************************************") print(('Still {} files to process').format(str(total))) print("**********************************************************")
def decompressWorker(q, output, totalStatus): while not q.empty(): try: path = q.get(block=False) totalStatus.add(1) path = NszDecompressor.decompress(path, output) if path: i = Nsp(path) i.move() except queue.Empty as e: return except BaseException as e: Print.info('DECOMPRESS WORKER EXCEPTION: ' + str(e)) traceback.print_exc(file=sys.stdout)
def getName(titleId, version, key=None, path=None): initTitles() initFiles() titleId = titleId.upper() nsp = Nsp() if path: nsp.setPath(os.path.basename(path)) nsp.titleId = titleId nsp.version = version nsp.hasValidTicket = True if path: filename, ext = os.path.splitext(path) else: ext = '.nsp' return os.path.join(Config.paths.nspOut, os.path.basename(nsp.fileName() or ('Untitled [%s][v%d]%s' % (titleId, int(version or 0), ext))))
def get_key_fromdict(fp): if fp.endswith('.nsp') or fp.endswith('.nsx'): files_list=sq_tools.ret_nsp_offsets(fp) files=list();filesizes=list() fplist=list() for k in range(len(files_list)): entry=files_list[k] fplist.append(entry[0]) for i in range(len(files_list)): entry=files_list[i] filepath=entry[0] if filepath.endswith('.cnmt.nca'): f=Nsp(fp,'rb') titleid,titleversion,base_ID,keygeneration,rightsId,RSV,RGV,ctype,metasdkversion,exesdkversion,hasHtmlManual,Installedsize,DeltaSize,ncadata=f.get_data_from_cnmt(filepath) titlekey,dectkey=f.db_get_titlekey(rightsId,keygeneration) f.flush() f.close() # print(titlekey);print(rightsId) return titlekey
def main(): global err try: if len(argv) > 1: args = ParseArguments.parse() else: from gui.NSZ_GUI import GUI args = GUI().run() if args == None: Print.info("Done!") return if args.output: outfolderToPharse = args.output if not outfolderToPharse.endswith( '/') and not outfolderToPharse.endswith('\\'): outfolderToPharse += "/" if not Path(outfolderToPharse).is_dir(): Print.error( 'Error: Output directory "{0}" does not exist!'.format( args.output)) return outfolder = Path(outfolderToPharse).resolve() if args.output else Path( '.').resolve() Print.info('') Print.info(' NSZ v3.0 ,;:;;,') Print.info(' ;;;;;') Print.info(' .=\', ;:;;:,') Print.info(' /_\', "=. \';:;:;') Print.info(' @=:__, \,;:;:\'') Print.info(' _(\.= ;:;;\'') Print.info(' `"_( _/="`') Print.info(' `"\'') Print.info('') barManager = enlighten.get_manager() poolManager = Manager() statusReport = poolManager.list() readyForWork = Counter(0) pleaseNoPrint = Counter(0) pleaseKillYourself = Counter(0) pool = [] work = poolManager.Queue() amountOfTastkQueued = Counter(0) if args.titlekeys: extractTitlekeys(args.file) if args.extract: for f_str in args.file: for filePath in expandFiles(Path(f_str)): filePath_str = str(filePath) Print.info('Extracting "{0}" to {1}'.format( filePath_str, outfolder)) f = factory(filePath) f.open(filePath_str, 'rb') dir = outfolder.joinpath(filePath.stem) f.unpack(dir, args.extractregex) f.close() if args.create: Print.info('Creating "{0}"'.format(args.create)) nsp = Nsp.Nsp(None, None) nsp.path = args.create nsp.pack(args.file) if args.C: targetDictNsz = CreateTargetDict(outfolder, args.parseCnmt, ".nsz") targetDictXcz = CreateTargetDict(outfolder, args.parseCnmt, ".xcz") sourceFileToDelete = [] for f_str in args.file: for filePath in expandFiles(Path(f_str)): if not isUncompressedGame(filePath): continue try: if filePath.suffix == '.nsp': if not AllowedToWriteOutfile( filePath, ".nsz", targetDictNsz, args.rm_old_version, args.overwrite, args.parseCnmt): continue elif filePath.suffix == '.xci': if not AllowedToWriteOutfile( filePath, ".xcz", targetDictXcz, args.rm_old_version, args.overwrite, args.parseCnmt): continue compress(filePath, outfolder, args, work, amountOfTastkQueued) if args.rm_source: sourceFileToDelete.append(filePath) except KeyboardInterrupt: raise except BaseException as e: Print.error('Error when compressing file: %s' % filePath) err.append({ "filename": filePath, "error": format_exc() }) print_exc() bars = [] compressedSubBars = [] BAR_FMT = u'{desc}{desc_pad}{percentage:3.0f}%|{bar}| {count:{len_total}d}/{total:d} {unit} [{elapsed}<{eta}, {rate:.2f}{unit_pad}{unit}/s]' parallelTasks = min(args.multi, amountOfTastkQueued.value()) if parallelTasks < 0: parallelTasks = 4 for i in range(parallelTasks): statusReport.append([0, 0, 100]) p = Process(target=solidCompressTask, args=(work, statusReport, readyForWork, pleaseNoPrint, pleaseKillYourself, i)) p.start() pool.append(p) for i in range(parallelTasks): bar = barManager.counter(total=100, desc='Compressing', unit='MiB', color='cyan', bar_format=BAR_FMT) compressedSubBars.append(bar.add_subcounter('green')) bars.append(bar) sleep(0.02) while readyForWork.value() < parallelTasks: sleep(0.2) if pleaseNoPrint.value() > 0: continue pleaseNoPrint.increment() for i in range(parallelTasks): compressedRead, compressedWritten, total = statusReport[i] if bars[i].total != total: bars[i].total = total // 1048576 bars[i].count = compressedRead // 1048576 compressedSubBars[i].count = compressedWritten // 1048576 bars[i].refresh() pleaseNoPrint.decrement() pleaseKillYourself.increment() for i in range(readyForWork.value()): work.put(None) while readyForWork.value() > 0: sleep(0.02) for i in range(parallelTasks): bars[i].close(clear=True) #barManager.stop() #We aren’t using stop because of it printing garbage to the console. for filePath in sourceFileToDelete: delete_source_file(filePath) if args.D: targetDictNsz = CreateTargetDict(outfolder, args.parseCnmt, ".nsp") targetDictXcz = CreateTargetDict(outfolder, args.parseCnmt, ".xci") for f_str in args.file: for filePath in expandFiles(Path(f_str)): if not isCompressedGame( filePath) and not isCompressedGameFile(filePath): continue try: if filePath.suffix == '.nsz': if not AllowedToWriteOutfile( filePath, ".nsp", targetDictNsz, args.rm_old_version, args.overwrite, args.parseCnmt): continue elif filePath.suffix == '.xcz': if not AllowedToWriteOutfile( filePath, ".xci", targetDictXcz, args.rm_old_version, args.overwrite, args.parseCnmt): continue elif filePath.suffix == '.ncz': outfile = changeExtension( outfolder.joinpath(filePath.name), ".nca") if not args.overwrite and outfile.is_file(): Print.info('{0} with the same file name already exists in the output directory.\n'\ 'If you want to overwrite it use the -w parameter!'.format(outfile.name)) continue decompress(filePath, outfolder) if args.rm_source: delete_source_file(filePath) except KeyboardInterrupt: raise except BaseException as e: Print.error( 'Error when decompressing file: {0}'.format( filePath)) err.append({ "filename": filePath, "error": format_exc() }) print_exc() if args.info: for f_str in args.file: for filePath in expandFiles(Path(f_str)): filePath_str = str(filePath) Print.info(filePath_str) f = factory(filePath) f.open(filePath_str, 'r+b') f.printInfo(args.depth + 1) f.close() if args.verify and not args.C and not args.D: for f_str in args.file: for filePath in expandFiles(Path(f_str)): try: if isGame(filePath): Print.info("[VERIFY {0}] {1}".format( getExtensionName(filePath), filePath.name)) verify(filePath, False) except KeyboardInterrupt: raise except BaseException as e: Print.error( 'Error when verifying file: {0}'.format(filePath)) err.append({ "filename": filePath, "error": format_exc() }) print_exc() if len(argv) == 1: pass except KeyboardInterrupt: Print.info('Keyboard exception') except BaseException as e: Print.info('nut exception: {0}'.format(str(e))) raise if err: Print.info( '\n\033[93m\033[1mSummary of errors which occurred while processing files:' ) for e in err: Print.info('\033[0mError when processing {0}'.format( e["filename"])) Print.info(e["error"]) Print.info('Done!')
def decompress_nsz(input,output,buffer = 65536,delta=False,xml_gen=False): f = Nsp(input, 'r+b') f.decompress_direct(output,buffer,delta,xml_gen) f.flush() f.close()
def nsz_hasher(input,buffer = 65536): f = Nsp(input, 'r+b') f.nsz_hasher(buffer) f.flush() f.close()
def verify_nsz(input,buffer = 65536): f = Nsp(input, 'r+b') f.verify_nsz(buffer) f.flush() f.close()
def gen_nsp_parts_spec1(filepath,target_cnmt=None,cachefolder=None,keypatch=False): if keypatch!=False: try: keypatch=int(keypatch) except: keypatch=False if cachefolder==None: cachefolder=os.path.join(ztools_dir, '_mtp_cache_') if not os.path.exists(cachefolder): os.makedirs(cachefolder) else: for f in os.listdir(cachefolder): fp = os.path.join(cachefolder, f) try: shutil.rmtree(fp) except OSError: os.remove(fp) files_list=sq_tools.ret_nsp_offsets(filepath) files=list();filesizes=list() fplist=list() for k in range(len(files_list)): entry=files_list[k] fplist.append(entry[0]) if target_cnmt==None: for i in range(len(files_list)): entry=files_list[i] cnmtfile=entry[0] if cnmtfile.endswith('.cnmt.nca'): target_cnmt=cnmtfile break for i in range(len(files_list)): entry=files_list[i] cnmtfile=entry[0] if cnmtfile.endswith('.cnmt.nca') and target_cnmt==cnmtfile: f=squirrelNSP(filepath) titleid,titleversion,base_ID,keygeneration,rightsId,RSV,RGV,ctype,metasdkversion,exesdkversion,hasHtmlManual,Installedsize,DeltaSize,ncadata=f.get_data_from_cnmt(cnmtfile) f.flush() f.close() for j in range(len(ncadata)): row=ncadata[j] # print(row) if row['NCAtype']!='Meta' and row['NCAtype']!='Program': test1=str(row['NcaId'])+'.nca';test2=str(row['NcaId'])+'.ncz' if test1 in fplist: files.append(str(row['NcaId'])+'.nca') filesizes.append(int(row['Size'])) elif test2 in fplist: files.append(str(row['NcaId'])+'.ncz') for k in range(len(files_list)): entry=files_list[k] if entry[0]==test2: filesizes.append(int(entry[3])) break for j in range(len(ncadata)): row=ncadata[j] if row['NCAtype']=='Meta': # print(str(row['NcaId'])+'.cnmt.nca') files.append(str(row['NcaId'])+'.cnmt.nca') filesizes.append(int(row['Size'])) for j in range(len(ncadata)): row=ncadata[j] # print(row) if row['NCAtype']=='Program': test1=str(row['NcaId'])+'.nca';test2=str(row['NcaId'])+'.ncz' if test1 in fplist: files.append(str(row['NcaId'])+'.nca') filesizes.append(int(row['Size'])) elif test2 in fplist: files.append(str(row['NcaId'])+'.ncz') for k in range(len(files_list)): entry=files_list[k] if entry[0]==test2: filesizes.append(int(entry[3])) break break f.flush() f.close() outheader = sq_tools.gen_nsp_header(files,filesizes) properheadsize=len(outheader) # print(properheadsize) # print(bucketsize) i=0;sum=properheadsize; nsp=squirrelNSP(filepath) outfile=os.path.join(cachefolder, "0") outf = open(outfile, 'w+b') outf.write(outheader) written=0 for fi in files: for nca in nsp: if nca._path==fi: nca=Nca(nca) crypto1=nca.header.getCryptoType() crypto2=nca.header.getCryptoType2() if crypto2>crypto1: masterKeyRev=crypto2 if crypto2<=crypto1: masterKeyRev=crypto1 crypto = aes128.AESECB(Keys.keyAreaKey(Keys.getMasterKeyIndex(masterKeyRev), nca.header.keyIndex)) hcrypto = aes128.AESXTS(uhx(Keys.get('header_key'))) gc_flag='00'*0x01 crypto1=nca.header.getCryptoType() crypto2=nca.header.getCryptoType2() if nca.header.getRightsId() != 0: nca.rewind() if crypto2>crypto1: masterKeyRev=crypto2 if crypto2<=crypto1: masterKeyRev=crypto1 from mtp_tools import get_nca_ticket check,titleKey=get_nca_ticket(filepath,fi) if check==False: sys.exit("Can't verify titleckey") titleKeyDec = Keys.decryptTitleKey(titleKey, Keys.getMasterKeyIndex(int(masterKeyRev))) encKeyBlock = crypto.encrypt(titleKeyDec * 4) if str(keypatch) != "False": t = tqdm(total=False, unit='B', unit_scale=False, leave=False) if keypatch < nca.header.getCryptoType2(): encKeyBlock,crypto1,crypto2=squirrelNSP.get_new_cryptoblock(squirrelNSP,nca,keypatch,encKeyBlock,t) t.close() if nca.header.getRightsId() == 0: nca.rewind() encKeyBlock = nca.header.getKeyBlock() if str(keypatch) != "False": t = tqdm(total=False, unit='B', unit_scale=False, leave=False) if keypatch < nca.header.getCryptoType2(): encKeyBlock,crypto1,crypto2=squirrelNSP.get_new_cryptoblock(squirrelNSP,nca,keypatch,encKeyBlock,t) t.close() nca.rewind() i=0 newheader=nsp.get_newheader(nca,encKeyBlock,crypto1,crypto2,hcrypto,gc_flag) outf.write(newheader) written+=len(newheader) nca.seek(0xC00) break else:pass
def decompress_nsz(input, output, buffer=65536): f = Nsp(input, 'r+b') f.decompress_direct(output, buffer) f.flush() f.close()
def main(): global err try: parser = ArgumentParser() parser.add_argument('file', nargs='*') parser.add_argument('-C', action="store_true", help='Compress NSP') parser.add_argument('-D', action="store_true", help='Decompress NSZ') parser.add_argument('-l', '--level', type=int, default=18, help='Compression Level') parser.add_argument( '-B', '--block', action="store_true", default=False, help= 'Uses highly multithreaded block compression with random read access allowing compressed games to be played without decompression in the future however this comes with a low compression ratio cost. Current title installers do not support this yet.' ) parser.add_argument( '-s', '--bs', type=int, default=20, help= 'Block Size for random read access 2^x while x between 14 and 32. Default is 20 => 1 MB. Current title installers do not support this yet.' ) parser.add_argument( '-V', '--verify', action="store_true", default=False, help= 'Verifies files after compression raising an unhandled exception on hash mismatch and verify existing NSP and NSZ files when given as parameter' ) parser.add_argument( '-p', '--parseCnmt', action="store_true", default=False, help= 'Extract TitleId/Version from Cnmt if this information cannot be obtained from the filename. Required for skipping/overwriting existing files and --rm-old-version to work properly if some not every file is named properly. Supported filenames: *TitleID*[vVersion]*' ) parser.add_argument( '-t', '--threads', type=int, default=-1, help= 'Number of threads to compress with. Numbers < 1 corresponds to the number of logical CPU cores.' ) parser.add_argument('-o', '--output', nargs='?', help='Directory to save the output NSZ files') parser.add_argument( '-w', '--overwrite', action="store_true", default=False, help= 'Continues even if there already is a file with the same name or title id inside the output directory' ) parser.add_argument('-r', '--rm-old-version', action="store_true", default=False, help='Removes older version if found') parser.add_argument('-i', '--info', help='Show info about title or file') parser.add_argument('--depth', type=int, default=1, help='Max depth for file info and extraction') parser.add_argument('-x', '--extract', nargs='+', help='extract / unpack a NSP') parser.add_argument('-c', '--create', help='create / pack a NSP') parser.add_argument( '--rm-source', action='store_true', default=False, help= 'Deletes source file/s after compressing/decompressing. It\'s recommended to only use this in combination with --verify' ) args = parser.parse_args() outfolder = str(Path(args.output)) if args.output else str(Path('.')) Print.info('') Print.info(' NSZ v2.1 ,;:;;,') Print.info(' ;;;;;') Print.info(' .=\', ;:;;:,') Print.info(' /_\', "=. \';:;:;') Print.info(' @=:__, \,;:;:\'') Print.info(' _(\.= ;:;;\'') Print.info(' `"_( _/="`') Print.info(' `"\'') Print.info('') if args.extract: for filePath in args.extract: f = factory(filePath) f.open(filePath, 'rb') dir = Path(Path(filePath).name).suffix[0] f.unpack(dir) f.close() if args.create: Print.info('creating ' + args.create) nsp = Nsp.Nsp(None, None) nsp.path = args.create nsp.pack(args.file) if args.C: targetDict = CreateTargetDict(outfolder, args.parseCnmt, ".nsz") for i in args.file: for filePath in expandFiles(i): try: if filePath.endswith('.nsp'): if not AllowedToWriteOutfile( filePath, ".nsz", targetDict, args.rm_old_version, args.overwrite, args.parseCnmt): continue compress(filePath, args) if args.rm_source: delete_source_file(filePath) except KeyboardInterrupt: raise except BaseException as e: Print.error('Error when compressing file: %s' % filePath) err.append({ "filename": filePath, "error": format_exc() }) print_exc() if args.D: targetDict = CreateTargetDict(outfolder, args.parseCnmt, ".nsp") for i in args.file: for filePath in expandFiles(i): try: if filePath.endswith('.nsz'): if not AllowedToWriteOutfile( filePath, ".nsp", targetDict, args.rm_old_version, args.overwrite, args.parseCnmt): continue decompress(filePath, args.output) if args.rm_source: delete_source_file(filePath) except KeyboardInterrupt: raise except BaseException as e: Print.error('Error when decompressing file: %s' % filePath) err.append({ "filename": filePath, "error": format_exc() }) print_exc() if args.info: f = factory(args.info) f.open(args.info, 'r+b') f.printInfo(args.depth + 1) if args.verify and not args.C and not args.D: for i in args.file: for filePath in expandFiles(i): try: if filePath.endswith('.nsp') or filePath.endswith( '.nsz'): if filePath.endswith('.nsp'): print("[VERIFY NSP] {0}".format(i)) if filePath.endswith('.nsz'): print("[VERIFY NSZ] {0}".format(i)) verify(filePath, False) except KeyboardInterrupt: raise except BaseException as e: Print.error('Error when verifying file: %s' % filePath) err.append({ "filename": filePath, "error": format_exc() }) print_exc() if len(argv) == 1: pass except KeyboardInterrupt: Print.info('Keyboard exception') except BaseException as e: Print.info('nut exception: ' + str(e)) raise if err: Print.info('\033[93m\033[1mErrors:') for e in err: Print.info('\033[0mError when processing %s' % e["filename"]) Print.info(e["error"]) Print.info('Done!')
def gen_mxci_parts(input_files, cachefolder=None, keypatch=False): from listmanager import calculate_name if keypatch != False: try: keypatch = int(keypatch) except: keypatch = False if cachefolder == None: cachefolder = os.path.join(ztools_dir, '_mtp_cache_') if not os.path.exists(cachefolder): os.makedirs(cachefolder) else: for f in os.listdir(cachefolder): fp = os.path.join(cachefolder, f) try: shutil.rmtree(fp) except OSError: os.remove(fp) end_name, prlist = calculate_name(input_files, romanize=True, ext='.xci') print(f"Calculated name {end_name}") outheader, properheadsize, sz, files = gen_multi_file_header( prlist, input_files) properheadsize = len(outheader) outfile = os.path.join(cachefolder, "0") outf = open(outfile, 'w+b') outf.write(outheader) # print(properheadsize) # print(bucketsize) i = 0 sum = properheadsize for fi in files: for filepath in input_files: if filepath.endswith('xci'): xci = squirrelXCI(filepath) written = 0 for nspF in xci.hfs0: if str(nspF._path) == "secure": for nca in nspF: if nca._path == fi: nca = Nca(nca) crypto1 = nca.header.getCryptoType() crypto2 = nca.header.getCryptoType2() if crypto2 > crypto1: masterKeyRev = crypto2 if crypto2 <= crypto1: masterKeyRev = crypto1 crypto = aes128.AESECB( Keys.keyAreaKey( Keys.getMasterKeyIndex(masterKeyRev), nca.header.keyIndex)) hcrypto = aes128.AESXTS( uhx(Keys.get('header_key'))) gc_flag = '00' * 0x01 crypto1 = nca.header.getCryptoType() crypto2 = nca.header.getCryptoType2() if nca.header.getRightsId() != 0: nca.rewind() if crypto2 > crypto1: masterKeyRev = crypto2 if crypto2 <= crypto1: masterKeyRev = crypto1 from mtp_tools import get_nca_ticket check, titleKey = get_nca_ticket( filepath, fi) if check == False: sys.exit("Can't verify titleckey") titleKeyDec = Keys.decryptTitleKey( titleKey, Keys.getMasterKeyIndex( int(masterKeyRev))) encKeyBlock = crypto.encrypt(titleKeyDec * 4) if str(keypatch) != "False": t = tqdm(total=False, unit='B', unit_scale=False, leave=False) if keypatch < nca.header.getCryptoType2( ): encKeyBlock, crypto1, crypto2 = squirrelXCI.get_new_cryptoblock( squirrelXCI, nca, keypatch, encKeyBlock, t) t.close() if nca.header.getRightsId() == 0: nca.rewind() encKeyBlock = nca.header.getKeyBlock() if str(keypatch) != "False": t = tqdm(total=False, unit='B', unit_scale=False, leave=False) if keypatch < nca.header.getCryptoType2( ): encKeyBlock, crypto1, crypto2 = squirrelXCI.get_new_cryptoblock( squirrelXCI, nca, keypatch, encKeyBlock, t) t.close() nca.rewind() i = 0 newheader = xci.get_newheader( nca, encKeyBlock, crypto1, crypto2, hcrypto, gc_flag) outf.write(newheader) written += len(newheader) nca.seek(0xC00) break else: pass xci.flush() xci.close() elif filepath.endswith('nsp'): nsp = squirrelNSP(filepath) written = 0 for nca in nsp: if nca._path == fi: nca = Nca(nca) crypto1 = nca.header.getCryptoType() crypto2 = nca.header.getCryptoType2() if crypto2 > crypto1: masterKeyRev = crypto2 if crypto2 <= crypto1: masterKeyRev = crypto1 crypto = aes128.AESECB( Keys.keyAreaKey( Keys.getMasterKeyIndex(masterKeyRev), nca.header.keyIndex)) hcrypto = aes128.AESXTS(uhx(Keys.get('header_key'))) gc_flag = '00' * 0x01 crypto1 = nca.header.getCryptoType() crypto2 = nca.header.getCryptoType2() if nca.header.getRightsId() != 0: nca.rewind() if crypto2 > crypto1: masterKeyRev = crypto2 if crypto2 <= crypto1: masterKeyRev = crypto1 from mtp_tools import get_nca_ticket check, titleKey = get_nca_ticket(filepath, fi) if check == False: sys.exit("Can't verify titleckey") titleKeyDec = Keys.decryptTitleKey( titleKey, Keys.getMasterKeyIndex(int(masterKeyRev))) encKeyBlock = crypto.encrypt(titleKeyDec * 4) if str(keypatch) != "False": t = tqdm(total=False, unit='B', unit_scale=False, leave=False) if keypatch < nca.header.getCryptoType2(): encKeyBlock, crypto1, crypto2 = squirrelNSP.get_new_cryptoblock( squirrelNSP, nca, keypatch, encKeyBlock, t) t.close() if nca.header.getRightsId() == 0: nca.rewind() encKeyBlock = nca.header.getKeyBlock() if str(keypatch) != "False": t = tqdm(total=False, unit='B', unit_scale=False, leave=False) if keypatch < nca.header.getCryptoType2(): encKeyBlock, crypto1, crypto2 = squirrelNSP.get_new_cryptoblock( squirrelNSP, nca, keypatch, encKeyBlock, t) t.close() nca.rewind() i = 0 newheader = nsp.get_newheader(nca, encKeyBlock, crypto1, crypto2, hcrypto, gc_flag) outf.write(newheader) written += len(newheader) nca.seek(0xC00) break else: pass nsp.flush() nsp.close() outf.flush() outf.close() tfile = os.path.join(cachefolder, "files.csv") with open(tfile, 'w') as csvfile: csvfile.write("{}|{}|{}|{}|{}|{}\n".format("step", "filepath", "size", "targetsize", "off1", "off2")) csvfile.write("{}|{}|{}|{}|{}|{}\n".format(0, outfile, properheadsize + written, properheadsize, 0, properheadsize)) k = 0 l = 0 for fi in files: for filepath in input_files: if filepath.endswith('xci'): files_list = sq_tools.ret_xci_offsets(filepath) elif filepath.endswith('nsp'): files_list = sq_tools.ret_nsp_offsets(filepath) for j in files_list: if j[0] == fi: csvfile.write("{}|{}|{}|{}|{}|{}\n".format( k + 1, outfile, properheadsize + written, 0xC00, (properheadsize + l * 0xC00), (properheadsize + (l * 0xC00) + 0xC00))) off1 = j[1] + 0xC00 off2 = j[2] targetsize = j[3] - 0xC00 csvfile.write("{}|{}|{}|{}|{}|{}\n".format( k + 2, filepath, (os.path.getsize(filepath)), targetsize, off1, off2)) break k += 2 l += 1 return end_name