예제 #1
0
    def unpack(self, fname):
        outData = RulesData()
        with file(fname, 'rb') as rfile:
            header = rfile.read(2)
            assert header == '\x00\x00'

            # Chunk 1
            format = '<H'
            numEntries = unpack(rfile, format)
            format = '<2B'
            chunk1PointArray = []
            for i in xrange(numEntries / 2):
                y, x = unpack(rfile, format)
                chunk1PointArray.append(PointData(x, y))
            outData.chunk1PointArray = chunk1PointArray

            # Chunk 2 - character data
            format = '<H'
            numEntries = unpack(rfile, format)
            assert numEntries <= 40
            characters = []
            for i in xrange(numEntries):
                cData = CharacterData()
                format = '<4H2b8B'
                (posX, posY, posAltitude, frameArray, _rulesBuffer2_5, _rulesBuffer2_6, _rulesBuffer2_7,
                    spriteSize, direction, _rulesBuffer2_10, _rulesBuffer2_11, _rulesBuffer2_12,
                    _rulesBuffer2_13_posX, _rulesBuffer2_14_posY) = unpack(rfile, format)
                cData.posX = posX if posX == 0xFFFF else ((posX << 3) + 4)
                cData.posY = posY if posY == 0xFFFF else ((posY << 3) + 4)
                cData.posAltitude = posAltitude & 0xFF
                cData.frameArray = frameArray
                cData._rulesBuffer2_5 = _rulesBuffer2_5
                cData._rulesBuffer2_6 = _rulesBuffer2_6
                cData._rulesBuffer2_7 = _rulesBuffer2_7
                cData.spriteSize = spriteSize
                cData.direction = direction
                cData._rulesBuffer2_10 = _rulesBuffer2_10
                cData._rulesBuffer2_11 = _rulesBuffer2_11
                cData._rulesBuffer2_12 = _rulesBuffer2_12
                cData._rulesBuffer2_13_posX = _rulesBuffer2_13_posX
                cData._rulesBuffer2_14_posY = _rulesBuffer2_14_posY
                format = '32B'
                cData.variables = unpack(rfile, format)
                cData._rulesBuffer2_16 = unpack(rfile, format)
                characters.append(cData)
            outData.characters = characters

            # Chunk 3 & 4 - packed strings and associated indexes
            format = '<2H' # this might actually be signed, going by the ScummVM Robin code.
            numEntries, size = unpack(rfile, format)
            stringIndexes = unpack(rfile, '<' + str(numEntries) + 'H') # not used, because we cheat below
            stringData = rfile.read(size)
            # Assume all strings are terminated by \x00, and all strings are used/listed in the index table.
            strings = stringData.split('\x00')
            del strings[-1]
            def unpackString(inChar):
                global packedStringLookup
                val = ord(inChar)
                if val < 0x80:
                    return inChar
                return packedStringLookup[0xFF - val]
            for i, packedString in enumerate(strings):
                strings[i] = ''.join(map(unpackString, packedString))
            outData.strings = strings

            # Chunk 5 - scripts
            format = '<H'
            numEntries = unpack(rfile, format)
            scripts = rfile.read(numEntries * 2) # each entry is a uint16
            outData.scripts = ScriptData('scripts', scripts)

            # Chunk 6 - menu scripts
            format = '<H'
            numEntries = unpack(rfile, format)
            menuScripts = rfile.read(numEntries * 2) # each entry is a uint16
            outData.menuScripts = ScriptData('menuScripts', menuScripts)

            # Chunk 7 & 8 - game scripts and indexes
            format = '<H'
            numEntries = unpack(rfile, format)
            gameScriptIndexes = unpack(rfile, '<' + str(numEntries) + 'H')
            size = unpack(rfile, format)
            # Here's an unnecessarily clever way to calculate the sizes of each script block.
            script_sizes = map(lambda x, y: (y if y is not None else size) - x, gameScriptIndexes, gameScriptIndexes[1:])
            gameScripts = []
            for i, script_size in enumerate(script_sizes):
                script_data = ScriptData('gameScript_{}'.format(i + 1), rfile.read(script_size))
                gameScripts.append(script_data)
            outData.gameScripts = gameScripts

            # Chunk 9
            format = '60B'
            outData.rulesChunk9 = unpack(rfile, format)

            # Chunk 10 & 11
            numEntries = unpack(rfile, 'B')
            assert numEntries <= 20
            chunk10Sizes = []
            if numEntries:
                totalSize = 0
                for i in xrange(numEntries):
                    val = unpack(rfile, 'B')
                    chunk10Sizes.append(val)
                    totalSize += val
                if totalSize:
                    rulesChunk11 = []
                    for size in chunk10Sizes:
                        format = '{}B'.format(size)
                        data = unpack(rfile, format)
                        rulesChunk11.append(data)
                    outData.rulesChunk11 = rulesChunk11

            # Chunk 12 - rectangles
            format = '<H'
            numEntries = unpack(rfile, format)
            rectangles = []
            format = '8B'
            for i in xrange(numEntries):
                rectData = RectData(
                    *(unpack(rfile, format))
                )
                rectangles.append(rectData)
            outData.rectangles = rectangles

            # Chunk 13 - interface hotspots
            format = '20B' # I think the first entry is actually numEntries, since it's 19
            outData.interfaceTwoStepAction = unpack(rfile, format) # might be a byte array
            format = '<20h'
            outData.interfaceHotspotsX = unpack(rfile, format)
            outData.interfaceHotspotsY = unpack(rfile, format)
            format = '20B'
            outData.keyboardMapping = unpack(rfile, format)
        return outData
