1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-07-12 19:04:38 +00:00

Merge commit 'f643499462' into doc_pause_menu

This commit is contained in:
Dragorn421 2024-08-01 20:34:36 +02:00
commit 3786fa4062
No known key found for this signature in database
GPG key ID: 381AEBAF3D429335
35 changed files with 1445 additions and 1121 deletions

View file

@ -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
@ -70,7 +67,7 @@ EXTRACTED_DIR := extracted/$(VERSION)
VENV := .venv
MAKE = make
CPPFLAGS += -fno-dollars-in-identifiers -P
CPPFLAGS += -P -xc -fno-dollars-in-identifiers
ifeq ($(DEBUG),1)
CFLAGS += -DOOT_DEBUG=1
@ -92,7 +89,6 @@ else
ifeq ($(UNAME_S),Darwin)
DETECTED_OS=macos
MAKE=gmake
CPPFLAGS += -xc++
endif
endif
@ -136,7 +132,9 @@ INC := -Iinclude -Iinclude/libc -Isrc -I$(BUILD_DIR) -I. -I$(EXTRACTED_DIR)
# Check code syntax with host compiler
CHECK_WARNINGS := -Wall -Wextra -Wno-format-security -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-variable -Wno-missing-braces
CPP := cpp
# The `cpp` command behaves differently on macOS (it behaves as if
# `-traditional-cpp` was passed) so we use `gcc -E` instead.
CPP := gcc -E
MKLDSCRIPT := tools/mkldscript
MKDMADATA := tools/mkdmadata
ELF2ROM := tools/elf2rom
@ -311,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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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];

View file

@ -801,8 +801,8 @@ typedef struct Player {
/* 0x0690 */ s16 naviTextId;
/* 0x0692 */ u8 stateFlags3;
/* 0x0693 */ s8 exchangeItemId;
/* 0x0694 */ Actor* targetActor;
/* 0x0698 */ f32 targetActorDistance;
/* 0x0694 */ Actor* talkActor; // Actor offering to talk, or currently talking to, depending on context
/* 0x0698 */ f32 talkActorDistance; // xz distance away from `talkActor`
/* 0x069C */ char unk_69C[0x004];
/* 0x06A0 */ f32 unk_6A0;
/* 0x06A4 */ f32 closestSecretDistSq;

10
spec
View file

@ -318,6 +318,7 @@ beginseg
name "code"
compress
after "dmadata"
align 0x20
include "$(BUILD_DIR)/src/code/z_en_a_keep.o"
include "$(BUILD_DIR)/src/code/z_en_item00.o"
include "$(BUILD_DIR)/src/code/z_eff_blure.o"
@ -447,15 +448,11 @@ 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"
#endif
pad_text // audio library aligned to 32 bytes?
pad_text // on GameCube, NTSC 1.0 and "0.9" prerelease
include "$(BUILD_DIR)/src/audio/lib/data.o"
include "$(BUILD_DIR)/src/audio/lib/synthesis.o"
include "$(BUILD_DIR)/src/audio/lib/heap.o"
@ -467,6 +464,9 @@ beginseg
include "$(BUILD_DIR)/src/audio/lib/effects.o"
include "$(BUILD_DIR)/src/audio/lib/seqplayer.o"
include "$(BUILD_DIR)/src/audio/general.o"
#if !OOT_DEBUG
pad_text // on retail GameCube
#endif
include "$(BUILD_DIR)/src/audio/sfx_params.o"
include "$(BUILD_DIR)/src/audio/sfx.o"
include "$(BUILD_DIR)/src/audio/sequence.o"

View file

@ -127,7 +127,10 @@ u8 sAudioBaseFilter2 = 0;
u8 sAudioExtraFilter2 = 0;
Vec3f* sSariaBgmPtr = NULL;
f32 D_80130650 = 2000.0f;
#if OOT_DEBUG
u8 sSeqModeInput = 0;
#endif
#define SEQ_FLAG_ENEMY (1 << 0) // Allows enemy bgm
#define SEQ_FLAG_FANFARE (1 << 1)

View file

@ -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 (;;) {}

View file

@ -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*);

View file

@ -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;

View file

