Пример #1
0
    def toFakeLZO(self, path, tabPath, outBinPath, outTabPath):
        """Convert a file's contents to "fake LZO" format.

        path: input file to convert.
        tabPath: table for input file.
        outBinPath: output path for .bin file.
        outTabPath: output path for .tab file.
        """
        inFile  = BinaryFile(path,    'rb')
        tabFile = BinaryFile(tabPath, 'rb')
        outBin  = BinaryFile(outBinPath, 'wb')
        outTab  = BinaryFile(outTabPath, 'wb')
        inZlb   = Zlb(inFile)
        offs    = tabFile.readu32()
        while True:
            nextOffs = tabFile.readu32()
            if nextOffs == 0xFFFFFFFF: break
            high = offs & 0xFF000000
            offs &= 0xFFFFFF
            size = (nextOffs & 0xFFFFFF) - offs
            if size > 0:
                inFile.seek(offs)
                data = inZlb.decompress()
                header = b'LZO\0' + struct.pack('>3I', 1, len(data), len(data)) + b'Rena'
                pad  = len(data) & 0xF
                if pad: data += b'\0' * (16-pad)
            outTab.writeu32(outBin.tell() | high)
            if size > 0: outBin.write(header + data)
            offs = nextOffs
        outTab.writeu32(outBin.tell()) # XXX verify
        outTab.writeu32(0xFFFFFFFF)
Пример #2
0
    def toLZO(self, path, tabPath, outBinPath, outTabPath):
        """Convert a file's contents to LZO.

        path: input file to convert.
        tabPath: table for input file.
        outBinPath: output path for .bin file.
        outTabPath: output path for .tab file.
        """
        inFile  = BinaryFile(path,    'rb')
        tabFile = BinaryFile(tabPath, 'rb')
        outBin  = BinaryFile(outBinPath, 'wb')
        outTab  = BinaryFile(outTabPath, 'wb')
        inZlb   = Zlb(inFile)
        outLzo  = DPLZO(outBin)
        while True:
            offs    = tabFile.readu32()
            if offs == 0xFFFFFFFF: break
            high = offs & 0xFF000000
            inFile.seek(offs & 0xFFFFFF)
            data = inZlb.decompress()
            pad  = len(data) & 0xF
            if pad: data += b'\0' * (16-pad)
            outTab.writeu32(outBin.tell() | high)
            outBin.write(outLzo.compress(data))
        outTab.writeu32(outBin.tell()) # XXX verify
        outTab.writeu32(0xFFFFFFFF)
Пример #3
0
    def modelstoFakeLZO(self, path, tabPath, outBinPath, outTabPath):
        """Convert a model file's contents to "fake LZO" format.

        path: input file to convert.
        tabPath: table for input file.
        outBinPath: output path for .bin file.
        outTabPath: output path for .tab file.
        """
        inFile  = BinaryFile(path,       'rb')
        tabFile = BinaryFile(tabPath,    'rb')
        outBin  = BinaryFile(outBinPath, 'wb')
        outTab  = BinaryFile(outTabPath, 'wb')
        inZlb   = Zlb(inFile)
        tabCksum = 0
        while True:
            offs    = tabFile.readu32()
            if offs == 0xFFFFFFFF: break
            high = offs & 0xFF000000
            if high & 0x10000000:
                #printf("Model %08X\r\n", offs)
                offs = offs & 0xFFFFFF
                inFile.seek(offs)

                data = inFile.read(4)
                if data == b'\xFA\xCE\xFE\xED':
                    while data not in (b'ZLB\0', b'DIR\0', b'\xE0\xE0\xE0\xE0', b'\xF0\xF0\xF0\xF0'):
                        outBin.write(data)
                        data = inFile.read(4)
                inFile.seek(offs)

                data = inZlb.decompress()
                header = b'ZLB\0' + struct.pack('>3I', 1, len(data), len(data)) + b'Rena'
                data = header + data
                tabVal = outBin.tell() | high
                outBin.write(data)
                while outBin.tell() & 0xF: outBin.writeu8(0)

            else: # don't use this model
                tabVal = 0x00000000
            tabCksum += ((tabVal >> 24) & 0xFF)
            tabCksum += ((tabVal >> 16) & 0xFF)
            tabCksum += ((tabVal >>  8) & 0xFF)
            tabCksum += ( tabVal        & 0xFF)
            outTab.writeu32(tabVal)

        tabVal = outBin.tell()
        outTab.writeu32(tabVal)
        tabCksum += ((tabVal >> 24) & 0xFF)
        tabCksum += ((tabVal >> 16) & 0xFF)
        tabCksum += ((tabVal >>  8) & 0xFF)
        tabCksum += ( tabVal        & 0xFF)

        outTab.writeu32(0xFFFFFFFF)
        tabCksum += (0xFF * 4)
        outTab.writeu32(tabCksum & 0xFFFFFFFF)
        for i in range(7):
            outTab.writeu32(0)
