diff --git a/Makefile b/Makefile index 16e2d07395..f1e7e75f22 100644 --- a/Makefile +++ b/Makefile @@ -53,9 +53,6 @@ endif # Version-specific settings ifeq ($(VERSION),gc-eu-mq) DEBUG := 0 - CFLAGS += -DNON_MATCHING - CPPFLAGS += -DNON_MATCHING - COMPARE := 0 else ifeq ($(VERSION),gc-eu-mq-dbg) DEBUG := 1 else @@ -312,9 +309,9 @@ $(BUILD_DIR)/src/code/jpegdecoder.o: CC := $(CC_OLD) # For using asm_processor on some files: #$(BUILD_DIR)/.../%.o: CC := $(PYTHON) tools/asm_processor/build.py $(CC) -- $(AS) $(ASFLAGS) -- -ifeq ($(PERMUTER),) # permuter + reencode.sh misbehaves, permuter doesn't care about encoding ((ro)data diffs) so just don't use it in that case -# Handle encoding (UTF-8 -> EUC-JP) -$(BUILD_DIR)/%.o: CC := tools/reencode.sh $(CC) +ifeq ($(PERMUTER),) # permuter + preprocess.py misbehaves, permuter doesn't care about rodata diffs or bss ordering so just don't use it in that case +# Handle encoding (UTF-8 -> EUC-JP) and custom pragmas +$(BUILD_DIR)/src/%.o: CC := $(PYTHON) tools/preprocess.py $(CC) endif else diff --git a/data/fault.bss.s b/data/fault.bss.s deleted file mode 100644 index d8d76a0518..0000000000 --- a/data/fault.bss.s +++ /dev/null @@ -1,27 +0,0 @@ -.include "macro.inc" - -# assembler directives -.set noat # allow manual use of $at -.set noreorder # don't insert nops after branches -.set gp=64 # allow use of 64-bit general purpose registers - -.section .bss - -# Note: This file is only included in the MATCHING build, the data is imported for non-matching - -.balign 16 - -glabel sFaultInstance - .space 4 - -glabel sFaultAwaitingInput - .space 4 - -glabel sFaultStack - .space 0x600 - -glabel sFaultThreadInfo - .space 0x20 - -glabel gFaultMgr - .space 0x850 diff --git a/data/fault_drawer.bss.s b/data/fault_drawer.bss.s deleted file mode 100644 index 89a29d8bb4..0000000000 --- a/data/fault_drawer.bss.s +++ /dev/null @@ -1,19 +0,0 @@ -.include "macro.inc" - -# assembler directives -.set noat # allow manual use of $at -.set noreorder # don't insert nops after branches -.set gp=64 # allow use of 64-bit general purpose registers - -.section .bss - -# Note: This file is only included in the MATCHING build, the data is imported for non-matching - -.balign 16 - -glabel sFaultDrawer - .space 0x3C - .space 0x04 # padding - -glabel D_8016B6C0 - .space 0x20 diff --git a/include/padmgr.h b/include/padmgr.h index 65705949ea..ba86315c6f 100644 --- a/include/padmgr.h +++ b/include/padmgr.h @@ -44,8 +44,6 @@ typedef struct PadMgr { /* 0x0464 */ void* retraceCallbackArg; } PadMgr; // size = 0x468 -extern PadMgr gPadMgr; - // Initialization void PadMgr_Init(PadMgr* padMgr, OSMesgQueue* serialEventQueue, IrqMgr* irqMgr, OSId id, OSPri priority, void* stack); diff --git a/include/variables.h b/include/variables.h index 1c7e4ebc85..a67d99246b 100644 --- a/include/variables.h +++ b/include/variables.h @@ -174,25 +174,38 @@ extern u8 gSampleBankTable[]; extern SaveContext gSaveContext; extern RegEditor* gRegEditor; +extern u8 gUseCutsceneCam; +extern u16 D_8015FCCC; +extern char D_8015FCD0[20]; +extern u8 D_8015FCE4; extern u16 gCamAtSplinePointsAppliedFrame; extern u16 gCamEyePointAppliedFrame; extern u16 gCamAtPointAppliedFrame; -extern u8 gUseCutsceneCam; +extern LightningStrike gLightningStrike; +// TODO: These variables are here for BSS ordering but ideally they should not +// be extern. This could be fixed by putting more stuff (e.g. struct definitions) +// between gLightningStrike and gCustomLensFlareOn. +extern s16 sLightningFlashAlpha; +extern s16 sSunDepthTestX; +extern s16 sSunDepthTestY; extern u8 gCustomLensFlareOn; extern Vec3f gCustomLensFlarePos; extern s16 gLensFlareScale; extern f32 gLensFlareColorIntensity; extern s16 gLensFlareGlareStrength; -extern LightningStrike gLightningStrike; extern MapData* gMapData; extern f32 gBossMarkScale; +extern u32 D_8016139C; extern PauseMapMarksData* gLoadedPauseMarkDataTable; +extern TransitionTile gTransitionTile; extern s32 gTransitionTileState; +extern VisMono gPlayVisMono; extern Color_RGBA8_u32 gVisMonoColor; extern PreNmiBuff* gAppNmiBufferPtr; -extern Scheduler gScheduler; extern uintptr_t gSegments[NUM_SEGMENTS]; +extern Scheduler gScheduler; +extern PadMgr gPadMgr; extern volatile OSTime gAudioThreadUpdateTimeTotalPerGfxTask; extern volatile OSTime gGfxTaskSentToNextReadyMinusAudioThreadUpdateTime; extern volatile OSTime gRSPAudioTimeTotal; @@ -204,6 +217,7 @@ extern volatile OSTime gAudioThreadUpdateTimeAcc; extern volatile OSTime gRSPAudioTimeAcc; extern volatile OSTime gRSPGfxTimeAcc; extern volatile OSTime gRSPOtherTimeAcc; +extern volatile OSTime D_8016A578; extern volatile OSTime gRDPTimeAcc; extern SfxBankEntry D_8016BAD0[9]; diff --git a/spec b/spec index 287659d1b9..1630ba28cc 100644 --- a/spec +++ b/spec @@ -448,10 +448,6 @@ beginseg #endif include "$(BUILD_DIR)/src/code/fault.o" include "$(BUILD_DIR)/src/code/fault_drawer.o" -#ifndef NON_MATCHING - include "$(BUILD_DIR)/data/fault.bss.o" - include "$(BUILD_DIR)/data/fault_drawer.bss.o" -#endif include "$(BUILD_DIR)/src/code/kanread.o" #if OOT_DEBUG include "$(BUILD_DIR)/src/code/ucode_disas.o" diff --git a/src/boot/idle.c b/src/boot/idle.c index dec3006b01..3d62994c47 100644 --- a/src/boot/idle.c +++ b/src/boot/idle.c @@ -1,7 +1,12 @@ #include "global.h" #include "terminal.h" -OSThread gMainThread; +// For retail BSS ordering, the block number of sMainThread must be 0 or +// just above (the exact upper bound depends on the block numbers assigned to +// extern variables declared in headers). +#pragma increment_block_number 60 + +OSThread sMainThread; STACK(sMainStack, 0x900); StackEntry sMainStackInfo; OSMesg sPiMgrCmdBuff[50]; @@ -86,8 +91,8 @@ void Idle_ThreadEntry(void* arg) { osViSwapBuffer((void*)0x803DA80); //! @bug Invalid vram address (probably intended to be 0x803DA800) osCreatePiManager(OS_PRIORITY_PIMGR, &gPiMgrCmdQueue, sPiMgrCmdBuff, ARRAY_COUNT(sPiMgrCmdBuff)); StackCheck_Init(&sMainStackInfo, sMainStack, STACK_TOP(sMainStack), 0, 0x400, "main"); - osCreateThread(&gMainThread, THREAD_ID_MAIN, Main_ThreadEntry, arg, STACK_TOP(sMainStack), THREAD_PRI_MAIN_INIT); - osStartThread(&gMainThread); + osCreateThread(&sMainThread, THREAD_ID_MAIN, Main_ThreadEntry, arg, STACK_TOP(sMainStack), THREAD_PRI_MAIN_INIT); + osStartThread(&sMainThread); osSetThreadPri(NULL, OS_PRIORITY_IDLE); for (;;) {} diff --git a/src/code/fault.c b/src/code/fault.c index 8b05fb8208..662c1a9f1a 100644 --- a/src/code/fault.c +++ b/src/code/fault.c @@ -44,6 +44,15 @@ #include "terminal.h" #include "alloca.h" +// For retail BSS ordering, the block number of sFaultInstance must be 0 or +// just above (the exact upper bound depends on the block numbers assigned to +// extern variables declared in headers). +#if OOT_DEBUG +#pragma increment_block_number 20 +#else +#pragma increment_block_number 25 +#endif + void FaultDrawer_Init(void); void FaultDrawer_SetOsSyncPrintfEnabled(u32 enabled); void FaultDrawer_DrawRecImpl(s32 xStart, s32 yStart, s32 xEnd, s32 yEnd, u16 color); @@ -76,21 +85,11 @@ const char* sFpExceptionNames[] = { "Unimplemented operation", "Invalid operation", "Division by zero", "Overflow", "Underflow", "Inexact operation", }; -#ifndef NON_MATCHING -// TODO: match .bss (has reordering issues) -extern FaultMgr* sFaultInstance; -extern u8 sFaultAwaitingInput; -extern STACK(sFaultStack, 0x600); -extern StackEntry sFaultThreadInfo; -extern FaultMgr gFaultMgr; -#else -// Non-matching version for struct shiftability FaultMgr* sFaultInstance; u8 sFaultAwaitingInput; STACK(sFaultStack, 0x600); StackEntry sFaultThreadInfo; FaultMgr gFaultMgr; -#endif typedef struct { /* 0x00 */ s32 (*callback)(void*, void*); diff --git a/src/code/fault_drawer.c b/src/code/fault_drawer.c index 8f5fbcbe49..5c82b7a0bb 100644 --- a/src/code/fault_drawer.c +++ b/src/code/fault_drawer.c @@ -99,15 +99,8 @@ FaultDrawer sFaultDrawerDefault = { NULL, }; -#ifndef NON_MATCHING -// TODO: match .bss (has reordering issues) -extern FaultDrawer sFaultDrawer; -extern char D_8016B6C0[0x20]; -#else -// Non-matching version for struct shiftability FaultDrawer sFaultDrawer; char D_8016B6C0[0x20]; -#endif void FaultDrawer_SetOsSyncPrintfEnabled(u32 enabled) { sFaultDrawer.osSyncPrintfEnabled = enabled; diff --git a/src/code/sys_math3d.c b/src/code/sys_math3d.c index 3e50249b12..a3b8ca2d61 100644 --- a/src/code/sys_math3d.c +++ b/src/code/sys_math3d.c @@ -1,6 +1,10 @@ #include "global.h" #include "terminal.h" +// For retail BSS ordering, the block number of cbf in Math3D_CylVsCylOverlapCenterDist +// must be 0. +#pragma increment_block_number 190 + s32 Math3D_LineVsLineClosestTwoPoints(Vec3f* lineAPointA, Vec3f* lineAPointB, Vec3f* lineBPointA, Vec3f* lineBPointB, Vec3f* lineAClosestToB, Vec3f* lineBClosestToA); s32 Math3D_TriLineIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, diff --git a/src/code/z_actor.c b/src/code/z_actor.c index dfa9d88dd8..5e8b86aaa6 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -8,6 +8,9 @@ #include "assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" #include "assets/objects/object_bdoor/object_bdoor.h" +// For retail BSS ordering, the block number of sCurCeilingPoly +// must be between 2 and 243 inclusive. + static CollisionPoly* sCurCeilingPoly; static s32 sCurCeilingBgId; @@ -1894,7 +1897,9 @@ s32 func_8002F9EC(PlayState* play, Actor* actor, CollisionPoly* poly, s32 bgId, return false; } -// Local data used for Farore's Wind light (stored in BSS, possibly a struct?) +#pragma increment_block_number 22 + +// Local data used for Farore's Wind light (stored in BSS) LightInfo D_8015BC00; LightNode* D_8015BC10; s32 D_8015BC14; diff --git a/src/code/z_camera.c b/src/code/z_camera.c index a54d640700..4caafe18c9 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -4,6 +4,10 @@ #include "terminal.h" #include "overlays/actors/ovl_En_Horse/z_en_horse.h" +// For retail BSS ordering, the block number of D_8015BD7C +// must be between 88 and 123 inclusive. +#pragma increment_block_number 30 + s16 Camera_RequestSettingImpl(Camera* camera, s16 requestedSetting, s16 flags); s32 Camera_RequestModeImpl(Camera* camera, s16 requestedMode, u8 forceModeChange); s32 Camera_UpdateWater(Camera* camera); @@ -3628,6 +3632,8 @@ s32 Camera_KeepOn3(Camera* camera) { return 1; } +#pragma increment_block_number 100 + s32 Camera_KeepOn4(Camera* camera) { static Vec3f D_8015BD50; static Vec3f D_8015BD60; diff --git a/src/code/z_collision_check.c b/src/code/z_collision_check.c index 14822cf1cd..118a445d7b 100644 --- a/src/code/z_collision_check.c +++ b/src/code/z_collision_check.c @@ -7,6 +7,10 @@ typedef void (*ColChkApplyFunc)(PlayState*, CollisionCheckContext*, Collider*); typedef void (*ColChkVsFunc)(PlayState*, CollisionCheckContext*, Collider*, Collider*); typedef s32 (*ColChkLineFunc)(PlayState*, CollisionCheckContext*, Collider*, Vec3f*, Vec3f*); +// For retail BSS ordering, the block number of sparkInit in CollisionCheck_BlueBlood +// must be between 183 and 255 inclusive. +#pragma increment_block_number 50 + #if OOT_DEBUG /** * Draws a red triangle with vertices vA, vB, and vC. @@ -2238,8 +2242,10 @@ void CollisionCheck_ATCylVsACQuad(PlayState* play, CollisionCheckContext* colChk } } +#if OOT_DEBUG static s8 sBssDummy0; static s8 sBssDummy1; +#endif void CollisionCheck_ATQuadVsACCyl(PlayState* play, CollisionCheckContext* colChkCtx, Collider* atCol, Collider* acCol) { static TriNorm tri1; @@ -2300,10 +2306,12 @@ void CollisionCheck_ATQuadVsACCyl(PlayState* play, CollisionCheckContext* colChk } } +#if OOT_DEBUG static s8 sBssDummy3; static s8 sBssDummy4; static s8 sBssDummy5; static s8 sBssDummy6; +#endif void CollisionCheck_ATTrisVsACTris(PlayState* play, CollisionCheckContext* colChkCtx, Collider* atCol, Collider* acCol) { @@ -2350,10 +2358,12 @@ void CollisionCheck_ATTrisVsACTris(PlayState* play, CollisionCheckContext* colCh } } +#if OOT_DEBUG static s8 sBssDummy7; static s8 sBssDummy8; static s8 sBssDummy9; static s8 sBssDummy10; +#endif void CollisionCheck_ATTrisVsACQuad(PlayState* play, CollisionCheckContext* colChkCtx, Collider* atCol, Collider* acCol) { @@ -2586,9 +2596,10 @@ static ColChkApplyFunc sColChkApplyFuncs[] = { */ void CollisionCheck_SetHitEffects(PlayState* play, CollisionCheckContext* colChkCtx) { Collider** acColP; + Collider* acCol; for (acColP = colChkCtx->colAC; acColP < colChkCtx->colAC + colChkCtx->colACCount; acColP++) { - Collider* acCol = *acColP; + acCol = *acColP; if (acCol != NULL && acCol->acFlags & AC_ON) { if (acCol->actor != NULL && acCol->actor->update == NULL) { @@ -2635,9 +2646,10 @@ static ColChkVsFunc sACVsFuncs[COLSHAPE_MAX][COLSHAPE_MAX] = { */ void CollisionCheck_AC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* atCol) { Collider** acColP; + Collider* acCol; for (acColP = colChkCtx->colAC; acColP < colChkCtx->colAC + colChkCtx->colACCount; acColP++) { - Collider* acCol = *acColP; + acCol = *acColP; if (acCol != NULL && acCol->acFlags & AC_ON) { if (acCol->actor != NULL && acCol->actor->update == NULL) { @@ -2661,12 +2673,13 @@ void CollisionCheck_AC(PlayState* play, CollisionCheckContext* colChkCtx, Collid */ void CollisionCheck_AT(PlayState* play, CollisionCheckContext* colChkCtx) { Collider** atColP; + Collider* atCol; if (colChkCtx->colATCount == 0 || colChkCtx->colACCount == 0) { return; } for (atColP = colChkCtx->colAT; atColP < colChkCtx->colAT + colChkCtx->colATCount; atColP++) { - Collider* atCol = *atColP; + atCol = *atColP; if (atCol != NULL && atCol->atFlags & AT_ON) { if (atCol->actor != NULL && atCol->actor->update == NULL) { @@ -2684,6 +2697,8 @@ typedef enum { /* 2 */ MASSTYPE_NORMAL } ColChkMassType; +#pragma increment_block_number 253 + /** * Get mass type. Immovable colliders cannot be pushed, while heavy colliders can only be pushed by heavy and immovable * colliders. @@ -3134,9 +3149,10 @@ static ColChkApplyFunc sApplyDamageFuncs[COLSHAPE_MAX] = { */ void CollisionCheck_Damage(PlayState* play, CollisionCheckContext* colChkCtx) { s32 i; + Collider* col; for (i = 0; i < colChkCtx->colACCount; i++) { - Collider* col = colChkCtx->colAC[i]; + col = colChkCtx->colAC[i]; if (col == NULL) { continue; @@ -3312,12 +3328,14 @@ void Collider_SetTrisDim(PlayState* play, ColliderTris* tris, s32 elemIndex, Col Collider_SetTrisElementDim(play, &trisElem->dim, src); } +#if OOT_DEBUG // Due to an unknown reason, bss ordering changed between the 2 static Vec3f variables in the function below. // In order to reproduce this behavior, we need a specific number of bss variables in the file before that point. // For this, we introduce a certain amount of dummy variables throughout the file, which we fit inside padding added // by the compiler between structs like TriNorm and/or Vec3f, so they don't take space in bss. static s8 sBssDummy11; static s8 sBssDummy12; +#endif /** * Updates the world spheres for all of the collider's JntSph elements attached to the specified limb diff --git a/src/code/z_common_data.c b/src/code/z_common_data.c index 2d7c36fc81..47aecd9e6a 100644 --- a/src/code/z_common_data.c +++ b/src/code/z_common_data.c @@ -1,5 +1,10 @@ #include "global.h" +// For retail BSS ordering, the block number of D_8015FA88 must be 0 or +// just above (the exact upper bound depends on the block numbers assigned to +// extern variables declared in headers). +#pragma increment_block_number 60 + ALIGNED(16) SaveContext gSaveContext; u32 D_8015FA88; u32 D_8015FA8C; diff --git a/src/code/z_kaleido_scope_call.c b/src/code/z_kaleido_scope_call.c index be1d9aa59e..7b53b8521a 100644 --- a/src/code/z_kaleido_scope_call.c +++ b/src/code/z_kaleido_scope_call.c @@ -1,6 +1,11 @@ #include "global.h" #include "terminal.h" +// For retail BSS ordering, the block number of sKaleidoScopeUpdateFunc must be 0 or +// just above (the exact upper bound depends on the block numbers assigned to +// extern variables declared in headers). +#pragma increment_block_number 60 + void (*sKaleidoScopeUpdateFunc)(PlayState* play); void (*sKaleidoScopeDrawFunc)(PlayState* play); f32 gBossMarkScale; diff --git a/src/code/z_kankyo.c b/src/code/z_kankyo.c index db80807355..ce79a7df93 100644 --- a/src/code/z_kankyo.c +++ b/src/code/z_kankyo.c @@ -4,6 +4,11 @@ #include "assets/objects/gameplay_keep/gameplay_keep.h" #include "assets/objects/gameplay_field_keep/gameplay_field_keep.h" +// For retail BSS ordering, the block number of sLensFlareUnused must be lower +// than the extern variables declared in the header (e.g. gLightningStrike) +// while the block number of sNGameOverLightNode must be higher. +#pragma increment_block_number 80 + typedef enum { /* 0x00 */ LIGHTNING_BOLT_START, /* 0x01 */ LIGHTNING_BOLT_WAIT, @@ -183,7 +188,7 @@ f32 sSandstormLerpScale = 0.0f; u8 gCustomLensFlareOn; Vec3f gCustomLensFlarePos; -s16 gLensFlareUnused; +s16 sLensFlareUnused; s16 gLensFlareScale; f32 gLensFlareColorIntensity; s16 gLensFlareGlareStrength; @@ -207,6 +212,11 @@ s16 sLightningFlashAlpha; s16 sSunDepthTestX; s16 sSunDepthTestY; +// These variables could be moved farther down in the file to reduce the amount +// of block number padding here, but currently this causes BSS ordering issues +// for debug. +#pragma increment_block_number 230 + LightNode* sNGameOverLightNode; LightInfo sNGameOverLightInfo; LightNode* sSGameOverLightNode; @@ -2208,7 +2218,7 @@ void Environment_DrawCustomLensFlare(PlayState* play) { pos.y = gCustomLensFlarePos.y; pos.z = gCustomLensFlarePos.z; - Environment_DrawLensFlare(play, &play->envCtx, &play->view, play->state.gfxCtx, pos, gLensFlareUnused, + Environment_DrawLensFlare(play, &play->envCtx, &play->view, play->state.gfxCtx, pos, sLensFlareUnused, gLensFlareScale, gLensFlareColorIntensity, gLensFlareGlareStrength, false); } } diff --git a/src/code/z_play.c b/src/code/z_play.c index c418c40899..f86986839b 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -9,9 +9,9 @@ UNK_TYPE D_8012D1F4 = 0; // unused Input* D_8012D1F8 = NULL; -TransitionTile sTransitionTile; +TransitionTile gTransitionTile; s32 gTransitionTileState; -VisMono sPlayVisMono; +VisMono gPlayVisMono; Color_RGBA8_u32 gVisMonoColor; #if OOT_DEBUG @@ -199,7 +199,7 @@ void Play_Destroy(GameState* thisx) { CollisionCheck_DestroyContext(this, &this->colChkCtx); if (gTransitionTileState == TRANS_TILE_READY) { - TransitionTile_Destroy(&sTransitionTile); + TransitionTile_Destroy(&gTransitionTile); gTransitionTileState = TRANS_TILE_OFF; } @@ -211,7 +211,7 @@ void Play_Destroy(GameState* thisx) { Letterbox_Destroy(); TransitionFade_Destroy(&this->transitionFadeFlash); - VisMono_Destroy(&sPlayVisMono); + VisMono_Destroy(&gPlayVisMono); if (gSaveContext.save.linkAge != this->linkAgeOnLoad) { Inventory_SwapAgeEquipment(); @@ -409,7 +409,7 @@ void Play_Init(GameState* thisx) { TransitionFade_SetType(&this->transitionFadeFlash, TRANS_INSTANCE_TYPE_FADE_FLASH); TransitionFade_SetColor(&this->transitionFadeFlash, RGBA8(160, 160, 160, 255)); TransitionFade_Start(&this->transitionFadeFlash); - VisMono_Init(&sPlayVisMono); + VisMono_Init(&gPlayVisMono); gVisMonoColor.a = 0; CutsceneFlags_UnsetAll(this); @@ -521,18 +521,18 @@ void Play_Update(PlayState* this) { if (gTransitionTileState != TRANS_TILE_OFF) { switch (gTransitionTileState) { case TRANS_TILE_PROCESS: - if (TransitionTile_Init(&sTransitionTile, 10, 7) == NULL) { + if (TransitionTile_Init(&gTransitionTile, 10, 7) == NULL) { PRINTF("fbdemo_init呼出し失敗!\n"); // "fbdemo_init call failed!" gTransitionTileState = TRANS_TILE_OFF; } else { - sTransitionTile.zBuffer = (u16*)gZBuffer; + gTransitionTile.zBuffer = (u16*)gZBuffer; gTransitionTileState = TRANS_TILE_READY; R_UPDATE_RATE = 1; } break; case TRANS_TILE_READY: - TransitionTile_Update(&sTransitionTile); + TransitionTile_Update(&gTransitionTile); break; default: @@ -687,7 +687,7 @@ void Play_Update(PlayState* this) { this->transitionMode = TRANS_MODE_OFF; if (gTransitionTileState == TRANS_TILE_READY) { - TransitionTile_Destroy(&sTransitionTile); + TransitionTile_Destroy(&gTransitionTile); gTransitionTileState = TRANS_TILE_OFF; R_UPDATE_RATE = 3; } @@ -1135,8 +1135,8 @@ void Play_Draw(PlayState* this) { TransitionFade_Draw(&this->transitionFadeFlash, &gfxP); if (gVisMonoColor.a > 0) { - sPlayVisMono.vis.primColor.rgba = gVisMonoColor.rgba; - VisMono_Draw(&sPlayVisMono, &gfxP); + gPlayVisMono.vis.primColor.rgba = gVisMonoColor.rgba; + VisMono_Draw(&gPlayVisMono, &gfxP); } gSPEndDisplayList(gfxP++); @@ -1147,7 +1147,7 @@ void Play_Draw(PlayState* this) { if (gTransitionTileState == TRANS_TILE_READY) { Gfx* sp88 = POLY_OPA_DISP; - TransitionTile_Draw(&sTransitionTile, &sp88); + TransitionTile_Draw(&gTransitionTile, &sp88); POLY_OPA_DISP = sp88; goto Play_Draw_DrawOverlayElements; } diff --git a/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index 0498724369..0d5b973618 100644 --- a/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -100,12 +100,22 @@ static ColliderCylinderInit sLightBallCylinderInit = { static u8 D_808E4C58[] = { 0, 12, 10, 12, 14, 16, 12, 14, 16, 12, 14, 16, 12, 14, 16, 10, 16, 14 }; static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f }; +// For retail BSS ordering, the block number of sGanondorf must be 0 or just above. + +// TODO: There's probably a way to do this with less padding by spreading the variables out and moving +// data around. It would be easier if we had more options for controlling BSS ordering in debug. +#pragma increment_block_number 50 + static EnGanonMant* sCape; +#pragma increment_block_number 200 + static s32 sSeed1; static s32 sSeed2; static s32 sSeed3; +#pragma increment_block_number 200 + static BossGanon* sGanondorf; static EnZl3* sZelda; diff --git a/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 3809daae4d..17eff561ad 100644 --- a/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -14,6 +14,9 @@ #include "assets/scenes/dungeons/ice_doukutu/ice_doukutu_scene.h" #include "terminal.h" +// For retail BSS ordering, the block number of sSfxPos +// must be between 0 and 213 inclusive. + #define FLAGS ACTOR_FLAG_4 void EnXc_Init(Actor* thisx, PlayState* play); @@ -387,6 +390,8 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) { void EnXc_DoNothing(EnXc* this, PlayState* play) { } +static Vec3f sSfxPos; + void EnXc_SetWalkingSFX(EnXc* this, PlayState* play) { s32 pad[2]; u32 sfxId; @@ -432,7 +437,6 @@ void EnXc_SetLandingSFX(EnXc* this, PlayState* play) { } void EnXc_SetColossusAppearSFX(EnXc* this, PlayState* play) { - static Vec3f sXyzDist; s16 sceneId; if (gSaveContext.sceneLayer == 4) { @@ -445,14 +449,14 @@ void EnXc_SetColossusAppearSFX(EnXc* this, PlayState* play) { if (csCurFrame == 119) { Vec3f pos = { -611.0f, 728.0f, -2.0f }; - SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &pos, &sXyzDist, wDest); - Sfx_PlaySfxAtPos(&sXyzDist, NA_SE_EV_JUMP_CONC); + SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &pos, &sSfxPos, wDest); + Sfx_PlaySfxAtPos(&sSfxPos, NA_SE_EV_JUMP_CONC); } else if (csCurFrame == 164) { Vec3f pos = { -1069.0f, 38.0f, 0.0f }; s32 pad; - SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &pos, &sXyzDist, wDest); - Sfx_PlaySfxAtPos(&sXyzDist, NA_SE_PL_WALK_GROUND + SURFACE_SFX_OFFSET_STONE); + SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &pos, &sSfxPos, wDest); + Sfx_PlaySfxAtPos(&sSfxPos, NA_SE_PL_WALK_GROUND + SURFACE_SFX_OFFSET_STONE); } } } @@ -466,8 +470,6 @@ void func_80B3D118(PlayState* play) { } } -static Vec3f D_80B42DA0; - void EnXc_SetColossusWindSFX(PlayState* play) { if (gSaveContext.sceneLayer == 4) { static s32 D_80B41D90 = 0; @@ -1394,7 +1396,10 @@ void func_80B3F3D8(void) { Sfx_PlaySfxCentered2(NA_SE_PL_SKIP); } +#pragma increment_block_number 20 + void EnXc_PlayDiveSFX(Vec3f* src, PlayState* play) { + static Vec3f D_80B42DA0; f32 wDest[2]; SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, src, &D_80B42DA0, wDest); diff --git a/src/overlays/actors/ovl_Fishing/z_fishing.c b/src/overlays/actors/ovl_Fishing/z_fishing.c index 7181accf39..bf1e59de7f 100644 --- a/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -10,6 +10,9 @@ #include "assets/objects/object_fish/object_fish.h" #include "terminal.h" +// For retail BSS ordering, the block number of sStreamSfxProjectedPos must be 0. +#pragma increment_block_number 201 + #define FLAGS ACTOR_FLAG_4 #define WATER_SURFACE_Y(play) play->colCtx.colHeader->waterBoxes->ySurface diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 6f4cc33c3f..fd2cc36c48 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -353,11 +353,24 @@ void Player_Action_80850E84(Player* this, PlayState* play); void Player_Action_CsAction(Player* this, PlayState* play); // .bss part 1 + +// For retail BSS ordering, the block number of sDogSpawnPos in Player_Update +// must be between 0 and 53 inclusive. + +// TODO: There's probably a way to do this with less padding by spreading the variables out and moving +// data around. It would be easier if we had more options for controlling BSS ordering in debug. +#pragma increment_block_number 30 + static s32 D_80858AA0; + +#pragma increment_block_number 250 + static s32 D_80858AA4; static Vec3f sInteractWallCheckResult; static Input* sControlInput; +#pragma increment_block_number 50 + // .data static u8 sUpperBodyLimbCopyMap[PLAYER_LIMB_MAX] = { @@ -11376,8 +11389,6 @@ typedef struct { static BunnyEarKinematics sBunnyEarKinematics; -static Vec3s D_80858AD8[25]; - static Gfx* sMaskDlists[PLAYER_MASK_MAX - 1] = { gLinkChildKeatonMaskDL, gLinkChildSkullMaskDL, gLinkChildSpookyMaskDL, gLinkChildBunnyHoodDL, gLinkChildGoronMaskDL, gLinkChildZoraMaskDL, gLinkChildGerudoMaskDL, gLinkChildMaskOfTruthDL, @@ -14080,6 +14091,7 @@ void Player_Action_80850AEC(Player* this, PlayState* play) { void Player_Action_80850C68(Player* this, PlayState* play) { if ((this->av2.actionVar2 != 0) && ((this->unk_858 != 0.0f) || (this->unk_85C != 0.0f))) { + static Vec3s D_80858AD8[25]; f32 updateScale = R_UPDATE_RATE * 0.5f; this->skelAnime.curFrame += this->skelAnime.playSpeed * updateScale; diff --git a/tools/disasm/gc-eu-mq/variables.txt b/tools/disasm/gc-eu-mq/variables.txt index 7be392076d..7bcb196227 100644 --- a/tools/disasm/gc-eu-mq/variables.txt +++ b/tools/disasm/gc-eu-mq/variables.txt @@ -41,7 +41,7 @@ sIdleThread = 0x80006590; // size:0x1B0 sIdleThreadStack = 0x80006740; // size:0x400 sIdleThreadInfo = 0x80006B40; // size:0x1C sBootThreadStack = 0x80006B60; // size:0x400 -gMainThread = 0x80006F60; // size:0x1B0 +sMainThread = 0x80006F60; // size:0x1B0 sMainStack = 0x80007110; // size:0x900 sMainStackInfo = 0x80007A10; // size:0x1C sPiMgrCmdBuff = 0x80007A30; // size:0xC8 @@ -570,9 +570,9 @@ sKaleidoScopeUpdateFunc = 0x8011B3C0; // size:0x4 sKaleidoScopeDrawFunc = 0x8011B3C4; // size:0x4 gBossMarkScale = 0x8011B3C8; // size:0x4 gLoadedPauseMarkDataTable = 0x8011B3D0; // size:0x4 -sTransitionTile = 0x8011B3E0; // size:0xE0 +gTransitionTile = 0x8011B3E0; // size:0xE0 gTransitionTileState = 0x8011B4C0; // size:0x4 -sPlayVisMono = 0x8011B4C8; // size:0x18 +gPlayVisMono = 0x8011B4C8; // size:0x18 gVisMonoColor = 0x8011B4E0; // size:0x4 D_801664D0 = 0x8011B4F0; // size:0x20 sVisCvg = 0x8011B510; // size:0x10 diff --git a/tools/ido_block_numbers.py b/tools/ido_block_numbers.py index 8858481dc2..2deb64c79c 100755 --- a/tools/ido_block_numbers.py +++ b/tools/ido_block_numbers.py @@ -222,7 +222,7 @@ def find_compiler_command_line(filename, oot_version): for line in make_output: parts = line.split() if "-o" in parts and str(filename) in parts: - makefile_command_line = parts + compiler_command_line = parts found += 1 if found != 1: @@ -231,49 +231,29 @@ def find_compiler_command_line(filename, oot_version): ) sys.exit(1) - # Assume command line is of the form: - # tools/reencode.sh [COMPILER] [COMPILER_ARGS] - compiler_command_line = makefile_command_line[1:] - print(f'Command line: {" ".join(compiler_command_line)}', file=sys.stderr) return compiler_command_line def generate_symbol_table(command_line): - # Find source file in compiler arguments - source_file = None - args = [] - for arg in command_line: - if arg.endswith(".c"): - source_file = Path(arg) - else: - args.append(arg) - - if source_file is None: - raise Exception("No source file found") - - source_contents = source_file.read_text() + # Assume command line is of the form: + # python3 tools/preprocess.py [COMPILER] [COMPILER_ARGS] [INPUT_FILE] + input_file = Path(command_line[-1]) + rest = command_line[:-1] - stem = "reencode_tmp" - input_file = Path(f"{stem}.c") + stem = input_file.stem symbol_table_file = Path(f"{stem}.T") ucode_file = Path(f"{stem}.B") try: - # Write temporary file with #line directive to simulate asm-processor - with open(input_file, "w") as f: - f.write('#line 1 "{}"\n'.format(source_file)) - f.write(source_contents) - # Invoke compiler # -Hf stops compilation after cfe so we can inspect the symbol table - subprocess.run(args + ["-Hf", input_file], check=True) + subprocess.run(rest + ["-Hf", input_file], check=True) # Read symbol table return symbol_table_file.read_bytes() finally: # Cleanup - input_file.unlink(missing_ok=True) symbol_table_file.unlink(missing_ok=True) ucode_file.unlink(missing_ok=True) diff --git a/tools/preprocess.py b/tools/preprocess.py new file mode 100755 index 0000000000..d84c3eef21 --- /dev/null +++ b/tools/preprocess.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: © 2024 ZeldaRET +# SPDX-License-Identifier: CC0-1.0 + +# Usage: preprocess.py [compile command minus input file...] [single input file] +# Preprocess a C file to: +# * Re-encode from UTF-8 to EUC-JP (the repo uses UTF-8 for text encoding, but +# the strings in the ROM are encoded in EUC-JP) +# * Replace `#pragma increment_block_number N` with `N` fake structs for +# controlling BSS ordering + +from pathlib import Path +import os +import tempfile +import subprocess +import sys + + +def fail(message): + print(message, file=sys.stderr) + sys.exit(1) + + +def process_file(filename, input, output): + output.write(f'#line 1 "{filename}"\n') + for i, line in enumerate(input, start=1): + if line.startswith("#pragma increment_block_number"): + parts = line.split() + if len(parts) != 3: + fail( + f"{filename}:{i}: increment_block_number must be followed by an integer" + ) + try: + amount = int(parts[2]) + except ValueError: + fail( + f"{filename}:{i}: increment_block_number must be followed by an integer" + ) + # Write fake structs for BSS ordering + for j in range(amount): + output.write(f"struct DummyStruct_{i:05}_{j:03};\n") + output.write(f'#line {i + 1} "{filename}"\n') + else: + output.write(line) + + +def main(): + filename = Path(sys.argv[-1]) + with tempfile.TemporaryDirectory(prefix="oot_") as tmpdir: + tmpfile = Path(tmpdir) / filename.name + + with open(filename, mode="r", encoding="utf-8") as input: + with open(tmpfile, mode="w", encoding="euc-jp") as output: + process_file(filename, input, output) + + compile_command = sys.argv[1:-1] + ["-I", filename.parent, tmpfile] + process = subprocess.run(compile_command) + return process.returncode + + +if __name__ == "__main__": + try: + sys.exit(main()) + except KeyboardInterrupt: + sys.exit(1) diff --git a/tools/reencode.sh b/tools/reencode.sh deleted file mode 100755 index d027faf5b9..0000000000 --- a/tools/reencode.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# The repo uses UTF-8 for text encoding, but the strings in the ROM are encoded in EUC-JP. -# This means for matching the source must be re-encoded to EUC-JP before IDO compiles it. -# This is conceptually equivalent to `gcc --finput-charset=UTF-8 --fexec-charset=EUC-JP`, -# except IDO has no equivalent arguments. -# Usage: reencode.sh [compile command minus input file...] [single input file] - -set -e - -# The last argument, the input source file to be compiled -srcfile="${@: -1}" - -# Create a temporary file, and remove it on script exit -tempfile=`mktemp`_oot.c -trap "rm -f $tempfile" EXIT - -# Re-encode from UTF-8 to EUC-JP -{ - printf '#line 1 "%s"\n' "$srcfile" # linemarker - cat "$srcfile" -} | iconv -f UTF-8 -t EUC-JP > "$tempfile" - -# All arguments but the last, forming the compile command -# Also include the source file's directory to have the include path as if we compiled the original source. -# Pass the EUC-JP encoded temporary file for compilation. -"${@:1:$# - 1}" -I `dirname $srcfile` $tempfile