Esempio n. 1
0
def compress(filePath,
             ofolder=None,
             level=17,
             threads=0,
             delta=False,
             ofile=None,
             buffer=65536,
             pos=False,
             nthreads=False):
    isthreaded = False
    if pos != False:
        isthreaded = True
    elif str(pos) == '0':
        isthreaded = True
    else:
        pos = 0
    pos = int(pos)
    files_list = sq_tools.ret_nsp_offsets(filePath)
    files = list()
    filesizes = list()
    if isthreaded == True and nthreads != False:
        tqlist = list()
        for i in range(nthreads):
            tq = tqdm(total=0,
                      unit='B',
                      unit_scale=True,
                      leave=False,
                      position=i)
            tqlist.append(tq)
    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]
        cnmtfile = entry[0]
        if cnmtfile.endswith('.cnmt.nca'):
            f = squirrelNSP(filePath, 'rb')
            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':
                    test1 = str(row['NcaId']) + '.nca'
                    test2 = str(row['NcaId']) + '.ncz'
                    if test1 in fplist or test2 in fplist:
                        # print(str(row['NcaId'])+'.nca')
                        files.append(str(row['NcaId']) + '.nca')
                        filesizes.append(int(row['Size']))
                else:
                    # print(str(row['NcaId'])+'.cnmt.nca')
                    files.append(str(row['NcaId']) + '.cnmt.nca')
                    filesizes.append(int(row['Size']))
    for k in range(len(files_list)):
        entry = files_list[k]
        fp = entry[0]
        sz = int(entry[3])
        if fp.endswith('xml'):
            files.append(fp)
            filesizes.append(sz)
    for k in range(len(files_list)):
        entry = files_list[k]
        fp = entry[0]
        sz = int(entry[3])
        if fp.endswith('.tik'):
            files.append(fp)
            filesizes.append(sz)
    for k in range(len(files_list)):
        entry = files_list[k]
        fp = entry[0]
        sz = int(entry[3])
        if fp.endswith('.cert'):
            files.append(fp)
            filesizes.append(sz)
    nspheader = sq_tools.gen_nsp_header(files, filesizes)
    properheadsize = len(nspheader)

    compressionLevel = int(level)
    container = nutFs.factory(filePath)

    container.open(filePath, 'rb')

    CHUNK_SZ = buffer

    if ofolder is None and ofile is None:
        nszPath = filePath[0:-1] + 'z'
    elif ofolder is not None:
        nszPath = os.path.join(ofolder, os.path.basename(filePath[0:-1] + 'z'))
    elif ofile is not None:
        nszPath = ofile

    tsize = properheadsize
    for sz in filesizes:
        tsize += sz
    if isthreaded == True:
        from colorama import Fore
        colors = Fore.__dict__
        k = 0
        l = pos
        for col in colors:
            if l > len(colors):
                l = l - len(colors)
            color = colors[col]
            if k == (l + 1):
                break
            else:
                k += 1
        t = tqdm(total=tsize,
                 unit='B',
                 unit_scale=True,
                 leave=False,
                 position=pos,
                 bar_format="{l_bar}%s{bar}%s{r_bar}" % (color, Fore.RESET))
    else:
        t = tqdm(total=tsize,
                 unit='B',
                 unit_scale=True,
                 leave=False,
                 position=0)
    # nszPath = os.path.abspath(nszPath)

    nszPath = Path(filePath)
    nszPath = os.path.join(nszPath.parents[0],
                           os.path.basename(filePath[0:-1] + 'z'))

    if isthreaded == False:
        t.write('\n Compressing with level %d and %d threads' %
                (compressionLevel, threads))
        t.write('%s -> %s \n' % (filePath, nszPath))
    newNsp = nutFs.Pfs0.Pfs0Stream(nszPath, headsize=properheadsize)

    for file in files:
        for nspf in container:
            if nspf._path == file:
                if isinstance(
                        nspf, nutFs.Nca.Nca
                ) and nspf.header.contentType == nutFs.Type.Content.DATA and delta == False:
                    if isthreaded == False:
                        t.write('-> Skipping delta fragment')
                    continue

                if isinstance(nspf, nutFs.Nca.Nca) and (
                        nspf.header.contentType == nutFs.Type.Content.PROGRAM
                        or nspf.header.contentType
                        == nutFs.Type.Content.PUBLIC_DATA):
                    if isNcaPacked(nspf):
                        cctx = zstandard.ZstdCompressor(level=compressionLevel,
                                                        threads=threads)

                        newFileName = nspf._path[0:-1] + 'z'

                        f = newNsp.add(newFileName, nspf.size, t, isthreaded)

                        start = f.tell()

                        nspf.seek(0)
                        f.write(nspf.read(ncaHeaderSize))
                        written = ncaHeaderSize

                        compressor = cctx.stream_writer(f)

                        sections = get_sections(nspf)

                        header = b'NCZSECTN'
                        header += len(sections).to_bytes(8, 'little')

                        i = 0
                        for fs in sections:
                            i += 1
                            header += fs.offset.to_bytes(8, 'little')
                            header += fs.size.to_bytes(8, 'little')
                            header += fs.cryptoType.to_bytes(8, 'little')
                            header += b'\x00' * 8
                            header += fs.cryptoKey
                            header += fs.cryptoCounter

                        f.write(header)
                        written += len(header)
                        timestamp = time.time()
                        decompressedBytes = ncaHeaderSize
                        totsize = 0
                        for fs in sections:
                            totsize += fs.size

                        for section in sections:
                            #print('offset: %x\t\tsize: %x\t\ttype: %d\t\tiv%s' % (section.offset, section.size, section.cryptoType, str(hx(section.cryptoCounter))))
                            o = nspf.partition(offset=section.offset,
                                               size=section.size,
                                               n=None,
                                               cryptoType=section.cryptoType,
                                               cryptoKey=section.cryptoKey,
                                               cryptoCounter=bytearray(
                                                   section.cryptoCounter),
                                               autoOpen=True)

                            while not o.eof():
                                buffer = o.read(CHUNK_SZ)
                                t.update(len(buffer))
                                if len(buffer) == 0:
                                    raise IOError('read failed')

                                written += compressor.write(buffer)

                                decompressedBytes += len(buffer)

                        compressor.flush(zstandard.FLUSH_FRAME)

                        elapsed = time.time() - timestamp
                        minutes = elapsed / 60
                        seconds = elapsed % 60

                        speed = 0 if elapsed == 0 else (nspf.size / elapsed)

                        written = f.tell() - start
                        if isthreaded == False:
                            t.write(
                                '\n  * Compressed at %d%% from %s to %s  - %s'
                                % (int(written * 100 / nspf.size),
                                   str(sq_tools.getSize(decompressedBytes)),
                                   str(sq_tools.getSize(written)), nspf._path))
                            t.write(
                                '  * Compressed in %02d:%02d at speed: %.1f MB/s\n'
                                % (minutes, seconds, speed / 1000000.0))
                        newNsp.resize(newFileName, written)
                        continue
                    else:
                        print('not packed!')

                f = newNsp.add(nspf._path, nspf.size, t, isthreaded)
                nspf.seek(0)
                while not nspf.eof():
                    buffer = nspf.read(CHUNK_SZ)
                    t.update(len(buffer))
                    f.write(buffer)
    t.close()
    newNsp.close()
    if isthreaded == True and nthreads != False:
        for i in range(nthreads):
            tqlist[i].close()