예제 #2
0
 def decode_objects(dct):
     try:
         type_val = dct['__type__']
     except KeyError:
         return dct
     if type_val == 'RulesData':
         rules = RulesData()
         rules.chunk1PointArray = dct['chunk1PointArray']
         rules.characters = dct['characters']
         rules.strings = dct['strings']
         rules.scripts = dct['scripts']
         rules.menuScripts = dct['menuScripts']
         #rules.gameScriptIndexes = dct['gameScriptIndexes']
         rules.gameScripts = dct['gameScripts']
         rules.rulesChunk9 = dct['rulesChunk9']
         #rules.chunk10Indexes = dct['chunk10Indexes']
         rules.rulesChunk11 = dct['rulesChunk11']
         rules.rectangles = dct['rectangles']
         rules.interfaceTwoStepAction = dct['hotspots']['interfaceTwoStepAction']
         rules.interfaceHotspotsX = dct['hotspots']['interfaceHotspotsX']
         rules.interfaceHotspotsY = dct['hotspots']['interfaceHotspotsY']
         rules.keyboardMapping = dct['hotspots']['keyboardMapping']
         return rules
     elif type_val == 'PointData':
         point = PointData()
         point.x = dct['x']
         point.y = dct['y']
         return point
     elif type_val == 'CharacterData':
         character = CharacterData()
         character.posX = dct['posX']
         character.posY = dct['posY']
         character.posAltitude = dct['posAltitude']
         character.frameArray = dct['frameArray']
         character._rulesBuffer2_5 = dct['_rulesBuffer2_5']
         character._rulesBuffer2_6 = dct['_rulesBuffer2_6']
         character._rulesBuffer2_7 = dct['_rulesBuffer2_7']
         character.spriteSize = dct['spriteSize']
         character.direction = dct['direction']
         character._rulesBuffer2_10 = dct['_rulesBuffer2_10']
         character._rulesBuffer2_11 = dct['_rulesBuffer2_11']
         character._rulesBuffer2_12 = dct['_rulesBuffer2_12']
         character._rulesBuffer2_13_posX = dct['_rulesBuffer2_13_posX']
         character._rulesBuffer2_14_posY = dct['_rulesBuffer2_14_posY']
         character.variables = dct['variables']
         character._rulesBuffer2_16 = dct['_rulesBuffer2_16']
         return character
     elif type_val == 'RectData':
         rect = RectData()
         rect.maxX = dct['maxX']
         rect.minX = dct['minX']
         rect.maxY = dct['maxY']
         rect.minY = dct['minY']
         rect.topLeftPosY = dct['topLeftPosY']
         rect.topLeftPosX = dct['topLeftPosX']
         rect.bottomRightPosY = dct['bottomRightPosY']
         rect.bottomRightPosX = dct['bottomRightPosX']
         return rect
     elif type_val == 'RawData':
         id = dct['id']
         base_name = dct['path']
         path_name = os.path.split(json_file_name)[0]
         raw_fname = os.path.join(path_name, base_name)
         raw_data = RawData(id, None) # Data will be populated later
         external_files.append(
             (raw_data, raw_fname)
         )
         return raw_data
     elif type_val == 'ScriptData':
         id = dct['id']
         base_name = dct['path']
         path_name = os.path.split(json_file_name)[0]
         script_fname = os.path.join(path_name, 'scripts', base_name)
         script_data = ScriptData(id, None) # Data will be populated later
         external_files.append(
             (script_data, script_fname)
         )
         return script_data