Пример #4
0
    def textoDIR(self, path, tabPath, outBinPath, outTabPath):
        """Convert a texture file's contents to uncompressed DIR format.

        path: input file to convert.
        tabPath: table for input file.
        outBinPath: output path for .bin file.
        outTabPath: output path for .tab file.
        """
        inFile  = BinaryFile(path,       'rb')
        tabFile = BinaryFile(tabPath,    'rb')
        outBin  = BinaryFile(outBinPath, 'wb')
        outTab  = BinaryFile(outTabPath, 'wb')
        inZlb   = Zlb(inFile)
        tabCksum = 0
        while True:
            offs    = tabFile.readu32()
            if offs == 0xFFFFFFFF: break
            high = offs & 0xFF000000
            if high & 0x80000000:
                offs = (offs & 0xFFFFFF) * 2
                nFrames = (high >> 24) & 0x3F
                inFile.seek(offs)

                # read frame values
                if nFrames > 1: frameData = inFile.readu32(nFrames+1)
                else: frameData = []

                data = inZlb.decompress()
                #data = b'\0\0\0\0' + b'\0\0\0\0' + b'\0\0\0\0' + data
                dl = len(data)
                header = b'DIR\0' + struct.pack('>3I', 0, dl, dl)
                header += b'\0\0\0\0' + b'\0\0\0\0' + b'\0\0\0\0' + b'\0\0\0\0'
                data = header + data
                tabVal = (outBin.tell() >> 1) | high
                if nFrames > 1: outBin.writeu32(*frameData)
                outBin.write(data)
                while outBin.tell() & 0xF: outBin.writeu8(0)

            else: # don't use this texture
                tabVal = 0x01000000
            tabCksum += ((tabVal >> 24) & 0xFF)
            tabCksum += ((tabVal >> 16) & 0xFF)
            tabCksum += ((tabVal >>  8) & 0xFF)
            tabCksum += ( tabVal        & 0xFF)
            outTab.writeu32(tabVal)
        outTab.writeu32(0xFFFFFFFF)
        tabCksum += (0xFF * 4)
        outTab.writeu32(tabCksum & 0xFFFFFFFF)
        for i in range(7):
            outTab.writeu32(0)
Пример #5
0
    def textoLZO(self, path, tabPath, outBinPath, outTabPath):
        """Convert a texture file's contents to LZO.

        path: input file to convert.
        tabPath: table for input file.
        outBinPath: output path for .bin file.
        outTabPath: output path for .tab file.
        """
        inFile  = BinaryFile(path,    'rb')
        tabFile = BinaryFile(tabPath, 'rb')
        outBin  = BinaryFile(outBinPath, 'wb')
        outTab  = BinaryFile(outTabPath, 'wb')
        inZlb   = Zlb(inFile)
        outLzo  = DPLZO(outBin)
        tabCksum = 0
        while True:
            offs    = tabFile.readu32()
            if offs == 0xFFFFFFFF: break
            high = offs & 0xFF000000
            if high & 0x80000000:
                offs = (offs & 0xFFFFFF) * 2
                nFrames = (high >> 24) & 0x3F
                inFile.seek(offs)

                # read frame values
                if nFrames > 1: frameData = inFile.readu32(nFrames+1)
                else: frameData = []

                data = outLzo.compress(inZlb.decompress())
                tabVal = (outBin.tell() >> 1) | (high & 0xC0000000) | ((nFrames-1) << 24)
                if nFrames > 1: outBin.writeu32(*frameData)
                outBin.write(data)
                while outBin.tell() & 0xF: outBin.writeu8(0)

            else: # don't use this texture
                tabVal = 0x01000000
            tabCksum += ((tabVal >> 24) & 0xFF)
            tabCksum += ((tabVal >> 16) & 0xFF)
            tabCksum += ((tabVal >>  8) & 0xFF)
            tabCksum += ( tabVal        & 0xFF)
            outTab.writeu32(tabVal)
        outTab.writeu32(0xFFFFFFFF)
        tabCksum += (0xFF * 4)
        outTab.writeu32(tabCksum & 0xFFFFFFFF)
        for i in range(7):
            outTab.writeu32(0)
