示例#1
0
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)
示例#2
0
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
示例#3
0
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
示例#4
0
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
示例#5
0
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]
示例#6
0
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
示例#7
0
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]
示例#8
0
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