Esempio n. 2
0
def gen_xci_parts_spec1(filepath=None,remote=None,target_cnmt=None,cachefolder=None,keypatch=False,files_list=None):
	if filepath=="":
		filepath=None
	if remote=="":
		remote=None
	if remote==None:
		test=filepath.split('|');TD=None
		if len(test)<2:
			filepath=test[0]		
			lib,TD,libpath=get_library_from_path(remote_lib_file,filepath)
		else:
			filepath=test[0]	
			TD=test[1]			
			if str(TD).upper()=="NONE":
				TD=None	
		ID,name,type,size,md5,remote=DrivePrivate.get_Data(filepath,TD=TD,Print=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)
	if files_list==None:		
		files_list=DriveTools.get_files_from_head(remote,remote.name)
	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:
			metadict,d1,d2=DriveTools.get_cnmt_data(target=cnmtfile,file=remote)
			ncadata=metadict['ncadata']		
			for j in range(len(ncadata)):		
				row=ncadata[j]
				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				
	remote.rewind()				
	outheader = sq_tools.gen_nsp_header(files,filesizes)	
	properheadsize=len(outheader)
	# print(properheadsize)
	# print(bucketsize)
	i=0;sum=properheadsize;
	outfile=os.path.join(cachefolder, "0")
	outf = open(outfile, 'w+b')		
	outf.write(outheader)	
	written=0
	for fi in files:
		if fi.endswith('nca') or fi.endswith('ncz') :	
			for i in range(len(files_list)):
				if str(files_list[i][0]).lower() == str(fi).lower():
					nca_name=files_list[i][0]
					off1=files_list[i][1]
					off2=files_list[i][2]
					nca_size=files_list[i][3]
					break				
			data=remote.read_at(off1,nca_size)		
			ncaHeader = NcaHeader()
			ncaHeader.open(MemoryFile(remote.read_at(off1,0x400), FsType.Crypto.XTS, uhx(Keys.get('header_key'))))	
			crypto1=ncaHeader.getCryptoType()
			crypto2=ncaHeader.getCryptoType2()		
			if crypto2>crypto1:
				masterKeyRev=crypto2
			if crypto2<=crypto1:	
				masterKeyRev=crypto1									
			crypto = aes128.AESECB(Keys.keyAreaKey(Keys.getMasterKeyIndex(masterKeyRev), ncaHeader.keyIndex))
			hcrypto = aes128.AESXTS(uhx(Keys.get('header_key')))	
			gc_flag='00'*0x01					
			crypto1=ncaHeader.getCryptoType()
			crypto2=ncaHeader.getCryptoType2()					
			if ncaHeader.getRightsId() != 0:					
				ncaHeader.rewind()	
				if crypto2>crypto1:
					masterKeyRev=crypto2
				if crypto2<=crypto1:	
					masterKeyRev=crypto1								
				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 < ncaHeader.getCryptoType2():
						encKeyBlock,crypto1,crypto2=get_new_cryptoblock(ncaHeader,keypatch,encKeyBlock,t)	
					t.close()
			if ncaHeader.getRightsId() == 0:
				ncaHeader.rewind()											
				encKeyBlock = ncaHeader.getKeyBlock()	
				if str(keypatch) != "False":
					t = tqdm(total=False, unit='B', unit_scale=False, leave=False)								
					if keypatch < ncaHeader.getCryptoType2():
						encKeyBlock,crypto1,crypto2=get_new_cryptoblock(ncaHeader,keypatch,encKeyBlock,t)	
					t.close()									
			ncaHeader.rewind()					
			i=0				
			newheader=get_newheader(MemoryFile(remote.read_at(off1,0xC00)),encKeyBlock,crypto1,crypto2,hcrypto,gc_flag)	
			outf.write(newheader)
			written+=len(newheader)
			break					
		else:pass					
	outf.flush()							
	outf.close()	
	tfile=os.path.join(cachefolder, "remote_files.csv")	
	with open(tfile,'w') as csvfile:	
		csvfile.write("{}|{}|{}|{}|{}|{}|{}\n".format("step","filepath","size","targetsize","off1","off2","token"))	
		csvfile.write("{}|{}|{}|{}|{}|{}|{}\n".format(0,outfile,properheadsize+written,properheadsize,0,properheadsize,"False"))	
		k=0;l=0	
		for fi in files:
			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),"False"))	
					off1=j[1]+0xC00
					off2=j[2]
					targetsize=j[3]-0xC00				
					URL='https://www.googleapis.com/drive/v3/files/'+remote.ID+'?alt=media'		
					token=remote.access_token					
					csvfile.write("{}|{}|{}|{}|{}|{}|{}\n".format(k+2,URL,remote.size,targetsize,off1,off2,token))	
					break
			k+=2;l+=1	
	nspname="test.nsp"				
	try:
		g=remote.name			
		g0=[pos for pos, char in enumerate(g) if char == '[']
		g0=(g[0:g0[0]]).strip()			
		titleid=metadict['titleid']
		titleversion=metadict['version']
		ctype=metadict['ctype']
		nspname=f"{g0} [{titleid}] [v{titleversion}] [{ctype}].nsp"
	except:pass
	return nspname						