Пример #6
0
    def mapstoFakeLZO(self, path, tabPath, outBinPath, outTabPath):
        """Convert MAPS.BIN file's contents to "fake LZO" format.

        path: input file to convert.
        tabPath: table for input file.
        outBinPath: output path for .bin file.
        outTabPath: output path for .tab file.
        """
        inFile  = BinaryFile(path,       'rb')
        tabFile = BinaryFile(tabPath,    'rb')
        outBin  = BinaryFile(outBinPath, 'wb')
        outTab  = BinaryFile(outTabPath, 'wb')
        inZlb   = Zlb(inFile)
        offs    = tabFile.readu32()
        while offs != 0xFFFFFFFF:
            nextOffs = tabFile.readu32()
            inLen    = nextOffs - offs
            inFile.seek(offs)

            tabVal = outBin.tell()
            outTab.writeu32(tabVal)

            while offs < nextOffs:
                inFile.seek(offs)
                data = inFile.read(4)
                if len(data) == 0: break
                elif data == b'\xFA\xCE\xFE\xED':
                    rawLen, zlbOffs, compLen = inFile.readStruct('3I')
                    dOut = data + struct.pack('>3I', rawLen+0x28, zlbOffs, rawLen+4)
                    printf("Write FACEFEED at %08X: %s\r\n", outBin.tell(),
                        dOut.hex())
                    outBin.write(dOut)
                    for i in range(zlbOffs):
                        outBin.writeu16(inFile.readu16())
                    offs += len(data)
                elif data == b'ZLB\0':
                    inFile.seek(offs)
                    data = inZlb.decompress()
                    dl   = len(data) + 4
                    outBin.write(b'LZO\0' + struct.pack('3I', 0, 0, dl) + b'Rena' + data)
                else:
                    outBin.write(data)
                offs = inFile.tell()
            offs = nextOffs

        tabVal = outBin.tell()
        outTab.writeu32(tabVal)
        outTab.writeu32(0xFFFFFFFF)
        for i in range(3):
            outTab.writeu32(0)
Пример #7
0
    def packTextures(self, path, outPath, which):
        """Pack images in `path` to TEXn.bin, TEXn.tab files, where n=which."""
        textures = {} # ID => tex
        # get list of files to pack
        for name in os.listdir(path):
            if re.match(r'^[0-9a-fA-F]+\.[0-9a-fA-F]+\.', name):
                fields = name.split('.')
                tid = int(fields[0], 16) # texture ID
                mid = int(fields[1], 16) # mipmap ID
                if tid not in textures: textures[tid] = {}
                textures[tid][mid] = name

        printf("Packing %d textures to %s.bin/tab\n", len(textures), outPath)

        # write out bin and tab files
        binFile = BinaryFile(outPath+'.bin', 'wb')
        tabFile = BinaryFile(outPath+'.tab', 'wb')
        maxId = self.MAX_TEX0_ID if str(which) == '0' else self.MAX_TEX1_ID
        for tid in range(maxId):
            if tid in textures:
                printf("%04X... ", tid)
                mips = textures[tid]
                offs = binFile.tell()
                nMips = len(mips)
                printf("%2d mips, %08X  ", nMips, offs)
                tabFile.writeu32(
                    0x80000000 | (offs>>1) | (nMips << 24))

                mipData = []
                for mip in range(nMips):
                    name = mips[mip]
                    fPath = os.path.join(path, name)
                    if name.endswith('.tex') or name.endswith('.bin'):
                        with open(fPath, 'rb') as file:
                            data = file.read()
                    else: # image file
                        fields = name.split('.')
                        fmt = ImageFormat[fields[2]]
                        img = Image.open(fPath)
                        tex = SfaTexture.fromImage(img, fmt=format, numMipMaps=numMipMaps)
                        data = tex.toData()
                    data = Zlb(None).compress(data)
                    pad = len(data) & 0x3
                    if pad: data += b'\0' * (4 - pad)
                    mipData.append(data)

                # write the mipmap offsets
                if nMips > 1:
                    mipOffs = 4 * (nMips+1)
                    for data in mipData:
                        binFile.writeu32(mipOffs)
                        mipOffs += len(data)
                    binFile.writeu32(mipOffs)

                # write the data
                for data in mipData:
                    binFile.write(data)

                # align to 32 bytes - required by game
                pad = binFile.tell() & 0x1F
                if pad: binFile.write(b'\0' * (32 - pad))

                printf("OK\n")
            else:
                tabFile.writeu32(0x01000000)
        # write size of last item and terminator
        tabFile.writeu32(binFile.tell() >> 1)
        tabFile.writeu32(0xFFFFFFFF)
        tabFile.writeu32(0xCFA2) # XXX what is this? never read?
        tabFile.writeu32(0, 0, 0, 0, 0, 0, 0)
        binFile.close()
        tabFile.close()