perfect_dark/tools/assetmgr/assetmgr.py

132 lines
4.2 KiB
Python

import os
import subprocess
def align4(value):
return (value + 3 | 3) ^ 3
def align16(value):
return (value + 15 | 15) ^ 15
def pad4(binary):
if len(binary) % 4:
amount = 4 - (len(binary) % 4)
binary += (0).to_bytes(amount, 'big')
return binary
def pad16(binary):
if len(binary) % 16:
amount = 16 - (len(binary) % 16)
binary += (0).to_bytes(amount, 'big')
return binary
def write_enums(typename, names, filename, terminator, start=0):
filename = 'src/generated/%s/%s' % (os.environ['ROMID'], filename)
mkpath(filename)
fd = open(filename, 'w')
fd.write('/**\n')
fd.write(' * This file was generated automatically. Changes may be overwritten.\n')
fd.write(' */\n')
fd.write('\n')
fd.write('enum %s {\n' % typename)
for index, name in enumerate(names):
if index == 0 and start != 0:
fd.write('\t%s = 0x%x,\n' % (name, start))
else:
fd.write('\t%s,\n' % name)
fd.write('\t%s\n' % terminator)
fd.write('};\n')
fd.close()
def write_object(data, filename):
filename = 'build/%s/assets/%s' % (os.environ['ROMID'], filename)
mkpath(filename)
fd = open(filename, 'wb')
# 0x00 - ELF header
fd.write(b'\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')
fd.write(b'\x00\x01\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00')
fd.write(b'\x00\x00\x00\x40\x10\x00\x10\x00\x00\x34\x00\x00\x00\x00\x00\x28')
fd.write(b'\x00\x03\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
# 0x40 - Section table index 0 (blank)
fd.write(b'\x00\x00\x00\x00') # offset to section name
fd.write(b'\x00\x00\x00\x00') # type
fd.write(b'\x00\x00\x00\x00') # attributes (writeable and occupies memory during execution)
fd.write(b'\x00\x00\x00\x00') # virtual address
fd.write(b'\x00\x00\x00\x00') # offset to data
fd.write(b'\x00\x00\x00\x00') # length
fd.write(b'\x00\x00\x00\x00') # section index
fd.write(b'\x00\x00\x00\x00') # extra information
fd.write(b'\x00\x00\x00\x00') # alignment
fd.write(b'\x00\x00\x00\x00') # entry size
# 0x68 - Section table index 1 (.data)
fd.write(b'\x00\x00\x00\x01') # offset to section name
fd.write(b'\x00\x00\x00\x01') # type
fd.write(b'\x00\x00\x00\x03') # attributes (writeable and occupies memory during execution)
fd.write(b'\x00\x00\x00\x00') # virtual address
fd.write(b'\x00\x00\x00\xd0') # offset to data
fd.write(align16(len(data)).to_bytes(4, 'big'))
fd.write(b'\x00\x00\x00\x00') # section index
fd.write(b'\x00\x00\x00\x00') # extra information
fd.write(b'\x00\x00\x00\x10') # alignment
fd.write(b'\x00\x00\x00\x00') # entry size
# 0x90 - Section table index 2 (.shstrtab)
fd.write(b'\x00\x00\x00\x07') # offset to section name
fd.write(b'\x00\x00\x00\x03') # type
fd.write(b'\x00\x00\x00\x00') # attributes (writeable and occupies memory during execution)
fd.write(b'\x00\x00\x00\x00') # virtual address
fd.write(b'\x00\x00\x00\xb8') # offset to data
fd.write(b'\x00\x00\x00\x18') # length
fd.write(b'\x00\x00\x00\x00') # section index
fd.write(b'\x00\x00\x00\x00') # extra information
fd.write(b'\x00\x00\x00\x01') # alignment
fd.write(b'\x00\x00\x00\x00') # entry size
# 0xb8 = .shstrtab
fd.write(b'\x00')
fd.write('.data'.encode('utf8'))
fd.write(b'\x00')
fd.write('.shstrtab'.encode('utf8'))
fd.write((0).to_bytes(8, 'big'))
# 0xd0 = .data
fd.write(data)
# Pad to next 16-byte boundary
amount = 16 - (len(data) % 16)
fd.write((0).to_bytes(amount, 'big'))
fd.close()
def zip(data):
filename = '/tmp/pd-assetmgr-%d' % os.getpid()
fd = open(filename, 'wb')
fd.write(data)
fd.close()
stream = subprocess.check_output(['tools/gzip', '-c', '--no-name', '--best', filename])[10:-8]
os.remove(filename)
return b'\x11\x73' + len(data).to_bytes(3, 'big') + stream
def mkpath(filename):
dirname = os.path.dirname(filename)
if not os.path.isdir(dirname):
os.makedirs(dirname, exist_ok=True)
def writefile(filename, contents):
mkpath(filename)
fd = open(filename, 'wb')
fd.write(contents)
fd.close()