Ejemplo n.º 1
0
class ShenmueModel:

    HRCM = 0x4D435248
    TEXD = 0x44584554
    PVRT = 0x54525650

    def __init__(self, filepath):
        self.fp = os.path.basename(filepath)
        self.bs = BitStream(filepath)
        self.iff = self.bs.readUInt()
        self.texOfs = self.bs.readUInt()

    def writePngImages(self):
        #Seek to texture offset
        self.bs.seek_set(self.texOfs)

        #Check offset for texture definition
        iff = self.bs.readUInt()
        if iff != ShenmueModel.TEXD:
            return 0
        iffLen = self.bs.readUInt()
        #Read number of textures
        nbTex = self.bs.readUInt()
        texBase = os.path.splitext(self.fp)[0]

        #Loop through each texture
        for i in range(nbTex):

            #Look for pvr file header
            if not self.bs.find(ShenmueModel.PVRT):
                return 0

            #Length of pvrFile
            pvrLen = self.bs.readUInt()
            pvr = PvrTexture(self.bs, False, True)
            bitmap = pvr.getBitmap()

            if len(bitmap) == 0:
                continue

            texName = "output/%s_%02d.png" % (texBase, i)
            print(texName)
            png.from_array(bitmap, 'RGBA').save(texName)

        return 1
Ejemplo n.º 2
0
class PvmArchive:

    #File Format Constants
    PVMH = 0x484D5650
    PVRT = 0x54525650

    def __init__(self, filepath):
        self.bs = BitStream(filepath)
        self.texList = self.readHeader()
        print(self.texList)

    def readHeader(self):
        #Create array
        texList = []

        #Check for PVMH file header
        iff = self.bs.readUInt()
        if iff != PvmArchive.PVMH:
            return 0

        #Offset of first texture entry
        texOfs = self.bs.readUInt()
        self.bs.setOffset()

        #Read flags and number of textures
        flags = self.bs.readUShort()
        nbTex = self.bs.readUShort()

        for i in range(nbTex):
            tex = {'id': self.bs.readUShort()}

            if flags & BIT_3:
                #Filename bit flag
                tex['name'] = self.bs.readStr(0x1C)
            if flags & BIT_2:
                #File format bitflag
                tex['format'] = self.bs.readUShort()
            if flags & BIT_1:
                #File dimensions bit flag
                tex['size'] = self.bs.readUShort()
            if flags & BIT_0:
                #Global Index bit flag
                tex['index'] = self.bs.readUInt()

            texList.append(tex)

        self.bs.seek_set(texOfs)
        return texList

    def writePngImages(self):

        #Loop through each texture
        for tex in self.texList:

            self.bs.seek_set(0)
            offset = self.bs.tell() % 4
            self.bs.seek_cur(offset)

            #Look for PVRT file header
            if not self.bs.find(PvmArchive.PVRT):
                #If not found, raise an error
                print("PVRT not found: 0x%x" % self.bs.tell())
                return 0

            #Length of pvr texture
            pvrLen = self.bs.readUInt()
            self.bs.setOffset()

            #Create PvrImage to convert bitmap
            print("Name: %s, Pos: 0x%x" % (tex['name'], self.bs.tell()))
            pvr = PvrTexture(self.bs, False, True)
            bitmap = pvr.getBitmap()
            imgName = "output/" + tex['name'] + '.png'
            png.from_array(bitmap, 'RGBA').save(imgName)

            #img = Image.open(imgName)
            #img = img.rotate(180)
            #img.save(imgName)

            print("")

        return 1