#!/usr/bin/env python3 import assetmgr import json import os import re import struct import sys class App(): floortypes = { 'default': 0, 'wood': 1, 'stone': 2, 'carpet': 3, 'metal': 4, 'mud': 5, 'water': 6, 'dirt': 7, 'snow': 8, } def run(self): self.load_data() self.room_names = self.json['rooms'].keys() self.make_header() self.make_object() def load_data(self): fd = open(sys.argv[1], 'r') data = fd.read() fd.close() self.json = json.loads(data) self.shortname = os.path.basename(sys.argv[1]).replace('.json', '') def make_header(self): typename = 'room_%s' % self.shortname enums = self.json['rooms'].keys() filename = 'tiles/%s.h' % self.shortname terminator = 'ROOM_%s_END' % self.shortname.upper() assetmgr.write_enums(typename, enums, filename, terminator) def make_object(self): binary = self.make_binary() zipped = assetmgr.zip(binary) # Write the zipped file, purely so `make test` can verify it assetmgr.writefile('build/%s/assets/files/bgdata/bg_%s_tilesZ' % (os.environ['ROMID'], self.shortname), zipped) filename = 'files/bgdata/bg_%s_tilesZ.o' % self.shortname assetmgr.write_object(zipped, filename) # Order of stuff: # - 0x00: number of rooms # - 0x04: room offset table, with end marker # - Room data def make_binary(self): rooms = self.make_rooms() output = bytes() # Write number of rooms output += len(rooms).to_bytes(4, 'big') # Write room offset table pos = 4 + len(rooms) * 4 + 4 for room in rooms: output += pos.to_bytes(4, 'big') pos += len(room) # Write end marker output += pos.to_bytes(4, 'big') # Write room data output += b''.join(rooms) output = assetmgr.pad16(output) return output def make_rooms(self): rooms = [] for data in self.json['rooms'].values(): rooms.append(self.make_room(data)) return rooms def make_room(self, tiles): output = bytes() for tile in tiles: output += self.make_tile(tile) return output def make_tile(self, tile): output = bytes() bbox = self.find_bbox(tile['vertices']) output += b'\x00' output += len(tile['vertices']).to_bytes(1, 'big') output += self.make_flags(tile).to_bytes(2, 'big') output += self.floortypes[tile['floortype']].to_bytes(2, 'big') output += bbox['xmin'].to_bytes(1, 'big') output += bbox['ymin'].to_bytes(1, 'big') output += bbox['zmin'].to_bytes(1, 'big') output += bbox['xmax'].to_bytes(1, 'big') output += bbox['ymax'].to_bytes(1, 'big') output += bbox['zmax'].to_bytes(1, 'big') output += tile['floorcolour'].to_bytes(2, 'big') for vert in tile['vertices']: output += self.make_unsigned(vert['x']).to_bytes(2, 'big') output += self.make_unsigned(vert['y']).to_bytes(2, 'big') output += self.make_unsigned(vert['z']).to_bytes(2, 'big') return output def find_bbox(self, verts): values = {} indices = {} values['xmin'] = 99999 values['ymin'] = 99999 values['zmin'] = 99999 values['xmax'] = -99999 values['ymax'] = -99999 values['zmax'] = -99999 indices['xmin'] = 0 indices['ymin'] = 0 indices['zmin'] = 0 indices['xmax'] = 0 indices['ymax'] = 0 indices['zmax'] = 0 for index, vert in enumerate(verts): if vert['x'] < values['xmin']: values['xmin'] = vert['x'] indices['xmin'] = index if vert['y'] < values['ymin']: values['ymin'] = vert['y'] indices['ymin'] = index if vert['z'] < values['zmin']: values['zmin'] = vert['z'] indices['zmin'] = index if vert['x'] > values['xmax']: values['xmax'] = vert['x'] indices['xmax'] = index if vert['y'] > values['ymax']: values['ymax'] = vert['y'] indices['ymax'] = index if vert['z'] > values['zmax']: values['zmax'] = vert['z'] indices['zmax'] = index return indices def make_flags(self, room): names = [ 'flag0001', 'flag0002', 'flag0004', 'flag0008', 'flag0010', 'flag0020', 'ladder', 'flag0080', 'flag0100', 'underwater', 'flag0400', 'aibotcrouch', 'aibotduck', 'flag2000', 'die', 'climbableledge', ] flags = 0 for index, name in enumerate(names): if room[name]: flags |= 1 << index return flags def make_unsigned(self, value): if value < 0: value = 0x10000 - abs(value) return value app = App() app.run()