Exemple #1
0
    def _read_block_table(self, f, size):
        block_struct = 'HBBBBBB'

        self.block_table = []
        for i in range(size / calcsize(block_struct)):
            block = Block(*unpack_file(block_struct, f))
            self.block_table.append(block)
Exemple #2
0
    def _read_object_positions(self, f, size):
        object_pos_struct = 'HHHBBHHH'
        block_size = calcsize(object_pos_struct)

        self.object_pos = []
        for i in range(size / block_size):
            data = unpack_file(object_pos_struct, f)
            self.object_pos.append(ObjectPos(*data))
Exemple #3
0
    def _read_navigation_data(self, f, size):
        nav_struct = 'BBBBB30s'
        self.districts = []

        f.seek(-size, os.SEEK_END)
        for i in range(size / calcsize(nav_struct)):
            data = unpack_file(nav_struct, f)
            self.districts.append(District(*data))
Exemple #4
0
    def read_palettes(self, data, size):
        data = StringIO.StringIO(data)

        palette_count = size / 1024
        self.palettes = [[] for i in range(palette_count)]

        for k in range(palette_count / 64):
            for j in range(256):
                for i in range(64):
                    b, g, r, x = unpack_file('BBBB', data)
                    self.palettes[k*64+i].extend((r, g, b))

        k = palette_count / 64
        for j in range(256):
            for i in range(palette_count % 64):
                b, g, r, x = unpack_file('BBBB', data)
                self.palettes[k*64 + i].extend((r, g, b))
Exemple #5
0
    def _read_grid(self, f):
        grid_columns = unpack_file('I' * 256 * 256, f)
        column_iter = iter(unpack_file('H' * (self.column_size / 2), f))

        cube_stack_table = {}
        pos = 0
        try:
            while True:
                d = column_iter.next()
                cubes = 6 - d

                cube_stack_table[pos] = [column_iter.next() for i in range(cubes)]
                pos += 2 * (1 + cubes)
        except StopIteration:
            pass

        self.grid = []
        for column in grid_columns:
            stack = cube_stack_table[column]
            self.grid.append(stack)
Exemple #6
0
    def _read_object_info(self, f, size):
        ObjectInfo = namedtuple('ObjectInfo', 'width height depth sprite_num')

        object_info_struct = 'IIIHxxxxxx'
        block_size = calcsize(object_info_struct)

        self.object_infos = []
        for i in range(size / block_size):
            data = unpack_file('IIIHxxxxxx', f)
            self.object_infos.append(ObjectInfo(*data))

        print "object infos:", len(self.object_infos)
Exemple #7
0
    def _read_sprite_numbers(self, f, size):
        fields = 'arrow digits boat bux bus car object ped speedo tank ' \
                 'traffic_lights train trdoors bike tram wbus wcar ex ' \
                 'tumcar tumtruck ferry'

        SpriteNumbers = namedtuple('SpriteNumbers', fields)
        self.sprite_numbers = SpriteNumbers(*unpack_file('H' * (size / 2), f))
        self.sprite_offset = {}

        for i, field in enumerate(SpriteNumbers._fields):
            fields_before = SpriteNumbers._fields[:i]
            self.sprite_offset[field] = sum(getattr(self.sprite_numbers, f) for f in fields_before)

        print "sprite numbers: ", ', '.join(("%d %s" % (v, k) for (k, v) in self.sprite_numbers._asdict().items()))