Esempio n. 3
0
def get_header_size(filepath):
	properheadsize=0;sz=0
	if filepath.endswith('xci') or filepath.endswith('xcz'):
		files_list=sq_tools.ret_xci_offsets(filepath)
		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]
			cnmtfile=entry[0]
			if cnmtfile.endswith('.cnmt.nca'):
				f=squirrelXCI(filepath)
				titleid,titleversion,base_ID,keygeneration,rightsId,RSV,RGV,ctype,metasdkversion,exesdkversion,hasHtmlManual,Installedsize,DeltaSize,ncadata=f.get_data_from_cnmt(cnmtfile)
				for j in range(len(ncadata)):
					row=ncadata[j]
					# print(row)
					if row['NCAtype']!='Meta':
						test1=str(row['NcaId'])+'.nca';test2=str(row['NcaId'])+'.ncz'
						if test1 in fplist or test2 in fplist:
							# print(str(row['NcaId'])+'.nca')
							files.append(str(row['NcaId'])+'.nca')
							filesizes.append(int(row['Size']))	
							sz+=int(row['Size'])		
					elif row['NCAtype']=='Meta':
						# print(str(row['NcaId'])+'.cnmt.nca')
						files.append(str(row['NcaId'])+'.cnmt.nca')
						filesizes.append(int(row['Size']))	
						sz+=int(row['Size'])
		sec_hashlist=list()
		try:
			for file in files:
				sha,size,gamecard=f.file_hash(file)
				# print(sha)
				if sha != False:
					sec_hashlist.append(sha)	
		except BaseException as e:
			Print.error('Exception: ' + str(e))									
		f.flush()
		f.close()	
		xci_header,game_info,sig_padding,xci_certificate,root_header,upd_header,norm_header,sec_header,rootSize,upd_multiplier,norm_multiplier,sec_multiplier=sq_tools.get_xciheader(files,filesizes,sec_hashlist)			
		outheader=xci_header
		outheader+=game_info
		outheader+=sig_padding
		outheader+=xci_certificate
		outheader+=root_header
		outheader+=upd_header
		outheader+=norm_header
		outheader+=sec_header		
	elif filepath.endswith('nsp') or filepath.endswith('nsz'):
		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])
		for i in range(len(files_list)):
			entry=files_list[i]
			cnmtfile=entry[0]
			if cnmtfile.endswith('.cnmt.nca'):
				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':
						test1=str(row['NcaId'])+'.nca';test2=str(row['NcaId'])+'.ncz'
						if test1 in fplist or test2 in fplist:
							# print(str(row['NcaId'])+'.nca')
							files.append(str(row['NcaId'])+'.nca')
							filesizes.append(int(row['Size']))	
							sz+=int(row['Size'])								
					elif row['NCAtype']=='Meta':
						# print(str(row['NcaId'])+'.cnmt.nca')
						files.append(str(row['NcaId'])+'.cnmt.nca')
						filesizes.append(int(row['Size']))
						sz+=int(row['Size'])												
		f.flush()
		f.close()	
		outheader = sq_tools.gen_nsp_header(files,filesizes)			
	properheadsize=len(outheader)
	return properheadsize,keygeneration,sz
