def writeTex(file, tex): surface = bytearray(GX2Surface().pack( tex.dim, tex.width, tex.height, tex.depth, tex.numMips, tex.format, tex.aa, tex.use, tex.imageSize, 0, tex.mipSize, 0, tex.tileMode, tex.swizzle, tex.alignment, tex.pitch, )) if tex.numMips > 1: for offset in tex.mipOffsets: surface += offset.to_bytes(4, 'big') surface += b'\0' * (15 - tex.numMips) * 4 else: surface += b'\0' * 56 surface += tex.numMips.to_bytes(4, 'big') surface += b'\0' * 4 surface += 1.to_bytes(4, 'big') for comp in tex.compSel: surface += bytes([comp]) surface += b'\0' * 20 ftexPos = tex.headAddr globals.fileData[ftexPos + 4:ftexPos + 0xA0] = surface dataAddr = struct.unpack(">i", globals.fileData[ftexPos + 0xB0:ftexPos + 0xB4])[0] + ftexPos + 0xB0 mipAddr = struct.unpack(">i", globals.fileData[ftexPos + 0xB4:ftexPos + 0xB8])[0] globals.fileData[dataAddr:dataAddr + tex.imageSize] = tex.data if mipAddr: mipAddr += ftexPos + 0xB4 globals.fileData[mipAddr:mipAddr + tex.mipSize] = tex.mipData with open(file, "wb+") as out: out.write(globals.fileData)
def STMtoSTM(f, magic, dest, dest_bom): outputBuffer = bytearray(len(f)) pos = 0 if f[4:6] == b'\xFF\xFE': bom = '<' elif f[4:6] == b'\xFE\xFF': bom = '>' else: print("\nInvalid BOM!") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) if not dest_bom: if dest in ["FSTM", "FSTP"]: dest_bom = '>' else: dest_bom = '<' header = Header(bom) header.data(f, pos) curr = magic dest_ver = {"FSTM": 0x40000, "CSTM": 0x2020000, "FSTP": 0x20100} if magic == dest: dest_ver[dest] = header.version outputBuffer[pos:pos + header.size] = bytes( Header(dest_bom).pack(to_bytes(dest, 4), header.size_, dest_ver[dest], header.fileSize, header.numBlocks, header.reserved)) outputBuffer[4:6] = (b'\xFE\xFF' if dest_bom == '>' else b'\xFF\xFE') pos += header.size dest_type = {"FSTM": 0x4002, "CSTM": 0x4002, "FSTP": 0x4004} sized_refs = {} for i in range(1, header.numBlocks + 1): sized_refs[i] = Ref(bom) sized_refs[i].data(f, pos + 12 * (i - 1)) if sized_refs[i].type_ in [0x4002, 0x4004]: outputBuffer[pos + 12 * (i - 1):pos + 12 * (i - 1) + sized_refs[i].size] = bytes( Ref(dest_bom).pack(dest_type[dest], sized_refs[i].offset)) else: outputBuffer[pos + 12 * (i - 1):pos + 12 * (i - 1) + sized_refs[i].size] = bytes( Ref(dest_bom).pack(sized_refs[i].type_, sized_refs[i].offset)) sized_refs[i].block_size = struct.unpack( bom + "I", f[pos + 12 * (i - 1) + 8:pos + 12 * i])[0] outputBuffer[pos + 12 * (i - 1) + 8:pos + 12 * i] = to_bytes( sized_refs[i].block_size, 4, dest_bom) if sized_refs[1].type_ != 0x4000 or sized_refs[1].offset in [0, -1]: print("\nSomething went wrong!\nError code: 1") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos = sized_refs[1].offset info = BLKHeader(bom) info.data(f, pos) outputBuffer[pos:pos + info.size] = bytes( BLKHeader(dest_bom).pack(info.magic, info.size_)) pos += info.size stmInfo_ref = Ref(bom) stmInfo_ref.data(f, pos) outputBuffer[pos:pos + stmInfo_ref.size] = bytes( Ref(dest_bom).pack(stmInfo_ref.type_, stmInfo_ref.offset)) if stmInfo_ref.type_ != 0x4100 or stmInfo_ref.offset in [0, -1]: print("\nSomething went wrong!\nError code: 2") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) stmInfo_ref.pos = pos pos += stmInfo_ref.size trkInfoTable_ref = Ref(bom) trkInfoTable_ref.data(f, pos) outputBuffer[pos:pos + trkInfoTable_ref.size] = bytes( Ref(dest_bom).pack(trkInfoTable_ref.type_, trkInfoTable_ref.offset)) if trkInfoTable_ref.type_ not in [0x0101, 0]: print("\nSomething went wrong!\nError code: 3") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos += trkInfoTable_ref.size channelInfoTable_ref = Ref(bom) channelInfoTable_ref.data(f, pos) outputBuffer[pos:pos + channelInfoTable_ref.size] = bytes( Ref(dest_bom).pack(channelInfoTable_ref.type_, channelInfoTable_ref.offset)) if channelInfoTable_ref.type_ != 0x0101: print("\nSomething went wrong!\nError code: 4") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos = stmInfo_ref.offset + stmInfo_ref.pos stmInfo = STMInfo(bom) stmInfo.data(f, pos) outputBuffer[pos:pos + stmInfo.size] = bytes( STMInfo(dest_bom).pack( stmInfo.codec, stmInfo.loop_flag, stmInfo.count, stmInfo.sample, stmInfo.loop_start, stmInfo.loop_end, stmInfo.sampleBlk_count, stmInfo.sampleBlk_size, stmInfo.sampleBlk_sampleCount, stmInfo.lSampleBlk_size, stmInfo.lSampleBlk_sampleCount, stmInfo.lSampleBlk_padSize, stmInfo.seek_size, stmInfo.SISC)) pos += stmInfo.size sampleData_ref = Ref(bom) sampleData_ref.data(f, pos) outputBuffer[pos:pos + sampleData_ref.size] = bytes( Ref(dest_bom).pack(sampleData_ref.type_, sampleData_ref.offset)) pos += 8 trkInfoTable = {} trkInfo = {} if trkInfoTable_ref.offset not in [0, -1]: pos = trkInfoTable_ref.offset + stmInfo_ref.pos count = struct.unpack(bom + "I", f[pos:pos + 4])[0] outputBuffer[pos:pos + 4] = to_bytes(count, 4, dest_bom) pos += 4 for i in range(1, count + 1): pos = trkInfoTable_ref.offset + stmInfo_ref.pos + 4 trkInfoTable[i] = Ref(bom) trkInfoTable[i].data(f, pos + 8 * (i - 1)) outputBuffer[pos + 8 * (i - 1):pos + 8 * (i - 1) + trkInfoTable[i].size] = bytes( Ref(dest_bom).pack(trkInfoTable[i].type_, trkInfoTable[i].offset)) if trkInfoTable[i].offset not in [0, -1]: pos = trkInfoTable[i].offset + pos - 4 trkInfo[i] = TRKInfo(bom) trkInfo[i].data(f, pos) outputBuffer[pos:pos + trkInfo[i].size] = bytes( TRKInfo(dest_bom).pack(trkInfo[i].volume, trkInfo[i].pan, trkInfo[i].unk)) pos += trkInfo[i].size channelIndexByteTable_ref = Ref(bom) channelIndexByteTable_ref.data(f, pos) outputBuffer[pos:pos + channelIndexByteTable_ref.size] = bytes( Ref(dest_bom).pack(channelIndexByteTable_ref.type_, channelIndexByteTable_ref.offset)) if channelIndexByteTable_ref.offset not in [0, -1]: pos = channelIndexByteTable_ref.offset + pos - trkInfo[ i].size count = struct.unpack(bom + "I", f[pos:pos + 4])[0] outputBuffer[pos:pos + 4] = to_bytes(count, 4, dest_bom) pos += 4 elem = f[pos:pos + count] outputBuffer[pos:pos + count] = elem channelInfoTable = {} ADPCMInfo_ref = {} param = {} pos = channelInfoTable_ref.offset + stmInfo_ref.pos count = struct.unpack(bom + "I", f[pos:pos + 4])[0] outputBuffer[pos:pos + 4] = to_bytes(count, 4, dest_bom) pos += 4 for i in range(1, count + 1): pos = channelInfoTable_ref.offset + stmInfo_ref.pos + 4 channelInfoTable[i] = Ref(bom) channelInfoTable[i].data(f, pos + 8 * (i - 1)) outputBuffer[pos + 8 * (i - 1):pos + 8 * (i - 1) + channelInfoTable[i].size] = bytes( Ref(dest_bom).pack(channelInfoTable[i].type_, channelInfoTable[i].offset)) if channelInfoTable[i].offset not in [0, -1]: pos = channelInfoTable[i].offset + pos - 4 ADPCMInfo_ref[i] = Ref(bom) ADPCMInfo_ref[i].data(f, pos) outputBuffer[pos:pos + ADPCMInfo_ref[i].size] = bytes( Ref(dest_bom).pack(ADPCMInfo_ref[i].type_, ADPCMInfo_ref[i].offset)) if ADPCMInfo_ref[i].offset not in [0, -1]: pos = ADPCMInfo_ref[i].offset + pos if ADPCMInfo_ref[i].type_ == 0x0300: for i in range(1, 17): param[i] = struct.unpack( bom + "H", f[pos + 2 * (i - 1):pos + 2 * (i - 1) + 2])[0] outputBuffer[pos + 2 * (i - 1):pos + 2 * (i - 1) + 2] = to_bytes(param[i], 2, dest_bom) pos += 32 context = DSPContext(bom) context.data(f, pos) outputBuffer[pos:pos + context.size] = bytes( DSPContext(dest_bom).pack(context.predictor_scale, context.preSample, context.preSample2)) pos += context.size loopContext = DSPContext(bom) loopContext.data(f, pos) outputBuffer[pos:pos + loopContext.size] = bytes( DSPContext(dest_bom).pack(loopContext.predictor_scale, loopContext.preSample, loopContext.preSample2)) pos += loopContext.size pos += 2 elif ADPCMInfo_ref[i].type_ == 0x0301: context = IMAContext(bom) context.data(f, pos) outputBuffer[pos:pos + context.size] = bytes( IMAContext(dest_bom).pack(context.data_, context.tableIndex)) pos += context.size loopContext = IMAContext(bom) loopContext.data(f, pos) outputBuffer[pos:pos + loopContext.size] = bytes( IMAContext(dest_bom).pack(loopContext.data_, loopContext.tableIndex)) pos += loopContext.size dest_dataHead = {"FSTM": b'DATA', "CSTM": b'DATA', "FSTP": b'PDAT'} for i in range(1, header.numBlocks + 1): if sized_refs[i].offset not in [0, -1]: if sized_refs[i].type_ == 0x4001: pos = sized_refs[i].offset seek = BLKHeader(bom) seek.data(f, pos) outputBuffer[pos:pos + seek.size] = bytes( BLKHeader(dest_bom).pack(seek.magic, seek.size_)) pos += seek.size seek.data_ = f[pos:pos + seek.size_ - 8] if curr[:-1] == dest[:-1]: outputBuffer[pos:pos + seek.size_ - 8] = seek.data_ else: for i in range(0, len(seek.data_), 2): outputBuffer[pos + i:pos + i + 2] = bytes([ seek.data_[i + 1], seek.data_[i], ]) elif sized_refs[i].type_ in [0x4002, 0x4004]: pos = sized_refs[i].offset data = BLKHeader(bom) data.data(f, pos) outputBuffer[pos:pos + data.size] = bytes( BLKHeader(dest_bom).pack(dest_dataHead[dest], data.size_)) pos += data.size data.data_ = f[pos:pos + data.size_ - 8] if bom != dest_bom and stmInfo.codec == 1: for i in range(0, len(data.data_), 2): outputBuffer[pos + i:pos + i + 2] = bytes([ data.data_[i + 1], data.data_[i], ]) else: outputBuffer[pos:pos + data.size_ - 8] = data.data_ return outputBuffer
def STMtoWAV(f, magic, dest, dest_bom): outputBuffer = bytearray(len(f)) if f[4:6] == b'\xFF\xFE': bom = '<' elif f[4:6] == b'\xFE\xFF': bom = '>' else: print("\nInvalid BOM!") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) if not dest_bom: if dest == "FWAV": dest_bom = '>' else: dest_bom = '<' header = Header(bom) header.data(f, 0) pos = header.size sized_refs = {} for i in range(1, header.numBlocks + 1): sized_refs[i] = Ref(bom) sized_refs[i].data(f, pos + 12 * (i - 1)) if sized_refs[1].type_ != 0x4000 or sized_refs[1].offset in [0, -1]: print("\nSomething went wrong!\nError code: 1") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos = sized_refs[1].offset info = BLKHeader(bom) info.data(f, pos) pos += 8 stmInfo_ref = Ref(bom) stmInfo_ref.data(f, pos) if stmInfo_ref.type_ != 0x4100 or stmInfo_ref.offset in [0, -1]: print("\nSomething went wrong!\nError code: 2") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) stmInfo_ref.pos = pos pos += stmInfo_ref.size * 2 channelInfoTable_ref = Ref(bom) channelInfoTable_ref.data(f, pos) if channelInfoTable_ref.type_ != 0x0101: print("\nSomething went wrong!\nError code: 4") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos = stmInfo_ref.offset + stmInfo_ref.pos stmInfo = STMInfo(bom) stmInfo.data(f, pos) sampleBlk_size = (stmInfo.sampleBlk_count - 1) * stmInfo.sampleBlk_size + stmInfo.lSampleBlk_size wavInfo = WAVInfo(bom) wavInfo.codec = stmInfo.codec wavInfo.loop_flag = stmInfo.loop_flag wavInfo.sample = stmInfo.sample wavInfo.loop_start = stmInfo.loop_start wavInfo.loop_end = stmInfo.loop_end wavInfo.reserved = 0 otherPos = 0x48 + wavInfo.size outputBuffer[0x48:otherPos] = bytes( WAVInfo(dest_bom).pack(wavInfo.codec, wavInfo.loop_flag, wavInfo.sample, wavInfo.loop_start, wavInfo.loop_end, wavInfo.reserved)) channelInfoTable = {} sampleData_ref = {} ADPCMInfo_ref = {} param = {} pos = channelInfoTable_ref.offset + stmInfo_ref.pos countPos = pos otherCountPos = otherPos count = struct.unpack(bom + "I", f[pos:pos + 4])[0] outputBuffer[otherPos:otherPos + 4] = to_bytes(count, 4, dest_bom) otherFstChInfPos = otherCountPos + 4 + count * 8 otherADPCMInfPos = otherFstChInfPos + count * 0x14 for i in range(1, count + 1): pos = countPos + 4 otherPos = otherCountPos + 4 channelInfoTable[i] = Ref(bom) channelInfoTable[i].data(f, pos + 8 * (i - 1)) if channelInfoTable[i].offset in [0, -1]: outputBuffer[otherPos + 8 * (i - 1):otherPos + 8 * (i - 1) + channelInfoTable[i].size] = bytes( Ref(dest_bom).pack(0x7100, channelInfoTable[i].offset)) else: outputBuffer[otherPos + 8 * (i - 1):otherPos + 8 * (i - 1) + channelInfoTable[i].size] = bytes( Ref(dest_bom).pack( 0x7100, otherFstChInfPos + 0x14 * (i - 1) - otherCountPos)) pos = channelInfoTable[i].offset + countPos otherPos = otherFstChInfPos + 0x14 * (i - 1) sampleData_ref[i] = Ref(bom) currsampleBlkSize = sampleBlk_size * (i - 1) outputBuffer[otherPos:otherPos + sampleData_ref[i].size] = bytes( Ref(dest_bom).pack(0x1F00, 0x18 + align(currsampleBlkSize, 0x20))) ADPCMInfo_ref[i] = Ref(bom) ADPCMInfo_ref[i].data(f, pos) if ADPCMInfo_ref[i].offset in [0, -1]: outputBuffer[otherPos + 8:otherPos + 8 + ADPCMInfo_ref[i].size] = bytes( Ref(dest_bom).pack(ADPCMInfo_ref[i].type_, ADPCMInfo_ref[i].offset)) else: pos = ADPCMInfo_ref[i].offset + pos if ADPCMInfo_ref[i].type_ == 0x0300: outputBuffer[otherPos + 8:otherPos + 8 + ADPCMInfo_ref[i].size] = bytes( Ref(dest_bom).pack( ADPCMInfo_ref[i].type_, otherADPCMInfPos + 0x2E * (i - 1) - otherPos)) otherPos = otherADPCMInfPos + 0x2E * (i - 1) for i in range(16): i += 1 param[i] = struct.unpack( bom + "H", f[pos + 2 * (i - 1):pos + 2 * (i - 1) + 2])[0] outputBuffer[otherPos + 2 * (i - 1):otherPos + 2 * (i - 1) + 2] = to_bytes( param[i], 2, dest_bom) pos += 32 otherPos += 32 context = DSPContext(bom) context.data(f, pos) outputBuffer[otherPos:otherPos + context.size] = bytes( DSPContext(dest_bom).pack(context.predictor_scale, context.preSample, context.preSample2)) pos += context.size otherPos += context.size loopContext = DSPContext(bom) loopContext.data(f, pos) outputBuffer[otherPos:otherPos + loopContext.size] = bytes( DSPContext(dest_bom).pack(loopContext.predictor_scale, loopContext.preSample, loopContext.preSample2)) pos += loopContext.size otherPos += loopContext.size pos += 2 otherPos += 2 elif ADPCMInfo_ref[i].type_ == 0x0301: outputBuffer[otherPos + 8:otherPos + 8 + ADPCMInfo_ref[i].size] = bytes( Ref(dest_bom).pack( ADPCMInfo_ref[i].type_, otherADPCMInfPos + 8 * (i - 1) - otherPos)) otherPos = otherADPCMInfPos + 8 * (i - 1) context = IMAContext(bom) context.data(f, pos) outputBuffer[otherPos:otherPos + context.size] = bytes( IMAContext(dest_bom).pack(context.data_, context.tableIndex)) pos += context.size otherPos += context.size loopContext = IMAContext(bom) loopContext.data(f, pos) outputBuffer[otherPos:otherPos + loopContext.size] = bytes( IMAContext(dest_bom).pack(loopContext.data_, loopContext.tableIndex)) pos += loopContext.size otherPos += loopContext.size else: otherPos += 0x14 dataBlkOffset = align(otherPos, 0x20) infoBlkSize = dataBlkOffset - 0x40 otherDataBlkOffset = 0 dataSize = 0 for i in range(1, header.numBlocks + 1): if sized_refs[i].offset not in [0, -1]: if sized_refs[i].type_ in [0x4002, 0x4004]: otherDataBlkOffset = sized_refs[i].offset dataBlkHead = BLKHeader(bom) dataBlkHead.data(f, otherDataBlkOffset) dataSize = dataBlkHead.size_ pos = header.size numBlocks = 0 for i in sized_refs: if sized_refs[i].type_ not in [0x4000, 0x4002]: continue elif sized_refs[i].type_ == 0x4000: numBlocks += 1 outputBuffer[pos:pos + 8] = bytes(Ref(dest_bom).pack(0x7000, 0x40)) outputBuffer[pos + 8:pos + 12] = struct.pack( dest_bom + "I", infoBlkSize) outputBuffer[0x40:0x48] = bytes( BLKHeader(dest_bom).pack(b'INFO', infoBlkSize)) else: if 0 not in [otherDataBlkOffset, dataSize ] and otherDataBlkOffset != -1: data = f[otherDataBlkOffset + 0x20:otherDataBlkOffset + dataSize] pos = 0 blocks = [] for i in range((stmInfo.sampleBlk_count - 1) * count): blocks.append(data[pos:pos + stmInfo.sampleBlk_size]) pos += stmInfo.sampleBlk_size for i in range(count): blocks.append(data[pos:pos + stmInfo.lSampleBlk_size]) pos += stmInfo.lSampleBlk_padSize sampleData = [[ blocks[i * count + j] for i in range(stmInfo.sampleBlk_count) ] for j in range(count)] samples = [] for channel in sampleData: channelSampleData = b''.join(channel) padding = b'\0' * (align(len(channelSampleData), 0x20) - len(channelSampleData)) samples.append(b''.join([channelSampleData, padding])) data = b''.join(samples) if bom != dest_bom and stmInfo.codec == 1: data_ = bytearray(data) for i in range(0, len(data), 2): data_[i:i + 2] = bytes([ data[i + 1], data[i], ]) data = bytes(data_) del data_ pos = header.size numBlocks += 1 outputBuffer[pos + 12:pos + 20] = bytes( Ref(dest_bom).pack(0x7001, dataBlkOffset)) outputBuffer[dataBlkOffset + 0x20:] = data outputBuffer[dataBlkOffset:dataBlkOffset + 8] = bytes( BLKHeader(dest_bom).pack(b'DATA', len(outputBuffer) - dataBlkOffset)) outputBuffer[pos + 20:pos + 24] = struct.pack( dest_bom + "I", len(outputBuffer) - dataBlkOffset) dest_ver = {"FWAV": 0x10100, "CWAV": 0x2010000} outputBuffer[:header.size] = bytes( Header(dest_bom).pack(to_bytes(dest, 4), 0x40, dest_ver[dest], len(outputBuffer), numBlocks, header.reserved)) outputBuffer[4:6] = (b'\xFE\xFF' if dest_bom == '>' else b'\xFF\xFE') return outputBuffer
def WAVtoWAV(f, magic, dest, dest_bom): outputBuffer = bytearray(len(f)) pos = 0 if f[4:6] == b'\xFF\xFE': bom = '<' elif f[4:6] == b'\xFE\xFF': bom = '>' else: print("\nInvalid BOM!") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) if dest_bom == '': if dest == "FWAV": dest_bom = '>' else: dest_bom = '<' header = Header(bom) header.data(f, pos) dest_ver = {"FWAV": 0x10100, "CWAV": 0x2010000} if magic == dest: dest_ver[dest] = header.version outputBuffer[pos:pos + header.size] = bytes( Header(dest_bom).pack(to_bytes(dest, 4), header.size_, dest_ver[dest], header.fileSize, header.numBlocks, header.reserved)) outputBuffer[4:6] = (b'\xFE\xFF' if dest_bom == '>' else b'\xFF\xFE') pos += header.size sized_refs = {} for i in range(1, header.numBlocks + 1): sized_refs[i] = Ref(bom) sized_refs[i].data(f, pos + 12 * (i - 1)) outputBuffer[pos + 12 * (i - 1):pos + 12 * (i - 1) + sized_refs[i].size] = bytes( Ref(dest_bom).pack(sized_refs[i].type_, sized_refs[i].offset)) sized_refs[i].block_size = struct.unpack( bom + "I", f[pos + 12 * (i - 1) + 8:pos + 12 * i])[0] outputBuffer[pos + 12 * (i - 1) + 8:pos + 12 * i] = to_bytes( sized_refs[i].block_size, 4, dest_bom) if sized_refs[1].type_ != 0x7000 or sized_refs[1].offset in [0, -1]: print("\nSomething went wrong!\nError code: 5") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos = sized_refs[1].offset info = BLKHeader(bom) info.data(f, pos) info.pos = pos outputBuffer[pos:pos + info.size] = bytes( BLKHeader(dest_bom).pack(info.magic, info.size_)) pos += info.size wavInfo = WAVInfo(bom) wavInfo.data(f, pos) outputBuffer[pos:pos + wavInfo.size] = bytes( WAVInfo(dest_bom).pack(wavInfo.codec, wavInfo.loop_flag, wavInfo.sample, wavInfo.loop_start, wavInfo.loop_end, wavInfo.reserved)) pos += wavInfo.size channelInfoTable = {} sampleData_ref = {} ADPCMInfo_ref = {} param = {} count = struct.unpack(bom + "I", f[pos:pos + 4])[0] outputBuffer[pos:pos + 4] = to_bytes(count, 4, dest_bom) countPos = pos for i in range(1, count + 1): pos = countPos + 4 channelInfoTable[i] = Ref(bom) channelInfoTable[i].data(f, pos + 8 * (i - 1)) outputBuffer[pos + 8 * (i - 1):pos + 8 * (i - 1) + channelInfoTable[i].size] = bytes( Ref(dest_bom).pack(channelInfoTable[i].type_, channelInfoTable[i].offset)) if channelInfoTable[i].offset not in [0, -1]: pos = channelInfoTable[i].offset + countPos sampleData_ref[i] = Ref(bom) sampleData_ref[i].data(f, pos) outputBuffer[pos:pos + sampleData_ref[i].size] = bytes( Ref(dest_bom).pack(sampleData_ref[i].type_, sampleData_ref[i].offset)) pos += 8 ADPCMInfo_ref[i] = Ref(bom) ADPCMInfo_ref[i].data(f, pos) outputBuffer[pos:pos + ADPCMInfo_ref[i].size] = bytes( Ref(dest_bom).pack(ADPCMInfo_ref[i].type_, ADPCMInfo_ref[i].offset)) if ADPCMInfo_ref[i].offset not in [0, -1]: pos = ADPCMInfo_ref[i].offset + pos - 8 if ADPCMInfo_ref[i].type_ == 0x0300: for i in range(16): i += 1 param[i] = struct.unpack( bom + "H", f[pos + 2 * (i - 1):pos + 2 * (i - 1) + 2])[0] outputBuffer[pos + 2 * (i - 1):pos + 2 * (i - 1) + 2] = to_bytes(param[i], 2, dest_bom) pos += 32 context = DSPContext(bom) context.data(f, pos) outputBuffer[pos:pos + context.size] = bytes( DSPContext(dest_bom).pack(context.predictor_scale, context.preSample, context.preSample2)) pos += context.size loopContext = DSPContext(bom) loopContext.data(f, pos) outputBuffer[pos:pos + loopContext.size] = bytes( DSPContext(dest_bom).pack(loopContext.predictor_scale, loopContext.preSample, loopContext.preSample2)) pos += loopContext.size pos += 2 elif ADPCMInfo_ref[i].type_ == 0x0301: context = IMAContext(bom) context.data(f, pos) outputBuffer[pos:pos + context.size] = bytes( IMAContext(dest_bom).pack(context.data_, context.tableIndex)) pos += context.size loopContext = IMAContext(bom) loopContext.data(f, pos) outputBuffer[pos:pos + loopContext.size] = bytes( IMAContext(dest_bom).pack(loopContext.data_, loopContext.tableIndex)) pos += loopContext.size for i in range(1, header.numBlocks + 1): if sized_refs[i].offset not in [0, -1]: if sized_refs[i].type_ == 0x7001: pos = sized_refs[i].offset data = BLKHeader(bom) data.data(f, pos) outputBuffer[pos:pos + data.size] = bytes( BLKHeader(dest_bom).pack(data.magic, data.size_)) pos += data.size data.data_ = f[pos:pos + data.size_ - 8] if bom != dest_bom and wavInfo.codec == 1: for i in range(0, len(data.data_), 2): outputBuffer[pos + i:pos + i + 2] = bytes([ data.data_[i + 1], data.data_[i], ]) else: outputBuffer[pos:pos + data.size_ - 8] = data.data_ return outputBuffer
def readFile(f): pos = 0 if f[4:6] == b'\xFF\xFE': bom = '<' elif f[4:6] == b'\xFE\xFF': bom = '>' else: print("\nInvalid BOM!") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) header = Header(bom) header.data(f, pos) if bytes_to_string(header.magic) not in ["FWAV", "CWAV"]: print("\nUnsupported file format!") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) print("\nMagic: " + bytes_to_string(header.magic)) print("Header size: " + hex(header.size_)) print("File version: " + hex(header.version)) print("File size: " + hex(header.fileSize)) print("Number of blocks: " + str(header.numBlocks)) pos += header.size sized_refs = {} for i in range(1, header.numBlocks + 1): sized_refs[i] = Ref(bom) sized_refs[i].data(f, pos + 12 * (i - 1)) sized_refs[i].block_size = struct.unpack( bom + "I", f[pos + 12 * (i - 1) + 8:pos + 12 * i])[0] if sized_refs[i].offset not in [0, -1]: if sized_refs[i].type_ == 0x7000: print("\nInfo Block offset: " + hex(sized_refs[i].offset)) elif sized_refs[i].type_ == 0x7001: print("\nData Block offset: " + hex(sized_refs[i].offset)) else: print("\n" + hex(sized_refs[i].type_) + " Block offset: " + hex(sized_refs[i].offset)) print("Size: " + hex(sized_refs[i].block_size)) if sized_refs[1].type_ != 0x7000 or sized_refs[1].offset in [0, -1]: print("\nSomething went wrong!\nError code: 5") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos = sized_refs[1].offset info = BLKHeader(bom) info.data(f, pos) info.pos = pos print("\nInfo Block Magic: " + bytes_to_string(info.magic)) print("Size: " + hex(info.size_)) pos += info.size wavInfo = WAVInfo(bom) wavInfo.data(f, pos) codec = {0: "PCM8", 1: "PCM16", 2: "DSP ADPCM", 3: "IMA ADPCM"} if wavInfo.codec in codec: print("\nEncoding: " + codec[wavInfo.codec]) else: print("\nEncoding: " + str(wavInfo.codec)) print("Loop Flag: " + str(wavInfo.loop_flag)) print("Sample Rate: " + str(wavInfo.sample)) print("Loop Start Frame: " + str(wavInfo.loop_start)) print("Loop End Frame: " + str(wavInfo.loop_end)) pos += wavInfo.size channelInfoTable = {} ADPCMInfo_ref = {} count = struct.unpack(bom + "I", f[pos:pos + 4])[0] print("Channel Count: " + str(count)) countPos = pos for i in range(1, count + 1): pos = countPos + 4 channelInfoTable[i] = Ref(bom) channelInfoTable[i].data(f, pos + 8 * (i - 1)) if channelInfoTable[i].offset not in [0, -1]: pos = channelInfoTable[i].offset + countPos print("\nChannel " + str(i) + " Info Entry offset: " + hex(pos)) sampleData_ref = Ref(bom) sampleData_ref.data(f, pos) if sampleData_ref.offset not in [0, -1]: for z in range(1, header.numBlocks + 1): if sized_refs[z].offset not in [0, -1]: if sized_refs[z].type_ == 0x7001: print("\nChannel " + str(i) + " Info Entry Sample Data offset: " + hex(sampleData_ref.offset + sized_refs[z].offset + 8)) pos += 8 print("\nChannel " + str(i) + " Info Entry ADPCM Info Reference offset: " + hex(pos)) ADPCMInfo_ref[i] = Ref(bom) ADPCMInfo_ref[i].data(f, pos) if ADPCMInfo_ref[i].offset not in [0, -1]: print("\nADPCM Info offset: " + hex(ADPCMInfo_ref[i].offset + pos - 8)) print("Type: " + hex(ADPCMInfo_ref[i].type_)) pos = ADPCMInfo_ref[i].offset + pos - 8 if ADPCMInfo_ref[i].type_ == 0x0300: param = b'' for i in range(1, 17): param += struct.unpack( bom + "H", f[pos + 2 * (i - 1):pos + 2 * (i - 1) + 2])[0].to_bytes(2, 'big') print("Param: " + str(param)) pos += 32 context = DSPContext(bom) context.data(f, pos) print("Context Predictor and Scale: " + hex(context.predictor_scale)) print("Context Previous Sample: " + hex(context.preSample)) print("Context Second Previous Sample: " + hex(context.preSample2)) pos += context.size loopContext = DSPContext(bom) loopContext.data(f, pos) print("Loop Context Predictor and Scale: " + hex(loopContext.predictor_scale)) print("Loop Context Previous Sample: " + hex(loopContext.preSample)) print("Loop Context Second Previous Sample: " + hex(loopContext.preSample2)) pos += loopContext.size pos += 2 elif ADPCMInfo_ref[i].type_ == 0x0301: context = IMAContext(bom) context.data(f, pos) print("Context Data: " + hex(context.data_)) print("Context Table Index: " + hex(context.tableIndex)) pos += context.size loopContext = IMAContext(bom) loopContext.data(f, pos) print("Loop Context Data: " + hex(loopContext.data_)) print("Loop Context Table Index: " + hex(loopContext.tableIndex)) pos += loopContext.size for i in range(1, header.numBlocks + 1): if sized_refs[i].offset not in [0, -1]: if sized_refs[i].type_ == 0x7001: pos = sized_refs[i].offset data = BLKHeader(bom) data.data(f, pos) print("\nData Block Magic: " + bytes_to_string(data.magic)) print("Size: " + hex(data.size_)) pos += data.size data.data_ = f[pos:pos + data.size_ - 8]
def read(file): with open(file, "rb") as inf: f = inf.read() if f[:4] != b"FRES" or f[4:8] == b' ': QtWidgets.QMessageBox.warning(None, "Error", "Invalid file header!") return False version = f[4] if version not in [3, 4]: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported BFRES version!") return False group = empty() group.pos = struct.unpack(">i", f[0x24:0x28])[0] if group.pos == 0: return False group.pos += 0x28 group.count = struct.unpack(">i", f[group.pos:group.pos + 4])[0] group.pos += 20 textures = [] texNames = [] texSizes = [] for i in range(group.count): nameAddr = struct.unpack( ">i", f[group.pos + 16 * i + 8:group.pos + 16 * i + 12])[0] nameAddr += group.pos + 16 * i + 8 name = bytes_to_string(f, nameAddr) pos = struct.unpack(">i", f[group.pos + 16 * i + 12:group.pos + 16 * i + 16])[0] pos += group.pos + 16 * i + 12 ftex = empty() ftex.headAddr = pos pos += 4 surface = GX2Surface() surface.data(f, pos) pos += surface.size if version == 4: surface.numMips = 1 elif surface.numMips > 14: continue mipOffsets = [] for j in range(13): mipOffsets.append(f[j * 4 + pos] << 24 | f[j * 4 + 1 + pos] << 16 | f[j * 4 + 2 + pos] << 8 | f[j * 4 + 3 + pos]) pos += 68 compSel = [] compSel2 = [] for j in range(4): comp = f[pos + j] compSel2.append(comp) if comp == 4: # Sorry, but this is unsupported. comp = j compSel.append(comp) pos += 24 ftex.name = name ftex.dim = surface.dim ftex.width = surface.width ftex.height = surface.height ftex.depth = surface.depth ftex.numMips = surface.numMips ftex.format = surface.format_ ftex.aa = surface.aa ftex.use = surface.use ftex.imageSize = surface.imageSize ftex.imagePtr = surface.imagePtr ftex.mipSize = surface.mipSize ftex.mipPtr = surface.mipPtr ftex.tileMode = surface.tileMode ftex.swizzle = surface.swizzle ftex.alignment = surface.alignment ftex.pitch = surface.pitch ftex.compSel = compSel ftex.compSel2 = compSel2 ftex.mipOffsets = mipOffsets ftex.surfInfo = addrlib.getSurfaceInfo(ftex.format, ftex.width, ftex.height, ftex.depth, ftex.dim, ftex.tileMode, ftex.aa, 0) if ftex.format in globals.BCn_formats: ftex.blkWidth, ftex.blkHeight = 4, 4 else: ftex.blkWidth, ftex.blkHeight = 1, 1 ftex.bpp = addrlib.surfaceGetBitsPerPixel(surface.format_) // 8 dataAddr = struct.unpack(">i", f[ftex.headAddr + 0xB0:ftex.headAddr + 0xB4])[0] dataAddr += ftex.headAddr + 0xB0 ftex.dataAddr = dataAddr ftex.data = f[dataAddr:dataAddr + ftex.imageSize] mipAddr = struct.unpack(">i", f[ftex.headAddr + 0xB4:ftex.headAddr + 0xB8])[0] if mipAddr and ftex.mipSize: mipAddr += ftex.headAddr + 0xB4 ftex.mipData = f[mipAddr:mipAddr + ftex.mipSize] else: ftex.mipData = b'' textures.append(ftex) texNames.append(name) texSizes.append([ftex.imageSize, ftex.mipSize]) globals.fileData = bytearray(f) globals.texSizes = texSizes return textures, texNames
def readFile(f): pos = 0 if f[4:6] == b'\xFF\xFE': bom = '<' elif f[4:6] == b'\xFE\xFF': bom = '>' else: print("Invalid BOM!") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) header = Header(bom) header.data(f, pos) if bytes_to_string(header.magic) not in ["FSTM", "CSTM", "FSTP"]: print("Unsupported file format!") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) print("Magic: " + bytes_to_string(header.magic)) print("Header size: " + hex(header.size_)) print("File version: " + hex(header.version)) print("File size: " + hex(header.fileSize)) print("Number of blocks: " + str(header.numBlocks)) pos += header.size sized_refs = {} for i in range(1, header.numBlocks + 1): sized_refs[i] = Ref(bom) sized_refs[i].data(f, pos + 12 * (i - 1)) sized_refs[i].block_size = struct.unpack( bom + "I", f[pos + 12 * (i - 1) + 8:pos + 12 * i])[0] if sized_refs[i].offset not in [0, -1]: if sized_refs[i].type_ == 0x4000: print("\nInfo Block offset: " + hex(sized_refs[i].offset)) elif sized_refs[i].type_ == 0x4001: print("\nSeek Block offset: " + hex(sized_refs[i].offset)) elif sized_refs[i].type_ == 0x4002: print("\nData Block offset: " + hex(sized_refs[i].offset)) elif sized_refs[i].type_ == 0x4004: print("\nPrefetch Data Block offset: " + hex(sized_refs[i].offset)) else: print("\n" + hex(sized_refs[i].type_) + " Block offset: " + hex(sized_refs[i].offset)) print("Size: " + hex(sized_refs[i].block_size)) if sized_refs[1].type_ != 0x4000 or sized_refs[1].offset in [0, -1]: print("\nSomething went wrong!\nError code: 1") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos = sized_refs[1].offset info = BLKHeader(bom) info.data(f, pos) print("\nInfo Block Magic: " + bytes_to_string(info.magic)) print("Size: " + hex(info.size_)) pos += info.size stmInfo_ref = Ref(bom) stmInfo_ref.data(f, pos) if stmInfo_ref.type_ != 0x4100 or stmInfo_ref.offset in [0, -1]: print("\nSomething went wrong!\nError code: 2") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) print("\nStream Info offset: " + hex(stmInfo_ref.offset + pos)) stmInfo_ref.pos = pos pos += stmInfo_ref.size trkInfoTable_ref = Ref(bom) trkInfoTable_ref.data(f, pos) if trkInfoTable_ref.offset not in [0, -1 ] and trkInfoTable_ref.type_ == 0x0101: print("\nTrack Info Reference Table offset: " + hex(trkInfoTable_ref.offset + stmInfo_ref.pos)) elif not trkInfoTable_ref.type_ or trkInfoTable_ref.offset in [0, -1]: pass else: print("\nSomething went wrong!\nError code: 3") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) pos += trkInfoTable_ref.size channelInfoTable_ref = Ref(bom) channelInfoTable_ref.data(f, pos) if channelInfoTable_ref.type_ != 0x0101: print("\nSomething went wrong!\nError code: 4") print("\nExiting in 5 seconds...") time.sleep(5) sys.exit(1) if channelInfoTable_ref.offset not in [0, -1]: print("\nChannel Info Reference Table offset: " + hex(channelInfoTable_ref.offset + stmInfo_ref.pos)) pos = stmInfo_ref.offset + stmInfo_ref.pos stmInfo = STMInfo(bom) stmInfo.data(f, pos) codec = {0: "PCM8", 1: "PCM16", 2: "DSP ADPCM", 3: "IMA ADPCM"} if stmInfo.codec in codec: print("\nEncoding: " + codec[stmInfo.codec]) else: print("\nEncoding: " + str(stmInfo.codec)) print("Loop Flag: " + str(stmInfo.loop_flag)) print("Channel Count: " + str(stmInfo.count)) print("Sample Rate: " + str(stmInfo.sample)) print("Loop Start Frame: " + str(stmInfo.loop_start)) print("Loop End Frame: " + str(stmInfo.loop_end)) print("Sample Block Count: " + str(stmInfo.sampleBlk_count)) print("Sample Block Size: " + hex(stmInfo.sampleBlk_size)) print("Sample Block Sample Count: " + str(stmInfo.sampleBlk_sampleCount)) print("Last Sample Block Size: " + hex(stmInfo.lSampleBlk_size)) print("Last Sample Block Sample Count: " + str(stmInfo.lSampleBlk_sampleCount)) print("Last Sample Block Padded Size: " + hex(stmInfo.lSampleBlk_padSize)) print("Seek Data Size: " + hex(stmInfo.seek_size)) print("Seek Interval Sample Count: " + str(stmInfo.SISC)) pos += stmInfo.size sampleData_ref = Ref(bom) sampleData_ref.data(f, pos) if sampleData_ref.offset not in [0, -1]: for i in range(1, header.numBlocks + 1): if sized_refs[i].offset not in [0, -1]: if sized_refs[i].type_ == 0x4002: print("Sample Data offset: " + hex(sampleData_ref.offset + sized_refs[i].offset + 8)) if sized_refs[i].type_ == 0x4004: print("Prefetch Data offset: " + hex(sampleData_ref.offset)) pos += 8 trkInfoTable = {} trkInfo = {} if trkInfoTable_ref.offset not in [0, -1]: pos = trkInfoTable_ref.offset + stmInfo_ref.pos count = struct.unpack(bom + "I", f[pos:pos + 4])[0] pos += 4 for i in range(1, count + 1): pos = trkInfoTable_ref.offset + stmInfo_ref.pos + 4 trkInfoTable[i] = Ref(bom) trkInfoTable[i].data(f, pos + 8 * (i - 1)) if trkInfoTable[i].offset not in [0, -1]: print("\nTrack Info Entry " + str(i) + " offset: " + hex(trkInfoTable[i].offset + pos - 4)) pos = trkInfoTable[i].offset + pos - 4 trkInfo[i] = TRKInfo(bom) trkInfo[i].data(f, pos) print("Volume: " + str(trkInfo[i].volume)) print("Pan: " + str(trkInfo[i].pan)) print("Unknown value: " + str(trkInfo[i].unk)) pos += trkInfo[i].size channelIndexByteTable_ref = Ref(bom) channelIndexByteTable_ref.data(f, pos) if channelIndexByteTable_ref.offset not in [0, -1]: print("Channel Index Byte Table offset: " + hex(channelIndexByteTable_ref.offset + pos - trkInfo[i].size)) pos = channelIndexByteTable_ref.offset + pos - trkInfo[ i].size count = struct.unpack(bom + "I", f[pos:pos + 4])[0] pos += 4 elem = f[pos:pos + count] print("Elements: " + str(elem)) channelInfoTable = {} ADPCMInfo_ref = {} pos = channelInfoTable_ref.offset + stmInfo_ref.pos count = struct.unpack(bom + "I", f[pos:pos + 4])[0] pos += 4 for i in range(1, count + 1): pos = channelInfoTable_ref.offset + stmInfo_ref.pos + 4 channelInfoTable[i] = Ref(bom) channelInfoTable[i].data(f, pos + 8 * (i - 1)) if channelInfoTable[i].offset not in [0, -1]: print("\nChannel " + str(i) + " Info Entry ADPCM Info Reference offset: " + hex(channelInfoTable[i].offset + pos - 4)) pos = channelInfoTable[i].offset + pos - 4 ADPCMInfo_ref[i] = Ref(bom) ADPCMInfo_ref[i].data(f, pos) if ADPCMInfo_ref[i].offset not in [0, -1]: print("\nADPCM Info offset: " + hex(ADPCMInfo_ref[i].offset + pos)) print("Type: " + hex(ADPCMInfo_ref[i].type_)) pos = ADPCMInfo_ref[i].offset + pos if ADPCMInfo_ref[i].type_ == 0x0300: param = b'' for i in range(1, 17): param += struct.unpack( bom + "H", f[pos + 2 * (i - 1):pos + 2 * (i - 1) + 2])[0].to_bytes(2, 'big') print("Param: " + str(param)) pos += 32 context = DSPContext(bom) context.data(f, pos) print("Context Predictor and Scale: " + hex(context.predictor_scale)) print("Context Previous Sample: " + hex(context.preSample)) print("Context Second Previous Sample: " + hex(context.preSample2)) pos += context.size loopContext = DSPContext(bom) loopContext.data(f, pos) print("Loop Context Predictor and Scale: " + hex(loopContext.predictor_scale)) print("Loop Context Previous Sample: " + hex(loopContext.preSample)) print("Loop Context Second Previous Sample: " + hex(loopContext.preSample2)) pos += loopContext.size pos += 2 elif ADPCMInfo_ref[i].type_ == 0x0301: context = IMAContext(bom) context.data(f, pos) print("Context Data: " + hex(context.data_)) print("Context Table Index: " + hex(context.tableIndex)) pos += context.size loopContext = IMAContext(bom) loopContext.data(f, pos) print("Loop Context Data: " + hex(loopContext.data_)) print("Loop Context Table Index: " + hex(loopContext.tableIndex)) pos += loopContext.size for i in range(1, header.numBlocks + 1): if sized_refs[i].offset not in [0, -1]: if sized_refs[i].type_ == 0x4001: pos = sized_refs[i].offset seek = BLKHeader(bom) seek.data(f, pos) print('') print("Seek Block Magic: " + bytes_to_string(seek.magic)) print("Size: " + hex(seek.size_)) pos += seek.size seek.data_ = f[pos:pos + seek.size_ - 8] elif sized_refs[i].type_ in [0x4002, 0x4004]: pos = sized_refs[i].offset data = BLKHeader(bom) data.data(f, pos) print('') if sized_refs[i].type_ == 0x4002: print("Data Block Magic: " + bytes_to_string(data.magic)) else: print("Prefetch Data Block Magic: " + bytes_to_string(data.magic)) print("Size: " + hex(data.size_)) pos += data.size data.data_ = f[pos:pos + data.size_ - 8]
def read(file): with open(file, "rb") as inf: f = inf.read() pos = 0 if f[0xc:0xe] == b'\xFF\xFE': bom = '<' elif f[0xc:0xe] == b'\xFE\xFF': bom = '>' else: QtWidgets.QMessageBox.warning(None, "Error", "Invalid BOM!") return False header = BNTXHeader(bom) header.data(f, pos) pos += header.size if header.magic != b'BNTX\0\0\0\0': QtWidgets.QMessageBox.warning(None, "Error", "Invalid file header!") return False fnameLen = struct.unpack(bom + 'H', f[header.fileNameAddr - 2:header.fileNameAddr])[0] fname = bytes_to_string( f[header.fileNameAddr:header.fileNameAddr + fnameLen], fnameLen) texContainer = TexContainer(bom) texContainer.data(f, pos) pos += texContainer.size if texContainer.target not in [b'NX ', b'Gen ']: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported target platform!") return False target = 0 if texContainer.target == b'Gen ' else 1 textures = [] texNames = [] texSizes = [] for i in range(texContainer.count): pos = struct.unpack( bom + 'q', f[texContainer.infoPtrsAddr + i * 8:texContainer.infoPtrsAddr + i * 8 + 8])[0] infoHeader = BlockHeader(bom) infoHeader.data(f, pos) pos += infoHeader.size info = TextureInfo(bom) info.data(f, pos) if infoHeader.magic != b'BRTI': continue nameLen = struct.unpack(bom + 'H', f[info.nameAddr:info.nameAddr + 2])[0] name = bytes_to_string( f[info.nameAddr + 2:info.nameAddr + 2 + nameLen], nameLen) compSel = [] compSel2 = [] for i in range(4): value = (info.compSel >> (8 * (3 - i))) & 0xff compSel2.append(value) if value == 0: value = 5 - len(compSel) compSel.append(value) if info.type_ not in globals.types: globals.types[info.type_] = "Unknown" dataAddr = struct.unpack(bom + 'q', f[info.ptrsAddr:info.ptrsAddr + 8])[0] mipOffsets = {0: 0} for i in range(1, info.numMips): mipOffset = struct.unpack( bom + 'q', f[info.ptrsAddr + (i * 8):info.ptrsAddr + (i * 8) + 8])[0] mipOffsets[i] = mipOffset - dataAddr tex = TexInfo() tex.infoAddr = pos tex.info = info tex.bom = bom tex.target = target tex.name = name tex.readTexLayout = info.flags & 1 tex.sparseBinding = info.flags >> 1 tex.sparseResidency = info.flags >> 2 tex.dim = info.dim tex.tileMode = info.tileMode tex.numMips = info.numMips tex.width = info.width tex.height = info.height tex.format = info.format_ tex.arrayLength = info.arrayLength tex.blockHeightLog2 = info.textureLayout & 7 tex.imageSize = info.imageSize tex.compSel = compSel tex.compSel2 = compSel2 tex.alignment = info.alignment tex.type = info.type_ tex.mipOffsets = mipOffsets tex.dataAddr = dataAddr tex.data = f[dataAddr:dataAddr + info.imageSize] textures.append(tex) texNames.append(name) texSizes.append(info.imageSize) globals.fileData = bytearray(f) globals.texSizes = texSizes return fname, texContainer.target.decode('utf-8'), textures, texNames