@ -159,7 +159,9 @@ void Graph_Destroy(GraphicsContext* gfxCtx) {
}
void Graph_TaskSet00(GraphicsContext* gfxCtx) {
#if OOT_DEBUG
static Gfx* sPrevTaskWorkBuffer = NULL;
#endif
static s32 sGraphCfbInfoIdx = 0;
OSTime timeNow;

View file

@ -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,

View file

@ -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;
@ -1601,13 +1604,13 @@ s32 Actor_OfferTalkExchange(Actor* actor, PlayState* play, f32 xzRange, f32 yRan
if ((player->actor.flags & ACTOR_FLAG_TALK) || ((exchangeItemId != EXCH_ITEM_NONE) && Player_InCsMode(play)) ||
(!actor->isTargeted &&
((yRange < fabsf(actor->yDistToPlayer)) || (player->targetActorDistance < actor->xzDistToPlayer) ||
((yRange < fabsf(actor->yDistToPlayer)) || (player->talkActorDistance < actor->xzDistToPlayer) ||
(xzRange < actor->xzDistToPlayer)))) {
return false;
}
player->targetActor = actor;
player->targetActorDistance = actor->xzDistToPlayer;
player->talkActor = actor;
player->talkActorDistance = actor->xzDistToPlayer;
player->exchangeItemId = exchangeItemId;
return true;
@ -1697,7 +1700,7 @@ s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange
if (!(player->stateFlags1 & (PLAYER_STATE1_7 | PLAYER_STATE1_12 | PLAYER_STATE1_13 | PLAYER_STATE1_14 |
PLAYER_STATE1_18 | PLAYER_STATE1_19 | PLAYER_STATE1_20 | PLAYER_STATE1_21)) &&
Player_GetExplosiveHeld(player) < 0) {
if ((((player->heldActor != NULL) || (actor == player->targetActor)) && (getItemId > GI_NONE) &&
if ((((player->heldActor != NULL) || (actor == player->talkActor)) && (getItemId > GI_NONE) &&
(getItemId < GI_MAX)) ||
(!(player->stateFlags1 & (PLAYER_STATE1_11 | PLAYER_STATE1_29)))) {
if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) {
@ -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;
@ -2204,7 +2209,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
}
if ((player->stateFlags1 & PLAYER_STATE1_6) && ((player->actor.textId & 0xFF00) != 0x600)) {
sp74 = player->targetActor;
sp74 = player->talkActor;
}
for (i = 0; i < ARRAY_COUNT(actorCtx->actorLists); i++, categoryFreezeMaskP++) {

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,8 @@ typedef struct {
/*==================================================================*/
// Data
#if OOT_DEBUG
s16 sOREGInit[] = {
0, // OREG(0)
1, // OREG(1)
@ -83,6 +85,7 @@ s16 sOREGInit[] = {
};
s16 sOREGInitCnt = ARRAY_COUNT(sOREGInit);
#endif
s16 sCamDataRegsInit[CAM_DATA_MAX] = {
-20, // CAM_DATA_Y_OFFSET
@ -116,6 +119,7 @@ s16 sCamDataRegsInit[CAM_DATA_MAX] = {
s16 sCamDataRegsInitCount = ARRAY_COUNT(sCamDataRegsInit);
#if OOT_DEBUG
char sCameraSettingNames[][12] = {
"NONE ", // CAM_SET_NONE
"NORMAL0 ", // CAM_SET_NORMAL0
@ -208,6 +212,7 @@ char sCameraModeNames[][12] = {
"PUSHPULL ", // CAM_MODE_PUSH_PULL
"BOOKEEPON ", // CAM_MODE_FOLLOW_BOOMERANG
};
#endif
/**
*=====================================================================
@ -2556,7 +2561,11 @@ s32 (*sCameraFunctions[])(Camera*) = {
s32 sInitRegs = 1;
s32 gDebugCamEnabled = false;
#if OOT_DEBUG
s32 sDbgModeIdx = -1;
#endif
s16 sNextUID = 0;
s32 sCameraInterfaceField = CAM_INTERFACE_FIELD(CAM_LETTERBOX_NONE, CAM_HUD_VISIBILITY_ALL, 1);
@ -2579,6 +2588,7 @@ s32 D_8011D3F0 = 0;
s32 sDemo5PrevAction12Frame = -16;
#if OOT_DEBUG
char sCameraFunctionNames[][8] = {
"NONE ", // CAM_FUNC_NONE
"NORM0()", // CAM_FUNC_NORM0
@ -2653,6 +2663,7 @@ char sCameraFunctionNames[][8] = {
"SPEC9()", // CAM_FUNC_SPEC9
"", "", "", "", "",
};
#endif
VecSph D_8011D658[] = {
{ 50.0f, 0xEE3A, 0xD558 },
@ -2668,371 +2679,10 @@ Vec3f D_8011D678[] = {
{ 0.0f, 3.0f, -3.0 },
};
/*******************************************************
* OnePoint initalization values for Attention Cutscenes (Demo5)
********************************************************/
s32 sDemo5PrevSfxFrame = -200;
// target is player, far from eye
OnePointCsFull D_8011D6AC[] = {
{
// viewFlags & 0x00FF (at): 2, atTarget is view lookAt + atInit
// viewFlags & 0xFF00 (eye): none
// action: 15, copy at, eye, roll, fov to camera
// result: eye remains in the same location, at is View's lookAt
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_15, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0002,
1,
0,
60.0f,
1.0f,
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
},
{
// viewFlags & 0x00FF (at): 3, atTarget is camera's current at + atInit
// viewFlags & 0xFF00 (eye): 3, eyeTarget is the camera's current eye + eyeInit
// action: interpolate eye and at.
// result: eye and at's y interpolate to become +20 from their current location.
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_1, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0303,
19,
0,
45.0f,
1.0f,
{ 0.0f, 20.0f, 0.0f },
{ 0.0f, 20.0f, 0.0f },
},
{
// viewFlags & 0x00FF (at): 0 none
// viewFlags & 0xFF00 (eye): 0 none
// action: 18, copy this camera to default camera.
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_18, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0000,
1,
0,
60.0f,
1.0f,
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
},
};
// target is player close to current eye
OnePointCsFull D_8011D724[] = {
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_15, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x2424,
1,
0,
60.0f,
1.0f,
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 10.0f, -20.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_1, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x2121,
19,
0,
50.0f,
1.0f,
{ 0.0f, -10.0f, 0.0f },
{ 0.0f, 0.0f, 60.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_18, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0000,
1,
0,
60.0f,
1.0f,
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
},
};
// target is close to player
OnePointCsFull D_8011D79C[] = {
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_15, true, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0002,
1,
0,
60.0f,
1.0f,
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_1, true, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0303,
19,
0,
45.0f,
1.0f,
{ 0.0f, -20.0f, 0.0f },
{ 0.0f, -10.0f, 5.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_1, true, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0303,
9,
0,
60.0f,
1.0f,
{ 0.0f, 10.0f, 0.0f },
{ 0.0f, 10.0f, 0.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_18, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0000,
1,
0,
60.0f,
1.0f,
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
},
};
// target is within 300 units of eye, and player is within 30 units of eye
OnePointCsFull D_8011D83C[] = {
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_3, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x2141,
20,
0,
45.0f,
0.2f,
{ 0.0f, 0.0f, 10.0f },
{ 0.0f, 0.0f, 10.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_18, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0000,
1,
0,
60.0f,
1.0f,
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
},
};
// target is within 700 units of eye, angle between player/eye and target/eye is less than
// 76.9 degrees. The x/y coordinates of the target on screen is between (21, 41) and (300, 200),
// and the player is farther than 30 units of the eye
OnePointCsFull D_8011D88C[] = {
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_1, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0303,
20,
0,
45.0f,
1.0f,
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_18, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0000,
1,
0,
60.0f,
1.0f,
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
},
};
// same as above, but the target is NOT within the screen area.
OnePointCsFull D_8011D8DC[] = {
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_15, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0404,
20,
1,
50.0f,
1.0f,
{ 0.0f, 5.0f, 10.0f },
{ 0.0f, 10.0f, -80.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_2, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x2121,
5,
0,
60.0f,
1.0f,
{ 0.0f, 5.0f, 0.0f },
{ 5.0f, 5.0f, -200.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_18, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0000,
1,
0,
60.0f,
1.0f,
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
},
};
// target is a door.
OnePointCsFull D_8011D954[] = {
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_15, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0xC1C1,
20,
0,
60.0f,
1.0f,
{ 0.0f, 0.0f, 50.0f },
{ 0.0f, 0.0f, 250.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_3, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x05B1,
5,
0,
60.0f,
0.1f,
{ 0.0f, 10.0f, 50.0f },
{ 0.0f, 10.0f, 100.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_2, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x2121,
5,
2,
60.0f,
1.0f,
{ 0.0f, 10.0f, 0.0f },
{ 0.0f, 20.0f, -150.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_18, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0000,
1,
0,
60.0f,
1.0f,
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
},
};
// otherwise
OnePointCsFull D_8011D9F4[] = {
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_15, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0504,
20,
2,
60.0f,
1.0f,
{ 0.0f, 5.0f, 50.0f },
{ 0.0f, 20.0f, 300.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_2, false, true),
ONEPOINT_CS_INIT_FIELD_NONE,
0x2121,
5,
2,
60.0f,
1.0f,
{ 0.0f, 10.0f, 0.0f },
{ 0.0f, 20.0f, -150.0f },
},
{
ONEPOINT_CS_ACTION(ONEPOINT_CS_ACTION_ID_18, false, false),
ONEPOINT_CS_INIT_FIELD_NONE,
0x0000,
1,
0,
60.0f,
1.0f,
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
},
};
typedef enum {
/* 0 */ CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_LOWER_FLOOR, // ACTOR_BG_HIDAN_ROCK
/* 1 */ CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_EAST_TOWER, // ACTOR_BG_HIDAN_FSLIFT
/* 2 */ CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_WEST_TOWER, // ACTOR_BG_HIDAN_SYOKU
/* 3 */ CAM_ELEVATOR_PLATFORM_SPIRIT_TEMPLE_ENTRANCE // ACTOR_BG_JYA_1FLIFT
} CamElevatorPlatform;
Vec3f sCamElevatorPlatformLowerEyePoints[] = {
{ 3050.0f, 700.0f, 0.0f }, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_LOWER_FLOOR
{ 1755.0f, 3415.0f, -380.0f }, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_EAST_TOWER
{ -3120.0f, 3160.0f, 245.0f }, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_WEST_TOWER
{ 0.0f, -10.0f, 240.0f }, // CAM_ELEVATOR_PLATFORM_SPIRIT_TEMPLE_ENTRANCE
};
Vec3f sCamElevatorPlatformUpperEyePoints[] = {
{ 3160.0f, 2150.0f, 0.0f }, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_LOWER_FLOOR
{ 1515.0f, 4130.0f, -835.0f }, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_EAST_TOWER
{ -3040.0f, 4135.0f, 230.0f }, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_WEST_TOWER
{ -50.0f, 600.0f, -75.0f }, // CAM_ELEVATOR_PLATFORM_SPIRIT_TEMPLE_ENTRANCE
};
// Trigger player y position to swap eye points
f32 sCamElevatorPlatformTogglePosY[] = {
1570.0f, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_LOWER_FLOOR
3680.0f, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_EAST_TOWER
3700.0f, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_WEST_TOWER
395.0f, // CAM_ELEVATOR_PLATFORM_SPIRIT_TEMPLE_ENTRANCE
};
f32 sCamElevatorPlatformFovRollParam[] = {
320.0f, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_LOWER_FLOOR
320.0f, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_EAST_TOWER
320.0f, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_WEST_TOWER
0.0f, // CAM_ELEVATOR_PLATFORM_SPIRIT_TEMPLE_ENTRANCE
};
s16 sCamElevatorPlatformRolls[] = {
-2000, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_LOWER_FLOOR
-1000, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_EAST_TOWER
0, // CAM_ELEVATOR_PLATFORM_FIRE_TEMPLE_WEST_TOWER
0 // CAM_ELEVATOR_PLATFORM_SPIRIT_TEMPLE_ENTRANCE
};
// unused
s32 D_8011DAF4 = 0;
s32 D_8011DAF8 = 0;
s16 D_8011DAFC[] = {
CAM_SET_NORMAL0, CAM_SET_NORMAL1, CAM_SET_NORMAL2, CAM_SET_DUNGEON0, CAM_SET_DUNGEON1, CAM_SET_DUNGEON2,
};
PlayState* D_8015BD7C;
#if OOT_DEBUG
DebugCam D_8015BD80;
#endif
CollisionPoly* playerFloorPoly;

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}

View file

@ -3060,7 +3060,6 @@ void Message_Update(PlayState* play) {
0x0015, 0x0016, 0x0017, 0x0003, 0x0000, 0x270B, 0x00C8, 0x012C, 0x012D, 0xFFDA, 0x0014, 0x0016, 0x0014, 0x0016,
};
static u8 D_80153D74 = 0;
static u16 D_80153D78 = 0;
MessageContext* msgCtx = &play->msgCtx;
InterfaceContext* interfaceCtx = &play->interfaceCtx;
Player* player = GET_PLAYER(play);
@ -3073,10 +3072,12 @@ void Message_Update(PlayState* play) {
#if OOT_DEBUG
if (BREG(0) != 0) {
static u16 sMessageDebuggerTextboxCount = 0;
if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN) && CHECK_BTN_ALL(input->cur.button, BTN_L)) {
PRINTF("msgno=%d\n", D_80153D78);
PRINTF("msgno=%d\n", sMessageDebuggerTextboxCount);
Message_StartTextbox(play, R_MESSAGE_DEBUGGER_TEXTID, NULL);
D_80153D78 = (D_80153D78 + 1) % 10;
sMessageDebuggerTextboxCount = (sMessageDebuggerTextboxCount + 1) % 10;
}
if (R_MESSAGE_DEBUGGER_SELECT != 0) {
while (R_MESSAGE_DEBUGGER_TEXTID != 0x8000) {
@ -3358,8 +3359,10 @@ void Message_SetTables(void) {
sStaffMessageEntryTablePtr = sStaffMessageEntryTable;
}
#if OOT_DEBUG
// Appears to be file padding
UNK_TYPE D_80153D7C = 0x00000000;
#endif
// This should be part of z_game_over.c, but cannot be moved there as the entire
// late_rodata section of this file is in the way

View file

@ -2,13 +2,16 @@
#include "quake.h"
#include "terminal.h"
#if OOT_DEBUG
void* gDebugCutsceneScript = NULL;
UNK_TYPE D_8012D1F4 = 0; // unused
#endif
Input* D_8012D1F8 = NULL;
TransitionTile sTransitionTile;
TransitionTile gTransitionTile;
s32 gTransitionTileState;
VisMono sPlayVisMono;
VisMono gPlayVisMono;
Color_RGBA8_u32 gVisMonoColor;
#if OOT_DEBUG
@ -196,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;
}
@ -208,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();
@ -406,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);
@ -518,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:
@ -684,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;
}
@ -1132,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++);
@ -1144,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;
}

145
src/makerom/rom_header.h Normal file
View file

@ -0,0 +1,145 @@
#ifndef ROM_HEADER_H
#define ROM_HEADER_H
/* Storage medium IDs, used internally in MEDIUM below */
#define STORAGE_MEDIUM_CARTRIDGE "N"
#define STORAGE_MEDIUM_CARTRIDGE_EXPANDABLE "C"
#define STORAGE_MEDIUM_DISK "D"
#define STORAGE_MEDIUM_DISK_EXPANSION "E"
/* Region IDs, used internally in REGION below */
#define REGION_CODE_ALL "A"
#define REGION_CODE_JP "J"
#define REGION_CODE_US "E"
#define REGION_CODE_PAL "P"
#define REGION_CODE_GATEWAY "G"
#define REGION_CODE_LODGENET "L"
/**
* Magic value to determine if the ROM is byteswapped.
*
* This is not totally reliable since the PI Domain 1 Latency could also hold this value, however generally it can be
* assumed that this is not the case.
*/
#define ENDIAN_IDENTIFIER \
.byte 0x80
/**
* Configures the timings for PI Domain 1. This determines how fast the PI hardware will read from the ROM. IPL2 reads
* this configuration using the slowest possible configuration before switching to the provided configuration.
*/
#define PI_DOMAIN_1_CFG(lat, pwd, pgs, rls) \
.byte (((rls) & 3) << 4) | ((pgs) & 0xF); \
.byte (pwd) & 0xFF; \
.byte (lat) & 0xFF
/**
* Some older libultra versions use this field to set osClockRate. It does not have any other meaningful effect, the
* clock rate of physical units does not actually change to match this value.
*/
#define SYSTEM_CLOCK_RATE_SETTING(num) \
.word (num)
/**
* Indicates the entrypoint address of the program that IPL3 will load the boot segment to and execute.
* This should be >= 0x80000400.
*/
#define ENTRYPOINT(sym) \
.word (sym)
/**
* Indicates the hardware revision the program is designed for (hw_major, hw_minor)
* and what libultra version (os_ver) it uses.
*
* The hardware revision for a retail N64 is (2,0).
* The libultra version may be a single letter, without quotes.
*/
#define LIBULTRA_VERSION(hw_major, hw_minor, os_ver) \
.half 0; \
.byte (hw_major) * 10 + (hw_minor); \
_os_ver_start = .; \
.ascii #os_ver ; \
.if (. - _os_ver_start) != 1; \
.error "OS version should be just one letter"; \
.endif
/**
* Leaves space to insert the ROM Checksum value. IPL3 computes a checksum over ROM data in the range 0x1000 to 0x101000
* and compares it to this value, if the results differ it will refuse to boot the program.
*
* This macro just writes 8 bytes of 0. The correct checksum value is filled in after the full ROM image is available to
* compute the checksum with.
*/
#define CHECKSUM() \
.word 0, 0
/**
* For unused header space. Fills num bytes with 0.
*/
#define PADDING(num) \
.fill (num)
/**
* Defines the ROM name. This should be a string that is at most 20 characters long, a null terminator is not required.
* If a name is less than 20 characters, the remaining space will be padded with spaces.
*/
#define ROM_NAME(name) \
_name_start = .; \
.ascii name; \
.if (. - _name_start) > 20; \
.error "ROM name too long, must be at most 20 characters"; \
.endif; \
.if (. - _name_start) < 20; \
.fill 20 - (. - _name_start), 1, 0x20; \
.endif
/**
* Identifies the storage medium the program intends to use.
*
* Should be one of:
* - CARTRIDGE
* - CARTRIDGE_EXPANDABLE
* - DISK
* - DISK_EXPANSION
*/
#define MEDIUM(type) \
.ascii STORAGE_MEDIUM_##type
/**
* Two-letter game identifier. Should be wrapped in quotes.
*/
#define GAME_ID(id) \
_game_id_start = .; \
.ascii id ; \
.if (. - _game_id_start) != 2; \
.error "Game ID should be two letters"; \
.endif
/**
* Identifies the region the game is made for.
*
* Should be one of:
* - ALL
* - JP
* - US
* - PAL
* - GATEWAY
* - LODGENET
*
* Note: Often flashcarts and emulators will read this value to determine whether to act as an NTSC or PAL system and
* will adjust the VI timings appropriately, which may be used to determine target FPS.
* This can lead to glitchy video output on hardware if the program configures a video mode other than the native
* video mode for the hardware version.
*/
#define REGION(name) \
.ascii REGION_CODE_##name
/**
* Identifies the game revision number. Can be between 0 and 255.
*/
#define GAME_REVISION(num) \
.byte (num)
#endif

View file

@ -1,18 +1,15 @@
/*
* The Legend of Zelda: Ocarina of Time ROM header
*/
#include "rom_header.h"
.byte 0x80, 0x37, 0x12, 0x40 /* PI BSD Domain 1 register */
.word 0x0000000F /* Clockrate setting */
.word 0x80000400 /* Entrypoint function (`entrypoint`) */
.word 0x0000144C /* Revision */
.word 0x917D18F6 /* Checksum 1 */
.word 0x69BC5453 /* Checksum 2 */
.word 0x00000000 /* Unknown */
.word 0x00000000 /* Unknown */
.ascii "THE LEGEND OF ZELDA " /* Internal ROM name */
.word 0x00000000 /* Unknown */
.word 0x0000004E /* Cartridge */
.ascii "ZL" /* Cartridge ID */
.ascii "P" /* Region */
.byte 0x0F /* Version */
/* 0x00 */ ENDIAN_IDENTIFIER
/* 0x01 */ PI_DOMAIN_1_CFG(64, 18, 7, 3)
/* 0x04 */ SYSTEM_CLOCK_RATE_SETTING(0xF)
/* 0x08 */ ENTRYPOINT(0x80000400)
/* 0x0C */ LIBULTRA_VERSION(2, 0, L)
/* 0x10 */ CHECKSUM()
/* 0x18 */ PADDING(8)
/* 0x20 */ ROM_NAME("THE LEGEND OF ZELDA")
/* 0x34 */ PADDING(7)
/* 0x3B */ MEDIUM(CARTRIDGE)
/* 0x3C */ GAME_ID("ZL")
/* 0x3E */ REGION(PAL)
/* 0x3F */ GAME_REVISION(15)

View file

@ -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;

View file

@ -235,6 +235,7 @@ void EnBa_SwingAtPlayer(EnBa* this, PlayState* play) {
s16 phi_fp;
Math_SmoothStepToF(&this->actor.world.pos.y, this->actor.home.pos.y + 60.0f, 1.0f, 10.0f, 0.0f);
if ((this->actor.xzDistToPlayer <= 175.0f) || (this->unk_31A != 0)) {
if (this->unk_318 == 20) {
Actor_PlaySfx(&this->actor, NA_SE_EN_BALINADE_HAND_UP);
@ -300,16 +301,22 @@ void EnBa_SwingAtPlayer(EnBa* this, PlayState* play) {
}
this->unk_2A8[13].x = this->unk_2A8[12].x;
this->unk_2A8[13].y = this->unk_2A8[12].y;
//! @bug This code being located here gives multiple opportunities for the current action to change
//! before damage handling can be done.
//! By, for example, taking damage on the same frame the collider contacts Player, a different action
//! will run and `AT_HIT` will remain set. Then when returning back to this action, Player
//! will get knocked back instantly, even though there was no apparent collision.
//! Handling `AT_HIT` directly in Update, where it can run every frame, would help catch these edge cases.
if (this->collider.base.atFlags & AT_HIT) {
this->collider.base.atFlags &= ~AT_HIT;
if (this->collider.base.at == &player->actor) {
func_8002F71C(play, &this->actor, 8.0f, this->actor.yawTowardsPlayer, 8.0f);
}
}
CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base);
return;
}
if ((this->actor.xzDistToPlayer > 175.0f) || (player->stateFlags1 & PLAYER_STATE1_26)) {
} else if ((this->actor.xzDistToPlayer > 175.0f) || (player->stateFlags1 & PLAYER_STATE1_26)) {
EnBa_SetupIdle(this);
} else {
EnBa_SetupSwingAtPlayer(this);

View file

@ -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);

View file

@ -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

View file

@ -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] = {
@ -5131,8 +5144,8 @@ void func_8083A2F8(PlayState* play, Player* this) {
this->stateFlags1 |= PLAYER_STATE1_6 | PLAYER_STATE1_29;
if (this->actor.textId != 0) {
Message_StartTextbox(play, this->actor.textId, this->targetActor);
this->unk_664 = this->targetActor;
Message_StartTextbox(play, this->actor.textId, this->talkActor);
this->unk_664 = this->talkActor;
}
}
@ -5499,7 +5512,7 @@ s32 Player_ActionChange_13(Player* this, PlayState* play) {
s32 sp2C;
s32 sp28;
GetItemEntry* giEntry;
Actor* targetActor;
Actor* talkActor;
if ((this->unk_6AD != 0) && (func_808332B8(this) || (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) ||
(this->stateFlags1 & PLAYER_STATE1_23))) {
@ -5526,7 +5539,7 @@ s32 Player_ActionChange_13(Player* this, PlayState* play) {
(sp28 = Player_ActionToBottle(this, this->itemAction) - 1,
((sp28 >= 0) && (sp28 < 6) &&
((this->itemAction > PLAYER_IA_BOTTLE_POE) ||
((this->targetActor != NULL) && (((this->itemAction == PLAYER_IA_BOTTLE_POE) &&
((this->talkActor != NULL) && (((this->itemAction == PLAYER_IA_BOTTLE_POE) &&
(this->exchangeItemId == EXCH_ITEM_BOTTLE_POE)) ||
(this->exchangeItemId == EXCH_ITEM_BOTTLE_BLUE_FIRE))))))) {
@ -5546,9 +5559,9 @@ s32 Player_ActionChange_13(Player* this, PlayState* play) {
sp2C = sp28 + 0x18;
}
targetActor = this->targetActor;
talkActor = this->talkActor;
if ((targetActor != NULL) &&
if ((talkActor != NULL) &&
((this->exchangeItemId == sp2C) || (this->exchangeItemId == EXCH_ITEM_BOTTLE_BLUE_FIRE) ||
((this->exchangeItemId == EXCH_ITEM_BOTTLE_POE) &&
(this->itemAction == PLAYER_IA_BOTTLE_BIG_POE)) ||
@ -5563,8 +5576,8 @@ s32 Player_ActionChange_13(Player* this, PlayState* play) {
this->av2.actionVar2 = 0x50;
this->av1.actionVar1 = -1;
}
targetActor->flags |= ACTOR_FLAG_TALK;
this->unk_664 = this->targetActor;
talkActor->flags |= ACTOR_FLAG_TALK;
this->unk_664 = this->talkActor;
} else if (sp2C == EXCH_ITEM_BOTTLE_RUTOS_LETTER) {
this->av1.actionVar1 = 1;
this->actor.textId = 0x4005;
@ -5642,7 +5655,7 @@ s32 Player_ActionChange_13(Player* this, PlayState* play) {
}
s32 Player_ActionChange_4(Player* this, PlayState* play) {
Actor* sp34 = this->targetActor;
Actor* sp34 = this->talkActor;
Actor* sp30 = this->unk_664;
Actor* sp2C = NULL;
s32 sp28 = 0;
@ -5691,7 +5704,7 @@ s32 Player_ActionChange_4(Player* this, PlayState* play) {
}
sp34 = sp2C;
this->targetActor = NULL;
this->talkActor = NULL;
if (sp28 || !sp24) {
sp2C->textId = ABS(this->naviTextId);
@ -10152,8 +10165,8 @@ void func_808473D4(PlayState* play, Player* this) {
doAction = DO_ACTION_CLIMB;
} else if ((this->stateFlags1 & PLAYER_STATE1_23) && !EN_HORSE_CHECK_4((EnHorse*)this->rideActor) &&
(Player_Action_8084D3E4 != this->actionFunc)) {
if ((this->stateFlags2 & PLAYER_STATE2_1) && (this->targetActor != NULL)) {
if (this->targetActor->category == ACTORCAT_NPC) {
if ((this->stateFlags2 & PLAYER_STATE2_1) && (this->talkActor != NULL)) {
if (this->talkActor->category == ACTORCAT_NPC) {
doAction = DO_ACTION_SPEAK;
} else {
doAction = DO_ACTION_CHECK;
@ -10161,8 +10174,8 @@ void func_808473D4(PlayState* play, Player* this) {
} else if (!func_8002DD78(this) && !(this->stateFlags1 & PLAYER_STATE1_20)) {
doAction = DO_ACTION_FASTER;
}
} else if ((this->stateFlags2 & PLAYER_STATE2_1) && (this->targetActor != NULL)) {
if (this->targetActor->category == ACTORCAT_NPC) {
} else if ((this->stateFlags2 & PLAYER_STATE2_1) && (this->talkActor != NULL)) {
if (this->talkActor->category == ACTORCAT_NPC) {
doAction = DO_ACTION_SPEAK;
} else {
doAction = DO_ACTION_CHECK;
@ -11211,10 +11224,10 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
func_808368EC(this, play);
if (CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_TALK)) {
this->targetActorDistance = 0.0f;
this->talkActorDistance = 0.0f;
} else {
this->targetActor = NULL;
this->targetActorDistance = MAXFLOAT;
this->talkActor = NULL;
this->talkActorDistance = MAXFLOAT;
this->exchangeItemId = EXCH_ITEM_NONE;
}
@ -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,
@ -11769,14 +11780,14 @@ void Player_Action_8084B530(Player* this, PlayState* play) {
if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
this->actor.flags &= ~ACTOR_FLAG_TALK;
if (!CHECK_FLAG_ALL(this->targetActor->flags, ACTOR_FLAG_0 | ACTOR_FLAG_2)) {
if (!CHECK_FLAG_ALL(this->talkActor->flags, ACTOR_FLAG_0 | ACTOR_FLAG_2)) {
this->stateFlags2 &= ~PLAYER_STATE2_13;
}
Camera_SetFinishedFlag(Play_GetCamera(play, CAM_ID_MAIN));
if (!func_8084B4D4(play, this) && !func_8084B3CC(play, this) && !Player_StartCsAction(play, this)) {
if ((this->targetActor != this->interactRangeActor) || !Player_ActionChange_2(this, play)) {
if ((this->talkActor != this->interactRangeActor) || !Player_ActionChange_2(this, play)) {
if (this->stateFlags1 & PLAYER_STATE1_23) {
s32 sp24 = this->av2.actionVar2;
func_8083A360(play, this);
@ -11800,7 +11811,7 @@ void Player_Action_8084B530(Player* this, PlayState* play) {
} else if (!func_8008E9C4(this) && LinkAnimation_Update(play, &this->skelAnime)) {
if (this->skelAnime.moveFlags != 0) {
func_80832DBC(this);
if ((this->targetActor->category == ACTORCAT_NPC) && (this->heldItemAction != PLAYER_IA_FISHING_POLE)) {
if ((this->talkActor->category == ACTORCAT_NPC) && (this->heldItemAction != PLAYER_IA_FISHING_POLE)) {
Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_normal_talk_free);
} else {
Player_AnimPlayLoop(play, this, func_80833338(this));
@ -13004,12 +13015,12 @@ void Player_Action_8084E3C4(Player* this, PlayState* play) {
if (play->msgCtx.ocarinaMode == OCARINA_MODE_04) {
Camera_SetFinishedFlag(Play_GetCamera(play, CAM_ID_MAIN));
if ((this->targetActor != NULL) && (this->targetActor == this->unk_6A8)) {
func_80853148(play, this->targetActor);
if ((this->talkActor != NULL) && (this->talkActor == this->unk_6A8)) {
func_80853148(play, this->talkActor);
} else if (this->naviTextId < 0) {
this->targetActor = this->naviActor;
this->talkActor = this->naviActor;
this->naviActor->textId = -this->naviTextId;
func_80853148(play, this->targetActor);
func_80853148(play, this->talkActor);
} else if (!Player_ActionChange_13(this, play)) {
func_8083A098(this, &gPlayerAnim_link_normal_okarina_end, play);
}
@ -13073,8 +13084,8 @@ void Player_Action_8084E6D4(Player* this, PlayState* play) {
}
if (func_8084DFF4(play, this) && (this->av2.actionVar2 == 1)) {
cond = ((this->targetActor != NULL) && (this->exchangeItemId < 0)) ||
(this->stateFlags3 & PLAYER_STATE3_5);
cond =
((this->talkActor != NULL) && (this->exchangeItemId < 0)) || (this->stateFlags3 & PLAYER_STATE3_5);
if (cond || (gSaveContext.healthAccumulator == 0)) {
if (cond) {
@ -13082,7 +13093,7 @@ void Player_Action_8084E6D4(Player* this, PlayState* play) {
this->exchangeItemId = EXCH_ITEM_NONE;
if (func_8084B4D4(play, this) == 0) {
func_80853148(play, this->targetActor);
func_80853148(play, this->talkActor);
}
} else {
func_8084DFAC(play, this);
@ -13360,14 +13371,14 @@ void Player_Action_8084F104(Player* this, PlayState* play) {
if (this->av2.actionVar2 < 0) {
func_8083C0E8(this, play);
} else if (this->exchangeItemId == EXCH_ITEM_NONE) {
Actor* targetActor = this->targetActor;
Actor* talkActor = this->talkActor;
this->unk_862 = 0;
if (targetActor->textId != 0xFFFF) {
if (talkActor->textId != 0xFFFF) {
this->actor.flags |= ACTOR_FLAG_TALK;
}
func_80853148(play, targetActor);
func_80853148(play, talkActor);
} else {
GetItemEntry* giEntry = &sGetItemTable[D_80854528[this->exchangeItemId - 1] - 1];
@ -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;
@ -15266,12 +15278,12 @@ void func_80853148(PlayState* play, Actor* actor) {
Player* this = GET_PLAYER(play);
s32 pad;
if ((this->targetActor != NULL) || (actor == this->naviActor) ||
if ((this->talkActor != NULL) || (actor == this->naviActor) ||
CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_0 | ACTOR_FLAG_18)) {
actor->flags |= ACTOR_FLAG_TALK;
}
this->targetActor = actor;
this->talkActor = actor;
this->exchangeItemId = EXCH_ITEM_NONE;
if (actor->textId == 0xFFFF) {
@ -15324,7 +15336,7 @@ void func_80853148(PlayState* play, Actor* actor) {
this->stateFlags1 |= PLAYER_STATE1_6 | PLAYER_STATE1_29;
}
if ((this->naviActor == this->targetActor) && ((this->targetActor->textId & 0xFF00) != 0x200)) {
if ((this->naviActor == this->talkActor) && ((this->talkActor->textId & 0xFF00) != 0x200)) {
this->naviActor->flags |= ACTOR_FLAG_TALK;
func_80835EA4(play, 0xB);
}

View file

@ -4506,7 +4506,7 @@ void KaleidoScope_Update(PlayState* play) {
gSaveContext.hudVisibilityMode = HUD_VISIBILITY_NO_CHANGE;
Interface_ChangeHudVisibilityMode(gSaveContext.prevHudVisibilityMode);
player->targetActor = NULL;
player->talkActor = NULL;
Player_SetEquipmentData(play, player);
PRINTF(VT_RST);

View file

@ -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

View file

@ -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)
# 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]
if source_file is None:
raise Exception("No source file found")
source_contents = source_file.read_text()
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)

View file

@ -51,11 +51,13 @@ static void write_ld_script(FILE *fout)
" ..%s ", seg->name, seg->name, seg->name, seg->name);
if (seg->fields & (1 << STMT_after))
fprintf(fout, "_%sSegmentEnd ", seg->after);
fprintf(fout, "(_%sSegmentEnd + %i) & ~ %i ", seg->after, seg->align - 1, seg->align - 1);
else if (seg->fields & (1 << STMT_number))
fprintf(fout, "0x%02X000000 ", seg->number);
else if (seg->fields & (1 << STMT_address))
fprintf(fout, "0x%08X ", seg->address);
else
fprintf(fout, "ALIGN(0x%X) ", seg->align);
// (AT(_RomSize) isn't necessary, but adds useful "load address" lines to the map file)
fprintf(fout, ": AT(_RomSize)\n {\n"
@ -64,9 +66,6 @@ static void write_ld_script(FILE *fout)
" _%sSegmentTextStart = .;\n",
seg->name, seg->name);
if (seg->fields & (1 << STMT_align))
fprintf(fout, " . = ALIGN(0x%X);\n", seg->align);
for (j = 0; j < seg->includesCount; j++)
{
fprintf(fout, " %s (.text)\n", seg->includes[j].fpath);
@ -166,9 +165,6 @@ static void write_ld_script(FILE *fout)
" _%sSegmentBssStart = .;\n",
seg->name, seg->name, seg->name, seg->name);
if (seg->fields & (1 << STMT_align))
fprintf(fout, " . = ALIGN(0x%X);\n", seg->align);
for (j = 0; j < seg->includesCount; j++)
fprintf(fout, " %s (.sbss)\n"
" . = ALIGN(0x10);\n", seg->includes[j].fpath);

66
tools/preprocess.py Executable file
View file

@ -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)

View file

@ -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