Esempio n. 4
0
def gen_xci_parts(filepath,cachefolder=None,keepupd=False,id_target=False,keypatch=False,export_type='csv'):
	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_xci_offsets(filepath)
	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]
		cnmtfile=entry[0]
		if cnmtfile.endswith('.cnmt.nca'):
			f=squirrelXCI(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 or test2 in fplist:
						# print(str(row['NcaId'])+'.nca')
						files.append(str(row['NcaId'])+'.nca')
						filesizes.append(int(row['Size']))					
				elif 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 or test2 in fplist:
						# print(str(row['NcaId'])+'.nca')
						files.append(str(row['NcaId'])+'.nca')
						filesizes.append(int(row['Size']))				
	f.flush()
	f.close()						
	outheader = sq_tools.gen_nsp_header(files,filesizes)	
	properheadsize=len(outheader)
	# print(properheadsize)
	# print(bucketsize)
	i=0;sum=properheadsize;
	for file in files:
		# print(file)
		# print(filesizes[i])
		if i<(len(files)-1):
			sum+=filesizes[i]
		i+=1
	# print(sum)
	# print(sum/bucketsize)
	multiplier=math.ceil(sum/bucketsize)
	# print(multiplier)
	remainder = bucketsize*multiplier - sum
	# print(bucketsize*multiplier)
	xci=squirrelXCI(filepath)
	outfile=os.path.join(cachefolder, "0")
	written=0;
	outf = open(outfile, 'w+b')		
	outf.write(outheader)	
	written+=len(outheader)
	for fi in files:
		for nspF in xci.hfs0:
			if str(nspF._path)=="secure":
				for nca in nspF:	
					if nca._path==fi:
						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()	
							encKeyBlock = crypto.encrypt(titleKeyDec * 4)
							if str(keypatch) != "False":
								if keypatch < nca.header.getCryptoType2():
									encKeyBlock,crypto1,crypto2=squirrelXCI.get_new_cryptoblock(nca, keypatch,encKeyBlock,t)	
						if nca.header.getRightsId() == 0:
							nca.rewind()				
							encKeyBlock = nca.header.getKeyBlock()	
							if str(keypatch) != "False":
								if keypatch < nca.header.getCryptoType2():
									encKeyBlock,crypto1,crypto2=squirrelXCI.get_new_cryptoblock(nca, keypatch,encKeyBlock,t)					
						nca.rewind()					
						i=0				
						newheader=xci.get_newheader(nca,encKeyBlock,crypto1,crypto2,hcrypto,gc_flag)		
						outf.write(newheader)
						written+=len(newheader)
						nca.seek(0xC00)	
						if (str(nca.header.contentType) != 'Content.PROGRAM'):
							data=nca.read()	
							nca.close()
							outf.write(data)
							written+=len(data)
						else:
							remainder = bucketsize*multiplier - written
							data=nca.read(remainder)
							nca.close()
							outf.write(data)
							written+=len(data)						
						break					
					else:pass
	outf.close()		
	if export_type=='json':
		files_json=os.path.join(cachefolder, "files.json")	
		d={}
		d['0']={"step": 0,
		  "filepath":outfile ,
		  "size":( bucketsize*multiplier) ,
		  "targetsize":( bucketsize*multiplier) ,
		  "off1":0,
		  "off2":( bucketsize*multiplier)
		}
		for j in files_list:
			if j[0]==files[-1]:
				off1=j[1]
				off2=j[2]
				targetsize=j[3]
		d['1']={"step": 1,
		  "filepath":filepath ,
		  "size":( os.path.getsize(filepath)) ,
		  "targetsize":targetsize,
		  "off1":off1,
		  "off2":off2
		}	
		app_json = json.dumps(d, indent=1)
		with open(files_json, 'w') as json_file:
		  json_file.write(app_json)			
		# print(os.path.getsize(filepath))	
	else:
		for j in files_list:
			if j[0]==files[-1]:
				off1=j[1]
				off2=j[2]
				targetsize=j[3]	
		tfile=os.path.join(cachefolder, "files.csv")
		i=0;
		with open(tfile,'w') as csvfile:
			if i==0:
				csvfile.write("{}|{}|{}|{}|{}|{}\n".format("step","filepath","size","targetsize","off1","off2"))
				i+=1
			if i==1:	
				csvfile.write("{}|{}|{}|{}|{}|{}\n".format(0,outfile,( bucketsize*multiplier),( bucketsize*multiplier),0,( bucketsize*multiplier)))		
				i+=1				
			if i==2:	
				csvfile.write("{}|{}|{}|{}|{}|{}".format(1,filepath,( os.path.getsize(filepath)),targetsize,off1,off2))		
				i+=1			
Esempio n. 5
0
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					
Esempio n. 6
0
def gen_xci_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_xci_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 = squirrelXCI(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
    xci = squirrelXCI(filepath)
    outfile = os.path.join(cachefolder, "0")
    outf = open(outfile, 'w+b')
    outf.write(outheader)
    written = 0
    for fi in files:
        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()
    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 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
    nspname = "test.nsp"
    try:
        g = os.path.basename(filepath)
        g0 = [pos for pos, char in enumerate(g) if char == '[']
        g0 = (g[0:g0[0]]).strip()
        nspname = f"{g0} [{titleid}] [v{titleversion}] [{ctype}].nsp"
    except:
        pass
    return nspname
Esempio n. 7
0
def gen_xci_parts_spec0(filepath,
                        target_cnmt=None,
                        cachefolder=None,
                        keypatch=False,
                        export_type='csv'):
    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)
    program_name = None
    files_list = sq_tools.ret_xci_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 = squirrelXCI(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 or test2 in fplist:
                        # print(str(row['NcaId'])+'.nca')
                        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 or test2 in fplist:
                        # print(str(row['NcaId'])+'.nca')
                        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
    for file in files:
        # print(file)
        # print(filesizes[i])
        if i < (len(files) - 1):
            sum += filesizes[i]
        i += 1
    # print(sum)
    # print(sum/bucketsize)
    multiplier = math.ceil(sum / bucketsize)
    # print(multiplier)
    remainder = bucketsize * multiplier - sum
    # print(bucketsize*multiplier)
    xci = squirrelXCI(filepath)
    outfile = os.path.join(cachefolder, "0")
    written = 0
    outf = open(outfile, 'w+b')
    outf.write(outheader)
    written += len(outheader)
    movoffset = 0
    for fi in files:
        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)
                        movoffset += 0xC00
                        if (str(nca.header.contentType) != 'Content.PROGRAM'):
                            data = nca.read()
                            nca.close()
                            outf.write(data)
                            written += len(data)
                        break
                    else:
                        pass
    xci.flush()
    xci.close()
    outf.close()
    if export_type == 'json':
        files_json = os.path.join(cachefolder, "files.json")
        d = {}
        d['0'] = {
            "step": 0,
            "filepath": outfile,
            "size": (written),
            "targetsize": (written),
            "off1": 0,
            "off2": (written)
        }
        for j in files_list:
            if j[0] == files[-1]:
                off1 = j[1] + 0xC00
                off2 = j[2]
                targetsize = j[3] - 0xC00
        d['1'] = {
            "step": 1,
            "filepath": filepath,
            "size": (os.path.getsize(filepath)),
            "targetsize": targetsize,
            "off1": off1,
            "off2": off2
        }
        app_json = json.dumps(d, indent=1)
        with open(files_json, 'w') as json_file:
            json_file.write(app_json)
        # print(os.path.getsize(filepath))
    else:
        for j in files_list:
            if j[0] == files[-1]:
                off1 = j[1] + 0xC00
                off2 = j[2]
                targetsize = j[3] - 0xC00
        tfile = os.path.join(cachefolder, "files.csv")
        i = 0
        while True:
            with open(tfile, 'w') as csvfile:
                if i == 0:
                    csvfile.write("{}|{}|{}|{}|{}|{}\n".format(
                        "step", "filepath", "size", "targetsize", "off1",
                        "off2"))
                    i += 1
                if i == 1:
                    csvfile.write("{}|{}|{}|{}|{}|{}\n".format(
                        0, outfile, os.path.getsize(outfile),
                        os.path.getsize(outfile), 0, os.path.getsize(outfile)))
                    i += 1
                if i == 2:
                    csvfile.write("{}|{}|{}|{}|{}|{}".format(
                        1, filepath, (os.path.getsize(filepath)), targetsize,
                        off1, off2))
                    i += 1
                    break
    nspname = "test.nsp"
    try:
        g = os.path.basename(filepath)
        g0 = [pos for pos, char in enumerate(g) if char == '[']
        g0 = (g[0:g0[0]]).strip()
        nspname = f"{g0} [{titleid}] [v{titleversion}] [{ctype}].nsp"
    except:
        pass
    return nspname
Esempio n. 8
0
def xci_to_nsz(filepath,buffer=65536,outfile=None,keepupd=False, level = 17,  threads = 0, pos=False, nthreads=False):
	isthreaded=False
	if pos!=False:
		isthreaded=True
	elif str(pos)=='0':
		isthreaded=True
	else:
		pos=0
	pos=int(pos)
	try:
		exchangefile.deletefile()
	except:pass
	f=squirrelXCI(filepath)
	for nspF in f.hfs0:
		if str(nspF._path)=="secure":
			for ticket in nspF:
				if str(ticket._path).endswith('.tik'):
					if isthreaded==False:
						print('- Titlerights: '+ticket.rightsId)
					tk=(str(hex(ticket.getTitleKeyBlock()))[2:]).upper()
					if isthreaded==False:
						print('- Titlekey: '+tk)
					exchangefile.add(ticket.rightsId,tk)
	f.flush()
	f.close()
	files_list=sq_tools.ret_xci_offsets(filepath)
	files=list();filesizes=list()
	if isthreaded==True and nthreads!=False:
		tqlist=list()
		for i in range(nthreads):
			tq = tqdm(total=0, unit='B', unit_scale=True, leave=False,position=i)
			tqlist.append(tq)
	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]
		cnmtfile=entry[0]
		if cnmtfile.endswith('.cnmt.nca'):
			f=squirrelXCI(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':
					test1=str(row['NcaId'])+'.nca';test2=str(row['NcaId'])+'.ncz'
					if test1 in fplist or test2 in fplist:
						# print(str(row['NcaId'])+'.nca')
						files.append(str(row['NcaId'])+'.nca')
						filesizes.append(int(row['Size']))
				else:
					# print(str(row['NcaId'])+'.cnmt.nca')
					files.append(str(row['NcaId'])+'.cnmt.nca')
					filesizes.append(int(row['Size']))
	for k in range(len(files_list)):
		entry=files_list[k]
		fp=entry[0];sz=int(entry[3])
		if fp.endswith('xml'):
			files.append(fp)
			filesizes.append(sz)
	for k in range(len(files_list)):
		entry=files_list[k]
		fp=entry[0];sz=int(entry[3])
		if fp.endswith('.tik'):
			files.append(fp)
			filesizes.append(sz)
	for k in range(len(files_list)):
		entry=files_list[k]
		fp=entry[0];sz=int(entry[3])
		if fp.endswith('.cert'):
			files.append(fp)
			filesizes.append(sz)
	nspheader=sq_tools.gen_nsp_header(files,filesizes)
	properheadsize=len(nspheader)

	compressionLevel=int(level)
	CHUNK_SZ = buffer
	if outfile==None:
		nszPath = filepath[0:-1] + 'z'
	else:
		nszPath=outfile
	nszPath = os.path.abspath(nszPath)

	tsize=properheadsize
	for sz in filesizes:
		tsize+=sz
	if isthreaded==True:
		from colorama import Fore
		colors=Fore.__dict__
		k=0;l=pos
		for col in colors:
			if l>len(colors):
				l=l-len(colors)
			color=colors[col]
			if k==(l+1):
				break
			else:
				k+=1
		t = tqdm(total=tsize, unit='B', unit_scale=True, leave=False,position=pos,bar_format="{l_bar}%s{bar}%s{r_bar}" % (color, Fore.RESET))
	else:
		t = tqdm(total=tsize, unit='B', unit_scale=True, leave=False,position=0)

	if isthreaded==False:
		t.write('Compressing with level %d and %d threads' % (compressionLevel, threads))
		t.write('\n  %s -> %s \n' % (filepath, nszPath))

	newNsp = nutFs.Pfs0.Pfs0Stream(nszPath,headsize=properheadsize,mode='wb+')

	xcicontainer = Xci(filepath)
	# f.compressed_supertrim(buffer,outfile,keepupd,level,threads)
	for nspF in xcicontainer.hfs0:
		if str(nspF._path)=="secure":
			for nca in nspF:
				if isinstance(nca, nutFs.Nca.Nca) and (nca.header.contentType == nutFs.Type.Content.PROGRAM or nca.header.contentType == nutFs.Type.Content.PUBLIC_DATA):
					if isNcaPacked(nca):
						skip=0
					else:
						skip=int(ncaHeaderSize-(((sortedFs(nca))[0]).offset))
					cctx = zstandard.ZstdCompressor(level=compressionLevel, threads = threads)

					newFileName = nca._path[0:-1] + 'z'

					f = newNsp.add(newFileName, nca.size,t,isthreaded)

					start = f.tell()

					nca.seek(0)
					data=nca.read(ncaHeaderSize)
					f.write(data)
					nca.seek(ncaHeaderSize)

					written = ncaHeaderSize

					compressor = cctx.stream_writer(f)

					sections = get_sections(nca)

					header = b'NCZSECTN'
					header += len(sections).to_bytes(8, 'little')

					i = 0
					for fs in sections:
						i += 1
						if skip>0:
							header += (fs.offset+skip).to_bytes(8, 'little')
							header += (fs.size-skip).to_bytes(8, 'little')
							header += fs.cryptoType.to_bytes(8, 'little')
							header += b'\x00' * 8
							header += fs.cryptoKey
							header += fs.cryptoCounter
						else:
							header += fs.offset.to_bytes(8, 'little')
							header += fs.size.to_bytes(8, 'little')
							header += fs.cryptoType.to_bytes(8, 'little')
							header += b'\x00' * 8
							header += fs.cryptoKey
							header += fs.cryptoCounter

					f.write(header)
					written += len(header)
					timestamp = time.time()
					decompressedBytes = ncaHeaderSize
					totsize=0
					for fs in sections:
						totsize+=fs.size
					c0=0
					for section in sections:
						#print('offset: %x\t\tsize: %x\t\ttype: %d\t\tiv%s' % (section.offset, section.size, section.cryptoType, str(hx(section.cryptoCounter))))
						o = nca.partition(offset = section.offset, size = section.size, n = None, cryptoType = section.cryptoType, cryptoKey = section.cryptoKey, cryptoCounter = bytearray(section.cryptoCounter), autoOpen = True)
						if c0==0 and skip>0:
							o.seek(skip)
						while not o.eof():
							buffer = o.read(CHUNK_SZ)
							t.update(len(buffer))
							if len(buffer) == 0:
								raise IOError('read failed')

							written += compressor.write(buffer)

							decompressedBytes += len(buffer)
						c0+=1
					compressor.flush(zstandard.FLUSH_FRAME)

					elapsed = time.time() - timestamp
					minutes = elapsed / 60
					seconds = elapsed % 60

					speed = 0 if elapsed == 0 else (nca.size / elapsed)

					written = f.tell() - start
					if isthreaded==False:
						t.write('\n  * Compressed at %d%% from %s to %s  - %s' % (int(written * 100 / nca.size), str(sq_tools.getSize(decompressedBytes)), str(sq_tools.getSize(written)), nca._path))
						t.write('  * Compressed in %02d:%02d at speed: %.1f MB/s\n' % (minutes, seconds, speed / 1000000.0))
					newNsp.resize(newFileName, written)
					continue

				f = newNsp.add(nca._path, nca.size,t,isthreaded)

				nca.seek(0)
				while not nca.eof():
					buffer = nca.read(CHUNK_SZ)
					t.update(len(buffer))
					f.write(buffer)
	t.close()
	newNsp.close()
	try:
		exchangefile.deletefile()
	except:pass
	if isthreaded==True and nthreads!=False:
		for i in range(nthreads):
			tqlist[i].close()
	return nszPath
def decompress_nsz(remote, ofolder):
    buf = 64 * 1024
    buffer = buf
    endname = remote.name[:-1] + 'p'
    output = os.path.join(ofolder, endname)
    files_list = DriveTools.get_files_from_head(remote, remote.name)
    remote.rewind()
    print('Decompressing {}'.format(remote.name))
    print('- Parsing headers...')
    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]
        cnmtfile = entry[0]
        metadict = {}
        if cnmtfile.endswith('.cnmt.nca'):
            metadict, d1, d2 = DriveTools.get_cnmt_data(target=cnmtfile,
                                                        file=remote)
            ncadata = metadict['ncadata']
            for j in range(len(ncadata)):
                row = ncadata[j]
                # print(row)
                if row['NCAtype'] != 'Meta':
                    test1 = str(row['NcaId']) + '.nca'
                    test2 = str(row['NcaId']) + '.ncz'
                    if test1 in fplist or test2 in fplist:
                        # print(str(row['NcaId'])+'.nca')
                        files.append(str(row['NcaId']) + '.nca')
                        filesizes.append(int(row['Size']))
                else:
                    # print(str(row['NcaId'])+'.cnmt.nca')
                    files.append(str(row['NcaId']) + '.cnmt.nca')
                    filesizes.append(int(row['Size']))
            for k in range(len(files_list)):
                entry = files_list[k]
                fp = entry[0]
                sz = int(entry[3])
                if fp.endswith('xml'):
                    files.append(fp)
                    filesizes.append(sz)
            for k in range(len(files_list)):
                entry = files_list[k]
                fp = entry[0]
                sz = int(entry[3])
                if fp.endswith('.tik'):
                    files.append(fp)
                    filesizes.append(sz)
            for k in range(len(files_list)):
                entry = files_list[k]
                fp = entry[0]
                sz = int(entry[3])
                if fp.endswith('.cert'):
                    files.append(fp)
                    filesizes.append(sz)
    nspheader = sq_tools.gen_nsp_header(files, filesizes)
    totsize = 0
    for s in filesizes:
        totsize += s
    # Hex.dump(nspheader)
    # print(totsize)
    print(files)
    t = tqdm(total=totsize, unit='B', unit_scale=True, leave=False)
    with open(output, 'wb') as o:
        o.write(nspheader)
        t.update(len(nspheader))
    for file in files:
        if file.endswith('cnmt.nca'):
            for i in range(len(files_list)):
                if str(files_list[i][0]).lower() == str(file).lower():
                    nca_name = files_list[i][0]
                    off1 = files_list[i][1]
                    off2 = files_list[i][2]
                    nca_size = files_list[i][3]
                    break
            t.write('- Appending {}'.format(nca_name))
            data = remote.read_at(off1, nca_size)
            with open(output, 'ab') as o:
                o.write(data)
                t.update(len(data))
        elif file.endswith('.nca'):
            for i in range(len(files_list)):
                if str(files_list[i][0]).lower() == str(file).lower():
                    nca_name = files_list[i][0]
                    off1 = files_list[i][1]
                    off2 = files_list[i][2]
                    nca_size = files_list[i][3]
                    t.write('- Appending {}'.format(nca_name))
                    o = open(output, 'ab+')
                    remote.seek(off1, off2)
                    for data in remote.response.iter_content(chunk_size=buf):
                        o.write(data)
                        t.update(len(data))
                        o.flush()
                        if not data:
                            o.close()
                            break
                elif (str(files_list[i][0]).lower())[:-1] == (
                        str(file).lower())[:-1] and str(
                            files_list[i][0]).endswith('ncz'):
                    ncz_name = files_list[i][0]
                    off1 = files_list[i][1]
                    off2 = files_list[i][2]
                    sz = files_list[i][3]
                    t.write('- Calculating compressed sections for: ' +
                            ncz_name)
                    remote.seek(off1, off2)
                    header = remote.read(0x4000)
                    magic = readInt64(remote)
                    sectionCount = readInt64(remote)
                    sections = []
                    for i in range(sectionCount):
                        sections.append(Section(remote))
                    t.write('  Detected {} sections'.format(str(sectionCount)))
                    with open(output, 'rb+') as o:
                        o.seek(0, os.SEEK_END)
                        curr_off = o.tell()
                        t.write('- Appending decompressed {}'.format(ncz_name))
                        t.write('  Writing nca header')
                        o.write(header)
                        t.update(len(header))
                        timestamp = time.time()
                        t.write('  Writing decompressed body in plaintext')
                        count = 0
                        checkstarter = 0
                        dctx = zstandard.ZstdDecompressor()
                        hd = Private.get_html_header(remote.access_token,
                                                     remote.position, off2)
                        remote.get_session(hd)
                        reader = dctx.stream_reader(remote.response.raw,
                                                    read_size=buffer)
                        c = 0
                        spsize = 0
                        for s in sections:
                            end = s.offset + s.size
                            if s.cryptoType == 1:  #plain text
                                t.write('    * Section {} is plaintext'.format(
                                    str(c)))
                                t.write('      %x - %d bytes, Crypto type %d' %
                                        ((s.offset), s.size, s.cryptoType))
                                spsize += s.size
                                end = s.offset + s.size
                                i = s.offset
                                while i < end:
                                    chunkSz = buffer if end - i > buffer else end - i
                                    chunk = reader.read(chunkSz)
                                    if not len(chunk):
                                        break
                                    o.write(chunk)
                                    t.update(len(chunk))
                                    i += chunkSz
                            elif s.cryptoType not in (3, 4):
                                raise IOError('Unknown crypto type: %d' %
                                              s.cryptoType)
                            else:
                                t.write('    * Section {} needs decompression'.
                                        format(str(c)))
                                t.write('      %x - %d bytes, Crypto type %d' %
                                        ((s.offset), s.size, s.cryptoType))
                                t.write('      Key: %s, IV: %s' %
                                        (str(hx(s.cryptoKey)),
                                         str(hx(s.cryptoCounter))))
                                crypto = AESCTR(s.cryptoKey, s.cryptoCounter)
                                spsize += s.size
                                test = int(spsize / (buffer))
                                i = s.offset
                                while i < end:
                                    crypto.seek(i)
                                    chunkSz = buffer if end - i > buffer else end - i
                                    chunk = reader.read(chunkSz)
                                    if not len(chunk):
                                        break
                                    o.write(crypto.encrypt(chunk))
                                    t.update(len(chunk))
                                    i += chunkSz
                            c += 1
                        elapsed = time.time() - timestamp
                        minutes = elapsed / 60
                        seconds = elapsed % 60

                        speed = 0 if elapsed == 0 else (spsize / elapsed)
                        t.write(
                            '\n    Decompressed in %02d:%02d at speed: %.1f MB/s\n'
                            % (minutes, seconds, speed / 1000000.0))
        else:
            for i in range(len(files_list)):
                if str(files_list[i][0]).lower() == str(file).lower():
                    file_name = files_list[i][0]
                    off1 = files_list[i][1]
                    off2 = files_list[i][2]
                    file_size = files_list[i][3]
                    break
            t.write('- Appending {}'.format(file_name))
            data = remote.read_at(off1, file_size)
            with open(output, 'ab') as o:
                o.write(data)
                t.update(len(data))
    t.close()