From 9764bd024170429dbd9e9f0a631d694a1f6ce1e5 Mon Sep 17 00:00:00 2001 From: rengstrom Date: Tue, 1 Sep 2026 20:12:00 +0000 Subject: [PATCH 1/4] world: decompile func_800987D8, the overlay's entry loop 1028 instructions, the largest world nonmatching: one long init followed by a frame loop whose every exit is a break that records where control goes next, then a shared teardown tail. The six huge "backedges" are not loops -- they are those breaks, with their bodies placed ahead of the loop. Two spellings the match turns on: the scratchpad stack switch around renderWorldMapFrame is inline asm (there is no way to express a stack switch in C -- the same device as fe_object1's SCRATCH_STACK_ENTER and common.h's GP_* family), and declaring $t0 clobbered there changes which temp the camera-magnitude multiply gets 900 bytes away. Names for what the loop does: the map display modes are what the player sees -- the corner globe, the transparent square, the full-screen map -- and with those named the screen geometry and the two edge-detected pad bits read plainly. Slot gains the SceneState field the loop saves into, carved from a pad. Fixes the declarations the unit tripped over on the way: a second, void-returning VSync in we_object2.h that contradicted the SDK; D_8005F146 living in a field header while field, world and battle all use it; D_800C9868 typed WorldPos when it is copied whole as 16 bytes and fed to GTE routines; and InitGeom, SquareRoot0, SetDispMask and deactivateBattleCmd being called by raw address. --- config/symbols.extern.txt | 1 + include/field/fe_object1.h | 1 - include/main.h | 3 + include/overlay.h | 8 +- include/world.h | 10 +- include/world/we_object0.h | 14 + include/world/we_object2.h | 5 +- include/world/we_object3.h | 51 ++++ include/world/we_object4.h | 2 +- src/battle/bc_object1.c | 2 +- src/world/we_object0.c | 533 ++++++++++++++++++++++++++++++++++++- src/world/we_object1.c | 4 +- src/world/we_object3.c | 75 ++---- src/world/we_object4.c | 20 +- src/world/we_object5.c | 16 +- src/world/we_object7.c | 2 +- src/world/we_object9.c | 12 +- 17 files changed, 656 insertions(+), 103 deletions(-) create mode 100644 include/world/we_object0.h diff --git a/config/symbols.extern.txt b/config/symbols.extern.txt index dad6faa8..8111b1a1 100644 --- a/config/symbols.extern.txt +++ b/config/symbols.extern.txt @@ -83,6 +83,7 @@ SetSprt = 0x8004D6E4; SetTile = 0x8004D704; SetDrawTPage = 0x8004D724; SetDrawMove = 0x8004D754; +deactivateBattleCmd = 0x800308B0; /* main; the world entry loop calls it on shutdown */ SetDrawLoad = 0x8004D7B4; g_gameState = 0x80077378; g_characterMagic = 0x80077818; diff --git a/include/field/fe_object1.h b/include/field/fe_object1.h index 838242b4..000746c1 100644 --- a/include/field/fe_object1.h +++ b/include/field/fe_object1.h @@ -23,7 +23,6 @@ extern CdFileDesc D_800C0910[]; /**< Streaming table, third descriptor (passed /** @brief Field id currently being streamed in (compared against @c D_8005F100). */ extern s16 D_8005F14E; /** @brief Field render/present state halfword; the loader spins while it reads 4. */ -extern volatile s16 D_8005F146; /** @brief Section-pointer table bases published by the loaded field bundle. */ extern u8 **D_800C7208; /**< Event-queue block; assigned to @c D_8005F0F8. */ diff --git a/include/main.h b/include/main.h index 86d608f2..a94a650d 100644 --- a/include/main.h +++ b/include/main.h @@ -53,6 +53,9 @@ extern u8 g_vsyncSkip; extern volatile s32 D_8005F154; /**< VSync frame-counter timing accumulator (+0x88F/VSync). */ extern volatile s32 D_8005F15C; /**< VSync countdown-timer timing accumulator (+0x88F/VSync). */ extern u16 D_8005F11E; /**< VSync-done / status flag. */ +/** Scene-transition handshake driven by the VSync path; shared by the field, + * world and battle engines (each spins on it with its own sentinel value). */ +extern volatile s16 D_8005F146; /* CD file-table descriptors + scratch buffers loaded/managed by main.c. */ extern CdFileDesc g_fileTableDesc[]; diff --git a/include/overlay.h b/include/overlay.h index 5fabf01f..c3f6a9b5 100644 --- a/include/overlay.h +++ b/include/overlay.h @@ -57,8 +57,10 @@ extern s32 func_8003646C(); /* K&R: called with 1 or 2 args */ /** @brief Run the loaded overlay's entry point (init / execute). */ extern void func_80098000(void); -/** @brief Query the loaded overlay; returns a status code (main checks @c == 1). - * @note Purpose uncertain - undecompiled; appears to report the overlay's - * load/ready result. */ +/** @brief Run the world overlay: set the map up, then drive its frame loop + * until something asks the world to hand off. Defined in + * src/world/we_object0.c. + * @return 0 normally; 1 when the loop ended on the two-frame stall check + * (main checks @c == 1). */ extern s32 func_800987D8(void); #endif /* OVERLAY_H */ diff --git a/include/world.h b/include/world.h index f2645dc7..d4f68525 100644 --- a/include/world.h +++ b/include/world.h @@ -5,6 +5,7 @@ #include "psxsdk/libgpu.h" #include "psxsdk/libgte.h" #include "battle.h" +#include "gamestate.h" /* SceneState, in Slot */ #include "sound.h" /** View of the sentinel ctx exposing the DISPENV template that sits past the @@ -261,7 +262,8 @@ extern s32 D_800C97F4; /**< World camera angle. Stored as a wo angular-delta helpers in we_object9 read only its low half — hence the (u16) cast at those sites. */ extern MATRIX D_800C9838; /**< World-to-screen matrix loaded into the GTE. */ -extern WorldPos D_800C9868; /**< Source camera world position (cast to VECTOR* for GTE transform func_800BC544). */ +extern VECTOR D_800C9868; /**< Source camera world position. 16 bytes: the world entry loop copies + it whole into @c D_800C9858 and hands it straight to func_800BC544. */ extern SVECTOR D_800C9770[2]; /**< Camera scratch: [0] is a position offset, [1] a rotation. */ extern s32 *D_800C9744; /**< Texture-strip animation block: a NULL-terminated s32 offset table; each offset, relative to this pointer, locates one @@ -527,7 +529,11 @@ typedef struct { typedef struct { /* 0x00 */ u8 pad00[0x18]; /* 0x18 */ Track tracks[2]; /**< Track A at 0x18, Track B at 0x24. */ - /* 0x30 */ u8 pad30[0x3C]; + /* 0x30 */ u8 pad30[0x38]; + /* 0x68 */ SceneState scene; /**< Saved scene state; the world entry loop + saves the whole record here on a cold + start and restores @c cmd from it on a + warm one. */ /* 0x6C */ s32 unk6C; /**< Flags word; see SLOT_FLAG_CMD_MIRROR. */ /* 0x70 */ u8 pad70[0x4]; /* 0x74 */ u32 flags[2]; /**< 64-bit flag set (low/high). */ diff --git a/include/world/we_object0.h b/include/world/we_object0.h new file mode 100644 index 00000000..79b9dd9a --- /dev/null +++ b/include/world/we_object0.h @@ -0,0 +1,14 @@ +#ifndef WORLD_WE_OBJECT0_H +#define WORLD_WE_OBJECT0_H + +#include "common.h" +#include "overlay.h" /* func_800987D8 -- the entry point this unit defines */ + +/* we_object0 has exactly one public symbol, the overlay entry point, and that + * is declared with the other overlay entry points in overlay.h rather than + * here. Everything else the unit touches is private to + * src/world/we_object0.c. This header exists so the unit has an owner for any + * public surface it grows, and so its users get the entry point by including + * it. */ + +#endif /* WORLD_WE_OBJECT0_H */ diff --git a/include/world/we_object2.h b/include/world/we_object2.h index 5dbc0d12..568ccd6d 100644 --- a/include/world/we_object2.h +++ b/include/world/we_object2.h @@ -4,6 +4,7 @@ #include "common.h" #include "world.h" #include "psxsdk/libgte.h" +#include "psxsdk/libetc.h" /* VSync */ typedef struct { s16 a; @@ -48,10 +49,6 @@ extern u16 D_800C5346; /* per-map yaw target (func_8009F6EC b extern s32 D_800C9730; /* GTE projection-plane distance (SetGeomScreen arg). */ extern s32 D_800D2448; /* world-ready gate flag (func_8009F6EC bit 0x10). */ -/* VSync is declared here with a void-returning view for this file's - * matching codegen (psxsdk/libetc.h's s32-returning prototype is not used). */ -extern void VSync(s32 mode); - extern void func_800A5F78(s32 screen); extern void func_800A5FD4(s32 screen); extern void func_80099EDC(s32 idx); diff --git a/include/world/we_object3.h b/include/world/we_object3.h index 5495f418..debb8b9c 100644 --- a/include/world/we_object3.h +++ b/include/world/we_object3.h @@ -129,4 +129,55 @@ extern void initWorldDoubleBuffer(void); color matrix. */ extern void setupWorldRenderParams(void); +/* The primitive pools. Public because the world entry loop (we_object0) + is what points D_800C9720 at a bank each frame; the glyph renderers + then draw out of whichever one it selected. */ +typedef struct { + POLY_GT3 *cur; /* 0x00 */ + POLY_GT3 *base; /* 0x04 */ + POLY_GT3 *end; /* 0x08 */ +} Gt3Pool; /* 0x0C */ + +typedef struct { + POLY_FT3 *cur; /* 0x00 */ + POLY_FT3 *base; /* 0x04 */ + POLY_FT3 *end; /* 0x08 */ +} Ft3Pool; /* 0x0C */ + +typedef struct { + POLY_FT4 *cur; /* 0x00 */ + POLY_FT4 *base; /* 0x04 */ + POLY_FT4 *end; /* 0x08 */ +} Ft4Pool; /* 0x0C */ + +/** The three pools of one bank, one per primitive kind. Both banks are laid out + at start-up by @c func_800A246C, and the world entry loop (@c func_800987D8 + in we_object0) re-points @c D_800C9720 at one of them every frame: bank 1 + while the active scene context is the no-battle sentinel @c D_800CA040, + bank 0 otherwise. The glyph renderers then draw out of whichever it picked. + (Not @c D_800C53A4 — that one indexes the sprite record banks + @c D_800D2508.) */ +typedef struct { + Gt3Pool gt3; /* 0x00 */ + Ft3Pool ft3; /* 0x0C */ + Ft4Pool ft4; /* 0x18 */ +} WorldPrimBank; /* 0x24 */ + +extern WorldPrimBank D_800C9E88[2]; /**< The two banks. @c func_800A246C lays + them out; the world entry loop indexes + this array directly to choose one, and + everything else reaches the chosen bank + through @c D_800C9720. */ +extern WorldPrimBank *D_800C9720; /**< The bank the glyph renderers allocate + from this frame. The world entry loop + (@c func_800987D8) re-points it every + frame; the readers (we_object6, + we_object7) are still asm. */ + +/* Also read by the world entry loop in we_object0. */ +extern s32 D_800C972C; /**< Accumulated glyph-entry count. */ +extern s32 D_800C9ED0; /**< Pad 0's raw frame parameter. */ +extern SVECTOR D_800CA038; /**< Reference offset fed to the pool placer. */ +extern s32 D_800D2238; + #endif /* WORLD_WE_OBJECT3_H */ diff --git a/include/world/we_object4.h b/include/world/we_object4.h index f635627c..3f630c6b 100644 --- a/include/world/we_object4.h +++ b/include/world/we_object4.h @@ -23,7 +23,7 @@ extern void func_800A7CD0(s32 *block); /**< Load a VRAM row animation extern void func_800A8400(void); /**< Draw the map-view HUD layer (panel, stars, gradient). */ extern void func_800A8C1C(void); /**< Re-blend the world palette for the camera's position. */ extern void func_800A9300(void); /**< Draw the D_800D9CB0 particle pool. */ -extern void func_800A9F54(WorldPos *pos, s32 x, s32 y); /**< Draw the world-map inset mesh at @p pos. */ +extern void func_800A9F54(VECTOR *pos, s32 x, s32 y); /**< Draw the world-map inset mesh at @p pos. */ /** The camera-follow reference is written as a word but published as its low * half by we_object3, so both views need a name. */ diff --git a/src/battle/bc_object1.c b/src/battle/bc_object1.c index 94be1120..ebe9193d 100644 --- a/src/battle/bc_object1.c +++ b/src/battle/bc_object1.c @@ -1,4 +1,5 @@ #include "common.h" +#include "main.h" /* D_8005F146 */ #include "battle.h" #include "gf.h" #include "battle/bc_object1.h" @@ -37,7 +38,6 @@ extern void func_800D0F74(void); extern SoundCmd* func_800B8564(s16, u8); /* bc_object9.c */ -extern volatile s16 D_8005F146; void func_80099D30(void) { s32 i; diff --git a/src/world/we_object0.c b/src/world/we_object0.c index 9b2930ee..17401c77 100644 --- a/src/world/we_object0.c +++ b/src/world/we_object0.c @@ -1,9 +1,530 @@ #include "common.h" +#include "gamestate.h" +#include "btl_color.h" /* deactivateBattleCmd */ +#include "psxsdk/libgpu.h" /* SetDispMask */ +#include "psxsdk/libgte.h" /* InitGeom, SquareRoot0 */ +#include "psxsdk/libetc.h" /* getScratchAddr */ +#include "world.h" +#include "world/we_object0.h" +#include "world/we_object1.h" +#include "world/we_object2.h" +#include "world/we_object3.h" +#include "world/we_object4.h" +#include "world/we_object5.h" +#include "world/we_object9.h" +#include "main.h" +#include "thread.h" -/* The world overlay's entry unit: one ~4.1KB function, called from main.s as - * the overlay's main loop. It sat inside the leading rodata blob until - * 2026-08-31, hidden from the split — which is why its callees (the render - * callback registration, the object-list machinery) once looked like dead - * islands. */ +/* Park the real stack pointer in the PS1 scratchpad and run the next call with + * its stack there, then put the real stack back. There is no way to express a + * stack switch in C, so this is the original's inline asm -- the same device as + * SCRATCH_STACK_ENTER/LEAVE in src/field/fe_object1.c and the GP_* family in + * include/common.h. As with GP_SAVE_SCRATCH the slot address arrives as an + * operand and the compiler materializes it: here it schedules the lui/ori four + * instructions away from the block, which is how we know the address is + * compiler-generated rather than part of the asm. $t0 is named explicitly (it + * is the same register at both call sites while the address register differs), + * and declaring it clobbered is load-bearing -- without it the allocator picks + * a different temp for the camera-magnitude multiply 900 bytes further down. */ +#define SP_SAVE_SCRATCH(slot) \ + asm volatile("addu $t0, %0, $zero\n\t" \ + "sw $sp, 0($t0)\n\t" \ + "addiu $t0, $t0, -4\n\t" \ + "addu $sp, $t0, $zero" : : "r"(slot) : "$8") -INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object0", func_800987D8); +#define SP_RESTORE() \ + asm volatile("addiu $sp, $sp, 4\n\t" \ + "lw $sp, 0($sp)") + +/* Screen size, used to calculate where to place the maps on screen. */ +#define WORLD_SCREEN_W 320 +#define WORLD_SCREEN_H 224 + +/* Frames the streamer is given to settle before the loop starts drawing; + * mode 4 (a warm re-entry) gets the short count. */ +#define WORLD_SETTLE_FRAMES 0x18 +#define WORLD_SETTLE_FRAMES_WARM 8 + +/* D_800C9ED0 holding this value for two consecutive frames ends the loop. */ +#define WORLD_STALL_CODE 0x90F +#define WORLD_STALL_FRAMES 2 + +/** Map display mode held in @c D_800C4D28. Mutually exclusive modes, + * not flags: the loop dispatches on the exact value. */ +typedef enum { + MAP_DISPLAY_OFF = 0, // No map at all + MAP_DISPLAY_GLOBE = 1, // Globe in the bottom right corner + MAP_DISPLAY_TRANSPARENT = 2, // Transparent square map in bottom right corner + MAP_DISPLAY_FULL = 3 // Full screen map with hand pointer and locations etc. +} MapDisplayMode; + +/* Edge-detected bits of the world pad word @c D_800D2278, tested as + cur & (cur ^ prev) -- "went set this frame". Which physical buttons these + are is not established, so each is named for what the loop does when it + fires; the pad word is FF8's own, not the raw PSX button mask. */ +#define WORLD_PAD_HANDOFF 0x20 /* runs the scene-change checks */ +#define WORLD_PAD_REDRAW 0x800 /* re-runs setupWorldRender() */ + +/* Columns the linear tile index from func_800A5DC8 decomposes into. */ +#define MAP_DISPLAY_COLS 128 + +/* Screen position of the corner globe; the other modes derive theirs from + the current screen size instead. */ +#define MAP_DISPLAY_GLOBE_X 0x104 +#define MAP_DISPLAY_GLOBE_Y 0xB4 + +/* The transparent map sits this far in from the screen's right/bottom edge. */ +#define MAP_DISPLAY_TRANSPARENT_DX 0x86 +#define MAP_DISPLAY_TRANSPARENT_DY 0x64 + +/* The full-screen map is this size, centred on the screen. */ +#define MAP_DISPLAY_FULL_W 0x100 +#define MAP_DISPLAY_FULL_H 0xC0 + +/* Globals this unit is the first C code to touch. Nothing else in the tree + names them yet, so they are file-local declarations here rather than a + header's public surface. */ +extern s32 D_800C4D08; /**< Hand-off action code published on the way out. */ +extern s32 D_800C4D28; /**< Map display mode; see MAP_DISPLAY_*. */ +extern s32 D_800C4D80; /**< Last render-callback status. */ +extern s32 D_800C4F0C[]; +extern s32 D_800C4FC4; /**< Frames left in the settle countdown. */ +extern SVECTOR D_800C5400; +extern MATRIX D_800C5408; +extern s32 D_800C8638; /**< Frames spent waiting for the streamer. */ +extern s32 D_800C973C; +extern u8 D_800C9762; +extern u8 *D_800C9768; +extern s32 D_800C97D8; +extern s32 D_800C9828[]; +extern SVECTOR D_800C9E60; /**< Scratch copy of the camera's second angle triple. */ +extern u8 *D_800C9E74; +extern u8 *D_800C9E78; +extern s32 D_800C9E7C; +extern s32 *D_800C9FEC; +extern s32 D_800C9FF0[]; +extern s32 D_800D2130[]; +extern s32 *D_800D2230; +extern s32 *D_800D2268; +extern s32 D_800D2270; +extern s32 D_800D2290[]; +extern u8 D_800D23DC; /**< Same byte as @c D_800D23D8[4]. */ +extern SVECTOR D_800D2450; +extern s32 *D_800D245C; + +extern Slot D_800785D8; /**< Slot-state record the loop publishes at D_800D226C. */ + +/* Still assembly. Each is declared here, tagged with the unit that owns it, + * until that unit is decompiled and can publish it from its own header. */ +extern s32 func_800997E8(u16 *out); /* we_object1 */ +extern void func_80099F78(void); /* we_object1 */ +extern void func_8009A954(void); /* we_object1 */ +extern void func_8009AEE4(s32 id); /* we_object1 */ +extern void func_8009B954(s32 a, s32 b, s32 c); /* we_object1 */ +extern void func_8009DB88(u8 *p); /* we_object2 */ +extern void func_8009E5C8(VECTOR *pos, u8 *p, SVECTOR *ang, void *x); /* we_object2 */ +extern void func_800AD698(SceneState *st, u8 *flags); /* we_object6 */ +extern void func_800AE31C(u8 *flags); /* we_object6 */ +extern s32 func_800AE518(u8 *flags); /* we_object6 */ +extern void func_800AEEB0(u8 *flags, void *a, void *b, void *c); /* we_object6 */ +extern void func_800B04CC(SVECTOR *ang, MATRIX *m, u8 *flags, s32 v); /* we_object6 */ +extern void func_800B164C(SceneState *st, Slot *slot, u8 *flags, + VECTOR *pos); /* we_object6 */ +extern void func_800B18B8(u8 *flags, VECTOR *pos, SVECTOR *ang); /* we_object6 */ +extern s32 func_800B1BCC(u8 *p); /* we_object6 */ +extern s32 func_800B4AA0(void); /* we_object7 */ +extern void func_800B56A0(void); /* we_object7 */ +extern void func_800B7240(s8 v); /* we_object7 */ +extern void func_800B881C(void); /* we_object7 */ +extern void func_800B893C(void); /* we_object7 */ +extern void func_800B8C70(void); /* we_object8 */ +extern s32 func_800B99A4(u16 *p); /* we_object8 */ +extern void func_800B9D38(void); /* we_object8 */ +extern void func_800BB150(Slot *slot); /* we_object9 */ +extern void func_800BB4E8(void); /* we_object9 */ +extern void func_800BEC60(u8 *flags); /* we_object10 */ +extern void func_800C4AE4(s32 a); /* we_object13 */ + +/** + * @brief The world overlay's entry point: set the map up, then run its frame + * loop until something asks the world to hand off. + * + * Called from the main state machine once the overlay is resident. The body is + * one long init followed by @c while(1), and every way out of that loop is a + * @c break that first records where control should go next -- a battle, a + * field map, the world menu, or a clean shutdown. After the loop a single tail + * tears the overlay down regardless of which exit fired. + * + * @c D_80082C8C.mode selects how much of the init runs. Mode 4 is a warm + * re-entry that skips straight to the render setup; mode 0 is a cold start and + * saves the whole scene-state block into the slot record; any other mode is a + * return from elsewhere and restores just the dispatch code from it. + * + * @return 0 normally; 1 when the loop ended because @c D_800C9ED0 held + * @c WORLD_STALL_CODE for @c WORLD_STALL_FRAMES consecutive frames. + */ +s32 func_800987D8(void) +{ + s32 trigger; + s8 code; + s32 transparentTile; + s32 fullMapTile; + s16 mapX; + s16 mapY; + s32 reqKind; + s32 padBank; + s32 mode; + s32 cmd; + s32 firstPass; + s32 stall; + /* Codes the loop hands to the scene-change helpers. Their producers + (func_800B85DC, func_800BC46C, func_800997E8, func_800B99A4) are still + assembly, so what distinguishes them is only known by use here. */ + u16 sceneCmd; + u16 hitCmd; + u16 objMarker; + s32 result; + + /* firstPass must be set before stall: gcc keeps them in the two highest + callee-saved registers and picks which by initialisation order. */ + firstPass = 1; + stall = 0; + result = 0; + + if (D_80082C8C.mode == 2) { + func_8009A7C0(); + func_8009CAE0(D_800C4F2C, NULL); + while (D_8005F146 == 4) { + } + } + func_800C4644(); + sndResetState(); + D_800C97EA = WORLD_SCREEN_W; + D_800C97E8 = WORLD_SCREEN_H; + D_800D226C = &D_800785D8; + if (D_80082C8C.mode != 0) { + D_80082C8C.cmd = D_800D226C->scene.cmd; + } else { + D_800D226C->scene = D_80082C8C; + } + D_800D2238 = 0; + D_800C971C = 0; + D_800C9762 = 1; + func_8009CCC8(func_80042634(-1)); + func_8009C8CC(func_80042634(-1)); + func_8009CCDC(0); + InitGeom(); + setupWorldRenderParams(); + initWorldDoubleBuffer(); + func_8009D0F0(); + + if (D_80082C8C.mode != 4) { + func_8009A638(); + func_800B7178(); + func_800AD688(); + func_800BC44C(); + if (D_80082C8C.mode != 2) { + func_8009A7C0(); + func_8009CAE0(D_800C4F2C, func_800A5D10); + } + func_8009A954(); + func_800AD698(&D_80082C8C, D_800D23D8); + func_80099C84(); + func_800B7240(D_80082C8C.unk02); + func_800AEEB0(D_800D23D8, D_800D2290, D_800D2130, D_800C9FF0); + func_800A581C(); + loadImageScript(D_800C9FEC); + loadImageScript(D_800D2268); + D_800D2270 = D_800C9E7C; + func_80099B48(D_800D23D8, D_800D245C); + func_800A7CD0(D_800D2230); + func_800BE7FC(D_800D23D8, D_800C9768); + D_800C9714 = 1; + D_800D2458 = 1; + func_8009CB70(D_800D23D8, &D_800C4F0C, D_800C9E74, D_800C9E78); + func_8009CC34(); + + if (D_800C4FBC != 0) { + if (sndGetStatus() != 0) { + while (sndGetMaxVolume(1) != 0) { + func_80042634(2); + } + } + sndCmdC0(0, 0); + sndCmd11(0); + func_80042634(2); + sndProcessAudio(D_800C4FC0, 1); + func_8009CDFC(D_800C4FBC, 0x7F); + } else { + D_800C4D88 = pickAudioTransition(D_80082C8C.cmd, D_800D23D8[0x6A]); + } + + func_800A40C0(); + func_800AE31C(D_800D23D8); + func_800ABD54(); + func_800ABC98(); + func_800A9ED4(); + func_800A9254(); + func_800B164C(&D_80082C8C, D_800D226C, D_800D23D8, &D_800C9868); + setupWorldMapView(&D_800C9868, D_800C9770, &D_800D2390, &D_800C9828); + D_800C9858 = D_800C9868; + D_800C97F8[0] = D_800C9770[0]; + D_800C9858.vz -= 0x100; + func_800AC468(D_800C9770, &D_800D2390, &D_800C9828, 0); + func_8009C070(); + func_800BC570(&D_800D2290, &D_800D2130, &D_800C9FF0); + + while ((D_800C4D88 >> 31 & 1) < (D_800C4D80 = func_800A47A4())) { + func_80042634(2); + func_800A5D10(); + D_800C8638++; + } + + func_8009C1A4(); + func_800BEECC(); + D_800C4D54 = (D_800C4D38 == 0x31) ? 5 : 0; + D_800C4D58 = 0; + func_800B881C(); + if (D_800C4D88 >= 0) { + D_800C4D84 = 1; + do { + func_80042634(2); + func_8009AEE4(D_800C4D88); + } while (D_800C4D84 != 0); + } + } + + func_800A64DC(); + func_800A6BE0(); + func_800A246C(); + SetGeomScreen(D_800C9730); + setCameraVibrateIntensity(0x1000); + activateBattleAnim(0); + func_80042634(0); + SetDispMask(1); + + while (1) { + func_800A01DC(firstPass); + + D_800C9720 = (D_800D244C == &D_800CA040) ? &D_800C9E88[1] : &D_800C9E88[0]; + g_activeDrawEnv = &D_800D244C->drawEnv; + + if (firstPass) { + D_800C4FC4 = (D_80082C8C.mode == 4) ? WORLD_SETTLE_FRAMES_WARM + : WORLD_SETTLE_FRAMES; + } + if (D_800C4FC4 != 0) { + func_8009A4DC(D_800C4FC4); + D_800C4FC4--; + } + + D_800C9E60 = D_800C9770[1]; + if (D_800C4FC4 == 0) { + func_8009DB88(D_800C9758); + } else { + func_8009FEDC(D_800C9758, 1); + } + func_800BE8B0(D_800D23D8, &D_800C9868, D_800C9770); + func_8009E5C8(&D_800C9868, D_800C9758, D_800C9770, &D_800D2390); + func_8009FEBC(&D_800C9868, D_800C9770); + func_800AC468(D_800C9770, &D_800D2390, &D_800C9828, 0); + func_8009C070(); + func_800A8C1C(); + func_8009FE80(&D_800C5400, &D_800C5408); + func_800A8270(&D_800D2450); + + trigger = func_800AE518(D_800D23D8); + if (trigger != 0) { + code = -1; + if (D_800D23D8[0] == 1 || D_800D23D8[0] == 2) { + code = D_800D23D8[4]; + } else if (D_800D23D8[0] == 3 && (trigger & 1)) { + code = func_800BEB84(0); + } else if (D_800D23D8[0] == 4 && (trigger & 2)) { + code = func_800BEB84(1); + } + if (code >= 0) { + D_80082C8C.mode = 1; + D_80082C8C.unk02 = code; + D_80082C8C.unk03 = -1; + D_80082C8C.cmd = D_800C4D38; + func_800B3FD4(D_800D226C, 1); + D_800C987C = 0; + D_800C4D08 = D_800D23DC; + func_8009D954(); + break; + } + } + + func_800B8C70(); + D_800C9720->ft3.base = D_800C9720->ft3.cur; + D_800C9720->ft4.base = D_800C9720->ft4.cur; + if (D_800D23D8[0] != 12) { + func_800B04CC(D_800C9770, &D_800C9838, D_800D23D8, D_800C973C); + if (D_800D23D8[0] != 12) { + func_800BB4E8(); + func_800A9300(); + } + } + if (D_800C4FC4 <= 0) { + func_800B4AA0(); + } + func_800BEED4(); + func_800BC544(&D_800C9868, &D_800C9748); + + D_800C97D8 = 0; + D_800C972C = 0; + D_800D2448 = 0; + D_800C9720->gt3.base = D_800C9720->gt3.cur; + + SP_SAVE_SCRATCH(getScratchAddr(255)); + if (D_800D23D8[0] != 12) { + renderWorldMapFrame(); + } + SP_RESTORE(); + + D_800C4D50 = SquareRoot0(D_800C9E38.vx * D_800C9E38.vx + + D_800C9E38.vy * D_800C9E38.vy + + D_800C9E38.vz * D_800C9E38.vz); + D_800C4D4C = SquareRoot0(D_800CA038.vx * D_800CA038.vx + + D_800CA038.vy * D_800CA038.vy + + D_800CA038.vz * D_800CA038.vz); + + func_800B18B8(D_800D23D8, &D_800C9868, D_800C9770); + func_800B893C(); + func_800BEC60(D_800D23D8); + func_800B9D38(); + func_800BB150(D_800D226C); + + if (D_800C4D84 != 0) { + func_8009AEE4(D_800C4D88); + } else { + D_800C4D80 = func_800A47A4(); + if (D_800C4D80 == 0 && D_800C4D88 >= 0) { + D_800C4D84 = 1; + } + } + + if (D_800C4FC4 <= 0) { + reqKind = func_800B85DC(&sceneCmd); + if (reqKind == 1) { + func_8009C294(sceneCmd); + break; + } + if (reqKind == 3) { + func_8009D44C(sceneCmd); + break; + } + } + + if (D_800C4FC4 <= 0) { + if (D_800D23D8[0] == 0) { + if (func_800BC46C(&hitCmd)) { + func_8009C294(hitCmd); + break; + } + if (func_800997E8(&objMarker) || func_800B99A4(&objMarker)) { + func_8009D44C(objMarker); + break; + } + } + } + + if (D_800C4FC4 <= 0) { + func_800BE9F8(func_800B1BCC(D_800D23D8)); + func_800B56A0(); + + padBank = D_800C4D04; + if ((D_800D2278[padBank] & (D_800D2278[padBank] ^ D_800D2278[(padBank + 1) % 2]) & WORLD_PAD_HANDOFF) != 0) { + if (((u32)D_800C4D38 < 0xA || D_800C4D38 == 0x80) && + D_800C4D88 == -1 && D_800D23D8[0] == 0) { + func_8009D3F4(); + func_8009D954(); + break; + } + + padBank = D_800C4D04; + if ((D_800D2278[padBank] & (D_800D2278[padBank] ^ D_800D2278[(padBank + 1) % 2]) & WORLD_PAD_HANDOFF) != 0) { + mode = D_800C4D38; + if ((mode == 0x30 || mode == 0x32) && + D_800C4D88 == -1 && D_800D23D8[0] == 0) { + func_8009C294(mode == 0x32 ? 0x2C : 0x41); + func_8009D954(); + break; + } + } + } + + if (D_800C9ED0 == 0x90F) { + stall++; + } else { + stall = 0; + } + if (stall >= 2) { + func_8009D630(); + result = 1; + func_8009D954(); + break; + } + + padBank = D_800C4D04; + if ((D_800D2278[padBank] & (D_800D2278[padBank] ^ D_800D2278[(padBank + 1) % 2]) & WORLD_PAD_REDRAW) != 0 && + D_800C4D84 == 0 && D_800C4D88 == -1) { + setupWorldRender(); + } + } + + cmd = D_800C4D38; + if ((u32)cmd < 0xA || cmd == 0x80 || (u32)(cmd - 0x20) < 9 || + cmd == 0x84 || cmd == 0x31) { + func_800C4AE4(D_800C4D50 / 8); + } + + func_800A63F0(); + func_800A7590(D_800D244C); + func_800A735C(D_800D244C); + func_800A6A74(D_800D244C); + + if (D_800C4D28 == MAP_DISPLAY_GLOBE) { + SP_SAVE_SCRATCH(getScratchAddr(255)); + func_800AB540(MAP_DISPLAY_GLOBE_X, MAP_DISPLAY_GLOBE_Y, (u32)(D_800D23D8[0] - 1) >= 4); + func_800A9F54(&D_800C9868, MAP_DISPLAY_GLOBE_X, MAP_DISPLAY_GLOBE_Y); + SP_RESTORE(); + } else if (D_800C4D28 == MAP_DISPLAY_TRANSPARENT) { + transparentTile = func_800A5DC8(D_800C9868.vx, D_800C9868.vy); + mapX = D_800C97EA - MAP_DISPLAY_TRANSPARENT_DX; + mapY = D_800C97E8 - MAP_DISPLAY_TRANSPARENT_DY; + func_800AB540(transparentTile % MAP_DISPLAY_COLS + mapX, transparentTile / MAP_DISPLAY_COLS + mapY, (u32)(D_800D23D8[0] - 1) >= 4); + func_8009C8E0(mapX, mapY, 1, 1); + } else if (D_800C4D28 == MAP_DISPLAY_FULL) { + fullMapTile = func_800A5DC8(D_800C9868.vx, D_800C9868.vy); + mapX = (D_800C97EA - MAP_DISPLAY_FULL_W) >> 1; + mapY = (D_800C97E8 - MAP_DISPLAY_FULL_H) >> 1; + func_800AB540((fullMapTile % MAP_DISPLAY_COLS) * 2 + mapX, (fullMapTile / MAP_DISPLAY_COLS) * 2 + mapY, 1); + func_8009B954(mapX, mapY, 0); + func_8009C8E0(mapX, mapY, 2, 0); + } + + if (D_800D23D8[0] != 0xC) { + func_800A8400(); + } + firstPass = 0; + func_80099F78(); + func_800AD690(); + func_8009B748(); + renderAndUpdateDisplay(D_800D2264); + renderBattleDisplayList(&D_800D244C->primList[BSC_COLORTAG_IDX]); + } + + func_800A9E24(D_800D244C); + func_8009C6CC(30, 0); + func_800C4450(); + flushCdAndWait(); + func_800A6358(); + deactivateBattleCmd(-1); + func_80027448(); + func_80048C50(0); + func_800488D4(3); + func_8009AD3C(); + return result; +} diff --git a/src/world/we_object1.c b/src/world/we_object1.c index e7dfe12c..e3bb8d2e 100644 --- a/src/world/we_object1.c +++ b/src/world/we_object1.c @@ -670,8 +670,8 @@ void func_8009C070(void) { func_8003FD84(&D_800C9838, &localA, &localB); } D_800D23C0.z = 0; - D_800D23C0.x = D_800C9868.x + localB.vx; - D_800D23C0.y = D_800C9868.y + localB.vz; + D_800D23C0.x = D_800C9868.vx + localB.vx; + D_800D23C0.y = D_800C9868.vy + localB.vz; SetRotMatrix(&D_800C9838); SetTransMatrix(&D_800C9838); } diff --git a/src/world/we_object3.c b/src/world/we_object3.c index 6f2ff801..ed0cf4ed 100644 --- a/src/world/we_object3.c +++ b/src/world/we_object3.c @@ -193,38 +193,6 @@ extern WorldZone D_800C59BC[]; The packets are tagged once at start-up, so allocating one is a pointer bump and the renderers need only fill in vertices. One struct per kind, because the packet type is what gives each pool its stride. */ -typedef struct { - POLY_GT3 *cur; /* 0x00 */ - POLY_GT3 *base; /* 0x04 */ - POLY_GT3 *end; /* 0x08 */ -} Gt3Pool; /* 0x0C */ - -typedef struct { - POLY_FT3 *cur; /* 0x00 */ - POLY_FT3 *base; /* 0x04 */ - POLY_FT3 *end; /* 0x08 */ -} Ft3Pool; /* 0x0C */ - -typedef struct { - POLY_FT4 *cur; /* 0x00 */ - POLY_FT4 *base; /* 0x04 */ - POLY_FT4 *end; /* 0x08 */ -} Ft4Pool; /* 0x0C */ - -/** The three pools of one bank, one per primitive kind. Both banks are laid out - at start-up and @c D_800C9720 is pointed at the table; picking a bank out of - it is left to the glyph renderers, which are still asm, so what drives that - choice is not yet known. (Not @c D_800C53A4 — that one indexes the sprite - record banks @c D_800D2508.) */ -typedef struct { - Gt3Pool gt3; /* 0x00 */ - Ft3Pool ft3; /* 0x0C */ - Ft4Pool ft4; /* 0x18 */ -} WorldPrimBank; /* 0x24 */ - -extern WorldPrimBank D_800C9E88[2]; /**< The two banks. No other code in the - tree names this array; everything - reaches it through @c D_800C9720. */ /** Work RAM the pools are carved from: one contiguous run per primitive kind, each split between the two banks — @c BASE starts bank 0, @c MID is bank 0's @@ -272,7 +240,6 @@ typedef struct { WorldSpriteRec rec[WORLD_BANK_RECORDS]; } WorldSpriteBank; /* 0x6E0 */ -extern SVECTOR D_800CA038; /**< Reference offset fed to the pool placer. */ /** Six probe-corner offsets, used as two batches of three by @c func_800A1678. It stays an extern rather than a file-scope @c const because the struct copy tests the source alignment at run time, which only happens when the compiler @@ -288,19 +255,12 @@ extern GlyphHeader *D_800C9740; /**< Glyph used when worldObjectById finds extern s32 D_800C53A4; /**< Active pool bank (0 or 1). */ extern s32 D_800C53A8; /**< Cleared when a record is placed, bumped by the fallback; the pass loop stops below 4. */ -extern WorldPrimBank *D_800C9720; /**< Primitive banks the glyph renderers - allocate from. @c func_800A246C is the - only writer in the tree and points it at - the table once; the readers (we_object6, - we_object7) are still asm. */ -extern s32 D_800C972C; /**< Accumulated glyph-entry count. */ extern s32 D_800C96D8[WORLD_PAD_AXES]; /**< Analog axes sampled this frame; element 0 is pad 0's X, compared against 0x7F +- 0x2D/0x2E to pick a bank. */ extern s32 D_800D2240[WORLD_PAD_AXES]; /**< Previous frame's copy of @c D_800C96D8, tested the same way. */ extern s32 D_800C9724; /**< Frames elapsed this tick; drives the repeat timers. */ -extern s32 D_800C9ED0; /**< Pad 0's raw frame parameter. */ extern s32 D_800C9ED4; /**< Pad 1's raw frame parameter, packed into the high half. */ extern s32 D_800D2470; /**< Repeat delay accumulator. */ extern s32 D_800D2474; /**< Repeat step counter. */ @@ -356,7 +316,6 @@ static void func_800A568C(void); /* func_800A5B48 is the only reference in the tree: when non-zero it skips the func_800A50A0 scan, admits a single node and zeroes the out-word. What sets it, and what it means, is unknown. */ -extern s32 D_800D2238; extern s32 func_800B21EC(WorldSpriteRec *rec, s32 mode, s32 c, s32 d); /* Both below are declared in we_object10.h, which this unit cannot include: * its func_800B0010 prototype is (void) to serve a no-argument caller there, @@ -598,7 +557,7 @@ void renderWorldMapFrame(void) { newHead = emptyHead; newTail = emptyTail; func_800A1F10(&D_800C9868, &D_800C9838); - xo = D_800C9868.x + 0x60000; + xo = D_800C9868.vx + 0x60000; { s32 rnd = xo; if (xo < 0) { @@ -607,7 +566,7 @@ void renderWorldMapFrame(void) { rnd = (rnd >> 18) << 18; xm = xo - rnd; } - coord = (xm / 0x800) + ((((D_800C9868.y + 0x48000) % 0x30000) / 0x800) << 7); + coord = (xm / 0x800) + ((((D_800C9868.vy + 0x48000) % 0x30000) / 0x800) << 7); ref = &D_800CA038; modeBias = mode - 0x20; for (bank = 0; bank < 2; bank++) { @@ -818,7 +777,7 @@ void renderWorldMapFrame(void) { if (((v >= 0) && (((u32) (D_800D23D8[0] - 1)) >= 2)) && (D_800D23D8[0] != 0xD)) { D_800C4D7C = v; - D_800C9770[0].vy = D_800C9868.z; + D_800C9770[0].vy = D_800C9868.vz; if (D_800C4D38 == 0x32) { D_800C4D40 = 0; } @@ -829,7 +788,7 @@ void renderWorldMapFrame(void) { if ((mode == 0x30) && (D_800D23D8[0] != 8)) { /* The (u16)/(s16) casts below pick the load width and signedness the heading comparison needs; each one changes the emitted code. */ - s16 cur = D_800C9868.z; + s16 cur = D_800C9868.vz; s32 want = (u16) rec->sprite[0].angle; s32 back = ((u16) rec->sprite[0].angle) - 0x80; u16 lo = rec->sprite[0].angle - 0x100; @@ -870,14 +829,14 @@ void renderWorldMapFrame(void) { if (D_800C4DC8 == 0) { cmdp = rec->sprite[0].cmd; if ((D_800D23D8[0] == 0) || (D_800D23D8[0] == 0xD)) { - t = (D_800C9868.z = h); + t = (D_800C9868.vz = h); D_800C9770[0].vy = t; D_800C9770[0].vx += - ((u16) rec->sprite[0].pos.vx) - ((u16) D_800C9868.x); - vyu = (u16) D_800C9868.y; + ((u16) rec->sprite[0].pos.vx) - ((u16) D_800C9868.vx); + vyu = (u16) D_800C9868.vy; D_800C9770[0].vz += vyu + rec->sprite[0].pos.vz; - D_800C9868.x = rec->sprite[0].pos.vx; - D_800C9868.y = -rec->sprite[0].pos.vz; + D_800C9868.vx = rec->sprite[0].pos.vx; + D_800C9868.vy = -rec->sprite[0].pos.vz; } D_800C4D74 = D_800C4D64; if (D_800C4D64 != NULL) { @@ -1498,7 +1457,7 @@ static WorldSpriteRec *func_800A26E8(GlyphHeader *p, WorldSpriteRec *rec, s32 v) continue; } if (sp->cellId == key) { - angle = D_800C9868.z; + angle = D_800C9868.vz; sp->angle = angle; if (D_800C4D64->type < 6) { sp->angle = angle - 0x140; @@ -1651,7 +1610,7 @@ static s32 func_800A2920(GlyphHeader *glyph, WorldSprite *st, s16 key, CmdDesc * continue; } if (mode == 0x32 - || (mode == 0x30 && ((g->type >= 0x1E && g->type < 0x23) || D_800C9868.z <= 0)) + || (mode == 0x30 && ((g->type >= 0x1E && g->type < 0x23) || D_800C9868.vz <= 0)) || g->type < 6 || D_800C4D64->type < 6 || (mode != 0x30 && mode != 0x32 @@ -1836,9 +1795,9 @@ s32 func_800A2D50(s32 code, s32 angZ, SVECTOR *angles, VECTOR *hitPos, s32 arg4, index compared below, and holding it in a callee-saved register is what lets the flag store share the constant. */ two = 2; - e->pos.vx = D_800C9868.x + xf.vx; - e->pos.vy = D_800C9868.z + xf.vy; - camY = D_800C9868.y; + e->pos.vx = D_800C9868.vx + xf.vx; + e->pos.vy = D_800C9868.vz + xf.vy; + camY = D_800C9868.vy; e->pos.vz = xf.vz - camY; if (j != 0) { if (j == 1) { @@ -2601,9 +2560,9 @@ void func_800A4420(WorldSpriteRec *rec, SVECTOR *ref, SVECTOR *ang, s32 size) { gte_stlvnl(&xf); for (i = 0; i < WORLD_FAN_SPRITES; i++, e++) { - e->pos.vx = D_800C9868.x + xf.vx; - e->pos.vy = D_800C9868.z + xf.vy; - depth = D_800C9868.y; + e->pos.vx = D_800C9868.vx + xf.vx; + e->pos.vy = D_800C9868.vz + xf.vy; + depth = D_800C9868.vy; e->pos.vz = xf.vz - depth; if (i != 0) { if (i == 1) { diff --git a/src/world/we_object4.c b/src/world/we_object4.c index 12e24528..7191a068 100644 --- a/src/world/we_object4.c +++ b/src/world/we_object4.c @@ -913,8 +913,8 @@ static void func_800A8024(void) { s16 w; s32 h; - x = D_800C9868.x; - y = D_800C9868.y; + x = D_800C9868.vx; + y = D_800C9868.vy; // Matching hack, but it's fine since it's all dead code, i.e. function is never called uninitReg(dx); @@ -922,8 +922,8 @@ static void func_800A8024(void) { func_800A5E40(x, y); ofs.vz = 0; - ofs.vx = MARKER_WORLD_X - D_800C9868.x; - ofs.vy = MARKER_WORLD_Y - D_800C9868.y; + ofs.vx = MARKER_WORLD_X - D_800C9868.vx; + ofs.vy = MARKER_WORLD_Y - D_800C9868.vy; falloff = MARKER_RANGE_SQ - (dx * dx + dy * dy); if (falloff == 0) { return; @@ -1408,8 +1408,8 @@ void func_800A8C1C(void) { SVECTOR *np; VECTOR *wp; - camX = D_800C9868.x; - camY = D_800C9868.y; + camX = D_800C9868.vx; + camY = D_800C9868.vy; /* The block is s32 offsets up front and WorldZone records behind them, so * reaching a record means stepping the base by a byte count and retyping. */ def = (WorldZone *)((u8 *)D_800C9EE8 + D_800C9EE8[0]); @@ -1602,7 +1602,7 @@ void func_800A9300(void) { tile = &D_800DA8D0[bank][0]; headingA = func_800A5DC8(D_800D23C0.x, D_800D23C0.y); - headingB = func_800A5DC8(D_800C9868.x, D_800C9868.y); + headingB = func_800A5DC8(D_800C9868.vx, D_800C9868.vy); gte_sttr(&savedTrans); gte_ReadRotMatrix(&savedMat); @@ -1911,7 +1911,7 @@ void func_800A9ED4(void) { * @param x Screen x of the mesh's top-left corner. * @param y Screen y of the mesh's top-left corner. */ -void func_800A9F54(WorldPos *pos, s32 x, s32 y) { +void func_800A9F54(VECTOR *pos, s32 x, s32 y) { WorldTessVert verts[4]; BattleSceneCtx *ctx; WorldPolyGT4 *gt4; @@ -1919,8 +1919,8 @@ void func_800A9F54(WorldPos *pos, s32 x, s32 y) { s32 mapX, mapY; s32 i, c; - mapX = (pos->x + MAP_ORIGIN_X) / MAP_CELL_SIZE; - mapY = (pos->y + MAP_ORIGIN_Y) / MAP_CELL_SIZE; + mapX = (pos->vx + MAP_ORIGIN_X) / MAP_CELL_SIZE; + mapY = (pos->vy + MAP_ORIGIN_Y) / MAP_CELL_SIZE; D_800D8808 = x + MESH_CENTRE_BIAS; D_800D880C = y + MESH_CENTRE_BIAS; diff --git a/src/world/we_object5.c b/src/world/we_object5.c index a42c63ac..d56295b0 100644 --- a/src/world/we_object5.c +++ b/src/world/we_object5.c @@ -594,28 +594,28 @@ void func_800AC468(void *unused_a0, WorldViewXform *oa, WorldViewXform *mh, s32 func_800BC51C(&D_800DD658, &D_800C9858); } else { /* Critically damp delta-X to [-0x20000, 0x20000] with ±0x40000 wraparound. */ - delta = D_800C9858.vx - D_800C9868.x; + delta = D_800C9858.vx - D_800C9868.vx; if (delta > 0x20000) D_800C9858.vx -= 0x40000; if (delta < -0x20000) D_800C9858.vx += 0x40000; /* Critically damp delta-Y to [-0x18000, 0x18000] with ±0x30000 wraparound. */ - delta = D_800C9858.vy - D_800C9868.y; + delta = D_800C9858.vy - D_800C9868.vy; if (delta > 0x18000) D_800C9858.vy -= 0x30000; if (delta < -0x18000) D_800C9858.vy += 0x30000; /* Blend XY 1:1 with the target. */ - D_800C9858.vx = ((D_800C9858.vx + D_800C9868.x) << 1) >> 2; - D_800C9858.vy = ((D_800C9858.vy + D_800C9868.y) << 1) >> 2; + D_800C9858.vx = ((D_800C9858.vx + D_800C9868.vx) << 1) >> 2; + D_800C9858.vy = ((D_800C9858.vy + D_800C9868.vy) << 1) >> 2; /* Blend Z 3:1 with a -0x100 bias (gated by D_800C5924 being 0). */ if (D_800C5924 == 0) { s32 z3 = D_800C9858.vz * 3; z3 -= 0x100; - z3 += D_800C9868.z; + z3 += D_800C9868.vz; D_800C9858.vz = z3 >> 2; } - viewAngle = func_800A5DC8(D_800C9868.x, D_800C9868.y); + viewAngle = func_800A5DC8(D_800C9868.vx, D_800C9868.vy); { VECTOR *vp = &viewPos; func_800BC544(&D_800C9858, vp); @@ -804,7 +804,7 @@ void func_800ACA70(VECTOR *out, Input32 *input) { func_800423DC(&local.a, &local.b_x, &result); - angle = func_800A5DC8(D_800C9868.x, D_800C9868.y); + angle = func_800A5DC8(D_800C9868.vx, D_800C9868.vy); func_800ACB70(angle, &vec); if (out != 0) { @@ -861,7 +861,7 @@ void func_800ACBD0(VECTOR *out, SVECTOR *in) { VECTOR vec; s16 angle; - angle = func_800A5DC8(D_800C9868.x, D_800C9868.y); + angle = func_800A5DC8(D_800C9868.vx, D_800C9868.vy); func_800ACB70(angle, &vec); if (out != 0) { diff --git a/src/world/we_object7.c b/src/world/we_object7.c index 491febde..12a8e9ff 100644 --- a/src/world/we_object7.c +++ b/src/world/we_object7.c @@ -38,7 +38,7 @@ void func_800B3868(TrackObj *obj) { s32 i; viewX = func_800A5DC8(D_800D23C0.x, D_800D23C0.y); - viewY = func_800A5DC8(D_800C9868.x, D_800C9868.y); + viewY = func_800A5DC8(D_800C9868.vx, D_800C9868.vy); SetRotMatrix(&D_800C9838); SetTransMatrix(&D_800C9838); diff --git a/src/world/we_object9.c b/src/world/we_object9.c index 75c7e243..4478c76d 100644 --- a/src/world/we_object9.c +++ b/src/world/we_object9.c @@ -1062,9 +1062,9 @@ s32 func_800BD09C(SlotEntry *slot, s32 arg1, CmdDesc *cmd, s32 worldAngle) { * * No-op when the @c D_800C4DC8 flag is zero. Otherwise copies: * - @c D_800DD698 → @c D_800C4D38 (primary cmd byte) - * - @c D_800DD680.vx → @c D_800C9868.x - * - @c D_800DD680.vy → @c D_800C9868.z (Y/Z swap for PS1 coord system) - * - -@c D_800DD680.vz → @c D_800C9868.y (Z negated) + * - @c D_800DD680.vx → @c D_800C9868.vx + * - @c D_800DD680.vy → @c D_800C9868.vz (Y/Z swap for PS1 coord system) + * - -@c D_800DD680.vz → @c D_800C9868.vy (Z negated) * - @c D_800DD690[0..8] → @c D_800C9770[1] (the rotation slot) * - @c D_800DD69C → @c D_800C4D3C (secondary cmd byte) * and calls @c worldPosToCell with the source vector and @c D_800C9770 buffer. @@ -1072,9 +1072,9 @@ s32 func_800BD09C(SlotEntry *slot, s32 arg1, CmdDesc *cmd, s32 worldAngle) { void func_800BD180(void) { if (D_800C4DC8 != 0) { D_800C4D38 = D_800DD698; - D_800C9868.x = D_800DD680.vx; - D_800C9868.z = D_800DD680.vy; - D_800C9868.y = -D_800DD680.vz; + D_800C9868.vx = D_800DD680.vx; + D_800C9868.vz = D_800DD680.vy; + D_800C9868.vy = -D_800DD680.vz; worldPosToCell(&D_800DD680, D_800C9770); memcpy(&D_800C9770[1], D_800DD690, 8); D_800C4D3C = D_800DD69C; From e148ee10caef1b87febcc3eb1187176f9c1d4c1c Mon Sep 17 00:00:00 2001 From: rengstrom Date: Tue, 1 Sep 2026 20:26:00 +0000 Subject: [PATCH 2/4] world: give every declaration a single owner Seven functions were declared in more than one place with signatures that disagreed, so each unit compiled happily against its own reading. Six are now declared once, by the unit that defines them, and the callers include that header: func_800AC0A0 -> we_object5.h, the definition's own signature. Its two callers had invented PosDesc and Velocity for the arguments; both are VECTOR and SVECTOR field for field, so they are gone. func_800ACC68 -> we_object6.h. The asm dereferences arg 1 at +0x14, which is MATRIX.t[0], and we_object6's own call site was casting an SVECTOR[] to u8 * to satisfy its version. func_800ACD38 needed no declaration at all: with none in scope the call is C89 implicit int, which is the view that matches and evidently what the original had. A commented-out include marks it. func_800B0010's caller looked like it passed nothing -- but the jal's delay-slot nop proves a0 was live going in, so func_800BD6EC takes the kind and forwards it. func_800A7E74 does take the scene context, it just ignores it. A (void) definition and one with an unused parameter compile identically, so the (void) reading was never evidence. func_800B01A0's every argument comes from the asm: two s16, a VECTOR * handed to worldPosToCell, an SVECTOR * written at +0/+2/+4, and two NULL-checked output pointers. Twelve more were declared identically in two or three headers, three of them battle or main-binary symbols that world headers had no business re-declaring. Removing such a declaration is not obviously safe here: gcc 2.8 accepts the call anyway as implicit int, silently and often without changing a byte. Eleven such calls appeared while doing this and each is now covered by a real include, checked by diffing -Wimplicit output against the same tree at HEAD. we_object3's seven externs for functions other units own are gone too; WorldSprite and WorldSpriteRec move to we_object3.h since we_object6's func_800B21EC takes one. --- include/world.h | 12 ++---- include/world/we_object0.h | 8 +--- include/world/we_object1.h | 8 +++- include/world/we_object10.h | 8 +++- include/world/we_object11.h | 11 ++++++ include/world/we_object13.h | 2 + include/world/we_object2.h | 4 +- include/world/we_object3.h | 8 ++-- include/world/we_object4.h | 8 ++-- include/world/we_object5.h | 6 ++- include/world/we_object6.h | 26 ++++++++++++- include/world/we_object7.h | 26 +++++++------ include/world/we_object8.h | 13 +++++++ include/world/we_object9.h | 29 +++++---------- src/world/we_object0.c | 73 +++++-------------------------------- src/world/we_object1.c | 5 ++- src/world/we_object10.c | 17 ++++++--- src/world/we_object2.c | 40 ++++++++++---------- src/world/we_object3.c | 18 ++------- src/world/we_object4.c | 18 +++++---- src/world/we_object5.c | 3 ++ src/world/we_object6.c | 16 ++++---- src/world/we_object7.c | 11 +++--- src/world/we_object9.c | 61 ++++++++++++++++--------------- 24 files changed, 214 insertions(+), 217 deletions(-) create mode 100644 include/world/we_object11.h create mode 100644 include/world/we_object8.h diff --git a/include/world.h b/include/world.h index d4f68525..77dc4758 100644 --- a/include/world.h +++ b/include/world.h @@ -205,14 +205,8 @@ extern s32 D_800DCB48; * @brief 8-byte world-transform block — four packed halfwords. * * Every field is read/written as @c lh / @c sh at a fixed offset. Only - * @c angle has an identified role (input to rotation helper @c getAngleDelta). */ -typedef struct { - /* 0x00 */ s16 unk0; - /* 0x02 */ s16 angle; - /* 0x04 */ s16 unk4; - /* 0x06 */ s16 unk6; -} WorldXformBlock; /* 0x08 */ + /** * @brief 16-byte world-transform record at @c D_800D2390 (pair of blocks). @@ -221,8 +215,8 @@ typedef struct { * snapshots @c tail, adjusts its @c angle, and forwards the modified copy. */ typedef struct { - /* 0x00 */ WorldXformBlock head; - /* 0x08 */ WorldXformBlock tail; + /* 0x00 */ SVECTOR head; + /* 0x08 */ SVECTOR tail; } WorldXform; /* 0x10 */ /* Shared world-overlay state referenced by more than one we_object*.c. diff --git a/include/world/we_object0.h b/include/world/we_object0.h index 79b9dd9a..dc87e00f 100644 --- a/include/world/we_object0.h +++ b/include/world/we_object0.h @@ -4,11 +4,7 @@ #include "common.h" #include "overlay.h" /* func_800987D8 -- the entry point this unit defines */ -/* we_object0 has exactly one public symbol, the overlay entry point, and that - * is declared with the other overlay entry points in overlay.h rather than - * here. Everything else the unit touches is private to - * src/world/we_object0.c. This header exists so the unit has an owner for any - * public surface it grows, and so its users get the entry point by including - * it. */ +/* The overlay entry point is declared with the others in overlay.h; this + * header re-exports it and owns any public surface the unit grows. */ #endif /* WORLD_WE_OBJECT0_H */ diff --git a/include/world/we_object1.h b/include/world/we_object1.h index 31d278fd..20494086 100644 --- a/include/world/we_object1.h +++ b/include/world/we_object1.h @@ -125,14 +125,12 @@ extern void func_80039678(s32 a, s32 b, s32 c); extern void func_8009CDC4(s32 a, s32 b); extern void func_8009CE40(void); extern s32 func_8009D7D8(s32 a); -extern s32 func_800ACD38(MATRIX *out); extern void func_8003FD84(MATRIX *xform, VECTOR *in, VECTOR *out); extern void func_800BC544(VECTOR *src, VECTOR *dst); extern void func_8009C478(s32 *src, s32 x, s32 y); extern CmdDesc *glyphAt(GlyphQuery *v, AngleSlot *out); extern s32 func_800BEC1C(s32 kind); extern void func_8009D630(void); -extern void func_800B3FD4(Slot *slot, s32 arg); extern void fadeOutSfxFast(s32 idx); extern void renderAndUpdateDisplay(s32 frames); extern s32 renderBattleDisplayList(s32 *colorTag); @@ -144,4 +142,10 @@ extern void sndSeqStartPan(s32 a0, s32 a1, s32 a2, s32 a3); extern void sndSeqPlayPan7bit(s32 a0, s32 a1, s32 a2, s32 a3); extern void func_8004D604(POLY_FT4 *prim, s32 frame); +extern s32 func_800997E8(u16 *out); +extern void func_80099F78(void); +extern void func_8009A954(void); +extern void func_8009AEE4(s32 id); +extern void func_8009B954(s32 a, s32 b, s32 c); + #endif /* WORLD_WE_OBJECT1_H */ diff --git a/include/world/we_object10.h b/include/world/we_object10.h index 0ebe18ef..0bdbe855 100644 --- a/include/world/we_object10.h +++ b/include/world/we_object10.h @@ -3,6 +3,7 @@ #include "common.h" #include "world.h" +#include "world/we_object3.h" /* CmdDesc, GlyphHeader, WorldPrimBank */ #include "psxsdk/libgte.h" /** @brief 32-byte record used by func_800BE5F8's table walker. */ @@ -57,8 +58,6 @@ extern u8 *D_800C9E34; extern void func_800BAC84(u8 *p); extern s32 func_800BA870(u8 *p); -extern s32 func_800B0010(void); -extern void func_800AC0A0(s32 marker, VECTOR *position, SVECTOR *vec, s32 zero); extern void *func_80047CE4(void *dst, s32 c, u32 n); extern s32 func_800BEF6C(void); extern s32 func_8009CC3C(void); @@ -73,4 +72,9 @@ extern void fadeOutSfxFast(s32 idx); extern void renderAndUpdateDisplay(s32 frameCount); extern s32 renderBattleDisplayList(s32 *colorTag); +extern void func_800BEC60(u8 *flags); + +extern void func_800BF20C(CmdDesc *p, s32 kind, s32 arg); +extern void func_800BF2E8(GlyphHeader *p, s32 *ot, WorldPrimBank *pools); + #endif /* WORLD_WE_OBJECT10_H */ diff --git a/include/world/we_object11.h b/include/world/we_object11.h new file mode 100644 index 00000000..96df8e07 --- /dev/null +++ b/include/world/we_object11.h @@ -0,0 +1,11 @@ +#ifndef WORLD_WE_OBJECT11_H +#define WORLD_WE_OBJECT11_H + +#include "common.h" +#include "world.h" +#include "world/we_object3.h" /* GlyphHeader, WorldPrimBank */ + +extern void func_800BF80C(GlyphHeader *p, s32 *ot, WorldPrimBank *pools); +extern void func_800BFBFC(s32 kind); + +#endif /* WORLD_WE_OBJECT11_H */ diff --git a/include/world/we_object13.h b/include/world/we_object13.h index 2ee96342..62fc6af6 100644 --- a/include/world/we_object13.h +++ b/include/world/we_object13.h @@ -44,4 +44,6 @@ extern s32 func_800C4480(s32 src, s32 len, u32 *buf); /* Reset the streaming controller; returns its status word. */ extern s32 func_800C4450(void); +extern void func_800C4AE4(s32 a); + #endif /* WORLD_WE_OBJECT13_H */ diff --git a/include/world/we_object2.h b/include/world/we_object2.h index 568ccd6d..694641f1 100644 --- a/include/world/we_object2.h +++ b/include/world/we_object2.h @@ -52,7 +52,6 @@ extern s32 D_800D2448; /* world-ready gate flag (func_8009F6E extern void func_800A5F78(s32 screen); extern void func_800A5FD4(s32 screen); extern void func_80099EDC(s32 idx); -extern void func_800B3FD4(Slot *a0, s32 a1); extern void func_8009D630(void); extern void renderAndUpdateDisplay(s32 mode); extern s32 renderBattleDisplayList(s32 *colorTag); @@ -75,4 +74,7 @@ extern void sndDisableReverb(u32 a); /* Defined in we_object2.c — shortest signed angular difference (0x1000 == 360°). */ extern s32 getAngleDelta(s32 a, s32 b); +extern void func_8009DB88(u8 *p); +extern void func_8009E5C8(VECTOR *pos, u8 *p, SVECTOR *ang, void *x); + #endif /* WORLD_WE_OBJECT2_H */ diff --git a/include/world/we_object3.h b/include/world/we_object3.h index debb8b9c..aa514aa0 100644 --- a/include/world/we_object3.h +++ b/include/world/we_object3.h @@ -102,9 +102,7 @@ extern s32 func_800A358C(s32 kind, SlotEntry *slot, SVECTOR *angles, s32 flag); code @p b (only b's low 16 bits are examined; D_800C4D20 == 0 force-passes). */ extern s32 func_800A45D8(u32 a, s32 b); -/* The seven entry points below are called from the world entry loop - * func_800987D8 (we_object0), which is still assembly: it reaches them - * through the linker rather than this header. */ +/* Entry points the world loop in we_object0 calls. */ /* Per-frame world setup: advance the frame clock, run the renderers and flip the scene context. */ @@ -171,8 +169,8 @@ extern WorldPrimBank D_800C9E88[2]; /**< The two banks. @c func_800A246C lays extern WorldPrimBank *D_800C9720; /**< The bank the glyph renderers allocate from this frame. The world entry loop (@c func_800987D8) re-points it every - frame; the readers (we_object6, - we_object7) are still asm. */ + frame; we_object6 and we_object7 + read it. */ /* Also read by the world entry loop in we_object0. */ extern s32 D_800C972C; /**< Accumulated glyph-entry count. */ diff --git a/include/world/we_object4.h b/include/world/we_object4.h index 3f630c6b..4941bacf 100644 --- a/include/world/we_object4.h +++ b/include/world/we_object4.h @@ -6,9 +6,7 @@ #include "world.h" /* we_object4's public surface. Everything else the unit owns is private to - * src/world/we_object4.c and declared at the top of that file. The callers - * below are still assembly, so they reach these through the linker rather - * than this header -- it is here for when they are decompiled. */ + * src/world/we_object4.c. */ extern s32 D_800D2264; /**< Counter increment per update (read by we_object3, we_object6). */ @@ -46,4 +44,8 @@ extern void func_800AB2D4(VECTOR *pos); extern TILE_1 D_800D4FB0[2][96]; /**< Night-sky star pool, also primed by we_object5 (func_800A84D0). */ +/* Steps the texture-strip animations. @p ctx is passed by its only caller but + the body works entirely off globals and never reads it. */ +extern void func_800A7E74(BattleSceneCtx *ctx); + #endif /* WORLD_WE_OBJECT4_H */ diff --git a/include/world/we_object5.h b/include/world/we_object5.h index 3a2ef52e..9a358710 100644 --- a/include/world/we_object5.h +++ b/include/world/we_object5.h @@ -69,8 +69,6 @@ extern void func_800423DC(VECTOR *a, s32 *b_pos, VECTOR *out); * the four packed screen points and @c outOTZ their average depth. */ extern void func_800ABEF0(SVECTOR *src, SVECTOR *rot, SVECTOR *trans, DVECTOR *outSXY, u32 *outOTZ); -extern void func_800ACC68(MATRIX *out_mat, SVECTOR *angles, - SVECTOR *rotBuf, SVECTOR *offset); extern void func_800B5C60(s32 ctx, s16 count, MATRIX *outMat, SVECTOR *outAngles, SVECTOR *rotBuf, u8 *xform, ActorRecord *recs); extern void func_800BC51C(VECTOR *src, VECTOR *dst); @@ -80,4 +78,8 @@ extern void func_800BC544(VECTOR *src, VECTOR *dst); per-pixel blend and the STP-bit packing). */ extern void func_800ABDD8(CVECTOR *input, u16 *output, s32 z, s16 count); +extern s32 func_800AC0A0(s32 type, VECTOR *pos, SVECTOR *vec, u16 flags); + +extern void func_800AC2B8(void); + #endif /* WORLD_WE_OBJECT5_H */ diff --git a/include/world/we_object6.h b/include/world/we_object6.h index ef01922a..fc2b2b78 100644 --- a/include/world/we_object6.h +++ b/include/world/we_object6.h @@ -2,9 +2,33 @@ #define WORLD_WE_OBJECT6_H #include "world.h" +#include "world/we_object3.h" /* GlyphHeader, WorldPrimBank */ #include "world/we_object2.h" /* getAngleDelta */ /* Defined in this file (via INCLUDE_ASM). */ -extern void func_800ACC68(s32 a, WorldXformBlock *buf, u8 *p1, WorldXform *xform); +/* Arg 1 is dereferenced at +0x14, which is MATRIX.t[0]. */ +extern void func_800ACC68(MATRIX *outMat, SVECTOR *angles, SVECTOR *rotBuf, + SVECTOR *offset); + +extern void func_800AD698(SceneState *st, u8 *flags); +extern void func_800AE31C(u8 *flags); +extern s32 func_800AE518(u8 *flags); +extern void func_800AEEB0(u8 *flags, void *a, void *b, void *c); +extern void func_800B04CC(SVECTOR *ang, MATRIX *m, u8 *flags, s32 v); +extern void func_800B164C(SceneState *st, Slot *slot, u8 *flags, VECTOR *pos); +extern void func_800B18B8(u8 *flags, VECTOR *pos, SVECTOR *ang); +extern s32 func_800B1BCC(u8 *p); + +extern s32 func_800B0010(u32 kind); + +extern void func_800ACD38(MATRIX *outMat); + +/* Projects @p pos to screen space in @p screenOut and returns a status of + -1, 0 or 1. @p byteOut and @p halfOut are optional outputs; both are + NULL-checked. */ +extern s32 func_800B01A0(s16 viewY, s16 viewX, VECTOR *pos, SVECTOR *screenOut, + s8 *byteOut, s16 *halfOut); + +extern void func_800ACDC4(GlyphHeader *p, BattleSceneCtx *ctx, WorldPrimBank *pools); #endif /* WORLD_WE_OBJECT6_H */ diff --git a/include/world/we_object7.h b/include/world/we_object7.h index 0b8de17f..1fa92ae4 100644 --- a/include/world/we_object7.h +++ b/include/world/we_object7.h @@ -8,21 +8,18 @@ * @brief 0x34-byte tracking entry — one world-space target with screen-space * projection state and a relative neighbour link. * - * Populated by @c func_800B01A0 (which fills the screen-space @c posX/Y/Z - * fields plus @c unk30 and @c unk2C from the world transform pipeline) and + * Populated by @c func_800B01A0 (which fills @c screen plus @c unk30 and + * @c unk2C from the world transform pipeline) and * consumed by @c func_800B3868 to compute pitch/yaw to a chained target. */ typedef struct { - u8 pad00[0x10]; - u16 posX; /**< 0x10: projected screen-space X. */ - u16 posY; /**< 0x12: projected screen-space Y. */ - u16 posZ; /**< 0x14: projected screen-space Z. */ - u8 pad16[0x02]; + VECTOR pos; /**< 0x00: world position; func_800B01A0 projects it. */ + SVECTOR screen; /**< 0x10: projected screen-space position (x, y, z). */ s16 unk18; /**< 0x18: roll/twist angle — zeroed when target valid. */ s16 yaw; /**< 0x1A: yaw angle to target (atan2 + 0x800 bias). */ s16 pitch; /**< 0x1C: pitch angle to target. */ u8 pad1E[0x0E]; - u8 unk2C[0x02]; /**< 0x2C: scratch byte pair filled by func_800B01A0. */ + s16 unk2C; /**< 0x2C: scratch halfword filled by func_800B01A0. */ s8 targetIdx; /**< 0x2E: relative index of the chained target entry (0 = none). */ s8 status; /**< 0x2F: -1 = uninitialized, 1 = visible/active. */ s8 unk30; /**< 0x30: secondary status byte. */ @@ -41,13 +38,20 @@ typedef struct { extern u8 *D_800C96C8; /* func_8009B358/func_8009B550 are defined in we_object1, func_8009D8A8 in - * we_object2; addItemToInventory and the func_800A5DC8/func_800B01A0/ - * func_80041E84 helpers are main-binary. Caller-local prototypes. */ -extern s8 func_800B01A0(s16 viewY, s16 viewX, TrackEntry *e, u16 *posOut, s8 *unk30Out, u8 *unk2COut); + * we_object2; addItemToInventory, func_800A5DC8 and func_80041E84 are + * main-binary. Caller-local prototypes. */ extern s32 func_80041E84(s32 y, s32 x); extern s32 func_8009B358(s32 slotIdx, s32 strIdx, u8 *text); extern void func_8009B550(s32 a0, s32 a1, s32 a2, s32 a3, s32 a4, s32 a5, s32 a6); extern void func_8009D8A8(s32 a0); extern void addItemToInventory(s32 itemId, s32 count); +extern s32 func_800B4AA0(void); +extern void func_800B56A0(void); +extern void func_800B7240(s8 v); +extern void func_800B881C(void); +extern void func_800B893C(void); + +extern void func_800B3FD4(Slot *slot, s32 mode); + #endif /* WORLD_WE_OBJECT7_H */ diff --git a/include/world/we_object8.h b/include/world/we_object8.h new file mode 100644 index 00000000..3dbccc87 --- /dev/null +++ b/include/world/we_object8.h @@ -0,0 +1,13 @@ +#ifndef WORLD_WE_OBJECT8_H +#define WORLD_WE_OBJECT8_H + +#include "common.h" +#include "world.h" + +extern void func_800B8C70(void); +extern s32 func_800B99A4(u16 *p); /**< Picks a world cell and checks its + terrain glyph; one of the two world + battle triggers. */ +extern void func_800B9D38(void); + +#endif /* WORLD_WE_OBJECT8_H */ diff --git a/include/world/we_object9.h b/include/world/we_object9.h index d6a94f49..6842a562 100644 --- a/include/world/we_object9.h +++ b/include/world/we_object9.h @@ -5,26 +5,13 @@ #include "world.h" #include "psxsdk/libgte.h" +/* Particle source: position + velocity (with 4-byte gap between). Stride 0x28. + func_800AC0A0 takes these two as VECTOR/SVECTOR; the spawner reads .vy of + each as the heading and .vz of the velocity as the height. */ typedef struct { - u32 pad0; - AngleSlot pos; - u32 pad8; - u32 padC; -} PosDesc; - -/* 8-byte unaligned velocity (copied via lwl/lwr to spawner's slot[0x18..0x1F]) */ -typedef struct { - u16 pad0; - u16 angle; - u16 height; - u16 pad6; -} Velocity; - -/* Particle source: position + velocity (with 4-byte gap between). Stride 0x28. */ -typedef struct { - PosDesc pos; - u32 pad10; - Velocity vel; + VECTOR pos; + u32 pad10; + SVECTOR vel; } ParticleSource; typedef struct { @@ -96,7 +83,6 @@ extern s32 D_800C971C; /* Per-scene angle bias applied to a placed sprite fan. */ extern s32 func_800BC5E0(s32 ctx); extern s32 func_8009CC3C(void); -extern s32 func_800AC0A0(s32 type, PosDesc *pos, Velocity *vel, s32 flags); extern void func_800BFFEC(void); extern void func_800C2C00(s32 a, s32 b, s32 c, s32 d, s32 e, U64 *f, s32 g, U64 *h); extern u8 *func_800BC8D8(u8 *buf, s32 magicId); @@ -106,4 +92,7 @@ extern u8 *getStatName(s32 statId); extern u8 *func_800BCE74(u8 *buf, s32 statId); extern s32 func_800B00D8(s32 a); +extern void func_800BB150(Slot *slot); +extern void func_800BB4E8(void); + #endif /* WORLD_WE_OBJECT9_H */ diff --git a/src/world/we_object0.c b/src/world/we_object0.c index 17401c77..4057c1de 100644 --- a/src/world/we_object0.c +++ b/src/world/we_object0.c @@ -1,9 +1,9 @@ #include "common.h" #include "gamestate.h" -#include "btl_color.h" /* deactivateBattleCmd */ -#include "psxsdk/libgpu.h" /* SetDispMask */ -#include "psxsdk/libgte.h" /* InitGeom, SquareRoot0 */ -#include "psxsdk/libetc.h" /* getScratchAddr */ +#include "btl_color.h" +#include "psxsdk/libgpu.h" +#include "psxsdk/libgte.h" +#include "psxsdk/libetc.h" #include "world.h" #include "world/we_object0.h" #include "world/we_object1.h" @@ -11,21 +11,15 @@ #include "world/we_object3.h" #include "world/we_object4.h" #include "world/we_object5.h" +#include "world/we_object6.h" +#include "world/we_object7.h" +#include "world/we_object8.h" #include "world/we_object9.h" +#include "world/we_object10.h" +#include "world/we_object13.h" #include "main.h" #include "thread.h" -/* Park the real stack pointer in the PS1 scratchpad and run the next call with - * its stack there, then put the real stack back. There is no way to express a - * stack switch in C, so this is the original's inline asm -- the same device as - * SCRATCH_STACK_ENTER/LEAVE in src/field/fe_object1.c and the GP_* family in - * include/common.h. As with GP_SAVE_SCRATCH the slot address arrives as an - * operand and the compiler materializes it: here it schedules the lui/ori four - * instructions away from the block, which is how we know the address is - * compiler-generated rather than part of the asm. $t0 is named explicitly (it - * is the same register at both call sites while the address register differs), - * and declaring it clobbered is load-bearing -- without it the allocator picks - * a different temp for the camera-magnitude multiply 900 bytes further down. */ #define SP_SAVE_SCRATCH(slot) \ asm volatile("addu $t0, %0, $zero\n\t" \ "sw $sp, 0($t0)\n\t" \ @@ -114,55 +108,6 @@ extern s32 *D_800D245C; extern Slot D_800785D8; /**< Slot-state record the loop publishes at D_800D226C. */ -/* Still assembly. Each is declared here, tagged with the unit that owns it, - * until that unit is decompiled and can publish it from its own header. */ -extern s32 func_800997E8(u16 *out); /* we_object1 */ -extern void func_80099F78(void); /* we_object1 */ -extern void func_8009A954(void); /* we_object1 */ -extern void func_8009AEE4(s32 id); /* we_object1 */ -extern void func_8009B954(s32 a, s32 b, s32 c); /* we_object1 */ -extern void func_8009DB88(u8 *p); /* we_object2 */ -extern void func_8009E5C8(VECTOR *pos, u8 *p, SVECTOR *ang, void *x); /* we_object2 */ -extern void func_800AD698(SceneState *st, u8 *flags); /* we_object6 */ -extern void func_800AE31C(u8 *flags); /* we_object6 */ -extern s32 func_800AE518(u8 *flags); /* we_object6 */ -extern void func_800AEEB0(u8 *flags, void *a, void *b, void *c); /* we_object6 */ -extern void func_800B04CC(SVECTOR *ang, MATRIX *m, u8 *flags, s32 v); /* we_object6 */ -extern void func_800B164C(SceneState *st, Slot *slot, u8 *flags, - VECTOR *pos); /* we_object6 */ -extern void func_800B18B8(u8 *flags, VECTOR *pos, SVECTOR *ang); /* we_object6 */ -extern s32 func_800B1BCC(u8 *p); /* we_object6 */ -extern s32 func_800B4AA0(void); /* we_object7 */ -extern void func_800B56A0(void); /* we_object7 */ -extern void func_800B7240(s8 v); /* we_object7 */ -extern void func_800B881C(void); /* we_object7 */ -extern void func_800B893C(void); /* we_object7 */ -extern void func_800B8C70(void); /* we_object8 */ -extern s32 func_800B99A4(u16 *p); /* we_object8 */ -extern void func_800B9D38(void); /* we_object8 */ -extern void func_800BB150(Slot *slot); /* we_object9 */ -extern void func_800BB4E8(void); /* we_object9 */ -extern void func_800BEC60(u8 *flags); /* we_object10 */ -extern void func_800C4AE4(s32 a); /* we_object13 */ - -/** - * @brief The world overlay's entry point: set the map up, then run its frame - * loop until something asks the world to hand off. - * - * Called from the main state machine once the overlay is resident. The body is - * one long init followed by @c while(1), and every way out of that loop is a - * @c break that first records where control should go next -- a battle, a - * field map, the world menu, or a clean shutdown. After the loop a single tail - * tears the overlay down regardless of which exit fired. - * - * @c D_80082C8C.mode selects how much of the init runs. Mode 4 is a warm - * re-entry that skips straight to the render setup; mode 0 is a cold start and - * saves the whole scene-state block into the slot record; any other mode is a - * return from elsewhere and restores just the dispatch code from it. - * - * @return 0 normally; 1 when the loop ended because @c D_800C9ED0 held - * @c WORLD_STALL_CODE for @c WORLD_STALL_FRAMES consecutive frames. - */ s32 func_800987D8(void) { s32 trigger; diff --git a/src/world/we_object1.c b/src/world/we_object1.c index e3bb8d2e..790e0dc6 100644 --- a/src/world/we_object1.c +++ b/src/world/we_object1.c @@ -10,6 +10,9 @@ #include "psxsdk/libapi.h" #include "psxsdk/libgpu.h" #include "psxsdk/libc.h" +//#include "world/we_object6.h" // Deliberately not included for matching reasons, original code likely forgot to include this + + INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object1", func_800997E8); @@ -633,8 +636,6 @@ void func_8009BFA0(DVECTOR *coords, s16 count) { } -/* func_800ACD38 is void func_800ACD38(s32) in we_object6; this call site sees an - int-returning function (K&R-era view), which the matching codegen requires. */ /** * @brief Compose the world-map view transform and the resulting camera position. diff --git a/src/world/we_object10.c b/src/world/we_object10.c index ad1b01e4..4726b598 100644 --- a/src/world/we_object10.c +++ b/src/world/we_object10.c @@ -2,9 +2,15 @@ #include "battle.h" #include "gamestate.h" #include "world.h" +#include "world/we_object5.h" +#include "world/we_object6.h" #include "world/we_object10.h" #include "world/we_object3.h" /* worldPosToCell */ + + + + /* Defined below; the reset path above is its only caller. */ static void func_800BEFEC(u8 *base); @@ -13,17 +19,18 @@ static void func_800BEFEC(u8 *base); * @brief Search @c D_800DBFB8 for the slot whose @c marker matches the * value returned by @c func_800B0010. * - * Calls @c func_800B0010 to get a marker byte, then linearly scans the + * Classifies @p kind via @c func_800B0010 to get a marker byte, then scans * first @c D_800C5B50 entries of @c D_800DBFB8 for the first slot whose * @c marker matches. Returns the slot index or @c -1 if not found. * - * Twin of @c func_800BD754 — same scan loop but the search key is - * sourced from @c func_800B0010 instead of an explicit argument. + * Twin of @c func_800BD754 — same scan loop, but the search key comes + * from classifying @p kind through @c func_800B0010. * + * @param kind Scene/map kind to classify. * @return Matching slot index, or @c -1 on no match. */ -s32 func_800BD6EC(void) { - s32 target = func_800B0010(); +s32 func_800BD6EC(u32 kind) { + s32 target = func_800B0010(kind); s32 i = 0; s32 count = D_800C5B50; if (count > 0) { diff --git a/src/world/we_object2.c b/src/world/we_object2.c index 3798edf9..12de1716 100644 --- a/src/world/we_object2.c +++ b/src/world/we_object2.c @@ -754,11 +754,11 @@ INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object2", func_8009F594); * - @c 0x1: projection distance @c D_800C9730 (±8), then @c SetGeomScreen. * - @c 0x2: zoom/scale @c D_800C4D30 (±0x80). * - @c 0x4: set @c D_800C4D40 / @c D_800C4D44 from the map id (immediate, no step). - * - @c 0x8: yaw @c D_800D2390.tail.angle — shortest-arc angle step (±0x20). - * - @c 0x10: pitch @c D_800D2390.tail.unk0 (±0x10); for map 0x32 the target is + * - @c 0x8: yaw @c D_800D2390.tail.vy — shortest-arc angle step (±0x20). + * - @c 0x10: pitch @c D_800D2390.tail.vx (±0x10); for map 0x32 the target is * @c -D_800C97F4 / 24 - 0x100. - * - @c 0x20: per-map scroll triple element [2] → @c D_800D2390.head.unk4 (±0x200). - * - @c 0x80: per-map scroll triple element [1] → @c D_800D2390.head.angle (±0x200). + * - @c 0x20: per-map scroll triple element [2] → @c D_800D2390.head.vz (±0x200). + * - @c 0x80: per-map scroll triple element [1] → @c D_800D2390.head.vy (±0x200). * * @c D_800C4D38 is the map id selecting targets; @c D_800C4D3C is a secondary * selector. Field roles are partly inferred. @@ -854,17 +854,17 @@ void func_8009F6EC(void) { } else { target = D_800D239A; } - cur = D_800D2390.tail.angle; + cur = D_800D2390.tail.vy; raw = target - cur; d = (s16)raw; if ((d < 0 ? -d : d) >= 0x21) { if ((u16)(raw - 1) < 0x7FF || d < -0x7FF) { - D_800D2390.tail.angle = cur + 0x20; + D_800D2390.tail.vy = cur + 0x20; } else { - D_800D2390.tail.angle = cur - 0x20; + D_800D2390.tail.vy = cur - 0x20; } } else { - D_800D2390.tail.angle = target; + D_800D2390.tail.vy = target; D_800C4D2C ^= 0x8; } } @@ -886,14 +886,14 @@ void func_8009F6EC(void) { } else if (d3c == 1) { target = D_800C5344; } - cur = D_800D2390.tail.unk0; + cur = D_800D2390.tail.vx; d = (s16)(cur - target); if (d < -0x10) { - D_800D2390.tail.unk0 = cur + 0x10; + D_800D2390.tail.vx = cur + 0x10; } else if (d >= 0x11) { - D_800D2390.tail.unk0 = cur - 0x10; + D_800D2390.tail.vx = cur - 0x10; } else { - D_800D2390.tail.unk0 = target; + D_800D2390.tail.vx = target; D_800C4D2C ^= 0x10; } if ((u32)D_800C4D38 < 0xA || D_800C4D38 == 0x80) { @@ -928,14 +928,14 @@ void func_8009F6EC(void) { buf[2] = D_800C5354[2]; } target = sp10[2]; - cur = D_800D2390.head.unk4; + cur = D_800D2390.head.vz; d = (s16)(cur - target); if (d < -0x200) { - D_800D2390.head.unk4 = cur + 0x200; + D_800D2390.head.vz = cur + 0x200; } else if (d >= 0x201) { - D_800D2390.head.unk4 = cur - 0x200; + D_800D2390.head.vz = cur - 0x200; } else { - D_800D2390.head.unk4 = target; + D_800D2390.head.vz = target; D_800C4D2C ^= 0x20; } } @@ -964,14 +964,14 @@ void func_8009F6EC(void) { sp18[2] = D_800C5354[2]; } target = sp18[1]; - cur = D_800D2390.head.angle; + cur = D_800D2390.head.vy; d = (s16)(cur - target); if (d < -0x200) { - D_800D2390.head.angle = cur + 0x200; + D_800D2390.head.vy = cur + 0x200; } else if (d >= 0x201) { - D_800D2390.head.angle = cur - 0x200; + D_800D2390.head.vy = cur - 0x200; } else { - D_800D2390.head.angle = target; + D_800D2390.head.vy = target; D_800C4D2C ^= 0x80; } } diff --git a/src/world/we_object3.c b/src/world/we_object3.c index ed0cf4ed..c9bca8b4 100644 --- a/src/world/we_object3.c +++ b/src/world/we_object3.c @@ -4,7 +4,10 @@ #include "world/we_object1.h" #include "world/we_object3.h" #include "world/we_object4.h" -#include "world/we_object5.h" /* D_800D23D0 */ +#include "world/we_object5.h" +#include "world/we_object6.h" +#include "world/we_object10.h" +#include "world/we_object11.h" /* D_800D23D0 */ #include "world/we_object9.h" /* func_800BC5E0 */ #include "thread.h" @@ -307,8 +310,6 @@ extern void func_80048DD4(BattleSceneCtx *ctx, s32 r, s32 g, s32 b); extern void func_80049244(s32 *tag); extern void func_800492B4(BattleSceneCtx *ctx); extern void func_80049480(void *disp); -extern void func_800A7E74(BattleSceneCtx *ctx); -extern void func_800AC2B8(void); static s32 func_800A5B48(void); /* Writes exactly one word through its out-parameter. */ extern s32 func_800A50A0(s32 *runs); @@ -317,12 +318,6 @@ static void func_800A568C(void); func_800A50A0 scan, admits a single node and zeroes the out-word. What sets it, and what it means, is unknown. */ extern s32 func_800B21EC(WorldSpriteRec *rec, s32 mode, s32 c, s32 d); -/* Both below are declared in we_object10.h, which this unit cannot include: - * its func_800B0010 prototype is (void) to serve a no-argument caller there, - * conflicting with the true (u32 kind) definition in we_object6.c that - * func_800A2D50 relies on. */ -extern void *func_80047CE4(void *dst, s32 c, u32 n); -extern s32 func_800B0010(u32 kind); static void func_800A1678(s32 col, s32 mode); static void func_800A0388(void); static void func_800A39BC(WorldSprite *out, s16 h); @@ -330,11 +325,6 @@ static void placeWorldSpriteFan(WorldSprite *out, VECTOR *v, SVECTOR s32 arg3, s32 arg4, VECTOR *origin); static s32 func_800A6254(WorldObject *head); static void func_800A62E0(s16 val, u16 *coarse, u16 *fine); -extern void func_800ACDC4(GlyphHeader *p, BattleSceneCtx *ctx, WorldPrimBank *pools); -extern void func_800BF80C(GlyphHeader *p, s32 *ot, WorldPrimBank *pools); -extern void func_800BF2E8(GlyphHeader *p, s32 *ot, WorldPrimBank *pools); -extern void func_800BF20C(CmdDesc *p, s32 kind, s32 arg); -extern void func_800BFBFC(s32 kind); /** diff --git a/src/world/we_object4.c b/src/world/we_object4.c index 7191a068..d1022937 100644 --- a/src/world/we_object4.c +++ b/src/world/we_object4.c @@ -6,6 +6,7 @@ #include "world/we_object3.h" #include "world/we_object5.h" #include "world/we_object10.h" +#include "world/we_object6.h" #include "world/we_object4.h" extern TILE_1 D_800D5430[96]; /**< Second half of the star pool (== &D_800D4FB0[1][0]). */ @@ -827,8 +828,11 @@ void func_800A7CD0(s32 *block) { * differs from the slot's last blitted one (@c D_800D4EB0), the 256x1 * source row at (u, v + frame) is copied to the slot's destination * (x, y) via @c MoveImage and the new frame is cached. + * + * @param ctx Scene context. The sole caller loads @c D_800D244C into it, but + * the body works entirely off globals and never reads it. */ -void func_800A7E74(void) { +void func_800A7E74(BattleSceneCtx *ctx) { WorldTexAnim *anim; s32 i; u32 n; @@ -975,7 +979,7 @@ static void func_800A8024(void) { * @brief Project the world-map view centre to screen space. * * Builds a rotation matrix from the world transform's tail angle - * (@c D_800D2390.tail.angle) with no translation, turns the map's zoom + * (@c D_800D2390.tail.vy) with no translation, turns the map's zoom * distance (@c D_800C4D30 * 4, biased by the transform's head field) into * a view-space offset through @c ApplyMatrixSV, shifts it by the camera * offset in @c D_800C9770, and runs the result through the GTE with the @@ -994,7 +998,7 @@ void func_800A8270(SVECTOR *out) { rot.vx = 0; rot.vz = 0; - rot.vy = D_800D2390.tail.angle; + rot.vy = D_800D2390.tail.vy; RotMatrix(&rot, &m); m.t[2] = 0; @@ -1003,7 +1007,7 @@ void func_800A8270(SVECTOR *out) { rot.vx = 0; rot.vy = 0; rot.vz = (u16)D_800C4D30 * 4; - rot.vz = rot.vz + D_800D2390.head.unk4; + rot.vz = rot.vz + D_800D2390.head.vz; ApplyMatrixSV(&m, &rot, &rot); rot.vx += D_800C9770[0].vx; @@ -1016,7 +1020,7 @@ void func_800A8270(SVECTOR *out) { gte_stsxy(&screen); gte_stsz(&depth); - screen.vy -= abs(D_800D2390.head.unk4) / 300; + screen.vy -= abs(D_800D2390.head.vz) / 300; if (out != NULL) { out->vx = screen.vx; out->vy = screen.vy; @@ -1537,8 +1541,6 @@ void func_800A9254(void) { /* Projects a slot into camera space. Declared here rather than pulled in from * we_object7.h: that unit prototypes it over its own TrackEntry view of the * same memory, which conflicts with Slot30. */ -extern s32 func_800B01A0(s16 headingA, s16 headingB, Slot30 *slot, - SVECTOR *viewOut, s32 unused4, s32 unused5); /** Depth past which a particle is dropped rather than linked into the OT. */ #define PARTICLE_MAX_OTZ 0x2000 @@ -1616,7 +1618,7 @@ void func_800A9300(void) { gte_SetRotMatrix(&D_800C9838); gte_SetTransVector(D_800C9838.t); - if (!func_800B01A0(headingB, headingA, slot, &slot->view, 0, 0)) { + if (!func_800B01A0(headingB, headingA, &slot->pos, &slot->view, NULL, NULL)) { continue; } diff --git a/src/world/we_object5.c b/src/world/we_object5.c index d56295b0..fac85de6 100644 --- a/src/world/we_object5.c +++ b/src/world/we_object5.c @@ -1,12 +1,15 @@ #include "common.h" #include "world.h" #include "world/we_object5.h" +#include "world/we_object6.h" #include "world/we_object3.h" /* worldPosToCell */ #include "battle.h" #include "psxsdk/libgpu.h" #include "psxsdk/libgte.h" #include "psxsdk/libc.h" + + /** * @brief Spawn a pair of POLY_FT4 quads into one of two world-scene icon * pools, with screen-space (x,y) projected through a per-iteration diff --git a/src/world/we_object6.c b/src/world/we_object6.c index 36d2cd86..4024c0fd 100644 --- a/src/world/we_object6.c +++ b/src/world/we_object6.c @@ -11,8 +11,8 @@ INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object6", func_800ACC68); * * Steps: * 1. Compute @c delta = @c getAngleDelta(@c D_800C977A, - * @c D_800D2390.tail.angle) @c >> @c 1 — half the signed result. - * 2. Snapshot @c D_800D2390.tail into a local @ref WorldXformBlock via + * @c D_800D2390.tail.vy) @c >> @c 1 — half the signed result. + * 2. Snapshot @c D_800D2390.tail into a local SVECTOR via * @c memcpy. The source is cast to @c (u8 @c *) so the compiler * emits @c lwl / @c lwr (matching the target's byte-granular 8-byte * copy). @@ -24,19 +24,19 @@ INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object6", func_800ACC68); * cached transform/rotation payload before dispatching world-render * work. * - * @param arg First arg forwarded verbatim to @c func_800ACC68. + * @param outMat Destination matrix, forwarded to @c func_800ACC68. */ -void func_800ACD38(s32 arg) { - WorldXformBlock buf; +void func_800ACD38(MATRIX *outMat) { + SVECTOR buf; s32 delta; - delta = getAngleDelta(D_800C977A, D_800D2390.tail.angle) >> 1; + delta = getAngleDelta(D_800C977A, D_800D2390.tail.vy) >> 1; memcpy(&buf, (u8 *)&D_800D2390.tail, sizeof(buf)); - buf.angle += delta; + buf.vy += delta; - func_800ACC68(arg, &buf, (u8 *)D_800C97F8, &D_800D2390); + func_800ACC68(outMat, &buf, D_800C97F8, &D_800D2390.head); } INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object6", func_800ACDC4); diff --git a/src/world/we_object7.c b/src/world/we_object7.c index 12a8e9ff..b90d7970 100644 --- a/src/world/we_object7.c +++ b/src/world/we_object7.c @@ -1,5 +1,6 @@ #include "common.h" #include "world.h" +#include "world/we_object6.h" #include "world/we_object7.h" #include "world/we_object3.h" /* func_800A5DC8 */ @@ -50,16 +51,16 @@ void func_800B3868(TrackObj *obj) { for (i = 0, current = obj->entries; i < obj->count; i++, current++) { if (current->status == -1) { - current->status = func_800B01A0(viewY, viewX, current, ¤t->posX, ¤t->unk30, current->unk2C); + current->status = func_800B01A0(viewY, viewX, ¤t->pos, ¤t->screen, ¤t->unk30, ¤t->unk2C); } if (current->targetIdx != 0 && current->status == 1) { target = current + current->targetIdx; if (target->status == -1) { - target->status = func_800B01A0(viewY, viewX, target, &target->posX, &target->unk30, target->unk2C); + target->status = func_800B01A0(viewY, viewX, &target->pos, &target->screen, &target->unk30, &target->unk2C); } - diff.vx = target->posX - current->posX; - diff.vy = target->posY - current->posY; - diff.vz = target->posZ - current->posZ; + diff.vx = target->screen.vx - current->screen.vx; + diff.vy = target->screen.vy - current->screen.vy; + diff.vz = target->screen.vz - current->screen.vz; current->unk18 = 0; horizDist = SquareRoot0(diff.vz * diff.vz + diff.vx * diff.vx); current->pitch = func_80041E84(-diff.vy, horizDist); diff --git a/src/world/we_object9.c b/src/world/we_object9.c index 4478c76d..4af00b5a 100644 --- a/src/world/we_object9.c +++ b/src/world/we_object9.c @@ -2,9 +2,12 @@ #include "psxsdk/libc.h" #include "gamestate.h" #include "world.h" +#include "world/we_object5.h" #include "world/we_object9.h" #include "world/we_object3.h" /* worldPosToCell */ + + #define SPAWN_FLAG_LIFETIME_JITTER 1 #define SPAWN_FLAG_SIZE_JITTER 2 @@ -136,8 +139,8 @@ INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object9", func_800BB4E8); * @param visRange Visibility threshold (higher = farther allowed). */ void func_800BBD74(ParticleSource *src, s32 visRange) { - Velocity localVel; - PosDesc localPos; + SVECTOR localVel; + VECTOR localPos; s32 jitter; s32 absdx; s16 dx; @@ -145,29 +148,29 @@ void func_800BBD74(ParticleSource *src, s32 visRange) { worldCam = D_800C97F4; localPos = src->pos; - dx = ((u16) D_800C97F4) - src->pos.pos.half; - localPos.pos.word = worldCam; + dx = ((u16) D_800C97F4) - (u16)src->pos.vy; + localPos.vy = worldCam; if ((func_8009CC3C() + (dx >> 2)) >= visRange) return; absdx = (dx >= 0) ? dx : -dx; if (absdx >= 0x258) return; /* Left-side spawn: +0x320 angle offset + RNG jitter on angle/height */ localVel = src->vel; - localVel.angle += 0x320; + localVel.vy += 0x320; jitter = (func_8009CC3C() - 0x80) * 8; - localVel.angle += jitter; + localVel.vy += jitter; jitter = (func_8009CC3C() - 0x80) * 4; - localVel.height += jitter; + localVel.vz += jitter; func_800AC0A0(0x13, &localPos, &localVel, SPAWN_FLAG_SIZE_JITTER | SPAWN_FLAG_LIFETIME_JITTER); /* Right-side spawn: -0x320 angle offset + RNG jitter on angle/height */ localVel = src->vel; - localVel.angle -= 0x320; + localVel.vy -= 0x320; jitter = (func_8009CC3C() - 0x80) * 8; - localVel.angle += jitter; + localVel.vy += jitter; jitter = (func_8009CC3C() - 0x80) * 4; - localVel.height += jitter; + localVel.vz += jitter; func_800AC0A0(0x13, &localPos, &localVel, SPAWN_FLAG_SIZE_JITTER | SPAWN_FLAG_LIFETIME_JITTER); } @@ -199,24 +202,24 @@ void func_800BBD74(ParticleSource *src, s32 visRange) { * * worldCam = D_800C97F4; * localPos = src->pos; - * dx = ((u16) D_800C97F4) - src->pos.pos.half; - * localPos.pos.word = worldCam; + * dx = ((u16) D_800C97F4) - (u16)src->pos.vy; + * localPos.vy = worldCam; * if (D_800C4D4C <= (func_8009CC3C() + (dx >> 2))) return; * absdx = (dx >= 0) ? dx : -dx; * if (absdx >= 0x1A4) return; * * localVel = src->vel; - * localVel.angle += 0x320; + * localVel.vy += 0x320; * jitter = (func_8009CC3C() - 0x80) * 8; - * localVel.angle += jitter; - * localVel.height += func_8009CC3C() - 0x80; + * localVel.vy += jitter; + * localVel.vz += func_8009CC3C() - 0x80; * func_800AC0A0(0xF, &localPos, &localVel, 3); * * localVel = src->vel; - * localVel.angle -= 0x320; + * localVel.vy -= 0x320; * jitter = (func_8009CC3C() - 0x80) * 8; - * localVel.angle += jitter; - * localVel.height += func_8009CC3C() - 0x80; + * localVel.vy += jitter; + * localVel.vz += func_8009CC3C() - 0x80; * func_800AC0A0(0xF, &localPos, &localVel, 3); * } */ @@ -226,7 +229,7 @@ INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object9", func_800BBF0C); * @brief Spawn a mirrored particle pair (type 0x14) gated on a word-angle delta. * * Sibling of @c func_800BBD74 but with word-scale angle math instead of - * halfword: computes @c (D_800C97F4 - src->pos.pos.word) >> 4 and + * halfword: computes @c (D_800C97F4 - src->pos.vy) >> 4 and * rejects the spawn when @c (rnd + delta) >= @c (D_800C4D4C / 2). When * the visibility gate opens, emits two particles via @c func_800AC0A0 * with symmetric ±0x320 angle offsets and RNG jitter on angle/height. @@ -239,8 +242,8 @@ INCLUDE_ASM("asm/ovl/world/nonmatchings/we_object9", func_800BBF0C); * @param src Particle source (position descriptor + velocity template). */ void func_800BC09C(ParticleSource *src) { - Velocity localVel; - PosDesc localPos; + SVECTOR localVel; + VECTOR localPos; s32 jitter; s32 threshold; u32 worldCam; @@ -248,25 +251,25 @@ void func_800BC09C(ParticleSource *src) { worldCam = D_800C97F4; localPos = src->pos; threshold = D_800C4D4C >> 1; - localPos.pos.word = worldCam; - if ((func_8009CC3C() + ((s32)(D_800C97F4 - src->pos.pos.word) >> 4)) >= threshold) return; + localPos.vy = worldCam; + if ((func_8009CC3C() + ((s32)(D_800C97F4 - src->pos.vy) >> 4)) >= threshold) return; /* Left-side spawn: +0x320 angle offset + RNG jitter on angle/height */ localVel = src->vel; - localVel.angle += 0x320; + localVel.vy += 0x320; jitter = (func_8009CC3C() - 0x80) * 8; - localVel.angle += jitter; + localVel.vy += jitter; jitter = (func_8009CC3C() - 0x80) * 4; - localVel.height += jitter; + localVel.vz += jitter; func_800AC0A0(0x14, &localPos, &localVel, 3); /* Right-side spawn: -0x320 angle offset + RNG jitter on angle/height */ localVel = src->vel; - localVel.angle -= 0x320; + localVel.vy -= 0x320; jitter = (func_8009CC3C() - 0x80) * 8; - localVel.angle += jitter; + localVel.vy += jitter; jitter = (func_8009CC3C() - 0x80) * 4; - localVel.height += jitter; + localVel.vz += jitter; func_800AC0A0(0x14, &localPos, &localVel, 3); } From 73ab67504553dd249afb39b1301cb242fe362813 Mon Sep 17 00:00:00 2001 From: rengstrom Date: Tue, 1 Sep 2026 20:34:00 +0000 Subject: [PATCH 3/4] Drop comments that narrate or restate, and add a rule for it Thirty includes carried a trailing note naming what they supply. They rot as soon as the unit uses something else from the header, and they drift: inserting an include above one moves the note onto the wrong line. One had ended up reading #include "world/we_object11.h" /* D_800D23D0 */ for a symbol that comes from we_object5.h. The same habit produced status narration -- "still assembly", "the readers are asm", "defined below; its only caller is" -- which every decomp session falsifies a little more and nobody goes back to correct. Two were already wrong: we_object3.h still described func_800987D8 as assembly reaching its callees through the linker, when it is C and includes that header directly. contrib_review gains rule 11 covering both, since they kept recurring: a comment earns its place only by carrying what the code cannot -- what a value means, why a spelling is load-bearing, or a measured fact. --- include/battle.h | 2 +- include/main.h | 4 +-- include/menuitem.h | 4 +-- include/tim.h | 2 +- include/tripletriad.h | 6 ++--- include/tripletriad/be_object1.h | 2 +- include/tripletriad/be_object1b.h | 2 +- include/tripletriad/be_object2.h | 2 +- include/tripletriad/be_object4.h | 2 +- include/world.h | 3 +-- include/world/we_object0.h | 2 +- include/world/we_object1.h | 13 ++++------ include/world/we_object10.h | 11 +-------- include/world/we_object11.h | 2 +- include/world/we_object2.h | 8 +++--- include/world/we_object3.h | 39 ++++++++++++++++++++++++++++- include/world/we_object5.h | 3 --- include/world/we_object6.h | 8 ++++-- include/world/we_object7.h | 2 -- include/world/we_object9.h | 5 +++- src/battle/bc_object1.c | 2 +- src/world/we_object0.c | 7 ++---- src/world/we_object1.c | 7 ++++-- src/world/we_object10.c | 7 ++++-- src/world/we_object2.c | 1 + src/world/we_object3.c | 41 ++----------------------------- src/world/we_object5.c | 4 ++- src/world/we_object7.c | 3 ++- src/world/we_object9.c | 4 ++- 29 files changed, 97 insertions(+), 101 deletions(-) diff --git a/include/battle.h b/include/battle.h index 3c0d5872..32f1dcb8 100644 --- a/include/battle.h +++ b/include/battle.h @@ -5,7 +5,7 @@ #include "psxsdk/libgpu.h" #include "psxsdk/libgte.h" #include "tim.h" -#include "battle_anim.h" /* AnimFrame, BattleAnimEntity, BattleAnimState, g_battleAnims */ +#include "battle_anim.h" /** @brief Battle result values (BattleConfig.result). */ #define BATTLE_RESULT_UNDETERMINED 0 diff --git a/include/main.h b/include/main.h index a94a650d..be57103f 100644 --- a/include/main.h +++ b/include/main.h @@ -2,8 +2,8 @@ #define MAIN_H #include "common.h" -#include "cd.h" /* CdFileDesc */ -#include "psxsdk/libgpu.h" /* TILE */ +#include "cd.h" +#include "psxsdk/libgpu.h" /* =============================================================== * * Public interface — functions in main.c called by other units. * diff --git a/include/menuitem.h b/include/menuitem.h index 8df7641b..df0d7cdb 100644 --- a/include/menuitem.h +++ b/include/menuitem.h @@ -9,8 +9,8 @@ #define MENUITEM_H #include "common.h" -#include "gamestate.h" /* g_gameState */ -#include "menumain.h" /* D_801F889C and the rest of the resident menu image */ +#include "gamestate.h" +#include "menumain.h" extern s32 D_80083850; extern s32 D_801ECC10; diff --git a/include/tim.h b/include/tim.h index eb1355e7..a54082f6 100644 --- a/include/tim.h +++ b/include/tim.h @@ -2,7 +2,7 @@ #define TIM_H #include "common.h" -#include "psxsdk/libgpu.h" /* RECT */ +#include "psxsdk/libgpu.h" /** * @brief One section of a PS1 TIM image file (CLUT block or pixel block). diff --git a/include/tripletriad.h b/include/tripletriad.h index d1cb2909..c6f0fb95 100644 --- a/include/tripletriad.h +++ b/include/tripletriad.h @@ -2,9 +2,9 @@ #define TRIPLETRIAD_H #include "common.h" -#include "psxsdk/libgpu.h" /* TSPRT (drawCardOverlaySprite) */ -#include "psxsdk/libgte.h" /* SVECTOR / MATRIX (CardRenderWork, CardAnimNode) */ -#include "main.h" /* g_activeDrawEnv */ +#include "psxsdk/libgpu.h" +#include "psxsdk/libgte.h" +#include "main.h" /* Types, constants, and globals for the Triple Triad card mini-game. Its code is the `tripletriad` overlay, which loads at the same VRAM address diff --git a/include/tripletriad/be_object1.h b/include/tripletriad/be_object1.h index 8267380b..0e9809ae 100644 --- a/include/tripletriad/be_object1.h +++ b/include/tripletriad/be_object1.h @@ -3,7 +3,7 @@ #include "common.h" #include "tripletriad.h" -#include "tim.h" /* Tim / TimSection (queued VRAM image uploads) */ +#include "tim.h" /* Declarations for be_object1.c (Triple Triad board/card setup, draw-buffer init, deferred VRAM transfers, the object-list system, debug text, and the diff --git a/include/tripletriad/be_object1b.h b/include/tripletriad/be_object1b.h index dfbda4b4..b208acaa 100644 --- a/include/tripletriad/be_object1b.h +++ b/include/tripletriad/be_object1b.h @@ -2,7 +2,7 @@ #define TRIPLETRIAD_BE_OBJECT1B_H #include "common.h" -#include "psxsdk/libgte.h" /* SVECTOR (layoutCardSlot) */ +#include "psxsdk/libgte.h" /* Declarations for be_object1b.c (Triple Triad match-flow controller, the per-frame update-list callbacks, and card-object search helpers). */ diff --git a/include/tripletriad/be_object2.h b/include/tripletriad/be_object2.h index bdea05c8..6dc7c3ce 100644 --- a/include/tripletriad/be_object2.h +++ b/include/tripletriad/be_object2.h @@ -2,7 +2,7 @@ #define TRIPLETRIAD_BE_OBJECT2_H #include "common.h" -#include "tripletriad.h" /* board/card types, SVECTOR / CVECTOR / VECTOR */ +#include "tripletriad.h" /* Declarations for be_object2.c (Triple Triad card objects, the rules engine, the menu/cursor sub-machine, and the AI move search). */ diff --git a/include/tripletriad/be_object4.h b/include/tripletriad/be_object4.h index b827592b..046f134e 100644 --- a/include/tripletriad/be_object4.h +++ b/include/tripletriad/be_object4.h @@ -3,7 +3,7 @@ #include "common.h" #include "tripletriad.h" -#include "battle_anim.h" /* BattleAnimState / BattleAnimEntity (func_800A29D4 prototype) */ +#include "battle_anim.h" /* Public interface of be_object4.c: the Triple Triad SFX request queue, the card-detail popup buffers, the rule-description string table, and the message-gate / menu helpers diff --git a/include/world.h b/include/world.h index 77dc4758..5d2465fd 100644 --- a/include/world.h +++ b/include/world.h @@ -5,7 +5,7 @@ #include "psxsdk/libgpu.h" #include "psxsdk/libgte.h" #include "battle.h" -#include "gamestate.h" /* SceneState, in Slot */ +#include "gamestate.h" #include "sound.h" /** View of the sentinel ctx exposing the DISPENV template that sits past the @@ -565,7 +565,6 @@ typedef struct { extern BattleSceneCtx D_800CA040; /**< Worldmap "no-battle" sentinel — also functions as an empty BattleSceneCtx. */ extern s16 D_800C53B8[]; /**< Bone-id table (used by we_object4). */ -extern ScriptOp *func_800AF004(u8 *base, s32 flag); extern s32 func_800AF28C(ScriptOp *p); extern s32 func_800BEFC4(void); extern void func_800BD82C(u8 *actor, SlotEntry *slot, s32 marker, s32 flag, SVECTOR *rot, VECTOR *trans); diff --git a/include/world/we_object0.h b/include/world/we_object0.h index dc87e00f..e72af65d 100644 --- a/include/world/we_object0.h +++ b/include/world/we_object0.h @@ -2,7 +2,7 @@ #define WORLD_WE_OBJECT0_H #include "common.h" -#include "overlay.h" /* func_800987D8 -- the entry point this unit defines */ +#include "overlay.h" /* The overlay entry point is declared with the others in overlay.h; this * header re-exports it and owns any public surface the unit grows. */ diff --git a/include/world/we_object1.h b/include/world/we_object1.h index 20494086..ab86fe28 100644 --- a/include/world/we_object1.h +++ b/include/world/we_object1.h @@ -6,7 +6,7 @@ #include "gamestate.h" #include "psxsdk/libgpu.h" #include "psxsdk/libgte.h" -#include "main.h" /* g_activeDrawEnv */ +#include "main.h" /* Projection scratch: worldPosToCell writes @c proj and returns @c angle. The trailing @c pad keeps the buffer 0x20 bytes (gcc reserves the full slot). @@ -104,8 +104,6 @@ extern POLY_FT4 D_800C8648[2]; /* double-buffered worldmap quad primitive */ extern void func_8009C528(s32 rc); extern void func_8009FEDC(u8 *work, u8 type); extern s32 func_80042634(s32 a); -extern void func_800A5F78(s32 screen); -extern void func_800A5FD4(s32 screen); extern void func_800A5D10(void); extern s32 getCurrentFieldMusic(void); /* defined u16 in btl_sfx; used full-width here */ extern void setSfxPitch(s32 idx, s32 val); @@ -126,14 +124,9 @@ extern void func_8009CDC4(s32 a, s32 b); extern void func_8009CE40(void); extern s32 func_8009D7D8(s32 a); extern void func_8003FD84(MATRIX *xform, VECTOR *in, VECTOR *out); -extern void func_800BC544(VECTOR *src, VECTOR *dst); extern void func_8009C478(s32 *src, s32 x, s32 y); extern CmdDesc *glyphAt(GlyphQuery *v, AngleSlot *out); extern s32 func_800BEC1C(s32 kind); -extern void func_8009D630(void); -extern void fadeOutSfxFast(s32 idx); -extern void renderAndUpdateDisplay(s32 frames); -extern s32 renderBattleDisplayList(s32 *colorTag); extern void sndSeqSetTempoAlt(s32 tempo); extern void sndSetMasterVolume(s32 vol); extern void sndCmdF1(void); @@ -148,4 +141,8 @@ extern void func_8009A954(void); extern void func_8009AEE4(s32 id); extern void func_8009B954(s32 a, s32 b, s32 c); +extern s32 func_8009B358(s32 slotIdx, s32 strIdx, u8 *text); + +extern s32 func_8009CC3C(void); + #endif /* WORLD_WE_OBJECT1_H */ diff --git a/include/world/we_object10.h b/include/world/we_object10.h index 0bdbe855..270f395d 100644 --- a/include/world/we_object10.h +++ b/include/world/we_object10.h @@ -3,7 +3,7 @@ #include "common.h" #include "world.h" -#include "world/we_object3.h" /* CmdDesc, GlyphHeader, WorldPrimBank */ +#include "world/we_object3.h" #include "psxsdk/libgte.h" /** @brief 32-byte record used by func_800BE5F8's table walker. */ @@ -60,17 +60,8 @@ extern void func_800BAC84(u8 *p); extern s32 func_800BA870(u8 *p); extern void *func_80047CE4(void *dst, s32 c, u32 n); extern s32 func_800BEF6C(void); -extern s32 func_8009CC3C(void); extern void func_800AEB58(XformEntry *entry, XformGroup *group); extern void func_8009C5FC(s32 *data); -extern void func_800BC51C(VECTOR *src, VECTOR *dst); -extern void func_800BC544(VECTOR *src, VECTOR *dst); -extern ScriptOp *func_800AF004(u8 *base, s32 flag); -extern s32 func_8009B358(s32 slotIdx, s32 strIdx, u8 *text); -extern void func_8009D8A8(s32 a0); -extern void fadeOutSfxFast(s32 idx); -extern void renderAndUpdateDisplay(s32 frameCount); -extern s32 renderBattleDisplayList(s32 *colorTag); extern void func_800BEC60(u8 *flags); diff --git a/include/world/we_object11.h b/include/world/we_object11.h index 96df8e07..74f8f3ab 100644 --- a/include/world/we_object11.h +++ b/include/world/we_object11.h @@ -3,7 +3,7 @@ #include "common.h" #include "world.h" -#include "world/we_object3.h" /* GlyphHeader, WorldPrimBank */ +#include "world/we_object3.h" extern void func_800BF80C(GlyphHeader *p, s32 *ot, WorldPrimBank *pools); extern void func_800BFBFC(s32 kind); diff --git a/include/world/we_object2.h b/include/world/we_object2.h index 694641f1..4fe95c91 100644 --- a/include/world/we_object2.h +++ b/include/world/we_object2.h @@ -4,7 +4,7 @@ #include "common.h" #include "world.h" #include "psxsdk/libgte.h" -#include "psxsdk/libetc.h" /* VSync */ +#include "psxsdk/libetc.h" typedef struct { s16 a; @@ -49,12 +49,8 @@ extern u16 D_800C5346; /* per-map yaw target (func_8009F6EC b extern s32 D_800C9730; /* GTE projection-plane distance (SetGeomScreen arg). */ extern s32 D_800D2448; /* world-ready gate flag (func_8009F6EC bit 0x10). */ -extern void func_800A5F78(s32 screen); -extern void func_800A5FD4(s32 screen); extern void func_80099EDC(s32 idx); extern void func_8009D630(void); -extern void renderAndUpdateDisplay(s32 mode); -extern s32 renderBattleDisplayList(s32 *colorTag); extern s32 func_800BD380(s16 *outLow, s16 *outHigh); extern s32 func_800BD2A0(s16 *outLow, s16 *outHigh); extern s32 func_800BD460(s16 *outLow, s16 *outHigh); @@ -77,4 +73,6 @@ extern s32 getAngleDelta(s32 a, s32 b); extern void func_8009DB88(u8 *p); extern void func_8009E5C8(VECTOR *pos, u8 *p, SVECTOR *ang, void *x); +extern void func_8009D8A8(s32 a0); + #endif /* WORLD_WE_OBJECT2_H */ diff --git a/include/world/we_object3.h b/include/world/we_object3.h index aa514aa0..2f19fc94 100644 --- a/include/world/we_object3.h +++ b/include/world/we_object3.h @@ -172,10 +172,47 @@ extern WorldPrimBank *D_800C9720; /**< The bank the glyph renderers allocate frame; we_object6 and we_object7 read it. */ -/* Also read by the world entry loop in we_object0. */ extern s32 D_800C972C; /**< Accumulated glyph-entry count. */ extern s32 D_800C9ED0; /**< Pad 0's raw frame parameter. */ extern SVECTOR D_800CA038; /**< Reference offset fed to the pool placer. */ extern s32 D_800D2238; +extern void func_800A5F78(s32 screen); + +extern void func_800A5FD4(s32 screen); + +/** + * @brief One placed world-map sprite produced by @c placeWorldSpriteFan (0x2C stride). + * + * @c pos is the final world position; @c cell receives the @c worldPosToCell + * projection; @c cellId/flag are the projected grid-cell id and a fixed marker. + * @note Field purpose partly uncertain — named from the access pattern. + */ +typedef struct { + VECTOR pos; /* 0x00 */ + SVECTOR cell; /* 0x10 — worldPosToCell output */ + u8 pad18[0x4]; /* 0x18 */ + CmdDesc *cmd; /* 0x1C — installed as the current descriptor D_800C4D64 */ + s16 cellId; /* 0x20 — worldPosToCell return */ + s16 flag; /* 0x22 — one of WORLD_SPRITE_* below */ + s16 angle; /* 0x24 — heading used to bias the camera track */ + s16 code; /* 0x26 — packed type | flag<<8 of the installed descriptor */ + u16 unk28; /* 0x28 — published to D_800C4D48; its readers are still asm */ + u8 pad2A[0x2]; /* 0x2A */ +} WorldSprite; /* 0x2C */ + +/** @c WorldSprite::flag states. */ +#define WORLD_SPRITE_FREE 0 /**< Slot unused. */ +#define WORLD_SPRITE_PENDING 1 /**< Re-probed this pass but matched no descriptor. */ +#define WORLD_SPRITE_PLACED 2 /**< Given a position this pass. */ +#define WORLD_SPRITE_CLAIMED 3 /**< Matched a glyph this frame. */ + +/** Sprites in one pool record: an anchor plus the four spread around it. */ +#define WORLD_FAN_SPRITES 5 + +/** A pool record: five sprites placed together as one fan. */ +typedef struct { + WorldSprite sprite[WORLD_FAN_SPRITES]; +} WorldSpriteRec; /* 0xDC */ + #endif /* WORLD_WE_OBJECT3_H */ diff --git a/include/world/we_object5.h b/include/world/we_object5.h index 9a358710..7671a2ce 100644 --- a/include/world/we_object5.h +++ b/include/world/we_object5.h @@ -61,7 +61,6 @@ extern VECTOR D_800DD658; /* source position for func_800BC51C extern void func_800A84D0(void); extern s32 func_8003F9F4(CVECTOR *input, CVECTOR *cue, s32 w1, s32 w2, CVECTOR *out); -extern s32 func_8009CC3C(void); extern s32 func_800A4700(s32 a, s32 b); extern s32 func_800A475C(s32 a, s32 b); extern void func_800423DC(VECTOR *a, s32 *b_pos, VECTOR *out); @@ -71,8 +70,6 @@ extern void func_800ABEF0(SVECTOR *src, SVECTOR *rot, SVECTOR *trans, DVECTOR *outSXY, u32 *outOTZ); extern void func_800B5C60(s32 ctx, s16 count, MATRIX *outMat, SVECTOR *outAngles, SVECTOR *rotBuf, u8 *xform, ActorRecord *recs); -extern void func_800BC51C(VECTOR *src, VECTOR *dst); -extern void func_800BC544(VECTOR *src, VECTOR *dst); /* Depth-cue a CVECTOR run into BGR555 halfwords (see the definition for the per-pixel blend and the STP-bit packing). */ diff --git a/include/world/we_object6.h b/include/world/we_object6.h index fc2b2b78..b371cabb 100644 --- a/include/world/we_object6.h +++ b/include/world/we_object6.h @@ -2,8 +2,8 @@ #define WORLD_WE_OBJECT6_H #include "world.h" -#include "world/we_object3.h" /* GlyphHeader, WorldPrimBank */ -#include "world/we_object2.h" /* getAngleDelta */ +#include "world/we_object3.h" +#include "world/we_object2.h" /* Defined in this file (via INCLUDE_ASM). */ /* Arg 1 is dereferenced at +0x14, which is MATRIX.t[0]. */ @@ -31,4 +31,8 @@ extern s32 func_800B01A0(s16 viewY, s16 viewX, VECTOR *pos, SVECTOR *screenOut, extern void func_800ACDC4(GlyphHeader *p, BattleSceneCtx *ctx, WorldPrimBank *pools); +extern ScriptOp *func_800AF004(u8 *base, s32 flag); + +extern s32 func_800B21EC(WorldSpriteRec *rec, s32 mode, s32 c, s32 d); + #endif /* WORLD_WE_OBJECT6_H */ diff --git a/include/world/we_object7.h b/include/world/we_object7.h index 1fa92ae4..4df2a8a1 100644 --- a/include/world/we_object7.h +++ b/include/world/we_object7.h @@ -41,9 +41,7 @@ extern u8 *D_800C96C8; * we_object2; addItemToInventory, func_800A5DC8 and func_80041E84 are * main-binary. Caller-local prototypes. */ extern s32 func_80041E84(s32 y, s32 x); -extern s32 func_8009B358(s32 slotIdx, s32 strIdx, u8 *text); extern void func_8009B550(s32 a0, s32 a1, s32 a2, s32 a3, s32 a4, s32 a5, s32 a6); -extern void func_8009D8A8(s32 a0); extern void addItemToInventory(s32 itemId, s32 count); extern s32 func_800B4AA0(void); diff --git a/include/world/we_object9.h b/include/world/we_object9.h index 6842a562..69b17ebd 100644 --- a/include/world/we_object9.h +++ b/include/world/we_object9.h @@ -82,7 +82,6 @@ extern s32 D_800C971C; /* Per-scene angle bias applied to a placed sprite fan. */ extern s32 func_800BC5E0(s32 ctx); -extern s32 func_8009CC3C(void); extern void func_800BFFEC(void); extern void func_800C2C00(s32 a, s32 b, s32 c, s32 d, s32 e, U64 *f, s32 g, U64 *h); extern u8 *func_800BC8D8(u8 *buf, s32 magicId); @@ -95,4 +94,8 @@ extern s32 func_800B00D8(s32 a); extern void func_800BB150(Slot *slot); extern void func_800BB4E8(void); +extern void func_800BC51C(VECTOR *src, VECTOR *dst); + +extern void func_800BC544(VECTOR *src, VECTOR *dst); + #endif /* WORLD_WE_OBJECT9_H */ diff --git a/src/battle/bc_object1.c b/src/battle/bc_object1.c index ebe9193d..614cd9a9 100644 --- a/src/battle/bc_object1.c +++ b/src/battle/bc_object1.c @@ -1,5 +1,5 @@ #include "common.h" -#include "main.h" /* D_8005F146 */ +#include "main.h" #include "battle.h" #include "gf.h" #include "battle/bc_object1.h" diff --git a/src/world/we_object0.c b/src/world/we_object0.c index 4057c1de..565521c2 100644 --- a/src/world/we_object0.c +++ b/src/world/we_object0.c @@ -19,6 +19,7 @@ #include "world/we_object13.h" #include "main.h" #include "thread.h" +#include "btl_anim.h" #define SP_SAVE_SCRATCH(slot) \ asm volatile("addu $t0, %0, $zero\n\t" \ @@ -122,16 +123,11 @@ s32 func_800987D8(void) s32 cmd; s32 firstPass; s32 stall; - /* Codes the loop hands to the scene-change helpers. Their producers - (func_800B85DC, func_800BC46C, func_800997E8, func_800B99A4) are still - assembly, so what distinguishes them is only known by use here. */ u16 sceneCmd; u16 hitCmd; u16 objMarker; s32 result; - /* firstPass must be set before stall: gcc keeps them in the two highest - callee-saved registers and picks which by initialisation order. */ firstPass = 1; stall = 0; result = 0; @@ -471,5 +467,6 @@ s32 func_800987D8(void) func_80048C50(0); func_800488D4(3); func_8009AD3C(); + return result; } diff --git a/src/world/we_object1.c b/src/world/we_object1.c index 790e0dc6..1b65fadc 100644 --- a/src/world/we_object1.c +++ b/src/world/we_object1.c @@ -5,11 +5,14 @@ #include "world.h" #include "gamestate.h" #include "world/we_object1.h" -#include "world/we_object2.h" /* getAngleDelta */ -#include "world/we_object3.h" /* func_800A2D50 */ +#include "world/we_object2.h" +#include "world/we_object3.h" #include "psxsdk/libapi.h" #include "psxsdk/libgpu.h" #include "psxsdk/libc.h" +#include "btl_sfx.h" +#include "btl_anim.h" +#include "world/we_object9.h" //#include "world/we_object6.h" // Deliberately not included for matching reasons, original code likely forgot to include this diff --git a/src/world/we_object10.c b/src/world/we_object10.c index 4726b598..73fe0970 100644 --- a/src/world/we_object10.c +++ b/src/world/we_object10.c @@ -5,13 +5,16 @@ #include "world/we_object5.h" #include "world/we_object6.h" #include "world/we_object10.h" -#include "world/we_object3.h" /* worldPosToCell */ +#include "world/we_object3.h" +#include "btl_sfx.h" +#include "btl_anim.h" +#include "world/we_object1.h" +#include "world/we_object9.h" -/* Defined below; the reset path above is its only caller. */ static void func_800BEFEC(u8 *base); diff --git a/src/world/we_object2.c b/src/world/we_object2.c index 12de1716..201f1afb 100644 --- a/src/world/we_object2.c +++ b/src/world/we_object2.c @@ -8,6 +8,7 @@ #include "world/we_object2.h" #include "world/we_object3.h" #include "world/we_object13.h" +#include "btl_anim.h" /** * @brief Walk a world-engine image script and blit each record to VRAM. diff --git a/src/world/we_object3.c b/src/world/we_object3.c index c9bca8b4..3fcc0a07 100644 --- a/src/world/we_object3.c +++ b/src/world/we_object3.c @@ -7,8 +7,8 @@ #include "world/we_object5.h" #include "world/we_object6.h" #include "world/we_object10.h" -#include "world/we_object11.h" /* D_800D23D0 */ -#include "world/we_object9.h" /* func_800BC5E0 */ +#include "world/we_object11.h" +#include "world/we_object9.h" #include "thread.h" /* ---- private to renderWorldMapFrame ------------------------------------- @@ -74,34 +74,6 @@ extern s32 D_800D34E8; /** World-engine mode flags; bit 0 picks the alternate code table. */ extern u16 D_800D241E; -/* None of the declarations below are referenced outside this unit either. */ - -/** - * @brief One placed world-map sprite produced by @c placeWorldSpriteFan (0x2C stride). - * - * @c pos is the final world position; @c cell receives the @c worldPosToCell - * projection; @c cellId/flag are the projected grid-cell id and a fixed marker. - * @note Field purpose partly uncertain — named from the access pattern. - */ -typedef struct { - VECTOR pos; /* 0x00 */ - SVECTOR cell; /* 0x10 — worldPosToCell output */ - u8 pad18[0x4]; /* 0x18 */ - CmdDesc *cmd; /* 0x1C — installed as the current descriptor D_800C4D64 */ - s16 cellId; /* 0x20 — worldPosToCell return */ - s16 flag; /* 0x22 — one of WORLD_SPRITE_* below */ - s16 angle; /* 0x24 — heading used to bias the camera track */ - s16 code; /* 0x26 — packed type | flag<<8 of the installed descriptor */ - u16 unk28; /* 0x28 — published to D_800C4D48; its readers are still asm */ - u8 pad2A[0x2]; /* 0x2A */ -} WorldSprite; /* 0x2C */ - -/** @c WorldSprite::flag states. */ -#define WORLD_SPRITE_FREE 0 /**< Slot unused. */ -#define WORLD_SPRITE_PENDING 1 /**< Re-probed this pass but matched no descriptor. */ -#define WORLD_SPRITE_PLACED 2 /**< Given a position this pass. */ -#define WORLD_SPRITE_CLAIMED 3 /**< Matched a glyph this frame. */ - /** @brief Probe vector: three unsigned halfword components plus padding. * * Unsigned because the cell deltas wrap modulo 0x10000 as they are added @@ -227,13 +199,6 @@ extern WorldZone D_800C59BC[]; #define WORLD_PRIM_GT3_MID ((POLY_GT3 *)0x801D0000) #define WORLD_PRIM_GT3_TOP ((POLY_GT3 *)WORLD_STAGE_ADDR) -/** Sprites in one pool record: an anchor plus the four spread around it. */ -#define WORLD_FAN_SPRITES 5 - -/** A pool record: five sprites placed together as one fan. */ -typedef struct { - WorldSprite sprite[WORLD_FAN_SPRITES]; -} WorldSpriteRec; /* 0xDC */ /** Records in one pool bank. */ #define WORLD_BANK_RECORDS 8 @@ -281,7 +246,6 @@ extern s16 D_800C9772; /**< Receives the low half of the camera-f for the call-site ABI. */ static void func_800A1F10(); static WorldObject *worldObjectById(s16 id, WorldObject *head); -/* All defined below; the render callback is the first caller in the file. */ static void buildViewportCellList(WorldPos *cam, WorldObject *out, MATRIX *m); static void func_800A6030(WorldObject **pp); static WorldObject *func_800A60B4(s32 key, WorldObject *head); @@ -317,7 +281,6 @@ static void func_800A568C(void); /* func_800A5B48 is the only reference in the tree: when non-zero it skips the func_800A50A0 scan, admits a single node and zeroes the out-word. What sets it, and what it means, is unknown. */ -extern s32 func_800B21EC(WorldSpriteRec *rec, s32 mode, s32 c, s32 d); static void func_800A1678(s32 col, s32 mode); static void func_800A0388(void); static void func_800A39BC(WorldSprite *out, s16 h); diff --git a/src/world/we_object5.c b/src/world/we_object5.c index fac85de6..6c70d920 100644 --- a/src/world/we_object5.c +++ b/src/world/we_object5.c @@ -2,11 +2,13 @@ #include "world.h" #include "world/we_object5.h" #include "world/we_object6.h" -#include "world/we_object3.h" /* worldPosToCell */ +#include "world/we_object3.h" #include "battle.h" #include "psxsdk/libgpu.h" #include "psxsdk/libgte.h" #include "psxsdk/libc.h" +#include "world/we_object1.h" +#include "world/we_object9.h" diff --git a/src/world/we_object7.c b/src/world/we_object7.c index b90d7970..c3bf7f5f 100644 --- a/src/world/we_object7.c +++ b/src/world/we_object7.c @@ -2,7 +2,8 @@ #include "world.h" #include "world/we_object6.h" #include "world/we_object7.h" -#include "world/we_object3.h" /* func_800A5DC8 */ +#include "world/we_object3.h" +#include "world/we_object1.h" /* ActorRecord now lives in world.h (shared across world TUs). */ diff --git a/src/world/we_object9.c b/src/world/we_object9.c index 4af00b5a..41dc5257 100644 --- a/src/world/we_object9.c +++ b/src/world/we_object9.c @@ -4,7 +4,9 @@ #include "world.h" #include "world/we_object5.h" #include "world/we_object9.h" -#include "world/we_object3.h" /* worldPosToCell */ +#include "world/we_object3.h" +#include "world/we_object1.h" +#include "world/we_object6.h" From 2e8ff1c4958b6a3282a34a1ef17f0717e9902168 Mon Sep 17 00:00:00 2001 From: rengstrom Date: Tue, 1 Sep 2026 21:05:33 +0000 Subject: [PATCH 4/4] Cleanup Signed-off-by: rengstrom --- config/symbols.extern.txt | 2 +- include/field/fe_object1.h | 1 - include/overlay.h | 7 +------ include/world/we_object0.h | 3 +-- include/world/we_object3.h | 2 -- include/world/we_object6.h | 2 -- 6 files changed, 3 insertions(+), 14 deletions(-) diff --git a/config/symbols.extern.txt b/config/symbols.extern.txt index 8111b1a1..e739faae 100644 --- a/config/symbols.extern.txt +++ b/config/symbols.extern.txt @@ -83,7 +83,7 @@ SetSprt = 0x8004D6E4; SetTile = 0x8004D704; SetDrawTPage = 0x8004D724; SetDrawMove = 0x8004D754; -deactivateBattleCmd = 0x800308B0; /* main; the world entry loop calls it on shutdown */ +deactivateBattleCmd = 0x800308B0; SetDrawLoad = 0x8004D7B4; g_gameState = 0x80077378; g_characterMagic = 0x80077818; diff --git a/include/field/fe_object1.h b/include/field/fe_object1.h index 000746c1..b186f996 100644 --- a/include/field/fe_object1.h +++ b/include/field/fe_object1.h @@ -22,7 +22,6 @@ extern CdFileDesc D_800C0910[]; /**< Streaming table, third descriptor (passed /** @brief Field id currently being streamed in (compared against @c D_8005F100). */ extern s16 D_8005F14E; -/** @brief Field render/present state halfword; the loader spins while it reads 4. */ /** @brief Section-pointer table bases published by the loaded field bundle. */ extern u8 **D_800C7208; /**< Event-queue block; assigned to @c D_8005F0F8. */ diff --git a/include/overlay.h b/include/overlay.h index c3f6a9b5..10e27df7 100644 --- a/include/overlay.h +++ b/include/overlay.h @@ -2,6 +2,7 @@ #define OVERLAY_H #include "common.h" +#include "world/we_object0.h" /** * @brief Overlay command queue entry (D_80085168, 8-slot ring buffer). @@ -57,10 +58,4 @@ extern s32 func_8003646C(); /* K&R: called with 1 or 2 args */ /** @brief Run the loaded overlay's entry point (init / execute). */ extern void func_80098000(void); -/** @brief Run the world overlay: set the map up, then drive its frame loop - * until something asks the world to hand off. Defined in - * src/world/we_object0.c. - * @return 0 normally; 1 when the loop ended on the two-frame stall check - * (main checks @c == 1). */ -extern s32 func_800987D8(void); #endif /* OVERLAY_H */ diff --git a/include/world/we_object0.h b/include/world/we_object0.h index e72af65d..b88988eb 100644 --- a/include/world/we_object0.h +++ b/include/world/we_object0.h @@ -4,7 +4,6 @@ #include "common.h" #include "overlay.h" -/* The overlay entry point is declared with the others in overlay.h; this - * header re-exports it and owns any public surface the unit grows. */ +extern s32 func_800987D8(void); #endif /* WORLD_WE_OBJECT0_H */ diff --git a/include/world/we_object3.h b/include/world/we_object3.h index 2f19fc94..83b7e8a4 100644 --- a/include/world/we_object3.h +++ b/include/world/we_object3.h @@ -102,8 +102,6 @@ extern s32 func_800A358C(s32 kind, SlotEntry *slot, SVECTOR *angles, s32 flag); code @p b (only b's low 16 bits are examined; D_800C4D20 == 0 force-passes). */ extern s32 func_800A45D8(u32 a, s32 b); -/* Entry points the world loop in we_object0 calls. */ - /* Per-frame world setup: advance the frame clock, run the renderers and flip the scene context. */ extern void func_800A01DC(s32 skipPresent); diff --git a/include/world/we_object6.h b/include/world/we_object6.h index b371cabb..a40f26fa 100644 --- a/include/world/we_object6.h +++ b/include/world/we_object6.h @@ -5,8 +5,6 @@ #include "world/we_object3.h" #include "world/we_object2.h" -/* Defined in this file (via INCLUDE_ASM). */ -/* Arg 1 is dereferenced at +0x14, which is MATRIX.t[0]. */ extern void func_800ACC68(MATRIX *outMat, SVECTOR *angles, SVECTOR *rotBuf, SVECTOR *offset);