imgfx data (#1029)

This commit is contained in:
Ethan Roseman 2023-04-25 13:55:14 +09:00 committed by GitHub
parent 44d1b29590
commit e0cfd078da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 429 additions and 71 deletions

23
include/imgfx.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _IMGFX_H_
#define _IMGFX_H_
#include "PR/gbi.h"
// 'compressed' vertex data for animated image fx keyframes
typedef struct ImgFXVtx {
/* 0x00 */ s16 ob[3];
/* 0x06 */ u8 tc[2];
/* 0x08 */ s8 cn[3];
/* 0x0B */ char unk_0B;
} ImgFXVtx; // size = 0x0C
typedef struct ImgFXAnimHeader {
/* 0x00 */ ImgFXVtx* keyframesOffset;
/* 0x04 */ Gfx* gfxOffset; // Gfx for creating mesh from vertices
/* 0x08 */ u16 vtxCount; // conserved across keyframes
/* 0x0A */ u16 gfxCount;
/* 0x0C */ u16 keyframesCount;
/* 0x0E */ u16 flags;
} ImgFXAnimHeader; // size = 0x10
#endif /* _IMGFX_H_ */

View File

@ -1,10 +1,11 @@
#include "common.h"
#include "ld_addrs.h"
#include "sprite.h"
#include "imgfx.h"
#if VERSION_IQUE
// TODO: remove if section is split in iQue release
extern Addr imgfx_gfx_data_ROM_START;
extern Addr imgfx_data_ROM_START;
#endif
typedef union ImgFXIntVars {
@ -98,15 +99,6 @@ typedef struct ImgFXCacheEntry {
/* 0x06 */ char unk_06[0x2];
} ImgFXCacheEntry; // size = 0x8
typedef struct ImgFXAnimHeader {
/* 0x00 */ s32 keyframesOffset;
/* 0x04 */ Gfx* gfxOffset; // Gfx for creating mesh from vertices
/* 0x08 */ u16 vtxCount; // conserved across keyframes
/* 0x0A */ u16 gfxCount;
/* 0x0C */ u16 keyframesCount;
/* 0x0E */ u16 flags;
} ImgFXAnimHeader; // size = 0x10
enum ImgFXAnimFlags {
IMGFX_ANIM_FLAG_ABSOLUTE_COORDS = 1, // image-relative (in percent) when unset
};
@ -117,14 +109,6 @@ typedef struct ImgFXRenderMode {
/* 0x8 */ u8 flags; // only checks TRUE so far. some kind of switch?
} ImgFXRenderMode; // size = 0xC
// 'compressed' vertex data for animated image fx keyframes
typedef struct ImgFXVtx {
/* 0x00 */ s16 ob[3];
/* 0x06 */ u8 tc[2];
/* 0x08 */ s8 cn[3];
/* 0x0B */ char unk_0B;
} ImgFXVtx; // size = 0x0C
typedef ImgFXState ImgFXInstanceList[MAX_IMGFX_INSTANCES];
extern HeapNode heap_spriteHead;
@ -194,28 +178,49 @@ ImgFXRenderMode ImgFXRenderModes[] = {
[IMGFX_RENDER_UNUSED] { 0x00441208, 0x00111208, 0 },
};
// all relative to imgfx_gfx_data_ROM_START
s32 ImgFXAnimOffsets[] = {
[IMGFX_ANIM_SHOCK] 0x14358,
[IMGFX_ANIM_SHIVER] 0x18200,
[IMGFX_ANIM_VERTICAL_PIPE_CURL] 0x1A858,
[IMGFX_ANIM_HORIZONTAL_PIPE_CURL] 0x1E830,
[IMGFX_ANIM_STARTLE] 0x29458,
[IMGFX_ANIM_FLUTTER_DOWN] 0x314E0,
[IMGFX_ANIM_UNFURL] 0x33498,
[IMGFX_ANIM_GET_IN_BED] 0x38988,
[IMGFX_ANIM_SPIRIT_CAPTURE] 0x39228,
[IMGFX_ANIM_UNUSED_1] 0x5B7A8,
[IMGFX_ANIM_UNUSED_2] 0x7CF10,
[IMGFX_ANIM_UNUSED_3] 0x86490,
[IMGFX_ANIM_TUTANKOOPA_GATHER] 0x96258,
[IMGFX_ANIM_TUTANKOOPA_SWIRL_2] 0xA1820,
[IMGFX_ANIM_TUTANKOOPA_SWIRL_1] 0xACDE8,
[IMGFX_ANIM_SHUFFLE_CARDS] 0xBBF68,
[IMGFX_ANIM_FLIP_CARD_1] 0xC0490,
[IMGFX_ANIM_FLIP_CARD_2] 0xC49B8,
[IMGFX_ANIM_FLIP_CARD_3] 0xC6150,
[IMGFX_ANIM_CYMBAL_CRUSH] 0xCA380,
extern Addr shock_header;
extern Addr shiver_header;
extern Addr vertical_pipe_curl_header;
extern Addr horizontal_pipe_curl_header;
extern Addr startle_header;
extern Addr flutter_down_header;
extern Addr unfurl_header;
extern Addr get_in_bed_header;
extern Addr spirit_capture_header;
extern Addr unused_1_header;
extern Addr unused_2_header;
extern Addr unused_3_header;
extern Addr tutankoopa_gather_header;
extern Addr tutankoopa_swirl_2_header;
extern Addr tutankoopa_swirl_1_header;
extern Addr shuffle_cards_header;
extern Addr flip_card_1_header;
extern Addr flip_card_2_header;
extern Addr flip_card_3_header;
extern Addr cymbal_crush_header;
// all relative to imgfx_data_ROM_START
u8* ImgFXAnimOffsets[] = {
[IMGFX_ANIM_SHOCK] shock_header,
[IMGFX_ANIM_SHIVER] shiver_header,
[IMGFX_ANIM_VERTICAL_PIPE_CURL] vertical_pipe_curl_header,
[IMGFX_ANIM_HORIZONTAL_PIPE_CURL] horizontal_pipe_curl_header,
[IMGFX_ANIM_STARTLE] startle_header,
[IMGFX_ANIM_FLUTTER_DOWN] flutter_down_header,
[IMGFX_ANIM_UNFURL] unfurl_header,
[IMGFX_ANIM_GET_IN_BED] get_in_bed_header,
[IMGFX_ANIM_SPIRIT_CAPTURE] spirit_capture_header,
[IMGFX_ANIM_UNUSED_1] unused_1_header,
[IMGFX_ANIM_UNUSED_2] unused_2_header,
[IMGFX_ANIM_UNUSED_3] unused_3_header,
[IMGFX_ANIM_TUTANKOOPA_GATHER] tutankoopa_gather_header,
[IMGFX_ANIM_TUTANKOOPA_SWIRL_2] tutankoopa_swirl_2_header,
[IMGFX_ANIM_TUTANKOOPA_SWIRL_1] tutankoopa_swirl_1_header,
[IMGFX_ANIM_SHUFFLE_CARDS] shuffle_cards_header,
[IMGFX_ANIM_FLIP_CARD_1] flip_card_1_header,
[IMGFX_ANIM_FLIP_CARD_2] flip_card_2_header,
[IMGFX_ANIM_FLIP_CARD_3] flip_card_3_header,
[IMGFX_ANIM_CYMBAL_CRUSH] cymbal_crush_header,
};
extern ImgFXCacheEntry ImgFXDataCache[8];
@ -1051,7 +1056,7 @@ void imgfx_appendGfx_mesh(ImgFXState* state, Matrix4f mtx) {
case IMGFX_RENDER_OVERLAY_RGBA:
// color: texture
// alpha: texture * prim
gDPSetCombineLERP(gMainGfxPos++,
gDPSetCombineLERP(gMainGfxPos++,
0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0,
0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0);
gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, state->ints.overlay.alpha);
@ -1215,7 +1220,7 @@ void imgfx_mesh_make_grid(ImgFXState* state) {
}
ImgFXAnimHeader* imgfx_load_anim(ImgFXState* state) {
u8* romStart = ImgFXAnimOffsets[state->ints.anim.type] + imgfx_gfx_data_ROM_START;
u8* romStart = (s32) ImgFXAnimOffsets[state->ints.anim.type] + imgfx_data_ROM_START;
ImgFXAnimHeader* anim = &ImgFXAnimHeaders[state->arrayIdx];
if (state->curAnimOffset != romStart) {
@ -1249,7 +1254,7 @@ ImgFXAnimHeader* imgfx_load_anim(ImgFXState* state) {
state->gfxBufs[0] = heap_malloc(anim->gfxCount * sizeof(Gfx));
state->gfxBufs[1] = heap_malloc(anim->gfxCount * sizeof(Gfx));
romStart = imgfx_gfx_data_ROM_START + (s32)anim->gfxOffset;
romStart = imgfx_data_ROM_START + (s32)anim->gfxOffset;
romEnd = romStart + anim->gfxCount * sizeof(Gfx);
dma_copy(romStart, romEnd, state->gfxBufs[0]);
dma_copy(romStart, romEnd, state->gfxBufs[1]);
@ -1271,7 +1276,7 @@ ImgFXAnimHeader* imgfx_load_anim(ImgFXState* state) {
// ImgFXVtx structs are 0xC bytes while Vtx are 0x10, so we need a (4/3) scaling factor
// to compute a new, equivalent Vtx[i] address for an existing ImgFXVtx[i] address.
// Unfortunately, using sizeof here does not match.
gfxBuffer[j-1].words.w1 = ((((s32) gfxBuffer[j-1].words.w1 - anim->keyframesOffset) / 3) * 4) +
gfxBuffer[j-1].words.w1 = ((((s32) gfxBuffer[j-1].words.w1 - (s32) anim->keyframesOffset) / 3) * 4) +
(s32) state->vtxBufs[i];
}
} while (cmd != G_ENDDL);
@ -1331,11 +1336,11 @@ void imgfx_mesh_anim_update(ImgFXState* state) {
// find the current + next keyframe vertex data
curKeyframe = heap_malloc(header->vtxCount * sizeof(ImgFXVtx));
romStart = (u8*)((s32)imgfx_gfx_data_ROM_START + header->keyframesOffset + curKeyIdx * header->vtxCount * sizeof(ImgFXVtx));
romStart = (u8*)((s32)imgfx_data_ROM_START + (s32) header->keyframesOffset + curKeyIdx * header->vtxCount * sizeof(ImgFXVtx));
dma_copy(romStart, romStart + header->vtxCount * sizeof(ImgFXVtx), curKeyframe);
if (keyframeInterval > 1) {
nextKeyframe = heap_malloc(header->vtxCount * sizeof(*nextKeyframe));
romStart = (u8*)((s32)imgfx_gfx_data_ROM_START + header->keyframesOffset + nextKeyIdx * header->vtxCount * sizeof(ImgFXVtx));
romStart = (u8*)((s32)imgfx_data_ROM_START + (s32) header->keyframesOffset + nextKeyIdx * header->vtxCount * sizeof(ImgFXVtx));
dma_copy(romStart, romStart + header->vtxCount * sizeof(ImgFXVtx), nextKeyframe);
}

View File

@ -217,6 +217,8 @@ def write_ninja_rules(ninja: ninja_syntax.Writer, cpp: str, extra_cppflags: str,
ninja.rule("pm_sprite_shading_profiles", command=f"$python {BUILD_TOOLS}/sprite/sprite_shading_profiles.py $in $out $header_path")
ninja.rule("pm_imgfx_data", command=f"$python {BUILD_TOOLS}/imgfx/imgfx_data.py $in $out")
with Path("tools/permuter_settings.toml").open("w") as f:
f.write(f"compiler_command = \"{cc} {CPPFLAGS.replace('$version', 'us')} {cflags} -DPERMUTER -fforce-addr\"\n")
f.write(f"assembler_command = \"{cross}as -EB -march=vr4300 -mtune=vr4300 -Iinclude\"\n")
@ -257,7 +259,7 @@ class Configure:
if assets:
modes.extend(["bin", "yay0", "img", "vtx", "vtx_common", "gfx", "gfx_common", "pm_map_data", "pm_msg",
"pm_npc_sprites", "pm_charset","pm_charset_palettes", "pm_effect_loads", "pm_effect_shims",
"pm_sprite_shading_profiles"])
"pm_sprite_shading_profiles", "pm_imgfx_data"])
if code:
modes.extend(["code", "c", "data", "rodata"])
@ -366,12 +368,12 @@ class Configure:
order_only.append("generated_headers_" + self.version)
ninja.build(
object_strs, # $out
task,
self.resolve_src_paths(src_paths), # $in
variables={ "version": self.version, **variables },
outputs=object_strs, # $out
rule=task,
inputs=self.resolve_src_paths(src_paths), # $in
implicit=implicit,
order_only=order_only,
variables={ "version": self.version, **variables },
implicit_outputs=implicit_outputs
)
@ -688,6 +690,15 @@ class Configure:
"header_path": header_path,
})
build(entry.object_path, [entry.object_path.with_suffix("")], "bin")
elif seg.type == "pm_imgfx_data":
c_file_path = Path(f"assets/{self.version}") / "imgfx" / (seg.name + ".c")
build(c_file_path, entry.src_paths, "pm_imgfx_data")
build(entry.object_path, [c_file_path], "cc" if not modern_gcc else "cc_modern", variables={
"cflags": "",
"cppflags": f"-DVERSION_{self.version.upper()}",
"encoding": "CP932", # similar to SHIFT-JIS, but includes backslash and tilde
})
elif seg.type == "linker" or seg.type == "linker_offset":
pass
else:

View File

View File

@ -0,0 +1,181 @@
#!/usr/bin/env python3
from dataclasses import dataclass
import argparse
import json
from pathlib import Path
from typing import Any, List
import yaml as yaml_loader
@dataclass
class Vertex:
idx: int
x: int
y: int
z: int
u: int
v: int
r: int
g: int
b: int
a: int
def toJSON(self):
return " { \"pos\": [" + f"{self.x}, {self.y}, {self.z}" + "], \"uv\": [" + f"{self.u}, {self.v}" + "], \"rgba\": [" + f"{self.r}, {self.g}, {self.b}, {self.a}" + "] }"
@dataclass
class Triangle:
i: int
j: int
k: int
def toJSON(self):
return f" [{self.i}, {self.j}, {self.k}]"
@dataclass
class Anim:
name: str
offset: int
vtx_offset: int
gfx_offset: int
vtx_count: int
gfx_count: int
keyframes: int
flags: int
frames: List[List[Vertex]]
triangles: List[Triangle]
def toJSON(self):
framestr = ",\n".join([" [\n" + ",\n".join([v.toJSON() for v in frame]) + "\n ]" for i, frame in enumerate(self.frames)])
trianglestr = ",\n".join([t.toJSON() for t in self.triangles])
ret = "{\n"
ret += " \"flags\": " + str(self.flags) + ",\n"
ret += " \"frames\": [\n" + framestr + "],\n"
ret += " \"triangles\": [\n" + trianglestr + "]\n"
ret += "}"
return ret
@staticmethod
def fromJSON(name: str, data: Any) -> "Anim":
flags = data["flags"]
frames = [[Vertex(idx, *vtx["pos"], *vtx["uv"], *vtx["rgba"]) for idx, vtx in enumerate(frame)] for frame in data["frames"]]
triangles = [Triangle(*t) for t in data["triangles"]]
return Anim(
name=name,
offset=0,
vtx_offset=0,
gfx_offset=0,
vtx_count=0,
gfx_count=0,
keyframes=len(frames),
flags=flags,
frames=frames,
triangles=triangles
)
def build(inputs: List[Path], output: Path):
with open(output, "w") as f:
f.write("/* NOTE: This file is autogenerated, do not edit */\n\n")
f.write("#include \"PR/gbi.h\"\n")
f.write("#include \"macros.h\"\n")
f.write("#include \"imgfx.h\"\n\n")
for input in inputs:
with open(input, "r") as fin:
in_json = json.load(fin)
anim = Anim.fromJSON(input.name[:-5], in_json)
vtx_name = f"{anim.name}_keyframes"
gfx_name = f"{anim.name}_gfx"
# this has padding before it..maybe a file split?
if anim.name == "unused_1":
f.write(f"s32 padding_{anim.name}[] = {{ 0, 0 }};\n\n")
# vtx
f.write(f"ImgFXVtx {vtx_name}[{len(anim.frames)}][{len(anim.frames[0])}] = {{\n")
for frame in anim.frames:
f.write(" {\n")
for vtx in frame:
f.write(f" {{ {{{vtx.x}, {vtx.y}, {vtx.z}}}, {{{vtx.u}, {vtx.v}}}, {{{vtx.r}, {vtx.g}, {vtx.b}}}, {vtx.a} }},\n")
f.write(" },\n")
f.write("};\n\n")
# gfx
f.write(f"Gfx {gfx_name}[] = {{\n")
# TODO hard-coded
cur_tri = 0
just_chunked = False
chunk_text = ""
max_t1 = 0
max_t2 = 0
min_t = 0
sub_num = 0
old_max_t = 0
while cur_tri < len(anim.triangles):
# Vertex command every 16 triangles
t1 = anim.triangles[cur_tri]
t2 = anim.triangles[cur_tri + 1] if cur_tri + 1 < len(anim.triangles) else None
t1x = t1.i - sub_num
t1y = t1.j - sub_num
t1z = t1.k - sub_num
max_t1 = max(max_t1, t1x, t1y, t1z)
t2x = 0 if t2 is None else t2.i - sub_num
t2y = 0 if t2 is None else t2.j - sub_num
t2z = 0 if t2 is None else t2.k - sub_num
max_t2 = max(max_t2, t2x, t2y, t2z)
min_t = min(min_t, t1x, t1y, t1z, t2x, t2y, t2z)
# We need a new chunk
if max_t1 >= 32 and not just_chunked:
chunk_text = f" gsSPVertex((u8*){vtx_name} + 0xC * {sub_num}, {min(32, max_t1 + 1)}, 0),\n" + chunk_text
just_chunked = True
f.write(chunk_text)
chunk_text = ""
sub_num += old_max_t - min_t + 1
min_t = 32
max_t1 = 0
max_t2 = 0
continue
just_chunked = False
if max_t2 >= 32 or t2 is None:
chunk_text += f" gsSP1Triangle({t1x}, {t1y}, {t1z}, 0),\n"
cur_tri += 1
old_max_t = max_t1
else:
chunk_text += f" gsSP2Triangles({t1x}, {t1y}, {t1z}, 0, {t2x}, {t2y}, {t2z}, 0),\n"
cur_tri += 2
old_max_t = max(max_t1, max_t2)
# Dump final chunk
chunk_text = f" gsSPVertex((u8*){vtx_name} + 0xC * {sub_num}, {max(max_t1, max_t2) + 1}, 0),\n" + chunk_text
f.write(chunk_text)
f.write(" gsSPEndDisplayList(),\n")
f.write("};\n\n")
# header
f.write(f"ImgFXAnimHeader {anim.name}_header = {{\n")
f.write(f" .keyframesOffset = {vtx_name}[0],\n")
f.write(f" .gfxOffset = {gfx_name},\n")
f.write(f" .vtxCount = ARRAY_COUNT({vtx_name}[0]),\n")
f.write(f" .gfxCount = ARRAY_COUNT({gfx_name}),\n")
f.write(f" .keyframesCount = ARRAY_COUNT({vtx_name}),\n")
f.write(f" .flags = {anim.flags},\n")
f.write("};\n\n")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="ImgFX animation c file builder")
parser.add_argument("inputs", type=Path, help="json files to build, passed in order", nargs="+")
parser.add_argument("output", type=Path, help="Output c file path")
args = parser.parse_args()
build(args.inputs, args.output)

View File

@ -0,0 +1,107 @@
import os
import struct
import sys
from pathlib import Path
import yaml as yaml_loader
from typing import List, Tuple
TOOLS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(str(Path(TOOLS_DIR) / "build/imgfx"))
from imgfx_data import Anim, Triangle, Vertex
from segtypes.n64.segment import N64Segment
from util import log, options
class N64SegPm_imgfx_data(N64Segment):
anims: List[Anim] = []
OUT_DIR: Path = options.opts.asset_path / "imgfx"
def scan(self, rom_bytes):
data = rom_bytes[self.rom_start:self.rom_end]
for name, offset in self.yaml.get("animations"):
pos = offset
# Animations start with vtx data which is followed by gfx data and ends with the header at `offset`
vtx_offset, gfx_offset, vtx_count, gfx_count, keyframes, flags = struct.unpack(">IIHHHH", data[pos:pos+16])
frames: List[List[Vertex]] = []
pos = vtx_offset
for i in range(keyframes):
frame: List[Vertex] = []
for j in range(vtx_count):
x, y, z, u, v, r, g, b, a = struct.unpack(">hhhBBbbbB", data[pos:pos+12])
pos += 12
frame.append(Vertex(j, x, y, z, u, v, r, g, b, a))
frames.append(frame)
triangles: List[Triangle] = []
vtx_buf: List[int] = []
# Align to 8 bytes
pos = (pos + 7) & ~(8 - 1)
assert(pos == gfx_offset)
def unpack_tri(word: int, vtx_buf: List[int]) -> Tuple[int, int, int]:
i = (word >> 16) & 0xFF
j = (word >> 8) & 0xFF
k = word & 0xFF
i = vtx_buf[int(i / 2)]
j = vtx_buf[int(j / 2)]
k = vtx_buf[int(k / 2)]
return (i, j, k)
for i in range(gfx_count):
w0, w1 = struct.unpack(">II", data[pos:pos+8])
pos += 8
op = (w0 >> 24) & 0xFF
if op == 1: # G_VTX
num = w0 >> 12 & 0xFF
end = int((w0 & 0xFF) / 2)
src_idx = int((w1 - vtx_offset) / 12)
start = end - num
for j in range(num):
to_place_pos = start + j
while len(vtx_buf) <= to_place_pos:
vtx_buf.append(0)
vtx_buf[to_place_pos] = src_idx + j
elif op == 5: # G_TRI1
triangles.append(Triangle(*unpack_tri(w0, vtx_buf)))
elif op == 6: # G_TRI2
triangles.append(Triangle(*unpack_tri(w0, vtx_buf)))
triangles.append(Triangle(*unpack_tri(w1, vtx_buf)))
elif op == 0xDF: # G_ENDDL
pass
else:
log.error(f"Unknown op: {op}")
self.anims.append(Anim(name, offset, vtx_offset, gfx_offset, vtx_count, gfx_count, keyframes, flags, frames, triangles))
def split(self, rom_bytes):
self.OUT_DIR.mkdir(parents=True, exist_ok=True)
for anim in self.anims:
with open(f"{self.OUT_DIR}/{anim.name}.json", "w") as f:
f.write(anim.toJSON())
def get_linker_entries(self):
from segtypes.linker_entry import LinkerEntry
return [
LinkerEntry(
self,
[self.OUT_DIR / f"{anim.name}.json" for anim in self.anims],
options.opts.asset_path / "imgfx" / f"{self.name}.c",
self.get_linker_section(),
)
]

View File

@ -409,7 +409,7 @@ segments:
- [0xC4010, c, C50A0]
- [0xCC0F0, c, cd180_len_38f0]
- [0xCDDB0, c, CEE40]
- [0xCF9E0, c, d0a70_len_4fe0]
- [0xCF9E0, c, imgfx]
- [0xD49C0, c, hud_element]
- [0xDA990, c, dba20_len_350]
- [0xDACE0, c, trigger]
@ -438,27 +438,14 @@ segments:
- [0xE3DE0, vtx, vtx/stencil2]
- [0xE3F60]
- [0xE4400, .data, CEE40]
- [0xE4480, .data, d0a70_len_4fe0]
- [0xE4480, .data, imgfx]
- [0xE4630, .data, hud_element]
- [0xE4790, .data, dc470_len_14c0]
- [0xE47B0, .data, audio/ambience]
- [0xE47C0, .data, windows]
- [0xE4940, .data, audio/sfx]
- [0xE4D60, .data, audio/e0b30_len_b80]
- [0xE4DB0, .rodata, a5dd0_len_114e0]
- [0xE54D0, .rodata, B4580]
- [0xE5720, .rodata, entity_model]
- [0xE59E0, .rodata, msg]
- [0xE60B0, .rodata, C50A0]
- [0xE6510, .rodata, cd180_len_38f0]
- [0xE65F0, .rodata, CEE40]
- [0xE6620, .rodata, d0a70_len_4fe0]
- [0xE67B0, .rodata, hud_element]
- [0xE6890, .rodata, dc470_len_14c0]
- [0xE68B0, .rodata, windows]
- [0xE68C0, .rodata, audio/sfx]
- [0xE6900, .rodata, audio/e0b30_len_b80]
- [0xE6920]
- [0xE4DB0]
- name: evt
dir: evt
type: code

View File

@ -1143,7 +1143,27 @@ entity_sbk_omo_ROM_START = 0x00e78190;
entity_jan_iwa_ROM_END = 0x00e78190;
entity_default_ROM_START = 0x00e73f70;
entity_default_ROM_END = 0x00e76170;
imgfx_gfx_data_ROM_START = 0x00294870;
imgfx_data_ROM_START = 0x00294870;
shock_header = 0x14358;
shiver_header = 0x18200;
vertical_pipe_curl_header = 0x1A858;
horizontal_pipe_curl_header = 0x1E830;
startle_header = 0x29458;
flutter_down_header = 0x314E0;
unfurl_header = 0x33498;
get_in_bed_header = 0x38988;
spirit_capture_header = 0x39228;
unused_1_header = 0x5B7A8;
unused_2_header = 0x7CF10;
unused_3_header = 0x86490;
tutankoopa_gather_header = 0x96258;
tutankoopa_swirl_2_header = 0xA1820;
tutankoopa_swirl_1_header = 0xACDE8;
shuffle_cards_header = 0xBBF68;
flip_card_1_header = 0xC0490;
flip_card_2_header = 0xC49B8;
flip_card_3_header = 0xC6150;
cymbal_crush_header = 0xCA380;
sort_items = 0x800e5aac;
suggest_player_anim_always_forward = 0x800de358;
add_item = 0x800e5954;

View File

@ -832,7 +832,7 @@ segments:
- [0xC50A0, c, C50A0]
- [0xCD180, c, cd180_len_38f0]
- [0xCEE40, c, CEE40]
- [0xD0A70, c, d0a70_len_4fe0]
- [0xD0A70, c, imgfx]
- [0xD5A50, c, hud_element]
- [0xDBA20, c, dba20_len_350]
- [0xDBD70, c, trigger]
@ -861,7 +861,7 @@ segments:
- [0xE4E70, vtx, vtx/stencil2]
- [0xE4FF0]
- [0xE5490, .data, CEE40]
- [0xE5510, .data, d0a70_len_4fe0]
- [0xE5510, .data, imgfx]
- [0xE56C0, .data, hud_element]
- [0xE5820, .data, dc470_len_14c0]
- [0xE5840, .data, audio/ambience]
@ -2596,7 +2596,31 @@ segments:
- [0x2435F0, ia8, title/tape, 128, 128]
- [0x2475F0, ci8, title/bowser_silhouette, 128, 128]
- [0x24B5F0, palette, title/bowser_silhouette]
- [0x24B7F0, bin, imgfx_gfx_data] # TODO extract into better format?
- start: 0x24B7F0
type: pm_imgfx_data
name: imgfx_data
vram: 0
animations:
- ["shock", 0x14358]
- ["shiver", 0x18200]
- ["vertical_pipe_curl", 0x1A858]
- ["horizontal_pipe_curl", 0x1E830]
- ["startle", 0x29458]
- ["flutter_down", 0x314E0]
- ["unfurl", 0x33498]
- ["get_in_bed", 0x38988]
- ["spirit_capture", 0x39228]
- ["unused_1", 0x5B7A8]
- ["unused_2", 0x7CF10]
- ["unused_3", 0x86490]
- ["tutankoopa_gather", 0x96258]
- ["tutankoopa_swirl_2", 0xA1820]
- ["tutankoopa_swirl_1", 0xACDE8]
- ["shuffle_cards", 0xBBF68]
- ["flip_card_1", 0xC0490]
- ["flip_card_2", 0xC49B8]
- ["flip_card_3", 0xC6150]
- ["cymbal_crush", 0xCA380]
- [0x315B80, pm_sprite_shading_profiles, sprite_shading_profiles]
- type: code
start: 0x3169F0