def parse_file(self): headerSize = self.inFile.readUInt() width, height = self.inFile.read('2L') self.inFile.readUInt() self.inFile.readUInt() pixSize = self.inFile.readUInt() self.inFile.read("2L") numColors = self.inFile.readUInt() self.inFile.readUInt() if numColors: palette = self.inFile.readBytes(numColors * 4) pixMap = self.inFile.readBytes(width * height) pixData = rapi.imageDecodeRawPal(pixMap, palette, height, width, 8, "b8g8r8p8") else: if pixSize == 0: pixSize = width * height * 3 pixData = self.inFile.readBytes(pixSize) pixData = rapi.imageDecodeRaw(pixData, width, height, 'b8g8r8') pixData = rapi.imageFlipRGBA32(pixData, width, height, 0, 1) tex = NoeTexture("tex", width, height, pixData, noesis.NOESISTEX_RGBA32) self.texList.append(tex)
def parse_file(self): self.inFile.readUInt() pixType = self.inFile.readUInt() pixSize = self.inFile.readUInt() width, height = self.inFile.read('2H') self.inFile.readBytes(4) self.inFile.read('3L') size = width * height * 4 if size != pixSize: print("width off by 1") width += 1 size = width * height * 4 # RGBA if size == pixSize: pixData = self.inFile.readBytes(width*height*3) pixData = rapi.imageDecodeRaw(pixData, width, height, 'b8g8r8') tex = NoeTexture("test", width, height, pixData, noesis.NOESISTEX_RGBA32) self.texList.append(tex) else: #total = 0 #for i in range(pixSize // 2): #count = self.inFile.readByte() #self.inFile.readByte() #total += count #print(total) print('unk') self.texList.append(None)
def parseTexture_BIN(self): texWidth = 256 texHeight = 256 pixMap = self.reader.readBytes(texWidth * texHeight) pixData = rapi.imageDecodeRaw(pixMap, texWidth, texHeight, "r3 g3 b2") return NoeTexture("bin", texWidth, texHeight, pixData, noesis.NOESISTEX_RGBA32)
def parseTexture(self): texWidth = self.reader.readUShort() texHeight = self.reader.readUShort() texType = self.reader.readShort() texMips = self.reader.readShort() texUnknown = self.reader.readShort() texFlag1 = self.reader.readUByte() texFlag2 = self.reader.readUByte() texFlag3 = self.reader.readUByte() texFlag4 = self.reader.readUByte() if texType == 1: # P8 palMap = self.reader.readBytes(256*4) pixMap = self.reader.readBytes(texWidth * texHeight) pixData = rapi.imageDecodeRawPal(pixMap, palMap, texWidth, texHeight, 8, "b8g8r8p8") if texType == 14: # PA8 palMap = self.reader.readBytes(256*4) pixMap = self.reader.readBytes(texWidth * texHeight) pixData = rapi.imageDecodeRawPal(pixMap, palMap, texWidth, texHeight, 8, "b8g8r8a8") if texType == 15: # P4_MC palMap = self.reader.readBytes(16*4) pixMap = self.reader.readBytes(int(texWidth * texHeight / 2)) pixData = rapi.imageDecodeRawPal(pixMap, palMap, texWidth, texHeight, 4, "b8g8r8p8") if texType == 16: # PA4_MC palMap = self.reader.readBytes(16*4) pixMap = self.reader.readBytes(int(texWidth * texHeight / 2)) pixData = rapi.imageDecodeRawPal(pixMap, palMap, texWidth, texHeight, 4, "b8g8r8a8") if texType == 17: # RGB888 pixMap = self.reader.readBytes(texWidth * texHeight * 3) pixData = rapi.imageDecodeRaw(pixMap, texWidth, texHeight, "r8g8b8") if texType == 18: # RGBA8888 pixMap = self.reader.readBytes(texWidth * texHeight * 4) pixData = rapi.imageDecodeRaw(pixMap, texWidth, texHeight, "r8g8b8a8") # Midnight Club 2 support (textype 26 not fully functional) if texType == 22: # DXT1 pixMap = self.reader.readBytes(int(texWidth * texHeight * 4 / 8)) pixData = rapi.imageDecodeDXT(pixMap, texWidth, texHeight, noesis.NOESISTEX_DXT1) if texType == 26: # DXT5 pixMap = self.reader.readBytes(int(texWidth * texHeight * 4 / 4)) pixData = rapi.imageDecodeDXT(pixMap, texWidth, texHeight, noesis.NOESISTEX_DXT5) #pixData = rapi.imageFlipRGBA32(pixData, texWidth, texHeight, 0, 1) return NoeTexture("tex", texWidth, texHeight, pixData, noesis.NOESISTEX_RGBA32)
def parseTexture_B16(self): texWidth = 256 texHeight = 256 pixMap = self.reader.readBytes(texWidth * texHeight * 2) pixData = rapi.imageDecodeRaw(pixMap, texWidth, texHeight, "b5 g5 r5 a1") return NoeTexture("b16", texWidth, texHeight, pixData, noesis.NOESISTEX_RGBA32)
def parse_file(self): self.inFile.readBytes(4) self.inFile.readBytes(6) self.inFile.read('2L') width, height = self.inFile.read('2L') self.inFile.read('2H') self.inFile.read('2L') self.inFile.read('2L') self.inFile.read('2L') pixData = self.inFile.readBytes(width*height*3) imgPix = rapi.imageDecodeRaw(pixData, width, height, "b8g8r8") imgPix = rapi.imageFlipRGBA32(imgPix, width, height, 0, 1) tex = NoeTexture("texture", width, height, imgPix, noesis.NOESISTEX_RGBA32) self.texList.append(tex)
def parse_file(self): headerSize = self.inFile.readUInt() width, height = self.inFile.read('2L') self.inFile.readUInt() self.inFile.readUInt() pixSize = self.inFile.readUInt() self.inFile.read("2L") numColors = self.inFile.readUInt() self.inFile.readUInt() if numColors: palette = self.inFile.readBytes(numColors*4) pixMap = self.inFile.readBytes(width*height) pixData = rapi.imageDecodeRawPal(pixMap, palette, height, width, 8, "b8g8r8p8") else: if pixSize == 0: pixSize = width * height * 3 pixData = self.inFile.readBytes(pixSize) pixData = rapi.imageDecodeRaw(pixData, width, height, 'b8g8r8') pixData = rapi.imageFlipRGBA32(pixData, width, height, 0, 1) tex = NoeTexture("tex", width, height, pixData, noesis.NOESISTEX_RGBA32) self.texList.append(tex)
def Bio1LoadRGBA(data, texList): textcount = 1 bs = NoeBitStream(data) filesize = bs.getSize() filesizeDiv4 = filesize//4 for i in range(0, filesizeDiv4-1): Temp = bs.readInt() # Texture headers if (Temp == 0x004F61C8) or (Temp == 0x004F8288) or (Temp == 0x004F5110) or (Temp == 0x004F9260) or (Temp == 0x004FD320) or (Temp == 0x004FF504) or (Temp == 0x004F7218) or (Temp == 0x00543B28) or (Temp == 0x004F8298) or (Temp == 0x004F8280) or (Temp == 0x004F92D0) or (Temp == 0x00543B28) or (Temp == 0x004F5130) or (Temp == 0x00567760): offset = bs.tell() bs.seek(0x09, NOESEEK_REL) palPosition = bs.readByte() bitDepth = bs.readByte() # Accomdation for wad version 101 if (Temp == 0x00543B28): bs.seek(0x5, NOESEEK_REL) off2pal = bs.readInt() bs.seek(0x10, NOESEEK_REL) value1 = bs.readInt() value2 = bs.readInt() width = bs.readInt() height = bs.readInt() else: bs.seek(0x19, NOESEEK_REL) off2pal = bs.readInt() bs.seek(0x04, NOESEEK_REL) value1 = bs.readInt() value2 = bs.readInt() width = bs.readInt() height = bs.readInt() if (width > 2048) or (height > 2048): continue print (textcount) print('Found a texture at {0}, width - {1}, height - {2}'.format(hex(offset - 0x4), width, height)) textcount+=1 # Accomdation for wad version 101 if (Temp == 0x00543B28): bs.seek(0x28, NOESEEK_REL) else: bs.seek(0x30, NOESEEK_REL) off2raw = bs.tell() bs.seek(off2pal, NOESEEK_ABS) print('Found a palette at {0}'.format(hex(off2pal))) bs.seek(0x50, NOESEEK_REL) palSize = 0x400 pal = bs.readBytes(palSize) f0 = io.BytesIO(pal) f1 = io.BytesIO(pal) count = 0 swapCount = 0 block0 = [] block1 = [] # Unswizzle palette block while count != 0x100: color = struct.unpack('i', f0.read(4))[0] f1.write(struct.pack("i", color)) count += 1 swapCount += 1 if count == 8 or swapCount == 16: for i in range(0,8): color = struct.unpack('i', f0.read(4))[0] block0+=[color] for i in range(0,8): color = struct.unpack('i', f0.read(4))[0] block1+=[color] for i in range(0,8): f1.write(struct.pack("i", block1[i])) for i in range(0,8): f1.write(struct.pack("i", block0[i])) block0=[] block1=[] count += 16 swapCount = 0 f1.seek(0x00, io.SEEK_SET) # Seek to correct palette in palette block if texture has a bit depth of 4 # Else, read the whole palette block if bitDepth == 0x14: newpalPosition = palPosition * 0x40 f1.seek(newpalPosition, io.SEEK_SET) thepal = f1.read(0x40) else: thepal = f1.read() newpal = bytearray(thepal) bs.seek(off2raw, NOESEEK_ABS) # 0x14: 16 color palette, 0x13: 256 color palette, 0x00: No palette # Accomdation for wad version 136 swizzling if bitDepth == 0x14: if (value1 != value2) and Temp == 0x00567760: width = width*2 height = height*2 img = rapi.imageUntwiddlePS2(bs.readBytes(width*height*4), width, height,4) img = rapi.imageDecodeRawPal(img, newpal, width, height, 4, "r8g8b8a8") else: img = rapi.imageDecodeRawPal(bs.readBytes(width*height), newpal, width, height, 4, "r8g8b8a8") if bitDepth == 0x13: if (value1 != value2) and Temp == 0x00567760: width = width*2 height = height*2 img = rapi.imageUntwiddlePS2(bs.readBytes(width*height*4), width, height,8) img = rapi.imageDecodeRawPal(img, newpal, width, height, 8, "r8g8b8a8") else: img = rapi.imageDecodeRawPal(bs.readBytes(width*height), newpal, width, height, 8, "r8g8b8a8") if bitDepth == 0x00: img = rapi.imageDecodeRaw(bs.readBytes(width*height*4), width, height, "r8g8b8a8") texList.append(NoeTexture(str(i), width, height, img, noesis.NOESISTEX_RGBA32)) bs.seek(offset, NOESEEK_ABS) # Texture package headers if (Temp == 0x004F5124) or (Temp == 0x004F92E4) or (Temp == 0x004F722C) or (Temp == 0x004FF518) or (Temp == 0x004F61DC) or (Temp == 0x004F829C): offset = bs.tell() bs.seek(0x09, NOESEEK_REL) palPosition = bs.readByte() bitDepth = bs.readByte() bs.seek(0x05, NOESEEK_REL) off2pal = bs.readInt() bs.seek(0x20, NOESEEK_REL) numTex = bs.readShort() print('Found a texture package at {0}, number of textures - {1}'.format(hex(offset - 0x4), numTex)) bs.seek(0x2, NOESEEK_REL) off2inf = bs.readInt() bs.seek(off2inf, NOESEEK_ABS) for j in range(0, numTex): bs.seek(0x8, NOESEEK_REL) width = bs.readInt() height = bs.readInt() off2tex = bs.readInt() bs.seek(0x4, NOESEEK_REL) print (textcount) print('Found a texture at {0}, width - {1}, height - {2}'.format(hex(off2tex), width, height)) textcount+=1 bs.seek(off2pal, NOESEEK_ABS) print('Found a palette at {0}'.format(hex(off2pal))) bs.seek(0x50, NOESEEK_REL) palSize = 0x400 pal = bs.readBytes(palSize) f0 = io.BytesIO(pal) f1 = io.BytesIO(pal) count = 0 swapCount = 0 block0 = [] block1 = [] # Unswizzle palette block while count != 0x100: color = struct.unpack('i', f0.read(4))[0] f1.write(struct.pack("i", color)) count += 1 swapCount += 1 if count == 8 or swapCount == 16: for i in range(0,8): color = struct.unpack('i', f0.read(4))[0] block0+=[color] for i in range(0,8): color = struct.unpack('i', f0.read(4))[0] block1+=[color] for i in range(0,8): f1.write(struct.pack("i", block1[i])) for i in range(0,8): f1.write(struct.pack("i", block0[i])) block0=[] block1=[] count += 16 swapCount = 0 f1.seek(0x00, io.SEEK_SET) # Seek to correct palette in palette block if texture has a bit depth of 4 # Else, read the whole palette block if bitDepth == 0x14: newpalPosition = palPosition * 0x40 f1.seek(newpalPosition, io.SEEK_SET) thepal = f1.read(0x40) else: thepal = f1.read() newpal = bytearray(thepal) bs.seek(off2tex + 0x20, NOESEEK_ABS) # 0x14: 16 color palette, 0x13: 256 color palette, 0x00: No palette if bitDepth == 0x14: img = rapi.imageDecodeRawPal(bs.readBytes(width*height), newpal, width, height, 4, "r8g8b8a8") if bitDepth == 0x13: img = rapi.imageDecodeRawPal(bs.readBytes(width*height), newpal, width, height, 8, "r8g8b8a8") if bitDepth == 0x00: img = rapi.imageDecodeRaw(bs.readBytes(width*height*4), width, height, "r8g8b8a8") texList.append(NoeTexture(str(i+j), width, height, img, noesis.NOESISTEX_RGBA32)) bs.seek(off2inf + (j + 1)*0x18, NOESEEK_ABS) bs.seek(offset, NOESEEK_ABS) return 1
def texLoadARGB(data, texList): bs = NoeBitStream(data) magic = bs.readUInt() if magic == 5784916 or magic == 1413830656: bigEndian = False if magic == 1413830656: bigEndian = True bs.setEndian(NOE_BIGENDIAN) bs.setByteEndianForBits(NOE_BIGENDIAN) Version = bs.readBits(12) if Version == 16: print( "Monster Hunter World textures not supported! Use Jodo's Texture Converter on Nexus Mods." ) return 0 unkn1 = bs.readBits(12) unused1 = bs.readBits(4) alphaFlags = bs.readBits(4) MipMapCount = bs.readBits(6) Width = bs.readBits(13) Height = bs.readBits(13) unkn2 = bs.readByte() Format = bs.readByte() unkn3 = bs.readUShort() Length = Width * Height if Version == 160: Length = bs.readUInt() if Debug: print("Endian: {endian}".format( endian="Big" if bigEndian else "Little")) print("Version: {}".format(Version)) print("Format: {}".format(Format)) print("Width: {}".format(Width)) print("Height: {}".format(Height)) print("Length: {}".format(Length)) MipOffsets = [] if Version == 160: for i in range(MipMapCount): MipOffsets.append(bs.readUInt()) #Switch - GU if Format == 7: blockWidth = blockHeight = 1 WidthInBlocks = (Width + (blockWidth - 1)) // blockWidth HeightInBlocks = (Height + (blockHeight - 1)) // blockHeight maxBlockHeight = 8 if Width < 256 or Height <= 256 else 16 maxBlockHeight = 4 if Width < 128 or Height <= 128 else maxBlockHeight maxBlockHeight = 2 if Width < 64 or Height <= 64 else maxBlockHeight maxBlockHeight = 1 if Width < 32 or Height <= 32 else maxBlockHeight pix = rapi.callExtensionMethod("untile_blocklineargob", bs.readBytes(Length), WidthInBlocks, HeightInBlocks, 4, maxBlockHeight) pix = rapi.imageDecodeRaw(pix, Width, Height, "b8g8r8a8", 2) elif Format == 19: blockWidth = blockHeight = 4 blockSize = 8 WidthInBlocks = (Width + (blockWidth - 1)) // blockWidth HeightInBlocks = (Height + (blockHeight - 1)) // blockHeight maxBlockHeight = 8 if Width < 256 or Height <= 256 else 16 maxBlockHeight = 4 if Width < 128 or Height <= 128 else maxBlockHeight maxBlockHeight = 2 if Width < 64 or Height <= 64 else maxBlockHeight maxBlockHeight = 1 if Width < 32 or Height <= 32 else maxBlockHeight pix = rapi.callExtensionMethod("untile_blocklineargob", bs.readBytes(Length), WidthInBlocks, HeightInBlocks, blockSize, maxBlockHeight) pix = rapi.imageDecodeDXT(pix, Width, Height, noesis.FOURCC_DXT1) elif Format == 23: blockWidth = blockHeight = 4 blockSize = 16 WidthInBlocks = (Width + (blockWidth - 1)) // blockWidth HeightInBlocks = (Height + (blockHeight - 1)) // blockHeight maxBlockHeight = 8 if Width < 256 or Height <= 256 else 16 maxBlockHeight = 4 if Width < 128 or Height <= 128 else maxBlockHeight maxBlockHeight = 2 if Width < 64 or Height <= 64 else maxBlockHeight maxBlockHeight = 1 if Width < 32 or Height <= 32 else maxBlockHeight pix = rapi.callExtensionMethod("untile_blocklineargob", bs.readBytes(Length), WidthInBlocks, HeightInBlocks, blockSize, maxBlockHeight) pix = rapi.imageDecodeDXT(pix, Width, Height, noesis.NOESISTEX_DXT5) elif Format == 25: blockWidth = blockHeight = 4 blockSize = 8 WidthInBlocks = (Width + (blockWidth - 1)) // blockWidth HeightInBlocks = (Height + (blockHeight - 1)) // blockHeight maxBlockHeight = 8 if Width < 256 or Height <= 256 else 16 maxBlockHeight = 4 if Width < 128 or Height <= 128 else maxBlockHeight maxBlockHeight = 2 if Width < 64 or Height <= 64 else maxBlockHeight maxBlockHeight = 1 if Width < 32 or Height <= 32 else maxBlockHeight pix = rapi.callExtensionMethod("untile_blocklineargob", bs.readBytes(Length), WidthInBlocks, HeightInBlocks, blockSize, maxBlockHeight) pix = rapi.imageDecodeDXT(pix, Width, Height, noesis.FOURCC_ATI1) elif Format == 31: blockWidth = blockHeight = 4 blockSize = 16 WidthInBlocks = (Width + (blockWidth - 1)) // blockWidth HeightInBlocks = (Height + (blockHeight - 1)) // blockHeight maxBlockHeight = 8 if Width < 256 or Height <= 256 else 16 maxBlockHeight = 4 if Width < 128 or Height <= 128 else maxBlockHeight maxBlockHeight = 2 if Width < 64 or Height <= 64 else maxBlockHeight maxBlockHeight = 1 if Width < 32 or Height <= 32 else maxBlockHeight pix = rapi.callExtensionMethod("untile_blocklineargob", bs.readBytes(Length), WidthInBlocks, HeightInBlocks, blockSize, maxBlockHeight) pix = rapi.imageDecodeDXT(pix, Width, Height, noesis.FOURCC_ATI2) else: print(Format) texList.append( NoeTexture("MTFTex", Width, Height, pix, noesis.NOESISTEX_RGBA32)) if Version == 165: #3DS v2 | Wii U if bigEndian: #adapted loosely from Zaramot's script gtxTex = ( b'\x47\x66\x78\x32\x00\x00\x00\x20\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42\x4C\x4B\x7B\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0A\x00\x00\x00\x9C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' ) gtxWidth = struct.pack(">I", Width) gtxheight = struct.pack(">I", Height) gtxTex += gtxWidth gtxTex += gtxheight gtxTex += (b'\x00\x00\x00\x01\x00\x00\x00\x01') if Format == 11: ddsFmt = noesis.FOURCC_BC1 type = struct.pack(">I", 49) gtxFmt = struct.pack(">I", 0xC40003FF) pixelInfo = struct.pack(">II", 4096, 256) ddsSize = (Width * Height * 4) // 8 ddsData = bs.readBytes(ddsSize) elif Format == 12: ddsFmt = noesis.FOURCC_BC2 type = struct.pack(">I", 50) gtxFmt = struct.pack(">I", 0xCC0003FF) pixelInfo = struct.pack(">II", 8192, 256) ddsSize = (Width * Height * 8) // 8 ddsData = bs.readBytes(ddsSize) else: print("Unknown format {}".format(Format)) return 0 gtxTex += type gtxTex += (b'\x00\x00\x00\x00\x00\x00\x00\x01') gtxTex += struct.pack(">I", ddsSize) gtxTex += ( b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x0D\x00\x00' ) gtxTex += pixelInfo gtxTex += ( b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x02\x03\x1F\xF8\x7F\x21' ) gtxTex += gtxFmt gtxTex += ( b'\x06\x88\x84\x00\x00\x00\x00\x00\x80\x00\x00\x10\x42\x4C\x4B\x7B\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0B' ) gtxTex += struct.pack(">I", ddsSize) gtxTex += (b'\x00\x00\x00\x00\x00\x00\x00\x00') gtxTex += ddsData gtxTex += ( b'\x42\x4C\x4B\x7B\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ) ddsName = rapi.getLocalFileName(rapi.getInputName()) dstFilePath = rapi.getDirForFilePath( rapi.getInputName()) + ddsName + ".gtx" newfile = open(dstFilePath, 'wb') newfile.write(gtxTex) newfile.close() subprocess.Popen( [noesis.getScenesPath() + 'TexConv2.bat', dstFilePath]).wait() try: texData = rapi.loadIntoByteArray(dstFilePath + ".dds") texture = rapi.loadTexByHandler(texData, ".dds") except: texture = NoeTexture(str(len(self.texList)), 0, 0, None, noesis.NOESISTEX_RGBA32) texture.name = ddsName texList.append(texture) else: print( "3DS MT Framework Textures not supported! Use Kukkii from the Kuriimu suite." ) return 1 elif magic == 542655828: #MHXR Mobile MT Version = bs.readBits(16) unkn1 = bs.readBits(8) Format = bs.readBits(8) MipMapCount = bs.readBits(6) R1 = bs.readBits(2) unused1 = bs.readBits(24) Width = bs.readBits(13) Height = bs.readBits(13) unkn4 = bs.readBits(2) unkn5 = bs.readBits( 4) #these could be part of the same thing, but I doubt it assert Version == 9 #according to https://github.com/IcySon55/Kuriimu/blob/master/src/image/image_mt/MobileMTTexSupport.cs this whole structure should be mostly inverted, so unless this file is somehow Big Endian, we need version check #noticed that any other version of the format also uses version 9, so there will be problems #also, only works with iOS textures. Android uses BC but has some issues within the data. The two are identical header-wise if Format == 4: #PVRTC4 length = int(Width * Height / 2) pix = rapi.imageDecodePVRTC(bs.readBytes(length), Width, Height, 4) elif Format == 0x10: #ABGR16 length = Width * Height * 2 pix = rapi.imageDecodeRaw(bs.readBytes(length), Width, Height, "a4b4g4r4") elif Format == 0x20: #ABGR32 length = Width * Height * 4 pix = rapi.imageDecodeRaw(bs.readBytes(length), Width, Height, "a8b8g8r8") else: print("Invalid Format {}".format(Format)) return 0 texList.append( NoeTexture("MobileMTFTex", Width, Height, pix, noesis.NOESISTEX_RGBA32)) return 1 else: return 0