예제 #1
0
    def __bytes__(self):
        # Write the header
        self.pointer_data = {'headers': list(), 'data': list()}
        self._bytes = BytesIO(b'')

        # Write each of the sections
        self._write_header()
        self._write_map_layout_pointer()
        self._write_moving_platform_data_pointers()
        self._write_pushblocks_pointers()
        self._write_map_layers_pointer()
        self._write_gimmick_data_pointer()

        p = Pointer(self._bytes)
        p.assign_data(lambda _data: write_int32(_data, 0))
        self.pointer_data['headers'].append(p)
        write_int32(self._bytes, 0)
        self._write_event_data_pointer()

        # write all the pointer data. Do all headers then do data
        # swap entries 30 and 32 for some reason?!?
        self.pointer_data['headers'] = swap(self.pointer_data['headers'],
                                            30, 32)
        for pointer in self.pointer_data['headers']:
            pointer.write()

        for pointer in self.pointer_data['data']:
            pointer.write()

        # write the final file size
        self._bytes.seek(0x8)
        _bytes = self._bytes.getvalue()
        write_int32(self._bytes, len(_bytes))
        del _bytes
        return self._bytes.getvalue()
예제 #2
0
 def _write_pushblocks_pointers(self):
     for pb in self.pushblocks:
         p = Pointer(self._bytes)
         p.assign_data(
             lambda _data, pb=pb: self._write_pushblocks(_data, pb))
         self.pointer_data['headers'].append(p)
         write_int32(self._bytes, 0)
예제 #3
0
 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))
예제 #4
0
 def _write_map_layer_info(self, data, layer_data):
     write_int32(data, self.height * self.width)
     p = Pointer(self._bytes)
     p.assign_data(
         lambda _data: self._write_map_layer(_data, layer_data))
     self.pointer_data['data'].append(p)
     write_int32(data, 0)
예제 #5
0
 def _write_moving_platform_data_pointers(self):
     for mp in self.moving_platforms:
         p = Pointer(self._bytes)
         p.assign_data(
             lambda _data, mp=mp: self._write_moving_platform_data(
                 _data, mp))
         self.pointer_data['headers'].append(p)
         write_int32(self._bytes, 0)
예제 #6
0
 def _write_map_layout_info(self, data):
     write_int32(data, self.width)
     write_int32(data, self.height)
     write_int32(data, self.height * self.width)
     p = Pointer(self._bytes)
     p.assign_data(self._write_map_layout)
     self.pointer_data['data'].append(p)
     write_int32(data, 0)
예제 #7
0
 def _write_map_layers_pointer(self):
     for i in range(0x7):
         p = Pointer(self._bytes)
         layer_data = getattr(self, 'layer{0}_data'.format(str(i)))
         p.assign_data(
             lambda _data, layer_data=layer_data: self._write_map_layer_info(  # noqa
                 _data, layer_data))
         self.pointer_data['headers'].append(p)
         write_int32(self._bytes, 0)
예제 #8
0
 def _write_event_data_info(self, data):
     write_int32(data, len(self.events))
     for event in self.events:
         p = Pointer(self._bytes)
         p.assign_data(
             lambda _data, event=event: self._write_event_data(
                 _data, event))
         self.pointer_data['headers'].append(p)
         write_int32(data, 0)
예제 #9
0
 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)
예제 #10
0
 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)
예제 #11
0
 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))
예제 #12
0
 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]
예제 #13
0
 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
예제 #14
0
 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)
예제 #15
0
 def _read_moving_platform_data(self, fobj):
     self.moving_platforms = list()
     for _ in range(0x14):
         with Pointer(fobj):
             self.moving_platforms.append(MovingPlatform(fobj))
예제 #16
0
 def _read_pushblocks(self, fobj):
     self.pushblocks = list()
     for _ in range(0x8):
         with Pointer(fobj):
             self.pushblocks.append(PushBlock(fobj))
예제 #17
0
 def _write_map_layout_pointer(self):
     p = Pointer(self._bytes)
     p.assign_data(self._write_map_layout_info)
     self.pointer_data['headers'].append(p)
     write_int32(self._bytes, 0)
예제 #18
0
 def _write_event_data_pointer(self):
     p = Pointer(self._bytes)
     p.assign_data(lambda _data: self._write_event_data_info(_data))
     self.pointer_data['headers'].append(p)
     write_int32(self._bytes, 0)