Exemple #8
0
    def load_from_file(self, f):
        # Header
        self.version, self.side_size, self.lid_size, self.aux_size, \
        self.anim_size, self.clut_size, self.tileclut_size, self.spriteclut_size, \
        self.newcarclut_size, self.fontclut_size, self.palette_index_size, \
        self.object_info_size, self.car_size, self.sprite_info_size, \
        self.sprite_graphics_size, self.sprite_numbers_size = unpack_file('I' * 16, f)

        # Tiles
        size = self.side_size + self.lid_size + self.aux_size
        if size % (64 * 64 * 4):
            size += (64 * 64 * 4) - (size % (64 * 64 * 4))
        side_lid_aux = f.read(size)

        # Animations
        self._read_animations(f, self.anim_size)

        # Palette
        clut = f.read(self.clut_size)
        if self.clut_size % (64 * 1024):
            f.read(64*1024 - (self.clut_size % (64*1024)))

        palette_index_data = f.read(self.palette_index_size)
        self.palette_index = PaletteIndex(tile_index_size=self.tileclut_size / 1024)
        self.palette_index.read_palettes(clut, self.clut_size)
        self.palette_index.read_index(palette_index_data, self.palette_index_size)

        # Object infos
        self._read_object_info(f, self.object_info_size)

        # Car infos
        self._read_car_infos(f, self.car_size)

        # Sprites
        sprite_info = f.read(self.sprite_info_size)
        sprite_graphics = f.read(self.sprite_graphics_size)
        self._read_sprite_numbers(f, self.sprite_numbers_size)

        self.sprites = Sprite(StringIO.StringIO(sprite_info), sprite_graphics, self.palette_index)
        self.sprites.colorize()

        self.colorize_tiles(side_lid_aux, self.palette_index)
Exemple #9
0
    def load_from_file(self, f):
        self.version, self.style_number, self.sample, _, self.route_size, \
        self.object_pos_size, self.column_size, self.block_size, \
        self.nav_data_size = unpack_file('IBBHIIIII', f)

        self._read_grid(f)
        self._read_block_table(f, self.block_size)
        self._read_object_positions(f, self.object_pos_size)
        self._read_navigation_data(f, self.nav_data_size)

        self.style = Style()
        self.style.load_from_file(open('data/STYLE00%d.G24' % self.style_number))

        # The lid attribute in a block stores a relative offset into the lid tiles.
        # By making it absolute, it becomes easier to work with on the client.
        lid_tile_offset = self.style.side_size / (64 * 64)
        for i in range(len(self.block_table)):
            block = self.block_table[i]
            if block.lid:
                block = block._replace(lid=block.lid + lid_tile_offset)
                self.block_table[i] = block
Exemple #10
0
    def _read_car_infos(self, f, size):
        fields = 'width height depth sprite_num weight max_speed min_speed acceleration braking grip handling ' \
                 'remap24 remap8 ' \
                 'vtype model turning damageable value mass_center_x mass_center_y moment ' \
                 'rbp_mass g1_thrust tyre_adhesion_x tyre_adhesion_y handbrake_friction footbrake_friction front_brake_bias ' \
                 'turn_ratio drive_wheel_offset ' \
                 'back_end_slide_value handbrake_slide_value ' \
                 'convertible engine radio horn sound_function fast_change_flag door_count doors'

        CarInfo = namedtuple('CarInfo', fields)

        hls_info_struct = 'hhh'
        door_info_struct = 'HHHH'

        fixed_to_float = lambda x: x * (1.0 / 2**16)

        start = f.tell()
        self.car_infos = []

        while f.tell() < start + size:
            data = list(unpack_file('hhhhhhhhhhh', f))
            data += [[unpack_file(hls_info_struct, f) for i in range(12)]]
            data += [unpack_file('B' * 12, f)]
            data += unpack_file('BBBB', f)
            data += [unpack_file('HHHH', f)]
            data += unpack_file('bb i', f)
            data += map(fixed_to_float, unpack_file('iiiiiii', f))
            data += unpack_file('hh', f)
            data += map(fixed_to_float, unpack_file('ii', f))
            data += unpack_file('BBBBBB', f)

            door_count, = unpack_file('h', f)
            doors = []
            for j in range(door_count):
                doors.append(unpack_file('hhhh', f))

            data += [door_count, doors]
            self.car_infos.append(CarInfo(*data))

        print "car infos:", len(self.car_infos)