def _read_header(self, fobj): self.magic = struct.unpack('4s', fobj.read(0x4))[0] if not self.magic == b'XBIN': raise ValueError('Provided file is not a valid BoxBoy map file') self.version = read_int32(fobj) self.filesize = read_int32(fobj) self.unknown_value1 = read_int32(fobj)
def __init__(self, fobj): try: self.param_names except AttributeError: self.param_names = ('param0', 'param1', 'param2', 'param3', 'param4', 'param5') self.wuid = read_int32(fobj) self.kind = read_int32(fobj) self.load_parameters(fobj) self.name = str(self.kind)
def _extract_xbin(self, fobj, name): entry_pt = fobj.tell() magic = struct.unpack('4s', fobj.read(0x4))[0] if not magic == b'XBIN': return read_int32(fobj) filesize = read_int32(fobj) fobj.seek(entry_pt) data = fobj.read(filesize) fpath = op.join(BASEPATH, *name.split('.')) + '.xbin' if not op.exists(op.dirname(fpath)): os.makedirs(op.dirname(fpath)) with open(fpath, 'wb') as fobj: fobj.write(data)
def _read_event_data(self, fobj): self.events = list() with Pointer(fobj): count = read_int32(fobj) for _ in range(count): with Pointer(fobj): self.events.append(EventSequenceData(fobj))
def __init__(self, fobj): self.x_start, self.y_start = struct.unpack('<ii', fobj.read(0x8)) self.x_end, self.y_end = struct.unpack('<ii', fobj.read(0x8)) self.num_blocks = read_int32(fobj) self.data = list() for _ in range(self.num_blocks): self.data.append(struct.unpack('<ii', fobj.read(0x8)))
def _read_gimmick_data(self, fobj): self.gimmick_data = list() with Pointer(fobj): count = read_int32(fobj) for _ in range(count): gimmick_bytes = BytesIO(fobj.read(0x30)) self.gimmick_data.append(gimmick_factory(gimmick_bytes))
def _read_data(self, fobj): fobj.seek(0x1C) count = read_int32(fobj) with Pointer(fobj): for _ in range(count): with Pointer(fobj): name = read_name(fobj).decode('utf') print(name) with Pointer(fobj): self._extract_xbin(fobj, name)
def __init__(self, fobj): # Specify some values irrespective of whether we are loading from bytes # or not if not self.param_fmts: self.param_fmts = ('<i', '<i', '<i', '<i', '<i', '<i') if not self.param_names: self.param_names = ('param0', 'param1', 'param2', 'param3', 'param4', 'param5') for i, name in enumerate(self.param_names): if name[:5] != "param": setattr(type(self), name, Param_Descriptor("param" + str(i))) self.name = 'Unknown' self.extra_tags = tuple() # If we aren't loading from some inital bytes, finish initializing the # class. if fobj is None: return # The rest of these values are loaded from the supplied data self.wuid = read_int32(fobj) self.kind = read_int32(fobj) self.x = read_int32(fobj) self.y = read_int32(fobj) self.group = read_int32(fobj) self.appearance = read_int32(fobj) self.load_parameters(fobj)
def load_parameters(self, fobj): self.param0 = read_int32(fobj) self.param1 = read_int32(fobj) self.param2 = read_int32(fobj) self.param3 = read_int32(fobj) self.param4 = read_int32(fobj) self.param5 = read_int32(fobj)
def _read_map_layout(self, fobj): """ Load the map layout. """ with Pointer(fobj): self.width, self.height = struct.unpack('<II', fobj.read(0x8)) # ignore the number of entries as it is simply width * height _, offset = struct.unpack('<II', fobj.read(0x8)) fobj.seek(offset) self.map_layout = list() for y in range(self.height): self.map_layout.append(list()) for _ in range(self.width): self.map_layout[y].append(read_int32(fobj)) self.map_layout = self.map_layout[::-1]
def _read_header(self, fobj): self.magic = struct.unpack('4s', fobj.read(0x4))[0] if not self.magic == b'XBIN': raise ValueError('Provided file is not a valid BoxBoy map file') self.version = read_int32(fobj) self.filesize = read_int32(fobj) self.unknown_value0 = read_int32(fobj) self.box_number = read_int32(fobj) self.box_set_num = read_int32(fobj) self.camera_height = read_int32(fobj) self.sound_tag = read_int32(fobj)
def _read_data(self, fobj): # print('reading data at {0}'.format(hex(fobj.tell()))) dtype = read_int32(fobj) if dtype == 1: # read an int data = read_int32(fobj) # maybe different dtypes? elif dtype == 2: # read a float data = read_float32(fobj) elif dtype == 3: # read a boolean values data = bool(read_byte(fobj)) elif dtype == 4: # Pointer to byte array? data = list() with Pointer(fobj): data = self._read_name(fobj).decode('utf') elif dtype == 5: data = list() count = read_int32(fobj) for _ in range(count): with Pointer(fobj): name = self._read_name(fobj).decode('utf') with Pointer(fobj): new_data = self._read_data(fobj) data.append({name: new_data}) elif dtype == 6: data = list() count = read_int32(fobj) for _ in range(count): with Pointer(fobj): data.append(self._read_data(fobj)) else: print(dtype, hex(fobj.tell())) data = None return data
def _read_map_layers(self, fobj): """ Read all of the map layers into variables """ for i in range(0x7): data = list() with Pointer(fobj): # skip the size fobj.seek(0x4, 1) with Pointer(fobj): for y in range(self.height): data.append(list()) for _ in range(self.width): data[y].append(read_int32(fobj)) # flip the data verically data = data[::-1] # assign to a variable setattr(self, 'layer{0}_data'.format(str(i)), data)
def event_factory(event_bytes): # First, get the kind: event_bytes.seek(0x4) kind = read_int32(event_bytes) event_bytes.seek(0) if kind == 0: return Event_OnEnterScene(event_bytes) elif kind == 6: return Event_Wait(event_bytes) elif kind == 13: return Event_MoveLandInit(event_bytes) elif kind == 14: return Event_MoveLandCmd(event_bytes) elif kind == 17: return Event_Flag(event_bytes) elif kind == 18: return Event_ToFlag(event_bytes) elif kind == 19: return Event_DamageMoveLandInit(event_bytes)
def gimmick_factory(gimmick_bytes): # first, get the kind: gimmick_bytes.seek(0x4) kind = read_int32(gimmick_bytes) gimmick_bytes.seek(0) if kind == 0: return Gimmick_SpawnPoint(gimmick_bytes) if kind == 2: return Gimmick_Door(gimmick_bytes) if kind == 3: return Gimmick_Laser(gimmick_bytes) if kind == 4: return Gimmick_Crown(gimmick_bytes) if kind == 6: return Gimmick_Button(gimmick_bytes) if kind == 7: return Gimmick_ToggleBlock(gimmick_bytes) if kind == 8: return Gimmick_BreakBlock(gimmick_bytes) if kind == 11: return Gimmick_Shutter(gimmick_bytes) if kind == 13: return Gimmick_HelpArea(gimmick_bytes) if kind == 17: return Gimmick_FallSplinter(gimmick_bytes) if kind == 18: return Gimmick_Spikey(gimmick_bytes) elif kind == 22: return Gimmick_Battery(gimmick_bytes) elif kind == 23: return Gimmick_WarpCloud(gimmick_bytes) elif kind == 26: return Gimmick_SpikeyEnd(gimmick_bytes) elif kind == 27: return Gimmick_Gravity(gimmick_bytes) else: return Gimmick(gimmick_bytes)
def __init__(self, fobj): self.num_blocks = read_int32(fobj) self.block_locations = list() for _ in range(self.num_blocks): self.block_locations.append(struct.unpack('<ii', fobj.read(0x8)))
def __init__(self, fobj): count = read_int32(fobj) self.event_data = list() for _ in range(count): event_bytes = BytesIO(fobj.read(0x20)) self.event_data.append(event_factory(event_bytes))
def _read_header(self, fobj): data = '' self.magic = struct.unpack('4s', fobj.read(0x4))[0] # 0x00 if not self.magic == b'XBIN': raise ValueError('Provided file is not a valid BoxBoy map file') self.version = read_int32(fobj) # 0x04 self.filesize = read_int32(fobj) # 0x08 self.unknown_value0 = read_int32(fobj) # 0x0C with Pointer(fobj): # 0x10 self.filename = read_name(fobj) self.unknown_value1 = read_int32(fobj) # 0x14 with Pointer(fobj): # 0x18 count = read_int32(fobj) self.unknown_bytes = fobj.read(count * 4) with Pointer(fobj): # 0x1C count = read_int32(fobj) for _ in range(count): with Pointer(fobj): with Pointer(fobj): attribute = read_name(fobj) data += attribute.decode('utf') + '\n' read_int32(fobj) read_int32(fobj) read_int32(fobj) with Pointer(fobj): count = read_int32(fobj) for _ in range(count): with Pointer(fobj): with Pointer(fobj): enum_name = read_name(fobj).decode('utf') enum_value = read_int32(fobj) data += (str(enum_name) + '\t' + str(enum_value) + '\n') if len(data) != 0: with open(self.fpath.replace('xbin', 'txt'), 'w') as f: f.write(data)
def _read_name(self, fobj): _len = read_int32(fobj) return struct.unpack('{0}s'.format(str(_len)), fobj.read(_len))[0]