Enemy sprite generation

This commit is contained in:
Luke Hubmayer-Werner 2017-03-18 23:22:27 +10:30
parent 1d3e3b4dfc
commit 2ce03a4011
2 changed files with 79 additions and 32 deletions

View File

@ -3,6 +3,7 @@ No license for now
'''
small_palette = [0xFF000000, 0x00000080, 0xFF808080, 0xFFFFFFFF]
dialogue_palette = [0xFF000080, 0xFFFFFFFF]
mono_palette = [0xFF000000, 0xFFFFFFFF]
Glyphs = (
@ -202,6 +203,6 @@ npc_layer_structure = [
("Move Pattern", 1, None),
("Palette", 1, None)
]
npc_layer_headers = ["Address", "Layer"] + [x[0] for x in npc_layer_structure]
npc_layer_headers = ["Ptr Address", "Layer", "Data Address"] + [x[0] for x in npc_layer_structure]
zone_count = 0x200

View File

@ -148,17 +148,8 @@ class FF5Reader(QMainWindow):
zone_data = []
for i in range(const.zone_count):
zone_data.append([])
offset = 0x0E9C00 + (i*0x1A)
zone_data[-1].append("0x{:06X}".format(offset))
j = 0
for z in zone_structure:
val = int.from_bytes(ROM_en[offset+j:offset+j+z[1]],'little')
if z[2] and val < len(z[2]):
zone_data[-1].append(z[2][val])
else:
zone_data[-1].append("0x{:0{}X}".format(val, z[1]*2))
j += z[1]
zone_data.append(parse_struct(ROM_en, offset, zone_structure))
tileset_headers = ("ID", "Offset", "Pointer", "Expected Length")
tileset_data = []
@ -170,26 +161,43 @@ class FF5Reader(QMainWindow):
'0x{:06X}'.format(pointer), '0x{:04X}'.format(length)))
npc_layers = []
offset = 0x0E59C0
for layer in range(const.npc_layer_count):
offset = 0x0E59C0
i = offset + (layer*2)
start = int.from_bytes(ROM_en[i:i+2],'little') + offset
next = int.from_bytes(ROM_en[i+2:i+4],'little') + offset
npcs = (next - start) // 7
for npc in range(npcs):
address = start + (npc*7)
npc_layers.append(["0x{0:06X}".format(address), "0x{0:03X}".format(layer)])
j = 0
for z in const.npc_layer_structure:
val = int.from_bytes(ROM_en[start+j:start+j+z[1]],'little')
if z[2] and val < len(z[2]):
npc_layers[-1].append(z[2][val])
else:
npc_layers[-1].append("0x{:0{}X}".format(val, z[1]*2))
j += z[1]
npc_layers.append(["0x{0:06X}".format(i), "0x{0:03X}".format(layer)] + parse_struct(ROM_en, address, const.npc_layer_structure))
enemy_tile_layouts = []
address = 0x10D004
for i in range(0x66):
offset = address + (i*8)
img = QImage(8, 8, QImage.Format_Mono)
img.setColorTable(const.mono_palette)
for i in range(8):
ptr = img.scanLine(i)
ptr.setsize(32)
ptr[0:1] = ROM_en[offset+i:offset+i+1]
pixmap = QPixmap.fromImage(img)
enemy_tile_layouts.append(pixmap.scaled(16, 16))
enemy_sprite_data = []
enemy_sprite_structure = [
("Sprite data offset", 2, None),
("Multiple things", 2, None),
("Tile Layout ID", 1, enemy_tile_layouts)
]
enemy_sprite_headers = ["Address"]+[i[0] for i in enemy_sprite_structure]+["EN Name","EN Name"]
address = 0x14B180
for i in range(0x180):
enemy_sprite_data.append(parse_struct(ROM_en, address + (i*5), enemy_sprite_structure) + enemy_names[i][2:4])
self.battle_strips = make_character_battle_sprites(ROM_en)
status_strips = make_character_status_sprites(ROM_en)
enemy_sprites = make_enemy_sprites(ROM_en)
self.tabwidget = QTabWidget()
strings_tab = QTabWidget()
@ -198,7 +206,6 @@ class FF5Reader(QMainWindow):
self.tabwidget.addTab(strings_tab, "Strings")
self.tabwidget.addTab(structs_tab, "Structs")
self.tabwidget.addTab(sprites_tab, "Images")
self.enemy_sprites = QFrame()
sprites_tab.addTab(make_pixmap_table(glyph_sprites_en_small, scale=4), "Glyphs (EN)")
sprites_tab.addTab(make_pixmap_table(glyph_sprites_en_large, scale=2), "Glyphs (Dialogue EN)")
@ -207,11 +214,12 @@ class FF5Reader(QMainWindow):
sprites_tab.addTab(make_pixmap_table(glyph_sprites_kanji, scale=2), "Glyphs (Kanji)")
sprites_tab.addTab(make_pixmap_table(self.battle_strips, cols=22, scale=2), "Character Battle Sprites")
sprites_tab.addTab(make_pixmap_table(status_strips, cols=22, scale=2), "Status Sprites")
sprites_tab.addTab(self.enemy_sprites, "Enemy Sprites")
sprites_tab.addTab(make_pixmap_table(enemy_sprites, scale=1), "Enemy Sprites")
structs_tab.addTab(make_table(zone_headers, zone_data, True), "Zones")
structs_tab.addTab(make_table(tileset_headers, tileset_data, True), "Tilesets")
structs_tab.addTab(make_table(const.npc_layer_headers, npc_layers, True), "NPC Layers")
structs_tab.addTab(make_table(enemy_sprite_headers, enemy_sprite_data, True), "Enemy Sprites")
strings_tab.addTab(make_table(imglist_headers, items, row_labels=False), "Items")
strings_tab.addTab(make_table(imglist_headers, magics, row_labels=False), "Magics")
@ -244,6 +252,48 @@ class Canvas:
def pixmap(self):
return QPixmap.fromImage(self.image)
def parse_struct(rom, offset, structure):
out = ["0x{:06X}".format(offset)]
j = 0
for z in structure:
val = int.from_bytes(rom[offset+j:offset+j+z[1]],'little')
if z[2] and val < len(z[2]):
out.append(z[2][val])
else:
out.append("0x{:0{}X}".format(val, z[1]*2))
j += z[1]
return out
def make_enemy_sprites(rom):
sprites = []
for e_id in range(0, 0x180*5, 5):
triplane = bool(rom[0x14B180+e_id]&0x80) # True if 3 planes, False if 4
bytes_per_tile = 24 if triplane else 32
tile_offset = ((((rom[0x14B180+e_id]&0x7F)<<8)| rom[0x14B181+e_id]) << 3) + 0x150000 # For whatever reason this is big endian
pal_offset = ((((rom[0x14B182+e_id]&0x03)<<8)| rom[0x14B183+e_id]) << 4) + 0x0ED000 # For whatever reason this is big endian
pal_size = 16 if triplane else 32
palette = generate_palette(rom, pal_offset, pal_size)
layout_id = rom[0x14B184+e_id]
boss_layout = bool(rom[0x14B182+e_id]&0x80)
if boss_layout:
layout = rom[0x10D334+(layout_id<<5):0x10D334+(layout_id<<5)+32]
sprite = Canvas(16, 16)
for x, y in [(x,y) for y in range(16) for x in range(16)]:
if (int.from_bytes(layout[y*2:y*2+2], 'little') & (0x8000 >> x)):
sprite.draw_pixmap(x, y, create_tile(rom[tile_offset:tile_offset+bytes_per_tile], palette))
tile_offset += bytes_per_tile
else:
layout = rom[0x10D004+(layout_id<<3):0x10D004+(layout_id<<3)+8]
sprite = Canvas(8, 8)
for x, y in [(x,y) for y in range(8) for x in range(8)]:
if (layout[y] & (0x80 >> x)):
sprite.draw_pixmap(x, y, create_tile(rom[tile_offset:tile_offset+bytes_per_tile], palette))
tile_offset += bytes_per_tile
# TODO: Shadow stuff
sprites.append(sprite.pixmap())
return sprites
def make_character_battle_sprites(rom):
tile_address = 0x120000
palette_address = 0x14A3C0
@ -252,15 +302,11 @@ def make_character_battle_sprites(rom):
palette = generate_palette(rom, palette_address + i)
# We don't want the background drawn, so we'll make that colour transparent
palette[0] = 0
battle_strip = QImage(16, 192, QImage.Format_ARGB32_Premultiplied)
battle_strip.fill(QColor(0,0,0,0))
painter = QtGui.QPainter(battle_strip)
for j in range(0, 24*8, 8):
offset = tile_address+(i*48)+(j*8)
painter.drawPixmap(0, j, create_tile(rom[offset:offset+32], palette))
painter.drawPixmap(8, j, create_tile(rom[offset+32:offset+64], palette))
del painter
battle_strips.append(QPixmap.fromImage(battle_strip))
battle_strip = Canvas(2, 24)
for j in range(48):
offset = tile_address+(i*48)+(j*32)
battle_strip.draw_pixmap(j%2, j//2, create_tile(rom[offset:offset+32], palette))
battle_strips.append(battle_strip.pixmap())
return battle_strips
def make_character_status_sprites(rom):