mirror of https://github.com/zeldaret/tmc.git
Remove python asset_extractor
This commit is contained in:
parent
02d9bda5db
commit
24e1a6091c
|
@ -1,2 +0,0 @@
|
||||||
!asset_extractor.py
|
|
||||||
!assets/*.py
|
|
|
@ -1 +0,0 @@
|
||||||
all:
|
|
|
@ -1,247 +0,0 @@
|
||||||
from pathlib import Path
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
from distutils.util import strtobool
|
|
||||||
import json
|
|
||||||
|
|
||||||
from assets.frame_obj_lists import FrameObjLists
|
|
||||||
from assets.animation import Animation
|
|
||||||
from assets.exit_list import ExitList
|
|
||||||
from assets.sprite_frame import SpriteFrame
|
|
||||||
|
|
||||||
verbose = False
|
|
||||||
|
|
||||||
def extract_assets(variant, assets_folder):
|
|
||||||
print(f'Extract assets from {variant}.', flush=True)
|
|
||||||
map = {
|
|
||||||
'USA': 'baserom.gba',
|
|
||||||
'EU': 'baserom_eu.gba',
|
|
||||||
'JP': 'baserom_jp.gba',
|
|
||||||
'DEMO_USA': 'baserom_demo.gba',
|
|
||||||
'DEMO_JP': 'baserom_demo_jp.gba',
|
|
||||||
}
|
|
||||||
|
|
||||||
if not os.path.exists(map[variant]):
|
|
||||||
print(f'Error: Baserom {map[variant]} is missing.', file=sys.stderr)
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
baserom = None
|
|
||||||
baserom_path = map[variant]
|
|
||||||
with open(baserom_path, 'rb') as file:
|
|
||||||
baserom = bytearray(file.read())
|
|
||||||
|
|
||||||
|
|
||||||
# Handle all json config files in the assets folder
|
|
||||||
configs = [x for x in os.listdir('assets') if x.endswith('.json')] # TODO this would break with a folder that is named .json
|
|
||||||
|
|
||||||
print(configs)
|
|
||||||
|
|
||||||
for config in configs:
|
|
||||||
path = os.path.join('assets', config)
|
|
||||||
config_modified = os.path.getmtime(path)
|
|
||||||
|
|
||||||
with open(path) as file:
|
|
||||||
current_offset = 0
|
|
||||||
#print('Parsing yaml...', flush=True)
|
|
||||||
#assets = yaml.safe_load(file)
|
|
||||||
#print('done', flush=True)
|
|
||||||
print(f'Parsing {config}...', flush=True)
|
|
||||||
assets = json.load(file)
|
|
||||||
print('done', flush=True)
|
|
||||||
for asset in assets:
|
|
||||||
if 'offsets' in asset: # Offset definition
|
|
||||||
if variant in asset['offsets']:
|
|
||||||
current_offset = asset['offsets'][variant]
|
|
||||||
elif 'path' in asset: # Asset definition
|
|
||||||
|
|
||||||
if 'variants' in asset:
|
|
||||||
if variant not in asset['variants']:
|
|
||||||
# This asset is not used in the current variant
|
|
||||||
continue
|
|
||||||
|
|
||||||
path = os.path.join(assets_folder, asset['path'])
|
|
||||||
|
|
||||||
extract_file = False
|
|
||||||
|
|
||||||
if os.path.isfile(path):
|
|
||||||
file_modified = os.path.getmtime(path)
|
|
||||||
if file_modified < config_modified:
|
|
||||||
if verbose:
|
|
||||||
print(f'{path} was created before the config was modified.')
|
|
||||||
extract_file = True
|
|
||||||
# TODO Extract when source file (depends on type) was modified after target file
|
|
||||||
#print(f'{file_modified} {config_modified}')
|
|
||||||
else:
|
|
||||||
if verbose:
|
|
||||||
print(f'{path} does not yet exist.')
|
|
||||||
extract_file = True
|
|
||||||
|
|
||||||
|
|
||||||
if extract_file:
|
|
||||||
if verbose:
|
|
||||||
print(f'Extracting {path}...')
|
|
||||||
|
|
||||||
start = 0
|
|
||||||
if 'start' in asset:
|
|
||||||
# Apply offset to the start of the USA variant
|
|
||||||
start = asset['start'] + current_offset
|
|
||||||
elif 'starts' in asset:
|
|
||||||
# Use start for the current variant
|
|
||||||
start = asset['starts'][variant]
|
|
||||||
|
|
||||||
mode = ''
|
|
||||||
if 'type' in asset:
|
|
||||||
mode = asset['type']
|
|
||||||
|
|
||||||
Path(os.path.dirname(path)).mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
if 'size' in asset: # The asset has a size and want to be extracted first.
|
|
||||||
size = asset['size'] # TODO can different sizes for the different variants ever occur?
|
|
||||||
|
|
||||||
with open(path, 'wb') as output:
|
|
||||||
output.write(baserom[start:start+size])
|
|
||||||
# If an asset has no size, the extraction tool reads the baserom iself.
|
|
||||||
|
|
||||||
options = asset['options'] if 'options' in asset else []
|
|
||||||
|
|
||||||
if mode == 'tileset':
|
|
||||||
extract_tileset(path)
|
|
||||||
elif mode == 'palette':
|
|
||||||
extract_palette(path)
|
|
||||||
elif mode == 'graphic' or mode == 'gfx':
|
|
||||||
extract_graphic(path, options)
|
|
||||||
elif mode == 'midi':
|
|
||||||
extract_midi(path, baserom_path, start, options)
|
|
||||||
elif mode == 'aif':
|
|
||||||
extract_aif(path, options)
|
|
||||||
elif mode == 'frame_obj_lists':
|
|
||||||
frame_obj_lists = FrameObjLists(path, start, size, options)
|
|
||||||
frame_obj_lists.extract_binary(baserom)
|
|
||||||
elif mode == 'animation':
|
|
||||||
animation = Animation(path, start, size, options)
|
|
||||||
animation.extract_binary(baserom)
|
|
||||||
elif mode == 'exit_list':
|
|
||||||
exit_list = ExitList(path, start, size, options)
|
|
||||||
exit_list.extract_binary(baserom)
|
|
||||||
elif mode == 'sprite_frames':
|
|
||||||
sprite_frames = SpriteFrame(path, start, size, options)
|
|
||||||
sprite_frames.extract_binary(baserom)
|
|
||||||
elif mode == 'unknown':
|
|
||||||
pass
|
|
||||||
elif mode != '':
|
|
||||||
print(f'Asset type {mode} not yet implemented')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def run_gbagfx(path_in, path_out, options):
|
|
||||||
subprocess.check_call([os.path.join('tools', 'gbagfx', 'gbagfx'), path_in, path_out] + options)
|
|
||||||
|
|
||||||
def extract_tileset(path):
|
|
||||||
assert(path.endswith('.4bpp.lz') or path.endswith('.8bpp.lz'))
|
|
||||||
base = path[0:-8]
|
|
||||||
|
|
||||||
bpp_extension = path[-8:-3]
|
|
||||||
# subprocess.call(['cp', path, path+'.bkp'])
|
|
||||||
run_gbagfx(path, base+bpp_extension, []) # decompress
|
|
||||||
run_gbagfx(base+bpp_extension, base+'.png', ['-mwidth', '32']) # convert to png
|
|
||||||
# TODO automatically generate tileset entries from tileset_headers.s
|
|
||||||
# TODO Possible to set the correct palette? Or not, because there is a set of palettes that can be chosen and the correct palette is only defined by the metatile?
|
|
||||||
|
|
||||||
def extract_palette(path):
|
|
||||||
assert(path.endswith('.gbapal'))
|
|
||||||
base = path[0:-7]
|
|
||||||
run_gbagfx(path, base+'.pal', [])
|
|
||||||
|
|
||||||
def extract_graphic(path, options):
|
|
||||||
if path.endswith('.4bpp'):
|
|
||||||
base = path[0:-5]
|
|
||||||
elif path.endswith('.4bpp.lz'):
|
|
||||||
base = path[0:-8]
|
|
||||||
elif path.endswith('.8bpp'):
|
|
||||||
base = path[0:-5]
|
|
||||||
elif path.endswith('.8bpp.lz'):
|
|
||||||
base = path[0:-8]
|
|
||||||
else:
|
|
||||||
assert False, f'Invalid graphic extension {path}'
|
|
||||||
params = []
|
|
||||||
for key in options:
|
|
||||||
params.append('-'+key)
|
|
||||||
params.append(str(options[key]))
|
|
||||||
run_gbagfx(path, base+'.png', params)
|
|
||||||
|
|
||||||
def extract_midi(path, baserom_path, start, options):
|
|
||||||
assert(path.endswith('.s'))
|
|
||||||
base = path[0:-2]
|
|
||||||
|
|
||||||
common_params = []
|
|
||||||
agb2mid_params = []
|
|
||||||
|
|
||||||
exactGateTime = True # Set exactGateTime by default
|
|
||||||
|
|
||||||
for key in options:
|
|
||||||
if key == 'group' or key == 'G':
|
|
||||||
common_params.append('-G')
|
|
||||||
common_params.append(str(options[key]))
|
|
||||||
elif key == 'priority' or key == 'P':
|
|
||||||
common_params.append('-P')
|
|
||||||
common_params.append(str(options[key]))
|
|
||||||
elif key == 'reverb' or key == 'R':
|
|
||||||
common_params.append('-R')
|
|
||||||
common_params.append(str(options[key]))
|
|
||||||
elif key == 'nominator':
|
|
||||||
agb2mid_params.append('-n')
|
|
||||||
agb2mid_params.append(str(options[key]))
|
|
||||||
elif key == 'denominator':
|
|
||||||
agb2mid_params.append('-d')
|
|
||||||
agb2mid_params.append(str(options[key]))
|
|
||||||
elif key == 'timeChanges':
|
|
||||||
changes = options['timeChanges']
|
|
||||||
if isinstance(changes, list):
|
|
||||||
# Multiple time changes
|
|
||||||
for change in changes:
|
|
||||||
agb2mid_params.append('-t')
|
|
||||||
agb2mid_params.append(str(change['nominator']))
|
|
||||||
agb2mid_params.append(str(change['denominator']))
|
|
||||||
agb2mid_params.append(str(change['time']))
|
|
||||||
else:
|
|
||||||
agb2mid_params.append('-t')
|
|
||||||
agb2mid_params.append(str(changes['nominator']))
|
|
||||||
agb2mid_params.append(str(changes['denominator']))
|
|
||||||
agb2mid_params.append(str(changes['time']))
|
|
||||||
elif key == 'exactGateTime':
|
|
||||||
if options[key] == 1:
|
|
||||||
exactGateTime = True
|
|
||||||
elif options[key] == 0:
|
|
||||||
exactGateTime = False
|
|
||||||
else:
|
|
||||||
exactGateTime = strtobool(options[key])
|
|
||||||
else:
|
|
||||||
common_params.append('-'+key)
|
|
||||||
common_params.append(str(options[key]))
|
|
||||||
|
|
||||||
if exactGateTime:
|
|
||||||
common_params.append('-E')
|
|
||||||
|
|
||||||
# To midi
|
|
||||||
subprocess.check_call([os.path.join('tools', 'agb2mid', 'agb2mid'), baserom_path, hex(start), baserom_path, base+'.mid'] + common_params + agb2mid_params)
|
|
||||||
# To assembly (TODO only do in build step, not if only extracting)
|
|
||||||
subprocess.check_call([os.path.join('tools', 'mid2agb', 'mid2agb'), base+'.mid', path] + common_params)
|
|
||||||
|
|
||||||
def extract_aif(path, options):
|
|
||||||
assert(path.endswith('.bin'))
|
|
||||||
base = path[0:-4]
|
|
||||||
subprocess.check_call([os.path.join('tools', 'aif2pcm', 'aif2pcm'), path, base+'.aif'])
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) == 1:
|
|
||||||
extract_assets('USA')
|
|
||||||
elif len(sys.argv) == 3:
|
|
||||||
extract_assets(sys.argv[1].upper(), sys.argv[2])
|
|
||||||
else:
|
|
||||||
print('Usage: asset_extractor.py VARIANT BUILD_FOLDER')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,32 +0,0 @@
|
||||||
from assets.base import BaseAsset, Reader, opt_param
|
|
||||||
|
|
||||||
class Animation(BaseAsset):
|
|
||||||
def __init__(self, path: str, addr: int, size: int, options: any) -> None:
|
|
||||||
super().__init__(path, addr, size, options)
|
|
||||||
|
|
||||||
def extract_binary(self, rom: bytearray) -> None:
|
|
||||||
reader = Reader(rom[self.addr:self.addr+self.size])
|
|
||||||
lines = []
|
|
||||||
end_of_animation = False
|
|
||||||
while not end_of_animation and reader.cursor+3 < self.size:
|
|
||||||
frame_index = reader.read_u8()
|
|
||||||
keyframe_duration = reader.read_u8()
|
|
||||||
bitfield = reader.read_u8()
|
|
||||||
bitfield2 = reader.read_u8()
|
|
||||||
|
|
||||||
end_of_animation = bitfield2 & 0x80 != 0
|
|
||||||
line = f'\tkeyframe frame_index={frame_index}'
|
|
||||||
line += opt_param('duration', '0', str(keyframe_duration))
|
|
||||||
line += opt_param('bitfield', '0x0', hex(bitfield))
|
|
||||||
line += opt_param('bitfield2', '0x0', hex(bitfield2))
|
|
||||||
lines.append(line + '\n')
|
|
||||||
if not end_of_animation:
|
|
||||||
lines.append('@ TODO why no terminator?\n')
|
|
||||||
while reader.cursor < self.size:
|
|
||||||
keyframe_count = reader.read_u8()
|
|
||||||
lines.append(f'\t.byte {keyframe_count} @ keyframe count\n')
|
|
||||||
|
|
||||||
assert(self.path.endswith('.bin'))
|
|
||||||
path = self.path[0:-4] + '.s'
|
|
||||||
with open(path, 'w') as file:
|
|
||||||
file.writelines(lines)
|
|
|
@ -1,56 +0,0 @@
|
||||||
ROM_OFFSET = 0x8000000
|
|
||||||
|
|
||||||
class BaseAsset:
|
|
||||||
def __init__(self, path: str, addr: int, size: int, options: any) -> None:
|
|
||||||
self.path = path
|
|
||||||
self.addr = addr
|
|
||||||
self.size = size
|
|
||||||
self.options = options
|
|
||||||
|
|
||||||
def extract_binary(self, rom: bytearray) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def convert(self) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Reader:
|
|
||||||
def __init__(self, data: bytearray) -> None:
|
|
||||||
self.data = data
|
|
||||||
self.cursor = 0
|
|
||||||
self.bitfield = 0
|
|
||||||
self.bitfield_remaining = 0
|
|
||||||
|
|
||||||
def read_u8(self) -> int:
|
|
||||||
val = self.data[self.cursor]
|
|
||||||
self.cursor += 1
|
|
||||||
return val
|
|
||||||
|
|
||||||
def read_s8(self) -> int:
|
|
||||||
val = self.data[self.cursor]
|
|
||||||
self.cursor += 1
|
|
||||||
if val > 127:
|
|
||||||
return val-256
|
|
||||||
else:
|
|
||||||
return val
|
|
||||||
|
|
||||||
def read_u16(self) -> int:
|
|
||||||
val = self.data[self.cursor:self.cursor+2]
|
|
||||||
self.cursor += 2
|
|
||||||
return int.from_bytes(val, 'little')
|
|
||||||
|
|
||||||
def read_s16(self) -> int:
|
|
||||||
val = self.read_u16()
|
|
||||||
if val > 32768:
|
|
||||||
return val - 65536
|
|
||||||
else:
|
|
||||||
return val
|
|
||||||
|
|
||||||
def read_u32(self) -> int:
|
|
||||||
val = self.data[self.cursor:self.cursor+4]
|
|
||||||
self.cursor += 4
|
|
||||||
return int.from_bytes(val, 'little')
|
|
||||||
|
|
||||||
def opt_param(name: str, default: str, value: str) -> str:
|
|
||||||
if value != default:
|
|
||||||
return f', {name}={value}'
|
|
||||||
return ''
|
|
|
@ -1,55 +0,0 @@
|
||||||
from assets.base import BaseAsset, Reader, opt_param
|
|
||||||
|
|
||||||
class ExitList(BaseAsset):
|
|
||||||
def __init__(self, path: str, addr: int, size: int, options: any) -> None:
|
|
||||||
super().__init__(path, addr, size, options)
|
|
||||||
|
|
||||||
def extract_binary(self, rom: bytearray) -> None:
|
|
||||||
reader = Reader(rom[self.addr:self.addr+self.size])
|
|
||||||
|
|
||||||
lines = []
|
|
||||||
|
|
||||||
while reader.cursor < self.size:
|
|
||||||
transition_type = reader.read_u16()
|
|
||||||
x_pos = reader.read_u16()
|
|
||||||
y_pos = reader.read_u16()
|
|
||||||
dest_x = reader.read_u16()
|
|
||||||
dest_y = reader.read_u16()
|
|
||||||
screen_edge = reader.read_u8()
|
|
||||||
dest_area = reader.read_u8()
|
|
||||||
dest_room = reader.read_u8()
|
|
||||||
unknown_2 = reader.read_u8()
|
|
||||||
unknown_3 = reader.read_u8()
|
|
||||||
unknown_4 = reader.read_u8()
|
|
||||||
unknown_5 = reader.read_u16()
|
|
||||||
padding_1 = reader.read_u16()
|
|
||||||
if transition_type == 0xffff:
|
|
||||||
lines.append(f'\texit_list_end\n')
|
|
||||||
break
|
|
||||||
# lines.append(f'\t.2byte {transition_type} @ transition_type\n')
|
|
||||||
# lines.append(f'\t.2byte {x_pos}, {y_pos} @ pos\n')
|
|
||||||
# lines.append(f'\t.2byte {dest_x}, {dest_y} @ dest\n')
|
|
||||||
# lines.append(f'\t.byte {screen_edge} @ screen edge\n')
|
|
||||||
# lines.append(f'\t.byte {dest_area} @ screen edge\n')
|
|
||||||
# lines.append(f'\t.byte {dest_room} @ screen edge\n')
|
|
||||||
# lines.append(f'\t.byte {unknown_2}, {unknown_3}, {unknown_4} @ unknown\n')
|
|
||||||
# lines.append(f'\t.2byte {unknown_5}, {padding_1} @ unknown\n')
|
|
||||||
line = f'\texit transition={transition_type}'
|
|
||||||
line += opt_param('x', '0x0', hex(x_pos))
|
|
||||||
line += opt_param('y', '0x0', hex(y_pos))
|
|
||||||
line += opt_param('destX', '0x0', hex(dest_x))
|
|
||||||
line += opt_param('destY', '0x0', hex(dest_y))
|
|
||||||
line += opt_param('screenEdge', '0x0', hex(screen_edge))
|
|
||||||
line += opt_param('destArea', '0x0', hex(dest_area))
|
|
||||||
line += opt_param('destRoom', '0x0', hex(dest_room))
|
|
||||||
line += opt_param('unknown', '0x0', hex(unknown_2))
|
|
||||||
line += opt_param('unknown2', '0x0', hex(unknown_3))
|
|
||||||
line += opt_param('unknown3', '0x0', hex(unknown_4))
|
|
||||||
line += opt_param('unknown4', '0x0', hex(unknown_5))
|
|
||||||
line += opt_param('padding', '0x0', hex(padding_1))
|
|
||||||
lines.append(line + '\n')
|
|
||||||
|
|
||||||
assert(self.path.endswith('.bin'))
|
|
||||||
path = self.path[0:-4] + '.s'
|
|
||||||
with open(path, 'w') as file:
|
|
||||||
file.writelines(lines)
|
|
|
@ -1,105 +0,0 @@
|
||||||
from assets.base import BaseAsset, Reader, opt_param
|
|
||||||
|
|
||||||
class FrameObjLists(BaseAsset):
|
|
||||||
def __init__(self, path: str, addr: int, size: int, options: any) -> None:
|
|
||||||
super().__init__(path, addr, size, options)
|
|
||||||
|
|
||||||
def extract_binary(self, rom: bytearray) -> None:
|
|
||||||
reader = Reader(rom[self.addr:self.addr+self.size])
|
|
||||||
|
|
||||||
first_level = []
|
|
||||||
second_level = []
|
|
||||||
|
|
||||||
lines = []
|
|
||||||
lines.append('@ First level of offsets\n')
|
|
||||||
while True:
|
|
||||||
if reader.cursor in first_level:
|
|
||||||
#print(f'first_level up to: {reader.cursor}')
|
|
||||||
break
|
|
||||||
pointer = reader.read_u32()
|
|
||||||
first_level.append(pointer)
|
|
||||||
lines.append(f'\t.4byte {hex(pointer)}\n')
|
|
||||||
|
|
||||||
#print(first_level)
|
|
||||||
lines.append('\n@ Second level of offsets\n')
|
|
||||||
while True:
|
|
||||||
#print(reader.cursor)
|
|
||||||
#if reader.cursor >= 24372:
|
|
||||||
#print(f'>< second_level up to: {reader.cursor}')
|
|
||||||
#
|
|
||||||
# break
|
|
||||||
if reader.cursor in second_level:
|
|
||||||
#print(f'second_level up to: {reader.cursor}')
|
|
||||||
break
|
|
||||||
pointer = reader.read_u32()
|
|
||||||
second_level.append(pointer)
|
|
||||||
lines.append(f'\t.4byte {hex(pointer)}\n')
|
|
||||||
#print(second_level)
|
|
||||||
|
|
||||||
obj_lists = []
|
|
||||||
last_second_level = max(second_level)
|
|
||||||
lines.append('\n@ Frame obj lists\n')
|
|
||||||
while True:
|
|
||||||
if reader.cursor > last_second_level:
|
|
||||||
#print(f'No longer in second level: {reader.cursor}')
|
|
||||||
break
|
|
||||||
if reader.cursor not in second_level:
|
|
||||||
#print(f'{reader.cursor} not in second_level {num_objects}')
|
|
||||||
next = -1
|
|
||||||
for i in second_level:
|
|
||||||
if i > reader.cursor:
|
|
||||||
if next == -1 or i < next:
|
|
||||||
next = i
|
|
||||||
|
|
||||||
diff = next-reader.cursor
|
|
||||||
#print(f'Skipping forward to {next} (+{diff})')
|
|
||||||
lines.append(f'@ Skipping {diff} bytes\n')
|
|
||||||
bytes = []
|
|
||||||
for i in range(diff):
|
|
||||||
bytes.append(reader.read_u8())
|
|
||||||
lines.append('\t.byte ' + ', '.join(str(x) for x in bytes) + '\n')
|
|
||||||
num_objects = reader.read_u8()
|
|
||||||
lines.append(f'\t.byte {num_objects} @ num_objs\n')
|
|
||||||
if num_objects > 200:
|
|
||||||
#print(f'num_objects: {num_objects} @{reader.cursor}/{last_second_level}')
|
|
||||||
break
|
|
||||||
list = []
|
|
||||||
#print(num_objects)
|
|
||||||
for i in range(num_objects):
|
|
||||||
x_offset = reader.read_s8()
|
|
||||||
y_offset = reader.read_s8()
|
|
||||||
bitfield = reader.read_u8()
|
|
||||||
bitfield2 = reader.read_u16()
|
|
||||||
|
|
||||||
# lines.append(f'\t.byte {x_offset}, {y_offset}, {hex(bitfield)}\n')
|
|
||||||
# lines.append(f'\t.2byte {hex(bitfield2)}\n')
|
|
||||||
|
|
||||||
# bitfield
|
|
||||||
override_entity_palette_index = (bitfield & 0x01) != 0
|
|
||||||
# Bit 02 seems unused.
|
|
||||||
h_flip = (bitfield & 0x04) != 0
|
|
||||||
v_flip = (bitfield & 0x08) != 0
|
|
||||||
size = (bitfield & 0x30) >> 4
|
|
||||||
shape = (bitfield & 0xC0) >> 6
|
|
||||||
|
|
||||||
# bitfield2
|
|
||||||
first_gfx_tile_offset = bitfield2 & 0x03FF
|
|
||||||
priority = (bitfield2 & 0x0C00) >> 10
|
|
||||||
palette_index = (bitfield2 & 0xF000) >> 12
|
|
||||||
|
|
||||||
|
|
||||||
# print(x_offset, y_offset, bitfield, bitfield2)
|
|
||||||
# print(override_entity_palette_index, h_flip, v_flip, size, shape)
|
|
||||||
# print(first_gfx_tile_offset, priority, palette_index)
|
|
||||||
line = f'\tobj x={hex(x_offset)}, y={hex(y_offset)}'
|
|
||||||
line += opt_param('bitfield', '0x0', hex(bitfield))
|
|
||||||
line += opt_param('bitfield2', '0x0', hex(bitfield2))
|
|
||||||
lines.append(line + '\n')
|
|
||||||
list.append({})
|
|
||||||
# print()
|
|
||||||
obj_lists.append(list)
|
|
||||||
#print(len(obj_lists))
|
|
||||||
assert(self.path.endswith('.bin'))
|
|
||||||
path = self.path[0:-4] + '.s'
|
|
||||||
with open(path, 'w') as file:
|
|
||||||
file.writelines(lines)
|
|
|
@ -1,26 +0,0 @@
|
||||||
from assets.base import BaseAsset, Reader, opt_param
|
|
||||||
|
|
||||||
class SpriteFrame(BaseAsset):
|
|
||||||
def __init__(self, path: str, addr: int, size: int, options: any) -> None:
|
|
||||||
super().__init__(path, addr, size, options)
|
|
||||||
|
|
||||||
def extract_binary(self, rom: bytearray) -> None:
|
|
||||||
reader = Reader(rom[self.addr:self.addr+self.size])
|
|
||||||
i = 0
|
|
||||||
lines = []
|
|
||||||
while reader.cursor < self.size:
|
|
||||||
num_gfx_tiles = reader.read_u8()
|
|
||||||
unk = reader.read_u8()
|
|
||||||
first_gfx_tile_index = reader.read_u16()
|
|
||||||
|
|
||||||
line = f'\tsprite_frame first_tile_index={hex(first_gfx_tile_index)}'
|
|
||||||
line += opt_param('num_tiles', '0', str(num_gfx_tiles))
|
|
||||||
line += opt_param('unknown', '0x0', hex(unk))
|
|
||||||
lines.append(line + '\n')
|
|
||||||
assert(unk == 0 or unk == 1 or unk == 0xff)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
assert(self.path.endswith('.bin'))
|
|
||||||
path = self.path[0:-4] + '.s'
|
|
||||||
with open(path, 'w') as file:
|
|
||||||
file.writelines(lines)
|
|
Loading…
Reference in New Issue