def __init__(self, data): self.gfx_chunk_id = read_word(data, 0x0) self.num_sprites = data[0x2] self.script_entry_point = read_word(data, 0x3) self.unk_5 = read_word(data, 0x5) self.unk_7 = read_word(data, 0x7) self.width = data[0x9] self.height = data[0xA] self.unk_B = read_word(data, 0xB) self.unk_D = read_word(data, 0xD) self.unk_F = read_word(data, 0xF) self.max_x_velocity = read_word(data, 0x11) self.max_y_velocity = read_word(data, 0x13)
def rlew_expand(source, length): dest = bytearray() while len(dest) < length: value = read_word(source) if value != state.RLEWtag: # uncompressed write_word(dest, value) else: # compressed string count = read_word(source) value = read_word(source) for i in range(count): write_word(dest, value) return dest
def carmack_expand(source, length): NEAR_TAG = 0xa7 FAR_TAG = 0xa8 length = length // 2 source = bytearray(source) dest = bytearray() while length > 0: ch = read_word(source, byteorder='little') ch_high = ch >> 8 if ch_high in (NEAR_TAG, FAR_TAG): count = ch & 0xff; if not count: # have to insert a word containing the tag byte ch |= source.pop(0) write_word(dest, ch) length -= 1; elif ch_high == NEAR_TAG: offset = source.pop(0) length -= count; if length >= 0: start = -offset * 2 end = (-offset + count) * 2 if (-offset + count) >= 0: end = len(dest) dest += dest[start : end] elif ch_high == FAR_TAG: offset = read_word(source, byteorder='little') length -= count if length >= 0: dest += dest[offset*2 : (offset + count) *2] else: write_word(dest, ch) length -= 1; return dest
def load_animation_list(data, pos): chunks = [] while True: chunk_id = read_word(data, pos) if chunk_id == 0xFFFF: break pos += 5 chunks.append(chunk_id) return chunks
def load_object_graphics_list(data, pos): chunks = [] while True: chunk_id = read_word(data, pos) pos += 2 if chunk_id == 0xFFFF: break chunks.append(chunk_id) return pos, chunks
def decompress_data(data, decoded_data_len=None): if decoded_data_len is None: decoded_data_len = read_word(data, 0) + 1 data = data[2:] scratch = array('B', itertools.repeat(0, 0x1000)) dst = array('B') scratch_i = 0 src_i = 0 while True: al = data[src_i] src_i += 1 for i in xrange(8): if al & 1: # Verbatim byte scratch[scratch_i] = data[src_i] scratch_i = (scratch_i + 1) % len(scratch) dst.append(data[src_i]) if len(dst) == decoded_data_len: return dst src_i += 1 else: # Copy previous bytes from scratch area copy_src = read_word(data, src_i) src_i += 2 copy_len = (copy_src >> 12) + 3 copy_src = copy_src & 0xFFF for j in xrange(copy_len): scratch[scratch_i] = scratch[copy_src] scratch_i = (scratch_i + 1) % len(scratch) dst.append(scratch[copy_src]) if len(dst) == decoded_data_len: return dst copy_src = (copy_src + 1) % len(scratch) al = al >> 1
def load_palette_cycle_list(data, pos): active_cycles = read_word(data, pos) pos += 2 cycles = [] while True: speed = data[pos] if speed == 0: pos += 1 break first = data[pos + 1] last = data[pos + 2] pos += 3 cycles.append((speed, first, last)) while True: val_d = read_word(data, pos) pos += 2 if val_d == 0xFFFF: break return pos, active_cycles, cycles
def load_palette_list(data, pos): pals = [] while True: chunk_id = read_word(data, pos) pos += 2 if chunk_id == 0xFFFF: break load_position = data[pos] pos += 1 pals.append((chunk_id, load_position)) return pos, pals
def load_object_list(data, pos): objects = [] while True: xpos = read_word(data, pos) if xpos == 0xFFFF: pos += 2 break ypos = read_word(data, pos + 2) width = read_word(data, pos + 4) height = read_word(data, pos + 6) type_id = read_word(data, pos + 8) unk4 = read_word(data, pos + 10) user_data = read_word(data, pos + 12) objects.append( ObjectInstance(xpos, ypos, width, height, type_id, unk4, user_data)) pos += 14 return pos, objects
def load(self, data): self.raw_data = data self.music_command = data[0x4] self.music_track = data[0x5] self.special_objs_type = data[0x7] self.special_obj_x = read_word(data, 0x8) self.special_obj_y = read_word(data, 0xA) self.special_obj_type = read_word(data, 0xC) self.special_obj_unk1 = read_word(data, 0xE) self.special_obj_user_data = read_word(data, 0x10) self.next_level = read_word(data, 0x16) self.sprite_sizes = read_word(data, 0x18) self.flags = data[0x1C] self.width = read_word(data, 0x29) self.height = read_word(data, 0x2B) self.tilemap_chunk = read_word(data, 0x2E) self.tileset_chunk = read_word(data, 0x30) self.metatile_chunk = read_word(data, 0x32) self.load_list = LoadList() self.load_list.load(data[0x43:])
def simple_scale_shape(vbuf, shape_num): view_width, view_height = id_vh.state.view_width, id_vh.state.view_height xcenter = view_width // 2 height = view_height + 1 shape, shape_bytes = id_pm.get_sprite(shape_num) scale = height >> 1 pixheight = scale * de.SPRITE_SCALE_FACTOR actx = xcenter - scale upperedge = view_height // 2 - scale # cmdptr=(word *) shape->dataofs; cmdptr = iter(shape.dataofs) i = shape.left_pix pixcnt = i * pixheight rpix = (pixcnt >> 6) + actx # for(i=shape->leftpix,pixcnt=i*pixheight,rpix=(pixcnt>>6)+actx;i<=shape->rightpix;i++,cmdptr++) while i <= shape.right_pix: lpix = rpix if lpix >= view_width: break pixcnt += pixheight rpix = (pixcnt >> 6) + actx if lpix != rpix and rpix > 0: if lpix < 0: lpix = 0 if rpix > view_width: rpix = view_width i = shape.right_pix + 1 # cline points to the offset indicated by the next cmdptr item # cline=(byte *)shape + *cmdptr; cline = shape_bytes[next(cmdptr):] while lpix < rpix: # turn into bytearray to pop when moving the pointer # maybe better to iterate some other way line = bytearray(cline) endy = read_word(line, byteorder='little') while endy: endy >>= 1 newstart = read_word(line, byteorder='little', signed=True) starty = read_word(line, byteorder='little') >> 1 j = starty ycnt = j * pixheight screndy = (ycnt >> 6) + upperedge if screndy < 0: vmem_index = lpix else: vmem_index = screndy * vbuf.pitch + lpix while j < endy: scrstarty = screndy ycnt += pixheight screndy = (ycnt >> 6) + upperedge if scrstarty != screndy and screndy > 0: col = shape_bytes[newstart + j] if scrstarty < 0: scrstarty = 0 if screndy > view_height: screndy = view_height j = endy while scrstarty < screndy: vbuf[vmem_index] = col vmem_index += vbuf.pitch scrstarty += 1 j += 1 endy = read_word(line, byteorder='little') lpix += 1 i += 1
def read_image(data): """Deinterleaves a length-prefixed image""" data_len = read_word(data, 0) * 4 return interleave_planar(data[2:2+data_len])