From c1341224f904631e7b702a4eebebad53cc5d6875 Mon Sep 17 00:00:00 2001 From: Tharo <17233964+Thar0@users.noreply.github.com> Date: Thu, 18 Jul 2024 17:58:59 +0100 Subject: [PATCH 01/14] Promote the warnings implicit-int, int-conversion, incompatible-pointer-types to errors (#1995) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c755a4ad6..47e0960e2 100644 --- a/Makefile +++ b/Makefile @@ -139,7 +139,7 @@ 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 -CHECK_WARNINGS += -Werror=implicit-function-declaration +CHECK_WARNINGS += -Werror=implicit-int -Werror=implicit-function-declaration -Werror=int-conversion -Werror=incompatible-pointer-types # The `cpp` command behaves differently on macOS (it behaves as if # `-traditional-cpp` was passed) so we use `gcc -E` instead. From e1dc4cf448ea475691ff0be0e89712fb6be91129 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Fri, 19 Jul 2024 02:56:53 +0100 Subject: [PATCH 02/14] Nicer AudioSeq_SequenceChannelProcessScript match (#1996) * Nicer AudioSeq_SequenceChannelProcessScript match * cadmic suggestion --- src/audio/lib/seqplayer.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/audio/lib/seqplayer.c b/src/audio/lib/seqplayer.c index 620f7a453..80f35bf2d 100644 --- a/src/audio/lib/seqplayer.c +++ b/src/audio/lib/seqplayer.c @@ -1475,16 +1475,14 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { case 0xE7: cmdArgU16 = (u16)cmdArgs[0]; data = &seqPlayer->seqData[cmdArgU16]; - channel->muteBehavior = data[0]; - data += 3; - channel->noteAllocPolicy = data[-2]; - AudioSeq_SetChannelPriorities(channel, data[-1]); - channel->transposition = (s8)data[0]; - data += 4; - channel->newPan = data[-3]; - channel->panChannelWeight = data[-2]; - channel->targetReverbVol = data[-1]; - channel->reverbIndex = data[0]; + channel->muteBehavior = *data++; + channel->noteAllocPolicy = *data++; + AudioSeq_SetChannelPriorities(channel, *data++); + channel->transposition = (s8)*data++; + channel->newPan = *data++; + channel->panChannelWeight = *data++; + channel->targetReverbVol = *data++; + channel->reverbIndex = *data++; //! @bug: Not marking reverb state as changed channel->changes.s.pan = true; break; From 2361a333078b2945a0f6a81025f1726f89ffdd43 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sun, 21 Jul 2024 12:22:54 -0700 Subject: [PATCH 03/14] Small cleanup of cleararena (bootclear) (#1999) * cleararena use boot end * cleararena -> bootclear --- src/boot/boot_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/boot/boot_main.c b/src/boot/boot_main.c index b8c08fe8a..23b8495f8 100644 --- a/src/boot/boot_main.c +++ b/src/boot/boot_main.c @@ -7,15 +7,15 @@ STACK(sIdleThreadStack, 0x400); StackEntry sIdleThreadInfo; STACK(sBootThreadStack, BOOT_STACK_SIZE); -void cleararena(void) { - bzero(_dmadataSegmentStart, osMemSize - OS_K0_TO_PHYSICAL(_dmadataSegmentStart)); +void bootclear(void) { + bzero(_bootSegmentEnd, osMemSize - OS_K0_TO_PHYSICAL(_bootSegmentEnd)); } void bootproc(void) { StackCheck_Init(&sBootThreadInfo, sBootThreadStack, STACK_TOP(sBootThreadStack), 0, -1, "boot"); osMemSize = osGetMemSize(); - cleararena(); + bootclear(); __osInitialize_common(); __osInitialize_autodetect(); From ab2ca85227bb4ed245d3a39faedc25f793a39a45 Mon Sep 17 00:00:00 2001 From: fig02 Date: Sun, 21 Jul 2024 19:27:25 -0400 Subject: [PATCH 04/14] Rename `ANIM_FLAG_NO_MOVE` to `ANIM_FLAG_ADJUST_STARTING_POS` (#1981) * rename flag and draft 1 of comment * draft 2 * tweak wording * format * format --- include/z64animation.h | 22 ++++++++- src/code/z_skelanime.c | 6 +-- .../actors/ovl_player_actor/z_player.c | 45 ++++++++++--------- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/include/z64animation.h b/include/z64animation.h index 2365db14b..782380ad2 100644 --- a/include/z64animation.h +++ b/include/z64animation.h @@ -112,8 +112,28 @@ typedef enum { // (player-only) Call AnimTaskQueue_AddActorMove #define ANIM_FLAG_PLAYER_SETMOVE (1 << 3) +// When this flag is set, movement in all axes will not be applied for one frame. The flag +// is unset automatically after one use, so movement can resume. The intent is for this flag to be used +// when changing between two different animations. +// In some contexts, disabling the first frame of movement is necessary for a seamless transition. // -#define ANIM_FLAG_NO_MOVE (1 << 4) +// Depending on specific implementations, an actor may choose to reset `prevTransl` to `baseTransl` when +// starting a new animation. This is helpful when an animation's translation data starts at the "origin" +// (in this case, the origin refers to `baseTransl`, in model space). +// Some animations have translation data that does not begin at the "origin". This is common when a +// longer sequence of animation is broken up into different parts as seperate animations. +// In this case, when one animation starts its translation at the same position where a different animation +// left off, resetting `prevTransl` is not desireable. This will cause the actor's position to noticeably change +// when the translation data from the first frame of the new animation is applied. +// +// When this flag is used during a transition between two animations, the first frame of movement is not applied. +// This allows the actor's world postiion to stay at the same location as where the previous animation ended. +// Because translations are calculated as a difference from the current and previous frame, all subsequent +// frames have their translation occur relative to this new starting point. +// +// Note that for Player, this flag is only relevant when transitioning from an animation that was also using +// animation translation. This is because of how `prevTransl` gets reset in `Player_AnimReplaceApplyFlags`. +#define ANIM_FLAG_ADJUST_STARTING_POS (1 << 4) // Disables "normal" movement from sources like speed/velocity and collisions, which allows the // animation to have full control over the actor's movement. diff --git a/src/code/z_skelanime.c b/src/code/z_skelanime.c index bef23de1e..c7ea06fd5 100644 --- a/src/code/z_skelanime.c +++ b/src/code/z_skelanime.c @@ -1839,7 +1839,7 @@ void SkelAnime_UpdateTranslation(SkelAnime* skelAnime, Vec3f* diff, s16 angle) { f32 cos; // If `ANIM_FLAG_UPDATE_XZ` behaved as expected, it would also be checked here - if (skelAnime->moveFlags & ANIM_FLAG_NO_MOVE) { + if (skelAnime->moveFlags & ANIM_FLAG_ADJUST_STARTING_POS) { diff->x = diff->z = 0.0f; } else { x = skelAnime->jointTable[0].x; @@ -1866,7 +1866,7 @@ void SkelAnime_UpdateTranslation(SkelAnime* skelAnime, Vec3f* diff, s16 angle) { skelAnime->jointTable[0].z = skelAnime->baseTransl.z; if (skelAnime->moveFlags & ANIM_FLAG_UPDATE_Y) { - if (skelAnime->moveFlags & ANIM_FLAG_NO_MOVE) { + if (skelAnime->moveFlags & ANIM_FLAG_ADJUST_STARTING_POS) { diff->y = 0.0f; } else { diff->y = skelAnime->jointTable[0].y - skelAnime->prevTransl.y; @@ -1879,7 +1879,7 @@ void SkelAnime_UpdateTranslation(SkelAnime* skelAnime, Vec3f* diff, s16 angle) { skelAnime->prevTransl.y = skelAnime->jointTable[0].y; } - skelAnime->moveFlags &= ~ANIM_FLAG_NO_MOVE; + skelAnime->moveFlags &= ~ANIM_FLAG_ADJUST_STARTING_POS; } /** diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index c397d8ea5..9ac957cc0 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -2008,7 +2008,7 @@ void Player_AnimReplacePlayOnceAdjusted(PlayState* play, Player* this, LinkAnima void Player_AnimReplaceNormalPlayOnceAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) { Player_AnimReplacePlayOnceAdjusted(play, this, anim, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE); + ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS); } void Player_AnimReplacePlayLoopSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, @@ -2027,7 +2027,7 @@ void Player_AnimReplacePlayLoopAdjusted(PlayState* play, Player* this, LinkAnima void Player_AnimReplaceNormalPlayLoopAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) { Player_AnimReplacePlayLoopAdjusted(play, this, anim, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE); + ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS); } void Player_ProcessControlStick(PlayState* play, Player* this) { @@ -3400,7 +3400,7 @@ s32 Player_UpdateUpperBody(Player* this, PlayState* play) { Player_AnimPlayOnce(play, this, &gPlayerAnim_link_hook_fly_start); Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); func_80832224(this); this->yaw = this->actor.shape.rot.y; this->actor.bgCheckFlags &= ~BGCHECKFLAG_GROUND; @@ -5368,7 +5368,7 @@ s32 func_8083A6AC(Player* this, PlayState* play) { this->stateFlags1 |= PLAYER_STATE1_21; Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 | - ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); this->av2.actionVar2 = -1; @@ -6724,7 +6724,7 @@ s32 Player_ActionChange_3(Player* this, PlayState* play) { Player_AnimPlayOnce(play, this, D_80854578[temp].anim); Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); this->actor.parent = this->rideActor; func_80832224(this); @@ -7071,7 +7071,7 @@ s32 func_8083EC18(Player* this, PlayState* play, u32 wallFlags) { Player_AnimPlayOnce(play, this, anim); Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 | - ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); return true; @@ -7153,7 +7153,7 @@ s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWall Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start); Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); return true; } @@ -7243,7 +7243,7 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end); Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); OnePointCutscene_Init(play, 9601, 999, NULL, CAM_ID_MAIN); } else { // Leaving a crawlspace backwards @@ -7253,7 +7253,7 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { 0.0f); Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); OnePointCutscene_Init(play, 9602, 999, NULL, CAM_ID_MAIN); } @@ -9983,7 +9983,7 @@ void func_808468A8(PlayState* play, Player* this) { Player_SetupAction(play, this, Player_Action_8084F9A0, 0); Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); } void func_808468E8(PlayState* play, Player* this) { @@ -11139,7 +11139,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { Player_AnimPlayOnce(play, this, &gPlayerAnim_link_uma_wait_1); Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); this->av2.actionVar2 = 99; } @@ -14549,7 +14549,7 @@ void func_808510D4(PlayState* play, Player* this, void* anim) { void func_808510F4(PlayState* play, Player* this, void* anim) { Player_AnimReplacePlayOnce(play, this, anim, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | + ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); } @@ -14559,7 +14559,7 @@ void func_80851114(PlayState* play, Player* this, void* anim) { void func_80851134(PlayState* play, Player* this, void* anim) { Player_AnimReplacePlayLoop(play, this, anim, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | + ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); } @@ -14918,12 +14918,13 @@ void func_80851E28(PlayState* play, Player* this, CsCmdActorCue* cue) { void func_80851E64(PlayState* play, Player* this, CsCmdActorCue* cue) { Player_AnimReplacePlayOnceAdjusted(play, this, &gPlayerAnim_link_swimer_swim_get, - ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | + ANIM_FLAG_OVERRIDE_MOVEMENT); } void func_80851E90(PlayState* play, Player* this, CsCmdActorCue* cue) { Player_AnimReplacePlayOnce(play, this, &gPlayerAnim_clink_op3_negaeri, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | + ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); func_80832698(this, NA_SE_VO_LI_GROAN); } @@ -14931,7 +14932,7 @@ void func_80851E90(PlayState* play, Player* this, CsCmdActorCue* cue) { void func_80851ECC(PlayState* play, Player* this, CsCmdActorCue* cue) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimReplacePlayLoop(play, this, &gPlayerAnim_clink_op3_wait2, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | + ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); } } @@ -14959,7 +14960,7 @@ static AnimSfxEntry D_808551BC[] = { void func_80851FB0(PlayState* play, Player* this, CsCmdActorCue* cue) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimReplacePlayLoop(play, this, &gPlayerAnim_clink_op3_wait3, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | + ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); this->av2.actionVar2 = 1; } else if (this->av2.actionVar2 == 0) { @@ -14985,7 +14986,7 @@ void func_80852048(PlayState* play, Player* this, CsCmdActorCue* cue) { void func_80852080(PlayState* play, Player* this, CsCmdActorCue* cue) { Player_AnimReplacePlayOnceAdjusted(play, this, &gPlayerAnim_clink_demo_futtobi, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); func_80832698(this, NA_SE_VO_LI_FALL_L); } @@ -15033,8 +15034,8 @@ void func_80852234(PlayState* play, Player* this, CsCmdActorCue* cue) { } void func_8085225C(PlayState* play, Player* this, CsCmdActorCue* cue) { - Player_AnimReplaceApplyFlags(play, this, - ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + Player_AnimReplaceApplyFlags( + play, this, ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); } void func_80852280(PlayState* play, Player* this, CsCmdActorCue* cue) { @@ -15466,8 +15467,8 @@ void func_80853148(PlayState* play, Actor* actor) { } if (this->skelAnime.animation == &gPlayerAnim_link_normal_backspace) { - Player_AnimReplaceApplyFlags(play, this, - ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE); + Player_AnimReplaceApplyFlags( + play, this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS); } func_80832224(this); From 47fd0232389eebcf883f58bdbc2002abd4e3ad18 Mon Sep 17 00:00:00 2001 From: cadmic Date: Sun, 21 Jul 2024 18:50:20 -0700 Subject: [PATCH 05/14] Match NTSC z_kanfont.c and z_message.c (#1997) * Match NTSC z_kanfont.c and z_message.c Co-authored-by: inspectredc * Apply suggestions from code review Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> * Remove now-unnecessary padding * Remove msgBufDecoded comment * Use == NULL for fake match * Rename Message_DrawText{JPN,NES} -> Message_DrawText[Wide] * Font_LoadKanji -> Font_LoadCharWide * Restore FONT_MESSAGE_OFFSET/FONT_MESSAGE_LENGTH --------- Co-authored-by: inspectredc Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> --- include/functions.h | 3 +- include/message_data_fmt.h | 32 + include/z64message.h | 6 +- src/code/z_kanfont.c | 33 +- src/code/z_message.c | 1579 ++++++++++++++----- src/overlays/actors/ovl_Fishing/z_fishing.c | 2 +- tools/disasm/gc-us/functions.txt | 6 +- 7 files changed, 1259 insertions(+), 402 deletions(-) diff --git a/include/functions.h b/include/functions.h index d9c29270a..d0547e5d6 100644 --- a/include/functions.h +++ b/include/functions.h @@ -776,7 +776,8 @@ s32 Jpeg_Decode(void* data, void* zbuffer, void* work, u32 workSize); void KaleidoSetup_Update(PlayState* play); void KaleidoSetup_Init(PlayState* play); void KaleidoSetup_Destroy(PlayState* play); -void func_8006EE50(Font* font, u16 arg1, u16 arg2); +s32 Kanji_OffsetFromShiftJIS(s32 character); +void Font_LoadCharWide(Font* font, u16 character, u16 codePointIndex); void Font_LoadChar(Font* font, u8 character, u16 codePointIndex); void Font_LoadMessageBoxIcon(Font* font, u16 icon); void Font_LoadOrderedFont(Font* font); diff --git a/include/message_data_fmt.h b/include/message_data_fmt.h index 2b184dac0..08e3a4999 100644 --- a/include/message_data_fmt.h +++ b/include/message_data_fmt.h @@ -75,6 +75,38 @@ #define MESSAGE_WIDE_HIGHSCORE 0x869F #define MESSAGE_WIDE_TIME 0x81A1 +/* + * Message character constants + */ + +// Non-Wide (nes/ger/fra) + +#define MESSAGE_CHAR_SPACE 0x20 // ' ' + +// Wide (jpn) + +#define MESSAGE_WIDE_CHAR_SPACE 0x8140 // ' ' +#define MESSAGE_WIDE_CHAR_TOUTEN 0x8141 // '、' +#define MESSAGE_WIDE_CHAR_KUTEN 0x8142 // '。' +#define MESSAGE_WIDE_CHAR_PERIOD 0x8144 // '.' +#define MESSAGE_WIDE_CHAR_NAKATEN 0x8145 // '・' +#define MESSAGE_WIDE_CHAR_QUESTION_MARK 0x8148 // '?' +#define MESSAGE_WIDE_CHAR_EXCLAMATION_MARK 0x8149 // '!' +#define MESSAGE_WIDE_CHAR_CIRCUMFLEX_ACCENT 0x814F // '^' +#define MESSAGE_WIDE_CHAR_DOUBLE_QUOTATION_MARK_LEFT 0x8167 // '“' +#define MESSAGE_WIDE_CHAR_DOUBLE_QUOTATION_MARK_RIGHT 0x8168 // '”' +#define MESSAGE_WIDE_CHAR_PARENTHESES_LEFT 0x8169 // '(' +#define MESSAGE_WIDE_CHAR_PARENTHESES_RIGHT 0x816A // ')' +#define MESSAGE_WIDE_CHAR_KAGIKAKKO_LEFT 0x8175 // '「' +#define MESSAGE_WIDE_CHAR_KAGIKAKKO_RIGHT 0x8176 // '」' +#define MESSAGE_WIDE_CHAR_NUMBER_SIGN 0x8194 // '#' +#define MESSAGE_WIDE_CHAR_ASTERISK 0x8196 // '*' +#define MESSAGE_WIDE_CHAR_ZERO 0x824F // '0' +#define MESSAGE_WIDE_CHAR_ONE 0x8250 // '1' +#define MESSAGE_WIDE_CHAR_HOURS 0x8E9E // '時' +#define MESSAGE_WIDE_CHAR_SECONDS 0x9562 // '秒' +#define MESSAGE_WIDE_CHAR_MINUTES 0x95AA // '分' + /* * Colors */ diff --git a/include/z64message.h b/include/z64message.h index cf942a4c5..014c379b8 100644 --- a/include/z64message.h +++ b/include/z64message.h @@ -235,8 +235,10 @@ typedef struct { /* 0xE2FE */ u8 textBoxPos; // text box position /* 0xE300 */ s32 msgLength; // original name : "msg_data" /* 0xE304 */ u8 msgMode; // original name: "msg_mode" - /* 0xE305 */ char unk_E305[0x1]; - /* 0xE306 */ u8 msgBufDecoded[200]; // decoded message buffer, may be smaller than this + /* 0xE306 */ union { + u8 msgBufDecoded[200]; + u16 msgBufDecodedWide[100]; + }; /* 0xE3CE */ u16 msgBufPos; // original name : "rdp" /* 0xE3D0 */ u16 unk_E3D0; // unused, only ever set to 0 /* 0xE3D2 */ u16 textDrawPos; // draw all decoded characters up to this buffer position diff --git a/src/code/z_kanfont.c b/src/code/z_kanfont.c index 83686a02e..30fa15d41 100644 --- a/src/code/z_kanfont.c +++ b/src/code/z_kanfont.c @@ -1,7 +1,15 @@ #include "global.h" #include "message_data_static.h" -void func_8006EE50(Font* font, u16 arg1, u16 arg2) { +/** + * Loads a texture from kanji for the requested `character` into the character texture buffer + * at `codePointIndex`. The value of `character` is the SHIFT-JIS encoding of the character. + */ +void Font_LoadCharWide(Font* font, u16 character, u16 codePointIndex) { +#if OOT_NTSC + DmaMgr_RequestSync(&font->charTexBuf[codePointIndex], + (uintptr_t)_kanjiSegmentRomStart + Kanji_OffsetFromShiftJIS(character), FONT_CHAR_TEX_SIZE); +#endif } /** @@ -33,14 +41,34 @@ void Font_LoadMessageBoxIcon(Font* font, u16 icon) { * the font buffer. */ void Font_LoadOrderedFont(Font* font) { + s32 size; s32 len; s32 codePointIndex; s32 fontBufIndex; u32 offset; font->msgOffset = FONT_MESSAGE_OFFSET; - len = font->msgLength = FONT_MESSAGE_LENGTH; + size = font->msgLength = FONT_MESSAGE_LENGTH; +#if OOT_NTSC + len = (u32)size / 2; + DmaMgr_RequestSync(font->msgBufWide, (uintptr_t)_jpn_message_data_staticSegmentRomStart + font->msgOffset, size); + + fontBufIndex = 0; + for (codePointIndex = 0; font->msgBufWide[codePointIndex] != MESSAGE_WIDE_END; codePointIndex++) { + if (len < codePointIndex) { + return; + } + + if (font->msgBufWide[codePointIndex] != MESSAGE_WIDE_NEWLINE) { + offset = Kanji_OffsetFromShiftJIS(font->msgBufWide[codePointIndex]); + DmaMgr_RequestSync(&font->fontBuf[fontBufIndex * 8], (uintptr_t)_kanjiSegmentRomStart + offset, + FONT_CHAR_TEX_SIZE); + fontBufIndex += FONT_CHAR_TEX_SIZE / 8; + } + } +#else + len = size; DMA_REQUEST_SYNC(font->msgBuf, (uintptr_t)_nes_message_data_staticSegmentRomStart + font->msgOffset, len, "../z_kanfont.c", 122); @@ -62,4 +90,5 @@ void Font_LoadOrderedFont(Font* font) { fontBufIndex += FONT_CHAR_TEX_SIZE / 8; } } +#endif } diff --git a/src/code/z_message.c b/src/code/z_message.c index 6e3477871..a4fede2ca 100644 --- a/src/code/z_message.c +++ b/src/code/z_message.c @@ -17,7 +17,9 @@ u16 sNextTextId = 0; s16 sTextIsCredits = false; +#if OOT_PAL UNK_TYPE D_8014B30C = 0; +#endif s16 sLastPlayedSong = 0xFF; @@ -356,9 +358,75 @@ void Message_GrowTextbox(MessageContext* msgCtx) { R_TEXTBOX_X = (R_TEXTBOX_X_TARGET + R_TEXTBOX_WIDTH_TARGET) - (R_TEXTBOX_WIDTH / 2); } -#if OOT_PAL // TODO: implement NTSC version +#if OOT_NTSC -void Message_FindMessage(PlayState* play, u16 textId) { +void Message_FindMessageJPN(PlayState* play, u16 textId) { + const char* foundSeg; + const char* nextSeg; + const char* seg; + Font* font = &play->msgCtx.font; + MessageTableEntry* messageTableEntry = sJpnMessageEntryTablePtr; + + seg = messageTableEntry->segment; + + while (messageTableEntry->textId != 0xFFFF) { + if (messageTableEntry->textId == textId) { + foundSeg = messageTableEntry->segment; + font->charTexBuf[0] = messageTableEntry->typePos; + messageTableEntry++; + nextSeg = messageTableEntry->segment; + font->msgOffset = foundSeg - seg; + font->msgLength = nextSeg - foundSeg; + return; + } + messageTableEntry++; + } + + messageTableEntry = sJpnMessageEntryTablePtr; + + foundSeg = messageTableEntry->segment; + font->charTexBuf[0] = messageTableEntry->typePos; + messageTableEntry++; + nextSeg = messageTableEntry->segment; + + font->msgOffset = foundSeg - seg; + font->msgLength = nextSeg - foundSeg; +} + +void Message_FindMessageNES(PlayState* play, u16 textId) { + const char* foundSeg; + const char* nextSeg; + const char* seg; + Font* font = &play->msgCtx.font; + MessageTableEntry* messageTableEntry = sNesMessageEntryTablePtr; + + seg = messageTableEntry->segment; + while (messageTableEntry->textId != 0xFFFF) { + if (messageTableEntry->textId == textId) { + foundSeg = messageTableEntry->segment; + font->charTexBuf[0] = messageTableEntry->typePos; + messageTableEntry++; + nextSeg = messageTableEntry->segment; + font->msgOffset = foundSeg - seg; + font->msgLength = nextSeg - foundSeg; + return; + } + messageTableEntry++; + } + + messageTableEntry = sNesMessageEntryTablePtr; + + foundSeg = messageTableEntry->segment; + font->charTexBuf[0] = messageTableEntry->typePos; + messageTableEntry++; + nextSeg = messageTableEntry->segment; + font->msgOffset = foundSeg - seg; + font->msgLength = nextSeg - foundSeg; +} + +#else + +void Message_FindMessagePAL(PlayState* play, u16 textId) { const char* foundSeg; const char* nextSeg; Font* font = &play->msgCtx.font; @@ -753,7 +821,11 @@ f32 sFontWidths[144] = { 10.0f, // '~' 10.0f, // '‾' 12.0f, // 'À' - 6.0f, // 'î' +#if OOT_NTSC + 12.0f, // 'î' +#else + 6.0f, // 'î' +#endif 12.0f, // 'Â' 12.0f, // 'Ä' 11.0f, // 'Ç' @@ -907,8 +979,332 @@ void Message_HandleOcarina(PlayState* play) { } } +#if OOT_NTSC /** - * Draws the text contents of a textbox, up to the current point that has + * Draws the text contents of a jpn textbox, up to the current point that has + * been scrolled to so far. + */ +void Message_DrawTextWide(PlayState* play, Gfx** gfxP) { + MessageContext* msgCtx = &play->msgCtx; + Font* font = &play->msgCtx.font; + u16 character; + u16 j; + u16 i; + u16 charTexIdx; + Gfx* gfx = *gfxP; + + play->msgCtx.textPosX = R_TEXT_INIT_XPOS; + play->msgCtx.textPosY = R_TEXT_INIT_YPOS; + + if (msgCtx->textBoxType == TEXTBOX_TYPE_NONE_NO_SHADOW) { + msgCtx->textColorR = msgCtx->textColorG = msgCtx->textColorB = 0; + } else { + msgCtx->textColorR = msgCtx->textColorG = msgCtx->textColorB = 255; + } + + msgCtx->unk_E3D0 = 0; + charTexIdx = 0; + + for (i = 0; i < msgCtx->textDrawPos; i++) { + character = msgCtx->msgBufDecodedWide[i]; + + switch (character) { + case MESSAGE_WIDE_NEWLINE: + msgCtx->textPosY += R_TEXT_LINE_SPACING; + msgCtx->textPosX = R_TEXT_INIT_XPOS; + if (msgCtx->choiceNum == 1) { + msgCtx->textPosX += 32; + } + if (msgCtx->choiceNum == 2) { + msgCtx->textPosX += 32; + } + break; + case MESSAGE_WIDE_COLOR: + Message_SetTextColor(msgCtx, msgCtx->msgBufDecodedWide[++i]); + break; + case MESSAGE_WIDE_CHAR_SPACE: + msgCtx->textPosX += MESSAGE_SPACE_WIDTH; + break; + case MESSAGE_WIDE_BOX_BREAK: + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + if (!sTextboxSkipped) { + Audio_PlaySfxGeneral(NA_SE_NONE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + msgCtx->msgMode = MSGMODE_TEXT_AWAIT_NEXT; + Font_LoadMessageBoxIcon(&play->msgCtx.font, TEXTBOX_ICON_TRIANGLE); + } else { + msgCtx->msgMode = MSGMODE_TEXT_NEXT_MSG; + msgCtx->textUnskippable = false; + msgCtx->msgBufPos++; + } + } + *gfxP = gfx; + return; + case MESSAGE_WIDE_SHIFT: + msgCtx->textPosX += msgCtx->msgBufDecodedWide[++i]; + break; + case MESSAGE_WIDE_TEXTID: + msgCtx->textboxEndType = TEXTBOX_ENDTYPE_HAS_NEXT; + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + Audio_PlaySfxGeneral(NA_SE_NONE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + msgCtx->msgMode = MSGMODE_TEXT_DONE; + Font_LoadMessageBoxIcon(&play->msgCtx.font, TEXTBOX_ICON_TRIANGLE); + } + *gfxP = gfx; + return; + case MESSAGE_WIDE_QUICKTEXT_ENABLE: + if (i + 1 == msgCtx->textDrawPos && (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING || + (msgCtx->msgMode >= MSGMODE_OCARINA_STARTING && + msgCtx->msgMode < MSGMODE_SCARECROW_LONG_RECORDING_START))) { + j = i; + while (true) { + character = msgCtx->msgBufDecodedWide[j]; + if ((character != MESSAGE_WIDE_QUICKTEXT_DISABLE) && (character != MESSAGE_WIDE_PERSISTENT) && + (character != MESSAGE_WIDE_EVENT) && (character != MESSAGE_WIDE_BOX_BREAK_DELAYED) && + (character != MESSAGE_WIDE_AWAIT_BUTTON_PRESS) && (character != MESSAGE_WIDE_BOX_BREAK) && + (character != MESSAGE_WIDE_END)) { + j++; + } else { + break; + } + } + i = j - 1; + msgCtx->textDrawPos = i + 1; + } + FALLTHROUGH; + case MESSAGE_WIDE_QUICKTEXT_DISABLE: + break; + case MESSAGE_WIDE_AWAIT_BUTTON_PRESS: + if (i + 1 == msgCtx->textDrawPos) { + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + msgCtx->msgMode = MSGMODE_TEXT_AWAIT_INPUT; + Font_LoadMessageBoxIcon(&play->msgCtx.font, TEXTBOX_ICON_TRIANGLE); + } + *gfxP = gfx; + return; + } + break; + case MESSAGE_WIDE_BOX_BREAK_DELAYED: + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + msgCtx->stateTimer = msgCtx->msgBufDecodedWide[++i]; + msgCtx->msgMode = MSGMODE_TEXT_DELAYED_BREAK; + } + *gfxP = gfx; + return; + case MESSAGE_WIDE_FADE2: + break; + case MESSAGE_WIDE_SFX: + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING && !sMessageHasSetSfx) { + sMessageHasSetSfx = true; + Audio_PlaySfxGeneral(msgCtx->msgBufDecodedWide[i + 1], &gSfxDefaultPos, 4, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + i++; + break; + case MESSAGE_WIDE_ITEM_ICON: + i = Message_DrawItemIcon(play, msgCtx->msgBufDecodedWide[i + 1], &gfx, i); + break; + case MESSAGE_WIDE_BACKGROUND: + // clang-format off + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { \ + Audio_PlaySfxGeneral(NA_SE_NONE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + // clang-format on + gDPPipeSync(gfx++); + gDPSetCombineMode(gfx++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + gDPSetPrimColor(gfx++, 0, 0, sTextboxBackgroundBackPrimColors[msgCtx->textboxBackgroundBackColorIdx][0], + sTextboxBackgroundBackPrimColors[msgCtx->textboxBackgroundBackColorIdx][1], + sTextboxBackgroundBackPrimColors[msgCtx->textboxBackgroundBackColorIdx][2], + msgCtx->textColorAlpha); + + gDPLoadTextureBlock_4b(gfx++, msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE, G_IM_FMT_I, 96, 48, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, + G_TX_NOLOD, G_TX_NOLOD); + gSPTextureRectangle( + gfx++, (msgCtx->textPosX + 1) << 2, + (R_TEXTBOX_BG_YPOS + sTextboxBackgroundYOffsets[msgCtx->textboxBackgroundYOffsetIdx]) << 2, + (msgCtx->textPosX + 96 + 1) << 2, + (R_TEXTBOX_BG_YPOS + sTextboxBackgroundYOffsets[msgCtx->textboxBackgroundYOffsetIdx] + 48) << 2, + G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + + gDPLoadTextureBlock_4b(gfx++, msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE + 0x900, G_IM_FMT_I, 96, + 48, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, + G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSPTextureRectangle( + gfx++, (msgCtx->textPosX + 96 + 1) << 2, + (R_TEXTBOX_BG_YPOS + sTextboxBackgroundYOffsets[msgCtx->textboxBackgroundYOffsetIdx]) << 2, + (msgCtx->textPosX + 96 + 1 + 96 + 1) << 2, + (R_TEXTBOX_BG_YPOS + sTextboxBackgroundYOffsets[msgCtx->textboxBackgroundYOffsetIdx] + 48) << 2, + G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + + gDPPipeSync(gfx++); + gDPSetPrimColor(gfx++, 0, 0, sTextboxBackgroundForePrimColors[msgCtx->textboxBackgroundForeColorIdx][0], + sTextboxBackgroundForePrimColors[msgCtx->textboxBackgroundForeColorIdx][1], + sTextboxBackgroundForePrimColors[msgCtx->textboxBackgroundForeColorIdx][2], + msgCtx->textColorAlpha); + + gDPLoadTextureBlock_4b(gfx++, (msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE), G_IM_FMT_I, 96, 48, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, + G_TX_NOLOD, G_TX_NOLOD); + gSPTextureRectangle(gfx++, msgCtx->textPosX << 2, R_TEXTBOX_BG_YPOS << 2, (msgCtx->textPosX + 96) << 2, + (R_TEXTBOX_BG_YPOS + 48) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + + gDPLoadTextureBlock_4b(gfx++, (msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE + 0x900), G_IM_FMT_I, + 96, 48, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, + G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSPTextureRectangle(gfx++, (msgCtx->textPosX + 96) << 2, R_TEXTBOX_BG_YPOS << 2, + (msgCtx->textPosX + 192) << 2, (R_TEXTBOX_BG_YPOS + 48) << 2, G_TX_RENDERTILE, 0, 0, + 1 << 10, 1 << 10); + + gDPPipeSync(gfx++); + gDPSetCombineLERP(gfx++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, + PRIMITIVE, 0); + + msgCtx->textPosX += 32; + break; + case MESSAGE_WIDE_TEXT_SPEED: + msgCtx->textDelay = msgCtx->msgBufDecodedWide[++i]; + break; + case MESSAGE_WIDE_UNSKIPPABLE: + msgCtx->textUnskippable = true; + break; + case MESSAGE_WIDE_TWO_CHOICE: + msgCtx->textboxEndType = TEXTBOX_ENDTYPE_2_CHOICE; + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + msgCtx->choiceTextId = msgCtx->textId; + msgCtx->stateTimer = 4; + msgCtx->choiceIndex = 0; + Font_LoadMessageBoxIcon(font, TEXTBOX_ICON_ARROW); + } + break; + case MESSAGE_WIDE_THREE_CHOICE: + msgCtx->textboxEndType = TEXTBOX_ENDTYPE_3_CHOICE; + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + msgCtx->choiceTextId = msgCtx->textId; + msgCtx->stateTimer = 4; + msgCtx->choiceIndex = 0; + Font_LoadMessageBoxIcon(font, TEXTBOX_ICON_ARROW); + } + break; + case MESSAGE_WIDE_END: + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + msgCtx->msgMode = MSGMODE_TEXT_DONE; + if (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_DEFAULT) { + Audio_PlaySfxGeneral(NA_SE_SY_MESSAGE_END, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + Font_LoadMessageBoxIcon(font, TEXTBOX_ICON_SQUARE); + if (play->csCtx.state == CS_STATE_IDLE) { + Interface_SetDoAction(play, DO_ACTION_RETURN); + } + } + } + *gfxP = gfx; + return; + case MESSAGE_WIDE_OCARINA: + if (i + 1 == msgCtx->textDrawPos) { + Message_HandleOcarina(play); + *gfxP = gfx; + return; + } + break; + case MESSAGE_WIDE_FADE: + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + msgCtx->msgMode = MSGMODE_TEXT_DONE; + msgCtx->textboxEndType = TEXTBOX_ENDTYPE_FADING; + msgCtx->stateTimer = msgCtx->msgBufDecodedWide[++i]; + Font_LoadMessageBoxIcon(font, TEXTBOX_ICON_SQUARE); + if (play->csCtx.state == CS_STATE_IDLE) { + Interface_SetDoAction(play, DO_ACTION_RETURN); + } + } + *gfxP = gfx; + return; + case MESSAGE_WIDE_PERSISTENT: + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + Audio_PlaySfxGeneral(NA_SE_NONE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + msgCtx->msgMode = MSGMODE_TEXT_DONE; + msgCtx->textboxEndType = TEXTBOX_ENDTYPE_PERSISTENT; + } + *gfxP = gfx; + return; + case MESSAGE_WIDE_EVENT: + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { + msgCtx->msgMode = MSGMODE_TEXT_DONE; + msgCtx->textboxEndType = TEXTBOX_ENDTYPE_EVENT; + Font_LoadMessageBoxIcon(&play->msgCtx.font, TEXTBOX_ICON_TRIANGLE); + Audio_PlaySfxGeneral(NA_SE_SY_MESSAGE_END, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + *gfxP = gfx; + return; + default: + switch (character) { + case MESSAGE_WIDE_CHAR_PARENTHESES_LEFT: + case MESSAGE_WIDE_CHAR_KAGIKAKKO_LEFT: + msgCtx->textPosX -= 6; + break; + case MESSAGE_WIDE_CHAR_NAKATEN: + msgCtx->textPosX -= 3; + break; + case MESSAGE_WIDE_CHAR_QUESTION_MARK: + case MESSAGE_WIDE_CHAR_EXCLAMATION_MARK: + case MESSAGE_WIDE_CHAR_CIRCUMFLEX_ACCENT: + case MESSAGE_WIDE_CHAR_ONE: + msgCtx->textPosX -= 2; + break; + } + if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING && i + 1 == msgCtx->textDrawPos && + msgCtx->textDelayTimer == msgCtx->textDelay) { + Audio_PlaySfxGeneral(NA_SE_NONE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + Message_DrawTextChar(play, &font->charTexBuf[charTexIdx], &gfx); + charTexIdx += FONT_CHAR_TEX_SIZE; + + switch (character) { + case MESSAGE_WIDE_CHAR_PERIOD: + msgCtx->textPosX += 3; + break; + case MESSAGE_WIDE_CHAR_PARENTHESES_RIGHT: + case MESSAGE_WIDE_CHAR_KAGIKAKKO_RIGHT: + msgCtx->textPosX += 5; + break; + case MESSAGE_WIDE_CHAR_TOUTEN: + case MESSAGE_WIDE_CHAR_KUTEN: + case MESSAGE_WIDE_CHAR_DOUBLE_QUOTATION_MARK_RIGHT: + msgCtx->textPosX += 7; + break; + case MESSAGE_WIDE_CHAR_CIRCUMFLEX_ACCENT: + case MESSAGE_WIDE_CHAR_NUMBER_SIGN: + case MESSAGE_WIDE_CHAR_ASTERISK: + msgCtx->textPosX += 9; + break; + case MESSAGE_WIDE_CHAR_NAKATEN: + msgCtx->textPosX += 10; + break; + default: + msgCtx->textPosX += (s32)(16.0f * (R_TEXT_CHAR_SCALE / 100.0f)); + break; + } + break; + } + } + + if (msgCtx->textDelayTimer == 0) { + msgCtx->textDrawPos = i + 1; + msgCtx->textDelayTimer = msgCtx->textDelay; + } else { + msgCtx->textDelayTimer--; + } + *gfxP = gfx; +} +#endif + +/** + * Draws the text contents of an eng/ger/fra textbox, up to the current point that has * been scrolled to so far. */ void Message_DrawText(PlayState* play, Gfx** gfxP) { @@ -923,7 +1319,6 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { Gfx* gfx = *gfxP; play->msgCtx.textPosX = R_TEXT_INIT_XPOS; - if (!sTextIsCredits) { msgCtx->textPosY = R_TEXT_INIT_YPOS; } else { @@ -956,7 +1351,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { case MESSAGE_COLOR: Message_SetTextColor(msgCtx, msgCtx->msgBufDecoded[++i] & 0xF); break; - case ' ': + case MESSAGE_CHAR_SPACE: msgCtx->textPosX += MESSAGE_SPACE_WIDTH; break; case MESSAGE_BOX_BREAK: @@ -1214,8 +1609,8 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { } void Message_LoadItemIcon(PlayState* play, u16 itemId, s16 y) { - static s16 sIconItem32XOffsets[] = { 74, 74, 74 }; - static s16 sIconItem24XOffsets[] = { 72, 72, 72 }; + static s16 sIconItem32XOffsets[] = LANGUAGE_ARRAY(54, 74, 74, 74); + static s16 sIconItem24XOffsets[] = LANGUAGE_ARRAY(50, 72, 72, 72); MessageContext* msgCtx = &play->msgCtx; InterfaceContext* interfaceCtx = &play->interfaceCtx; @@ -1245,398 +1640,744 @@ void Message_LoadItemIcon(PlayState* play, u16 itemId, s16 y) { } void Message_Decode(PlayState* play) { - u8 curChar; - u8 curChar2; - u16 value; - s32 loadChar; - s32 charTexIdx = 0; - s16 playerNameLen; - s16 decodedBufPos = 0; - s16 numLines = 0; - s16 i; - s16 digits[4]; - f32 timeInSeconds; MessageContext* msgCtx = &play->msgCtx; Font* font = &play->msgCtx.font; + s32 charTexIdx = 0; + s16 i; +#if OOT_NTSC + s16 j; +#endif + s16 decodedBufPos = 0; + s16 numLines = 0; + s16 digits[4]; + f32 timeInSeconds; + s16 playerNameLen; + s16 loadChar; + u16 value; + u8 curChar; +#if OOT_NTSC + u16 curCharWide; + u8* fontBuf; +#endif play->msgCtx.textDelayTimer = 0; play->msgCtx.textUnskippable = play->msgCtx.textDelay = play->msgCtx.textDelayTimer = 0; sTextFade = false; - while (true) { - curChar2 = curChar = msgCtx->msgBufDecoded[decodedBufPos] = font->msgBuf[msgCtx->msgBufPos]; +#if OOT_NTSC + if (gSaveContext.language == LANGUAGE_JPN && !sTextIsCredits) { + // Japanese text (NTSC only) + while (true) { + curCharWide = msgCtx->msgBufDecodedWide[decodedBufPos] = font->msgBufWide[msgCtx->msgBufPos]; - if (curChar == MESSAGE_BOX_BREAK || curChar == MESSAGE_TEXTID || curChar == MESSAGE_BOX_BREAK_DELAYED || - curChar == MESSAGE_EVENT || curChar == MESSAGE_END) { - // Textbox decoding ends with any of the above text control characters - msgCtx->msgMode = MSGMODE_TEXT_DISPLAYING; - msgCtx->textDrawPos = 1; - R_TEXT_INIT_YPOS = R_TEXTBOX_Y + 8; - PRINTF("JJ=%d\n", numLines); - if (msgCtx->textBoxType != TEXTBOX_TYPE_NONE_BOTTOM) { - if (numLines == 0) { - R_TEXT_INIT_YPOS = (u16)(R_TEXTBOX_Y + 26); - } else if (numLines == 1) { - R_TEXT_INIT_YPOS = (u16)(R_TEXTBOX_Y + 20); - } else if (numLines == 2) { - R_TEXT_INIT_YPOS = (u16)(R_TEXTBOX_Y + 16); + if (curCharWide == MESSAGE_WIDE_BOX_BREAK || curCharWide == MESSAGE_WIDE_TEXTID || + curCharWide == MESSAGE_WIDE_BOX_BREAK_DELAYED || curCharWide == MESSAGE_WIDE_EVENT || + curCharWide == MESSAGE_WIDE_END) { + // Textbox decoding ends with any of the above text control characters + msgCtx->msgMode = MSGMODE_TEXT_DISPLAYING; + msgCtx->textDrawPos = 1; + R_TEXT_INIT_YPOS = R_TEXTBOX_Y + 6; + if (msgCtx->textBoxType != TEXTBOX_TYPE_NONE_BOTTOM) { + if (numLines == 0) { + R_TEXT_INIT_YPOS = (u16)(R_TEXTBOX_Y + 22); + } else if (numLines == 1) { + R_TEXT_INIT_YPOS = (u16)(R_TEXTBOX_Y + 14); + } } - } - if (curChar2 == MESSAGE_TEXTID) { - PRINTF("NZ_NEXTMSG=%x, %x, %x\n", font->msgBuf[msgCtx->msgBufPos], font->msgBuf[msgCtx->msgBufPos + 1], - font->msgBuf[msgCtx->msgBufPos + 2]); - curChar = msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[msgCtx->msgBufPos + 1]; - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[msgCtx->msgBufPos + 2]; - value = curChar << 8; - sNextTextId = msgCtx->msgBufDecoded[decodedBufPos] | value; - } - if (curChar2 == MESSAGE_BOX_BREAK_DELAYED) { - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[msgCtx->msgBufPos + 1]; - msgCtx->msgBufPos += 2; - } - msgCtx->decodedTextLen = decodedBufPos; - if (sTextboxSkipped) { - msgCtx->textDrawPos = msgCtx->decodedTextLen; - } - break; - } else if (curChar == MESSAGE_NAME) { - // Substitute the player name control character for the file's player name. - for (playerNameLen = ARRAY_COUNT(gSaveContext.save.info.playerData.playerName); playerNameLen > 0; - playerNameLen--) { - if (gSaveContext.save.info.playerData.playerName[playerNameLen - 1] != FILENAME_SPACE) { - break; + if (curCharWide == MESSAGE_WIDE_TEXTID) { + sNextTextId = msgCtx->msgBufDecodedWide[++decodedBufPos] = font->msgBufWide[msgCtx->msgBufPos + 1]; } - } - // "Name" - PRINTF("\n名前 = "); - for (i = 0; i < playerNameLen; i++) { - curChar2 = gSaveContext.save.info.playerData.playerName[i]; - if (curChar2 == FILENAME_SPACE) { - curChar2 = ' '; - } else if (curChar2 == FILENAME_PERIOD) { - curChar2 = '.'; - } else if (curChar2 == FILENAME_DASH) { - curChar2 = '-'; - } else if (curChar2 <= FILENAME_DIGIT('9')) { - curChar2 -= FILENAME_DIGIT('0'); - curChar2 += '0'; - } else if (curChar2 <= FILENAME_UPPERCASE('Z')) { - curChar2 -= FILENAME_UPPERCASE('A'); - curChar2 += 'A'; - } else if (curChar2 <= FILENAME_LOWERCASE('z')) { - curChar2 -= FILENAME_LOWERCASE('a'); - curChar2 += 'a'; + if (curCharWide == MESSAGE_WIDE_BOX_BREAK_DELAYED) { + msgCtx->msgBufDecodedWide[++decodedBufPos] = font->msgBufWide[msgCtx->msgBufPos + 1]; + msgCtx->msgBufPos += 2; } - if (curChar2 != ' ') { - Font_LoadChar(font, curChar2 - ' ', charTexIdx); + msgCtx->decodedTextLen = decodedBufPos; + if (sTextboxSkipped) { + msgCtx->textDrawPos = msgCtx->decodedTextLen; + } + break; + } + if (curCharWide == MESSAGE_WIDE_NAME) { + // Substitute the player name control character for the file's player name. + for (playerNameLen = ARRAY_COUNT(gSaveContext.save.info.playerData.playerName); playerNameLen > 0; + playerNameLen--) { + if (gSaveContext.save.info.playerData.playerName[playerNameLen - 1] != FILENAME_SPACE) { + break; + } + } + for (i = 0; i < playerNameLen; i++) { + curCharWide = gSaveContext.save.info.playerData.playerName[i]; + fontBuf = &font->fontBuf[(curCharWide * 32) << 2]; // fake + msgCtx->msgBufDecodedWide[decodedBufPos + i] = MESSAGE_WIDE_NAME; + + for (j = 0; j < FONT_CHAR_TEX_SIZE; j += 4) { + font->charTexBuf[charTexIdx + j + 0] = fontBuf[j + 0]; + font->charTexBuf[charTexIdx + j + 1] = fontBuf[j + 1]; + font->charTexBuf[charTexIdx + j + 2] = fontBuf[j + 2]; + font->charTexBuf[charTexIdx + j + 3] = fontBuf[j + 3]; + } charTexIdx += FONT_CHAR_TEX_SIZE; } - PRINTF("%x ", curChar2); - msgCtx->msgBufDecoded[decodedBufPos] = curChar2; - decodedBufPos++; - } - decodedBufPos--; - } else if (curChar == MESSAGE_MARATHON_TIME || curChar == MESSAGE_RACE_TIME) { - // Convert the values of the appropriate timer to digits and add the - // digits to the decoded buffer in place of the control character. - // "EVENT timer" - PRINTF("\nEVENTタイマー = "); - digits[0] = digits[1] = digits[2] = 0; - if (curChar == MESSAGE_RACE_TIME) { - digits[3] = gSaveContext.timerSeconds; - } else { - digits[3] = gSaveContext.subTimerSeconds; - } + decodedBufPos += playerNameLen - 1; + } else if (curCharWide == MESSAGE_WIDE_MARATHON_TIME || curCharWide == MESSAGE_WIDE_RACE_TIME) { + // Convert the values of the appropriate timer to digits and add the + // digits to the decoded buffer in place of the control character. + digits[0] = digits[1] = digits[2] = 0; + if (curCharWide == MESSAGE_WIDE_RACE_TIME) { + digits[3] = gSaveContext.timerSeconds; + } else { + digits[3] = gSaveContext.subTimerSeconds; + } + while (digits[3] >= 60) { + digits[1]++; + if (digits[1] >= 10) { + digits[0]++; + digits[1] -= 10; + } + digits[3] -= 60; + } + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } - while (digits[3] >= 60) { - digits[1]++; - if (digits[1] >= 10) { + for (i = 0; i < 4; i++) { + Font_LoadCharWide(font, digits[i] + MESSAGE_WIDE_CHAR_ZERO, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = digits[i] + MESSAGE_WIDE_CHAR_ZERO; + decodedBufPos++; + if (i == 1) { + Font_LoadCharWide(font, MESSAGE_WIDE_CHAR_MINUTES, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = MESSAGE_WIDE_CHAR_MINUTES; + decodedBufPos++; + } else if (i == 3) { + Font_LoadCharWide(font, MESSAGE_WIDE_CHAR_SECONDS, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = MESSAGE_WIDE_CHAR_SECONDS; + } + } + } else if (curCharWide == MESSAGE_WIDE_POINTS) { + // Convert the values of the current minigame score to digits and + // add the digits to the decoded buffer in place of the control character. + digits[0] = digits[1] = digits[2] = 0; + digits[3] = gSaveContext.minigameScore; + + while (digits[3] >= 1000) { + digits[0]++; + digits[3] -= 1000; + } + while (digits[3] >= 100) { + digits[1]++; + digits[3] -= 100; + } + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } + loadChar = false; + for (i = 0; i < 4; i++) { + if (i == 3 || digits[i] != 0) { + loadChar = true; + } + if (loadChar) { + Font_LoadCharWide(font, digits[i] + MESSAGE_WIDE_CHAR_ZERO, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = digits[i] + MESSAGE_WIDE_CHAR_ZERO; + decodedBufPos++; + } + } + decodedBufPos--; + } else if (curCharWide == MESSAGE_WIDE_TOKENS) { + // Convert the current number of collected gold skulltula tokens to digits and + // add the digits to the decoded buffer in place of the control character. + digits[0] = digits[1] = 0; + digits[2] = gSaveContext.save.info.inventory.gsTokens; + + while (digits[2] >= 100) { + digits[0]++; + digits[2] -= 100; + } + while (digits[2] >= 10) { + digits[1]++; + digits[2] -= 10; + } + + loadChar = false; + for (i = 0; i < 3; i++) { + if (i == 2 || digits[i] != 0) { + loadChar = true; + } + if (loadChar) { + Font_LoadCharWide(font, digits[i] + MESSAGE_WIDE_CHAR_ZERO, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = digits[i] + MESSAGE_WIDE_CHAR_ZERO; + decodedBufPos++; + } + } + decodedBufPos--; + } else if (curCharWide == MESSAGE_WIDE_FISH_INFO) { + digits[0] = 0; + digits[1] = gSaveContext.minigameScore; + + while (digits[1] >= 10) { digits[0]++; digits[1] -= 10; } - digits[3] -= 60; - } - while (digits[3] >= 10) { - digits[2]++; - digits[3] -= 10; - } - for (i = 0; i < 4; i++) { - Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; - decodedBufPos++; - if (i == 1) { - Font_LoadChar(font, '"' - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = '"'; - decodedBufPos++; - } else if (i == 3) { - Font_LoadChar(font, '"' - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = '"'; - } - } - } else if (curChar == MESSAGE_POINTS) { - // Convert the values of the current minigame score to digits and - // add the digits to the decoded buffer in place of the control character. - // "Yabusame score" - PRINTF("\n流鏑馬スコア = %d\n", gSaveContext.minigameScore); - digits[0] = digits[1] = digits[2] = 0; - digits[3] = gSaveContext.minigameScore; - - while (digits[3] >= 1000) { - digits[0]++; - digits[3] -= 1000; - } - while (digits[3] >= 100) { - digits[1]++; - digits[3] -= 100; - } - while (digits[3] >= 10) { - digits[2]++; - digits[3] -= 10; - } - - loadChar = false; - for (i = 0; i < 4; i++) { - if (i == 3 || digits[i] != 0) { - loadChar = true; - } - if (loadChar) { - Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); - msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; - charTexIdx += FONT_CHAR_TEX_SIZE; - decodedBufPos++; - } - } - decodedBufPos--; - } else if (curChar == MESSAGE_TOKENS) { - // Convert the current number of collected gold skulltula tokens to digits and - // add the digits to the decoded buffer in place of the control character. - // "Total number of gold stars" - PRINTF("\n金スタ合計数 = %d", gSaveContext.save.info.inventory.gsTokens); - digits[0] = digits[1] = 0; - digits[2] = gSaveContext.save.info.inventory.gsTokens; - - while (digits[2] >= 100) { - digits[0]++; - digits[2] -= 100; - } - while (digits[2] >= 10) { - digits[1]++; - digits[2] -= 10; - } - - loadChar = false; - for (i = 0; i < 3; i++) { - if (i == 2 || digits[i] != 0) { - loadChar = true; - } - if (loadChar) { - Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; - PRINTF("%x(%x) ", digits[i] + '0' - ' ', digits[i]); - decodedBufPos++; - } - } - decodedBufPos--; - } else if (curChar == MESSAGE_FISH_INFO) { - // "Fishing hole fish size" - PRINTF("\n釣り堀魚サイズ = "); - digits[0] = 0; - digits[1] = gSaveContext.minigameScore; - - while (digits[1] >= 10) { - digits[0]++; - digits[1] -= 10; - } - - for (i = 0; i < 2; i++) { - if (i == 1 || digits[i] != 0) { - Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; - PRINTF("%x(%x) ", digits[i] + '0' - ' ', digits[i]); - decodedBufPos++; - } - } - decodedBufPos--; - } else if (curChar == MESSAGE_HIGHSCORE) { - value = HIGH_SCORE((u8)font->msgBuf[++msgCtx->msgBufPos]); - // "Highscore" - PRINTF("ランキング=%d\n", font->msgBuf[msgCtx->msgBufPos]); - if ((font->msgBuf[msgCtx->msgBufPos] & 0xFF) == 2) { - if (LINK_AGE_IN_YEARS == YEARS_CHILD) { - value &= 0x7F; - } else { - PRINTF("HI_SCORE( kanfont->mbuff.nes_mes_buf[message->rdp] & 0xff000000 ) = %x\n", - HIGH_SCORE(font->msgBufWide[msgCtx->msgBufPos] & 0xFF000000)); - value = ((HIGH_SCORE((u8)font->msgBuf[msgCtx->msgBufPos]) & 0xFF000000) >> 0x18) & 0x7F; - } - value = SQ((f32)value) * 0.0036f + 0.5f; - PRINTF("score=%d\n", value); - } - switch (font->msgBuf[msgCtx->msgBufPos] & 0xFF) { - case HS_HBA: - case HS_POE_POINTS: - case HS_FISHING: - digits[0] = digits[1] = digits[2] = 0; - digits[3] = value; - - while (digits[3] >= 1000) { - digits[0]++; - digits[3] -= 1000; + for (i = 0; i < 2; i++) { + if (i == 1 || digits[i] != 0) { + Font_LoadCharWide(font, digits[i] + MESSAGE_WIDE_CHAR_ZERO, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = digits[i] + MESSAGE_WIDE_CHAR_ZERO; + decodedBufPos++; } - while (digits[3] >= 100) { - digits[1]++; - digits[3] -= 100; - } - while (digits[3] >= 10) { - digits[2]++; - digits[3] -= 10; + } + decodedBufPos--; + } else if (curCharWide == MESSAGE_WIDE_HIGHSCORE) { + value = HIGH_SCORE(font->msgBufWide[++msgCtx->msgBufPos] & 0xFF); + if ((font->msgBufWide[msgCtx->msgBufPos] & 0xFF) == 2) { + if (LINK_AGE_IN_YEARS == YEARS_CHILD) { + value &= 0x7F; + } else { + value = ((HIGH_SCORE(font->msgBufWide[msgCtx->msgBufPos]) & 0xFF000000) >> 0x18) & 0x7F; } + } + switch (font->msgBufWide[msgCtx->msgBufPos] & 0xFF) { + case HS_HBA: + case HS_POE_POINTS: + case HS_FISHING: + digits[0] = digits[1] = digits[2] = 0; + digits[3] = value; - loadChar = false; - for (i = 0; i < 4; i++) { - if (i == 3 || digits[i] != 0) { - loadChar = true; - } - if (loadChar) { - Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); - msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; - charTexIdx += FONT_CHAR_TEX_SIZE; - decodedBufPos++; - } - } - decodedBufPos--; - break; - case HS_UNK_05: - break; - case HS_HORSE_RACE: - case HS_MARATHON: - case HS_DAMPE_RACE: - digits[0] = digits[1] = digits[2] = 0; - digits[3] = value; - - while (digits[3] >= 60) { - digits[1]++; - if (digits[1] >= 10) { + while (digits[3] >= 1000) { digits[0]++; - digits[1] -= 10; + digits[3] -= 1000; + } + while (digits[3] >= 100) { + digits[1]++; + digits[3] -= 100; + } + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; } - digits[3] -= 60; - } - while (digits[3] >= 10) { - digits[2]++; - digits[3] -= 10; - } - for (i = 0; i < 4; i++) { + loadChar = false; + for (i = 0; i < 4; i++) { + if (i == 3 || digits[i] != 0) { + loadChar = true; + } + if (loadChar) { + Font_LoadCharWide(font, digits[i] + MESSAGE_WIDE_CHAR_ZERO, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = digits[i] + MESSAGE_WIDE_CHAR_ZERO; + decodedBufPos++; + } + } + decodedBufPos--; + break; + case HS_UNK_05: + break; + case HS_HORSE_RACE: + case HS_MARATHON: + case HS_DAMPE_RACE: + digits[0] = digits[1] = digits[2] = 0; + digits[3] = value; + + while (digits[3] >= 60) { + digits[1]++; + if (digits[1] >= 10) { + digits[0]++; + digits[1] -= 10; + } + digits[3] -= 60; + } + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } + + for (i = 0; i < 4; i++) { + Font_LoadCharWide(font, digits[i] + MESSAGE_WIDE_CHAR_ZERO, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = digits[i] + MESSAGE_WIDE_CHAR_ZERO; + decodedBufPos++; + if (i == 1) { + Font_LoadCharWide(font, MESSAGE_WIDE_CHAR_MINUTES, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = MESSAGE_WIDE_CHAR_MINUTES; + decodedBufPos++; + } else if (i == 3) { + Font_LoadCharWide(font, MESSAGE_WIDE_CHAR_SECONDS, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = MESSAGE_WIDE_CHAR_SECONDS; + } + } + break; + } + } else if (curCharWide == MESSAGE_WIDE_TIME) { + digits[0] = 0; + timeInSeconds = gSaveContext.save.dayTime * (24.0f * 60.0f / 0x10000); + + digits[1] = timeInSeconds / 60.0f; + while (digits[1] >= 10) { + digits[0]++; + digits[1] -= 10; + } + digits[2] = 0; + digits[3] = (s16)timeInSeconds % 60; + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } + + for (i = 0; i < 4; i++) { + Font_LoadCharWide(font, digits[i] + MESSAGE_WIDE_CHAR_ZERO, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = digits[i] + MESSAGE_WIDE_CHAR_ZERO; + decodedBufPos++; + if (i == 1) { + Font_LoadCharWide(font, MESSAGE_WIDE_CHAR_HOURS, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = MESSAGE_WIDE_CHAR_HOURS; + decodedBufPos++; + } else if (i == 3) { + Font_LoadCharWide(font, MESSAGE_WIDE_CHAR_MINUTES, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecodedWide[decodedBufPos] = MESSAGE_WIDE_CHAR_MINUTES; + } + } + } else if (curCharWide == MESSAGE_WIDE_ITEM_ICON) { + msgCtx->msgBufDecodedWide[++decodedBufPos] = font->msgBufWide[msgCtx->msgBufPos + 1]; + Message_LoadItemIcon(play, font->msgBufWide[msgCtx->msgBufPos + 1], R_TEXTBOX_Y + 10); + } else if (curCharWide == MESSAGE_WIDE_BACKGROUND) { + msgCtx->textboxBackgroundIdx = font->msgBufWide[msgCtx->msgBufPos + 1] * 2; + msgCtx->textboxBackgroundForeColorIdx = (font->msgBufWide[msgCtx->msgBufPos + 2] & 0xF000) >> 12; + msgCtx->textboxBackgroundBackColorIdx = (font->msgBufWide[msgCtx->msgBufPos + 2] & 0xF00) >> 8; + msgCtx->textboxBackgroundYOffsetIdx = (font->msgBufWide[msgCtx->msgBufPos + 2] & 0xF0) >> 4; + msgCtx->textboxBackgroundUnkArg = font->msgBufWide[msgCtx->msgBufPos + 2] & 0xF; + DmaMgr_RequestSync(msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE, + (uintptr_t)_message_texture_staticSegmentRomStart + + msgCtx->textboxBackgroundIdx * MESSAGE_TEXTURE_STATIC_TEX_SIZE, + MESSAGE_TEXTURE_STATIC_TEX_SIZE); + DmaMgr_RequestSync(msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE + MESSAGE_TEXTURE_STATIC_TEX_SIZE, + (uintptr_t)_message_texture_staticSegmentRomStart + + (msgCtx->textboxBackgroundIdx + 1) * MESSAGE_TEXTURE_STATIC_TEX_SIZE, + MESSAGE_TEXTURE_STATIC_TEX_SIZE); + numLines = 2; + msgCtx->msgBufPos += 2; + R_TEXTBOX_BG_YPOS = R_TEXTBOX_Y + 8; + } else if (curCharWide == MESSAGE_WIDE_COLOR) { + msgCtx->msgBufDecodedWide[++decodedBufPos] = font->msgBufWide[++msgCtx->msgBufPos] & 0xF; + } else if (curCharWide == MESSAGE_WIDE_NEWLINE) { + numLines++; + } else if (curCharWide != MESSAGE_WIDE_QUICKTEXT_ENABLE && curCharWide != MESSAGE_WIDE_QUICKTEXT_DISABLE && + curCharWide != MESSAGE_WIDE_AWAIT_BUTTON_PRESS && curCharWide != MESSAGE_WIDE_OCARINA && + curCharWide != MESSAGE_WIDE_PERSISTENT && curCharWide != MESSAGE_WIDE_UNSKIPPABLE) { + if (curCharWide == MESSAGE_WIDE_FADE) { + sTextFade = true; + msgCtx->msgBufDecodedWide[++decodedBufPos] = font->msgBufWide[++msgCtx->msgBufPos] & 0xFF; + } else if (curCharWide == MESSAGE_WIDE_SHIFT || curCharWide == MESSAGE_WIDE_TEXT_SPEED) { + msgCtx->msgBufDecodedWide[++decodedBufPos] = font->msgBufWide[++msgCtx->msgBufPos] & 0xFF; + } else if (curCharWide == MESSAGE_WIDE_SFX) { + msgCtx->msgBufDecodedWide[++decodedBufPos] = font->msgBufWide[++msgCtx->msgBufPos]; + } else if (curCharWide == MESSAGE_WIDE_TWO_CHOICE) { + msgCtx->choiceNum = 2; + } else if (curCharWide == MESSAGE_WIDE_THREE_CHOICE) { + msgCtx->choiceNum = 3; + R_TEXT_INIT_XPOS += 32; + } else if (curCharWide != MESSAGE_WIDE_CHAR_SPACE) { + Font_LoadCharWide(font, curCharWide, charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + } + } + decodedBufPos++; + msgCtx->msgBufPos++; + } + } else { +#endif + // English text for NTSC, eng/ger/fra text for PAL + while (true) { + curChar = msgCtx->msgBufDecoded[decodedBufPos] = font->msgBuf[msgCtx->msgBufPos]; + + if (curChar == MESSAGE_BOX_BREAK || curChar == MESSAGE_TEXTID || curChar == MESSAGE_BOX_BREAK_DELAYED || + curChar == MESSAGE_EVENT || curChar == MESSAGE_END) { + // Textbox decoding ends with any of the above text control characters + msgCtx->msgMode = MSGMODE_TEXT_DISPLAYING; + msgCtx->textDrawPos = 1; + R_TEXT_INIT_YPOS = R_TEXTBOX_Y + 8; + PRINTF("JJ=%d\n", numLines); + if (msgCtx->textBoxType != TEXTBOX_TYPE_NONE_BOTTOM) { + if (numLines == 0) { + R_TEXT_INIT_YPOS = (u16)(R_TEXTBOX_Y + 26); + } else if (numLines == 1) { + R_TEXT_INIT_YPOS = (u16)(R_TEXTBOX_Y + 20); + } else if (numLines == 2) { + R_TEXT_INIT_YPOS = (u16)(R_TEXTBOX_Y + 16); + } + } + if (curChar == MESSAGE_TEXTID) { + PRINTF("NZ_NEXTMSG=%x, %x, %x\n", font->msgBuf[msgCtx->msgBufPos], + font->msgBuf[msgCtx->msgBufPos + 1], font->msgBuf[msgCtx->msgBufPos + 2]); + value = msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[msgCtx->msgBufPos + 1]; + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[msgCtx->msgBufPos + 2]; + value <<= 8; + sNextTextId = msgCtx->msgBufDecoded[decodedBufPos] | value; + } + if (curChar == MESSAGE_BOX_BREAK_DELAYED) { + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[msgCtx->msgBufPos + 1]; + msgCtx->msgBufPos += 2; + } + msgCtx->decodedTextLen = decodedBufPos; + if (sTextboxSkipped) { + msgCtx->textDrawPos = msgCtx->decodedTextLen; + } + break; + } else if (curChar == MESSAGE_NAME) { + // Substitute the player name control character for the file's player name. + for (playerNameLen = ARRAY_COUNT(gSaveContext.save.info.playerData.playerName); playerNameLen > 0; + playerNameLen--) { + if (gSaveContext.save.info.playerData.playerName[playerNameLen - 1] != FILENAME_SPACE) { + break; + } + } + // "Name" + PRINTF("\n名前 = "); + for (i = 0; i < playerNameLen; i++) { + curChar = gSaveContext.save.info.playerData.playerName[i]; + if (curChar == FILENAME_SPACE) { + curChar = ' '; + } else if (curChar == FILENAME_PERIOD) { + curChar = '.'; + } else if (curChar == FILENAME_DASH) { + curChar = '-'; + } else if (curChar <= FILENAME_DIGIT('9')) { + curChar -= FILENAME_DIGIT('0'); + curChar += '0'; + } else if (curChar <= FILENAME_UPPERCASE('Z')) { + curChar -= FILENAME_UPPERCASE('A'); + curChar += 'A'; + } else if (curChar <= FILENAME_LOWERCASE('z')) { + curChar -= FILENAME_LOWERCASE('a'); + curChar += 'a'; + } + if (curChar != ' ') { + Font_LoadChar(font, curChar - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + } + PRINTF("%x ", curChar); + msgCtx->msgBufDecoded[decodedBufPos] = curChar; + decodedBufPos++; + } + decodedBufPos--; + } else if (curChar == MESSAGE_MARATHON_TIME || curChar == MESSAGE_RACE_TIME) { + // Convert the values of the appropriate timer to digits and add the + // digits to the decoded buffer in place of the control character. + // "EVENT timer" + PRINTF("\nEVENTタイマー = "); + digits[0] = digits[1] = digits[2] = 0; + if (curChar == MESSAGE_RACE_TIME) { + digits[3] = gSaveContext.timerSeconds; + } else { + digits[3] = gSaveContext.subTimerSeconds; + } + + while (digits[3] >= 60) { + digits[1]++; + if (digits[1] >= 10) { + digits[0]++; + digits[1] -= 10; + } + digits[3] -= 60; + } + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } + + for (i = 0; i < 4; i++) { + Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; + decodedBufPos++; + if (i == 1) { + Font_LoadChar(font, '"' - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecoded[decodedBufPos] = '"'; + decodedBufPos++; + } else if (i == 3) { + Font_LoadChar(font, '"' - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecoded[decodedBufPos] = '"'; + } + } + } else if (curChar == MESSAGE_POINTS) { + // Convert the values of the current minigame score to digits and + // add the digits to the decoded buffer in place of the control character. + // "Yabusame score" + PRINTF("\n流鏑馬スコア = %d\n", gSaveContext.minigameScore); + digits[0] = digits[1] = digits[2] = 0; + digits[3] = gSaveContext.minigameScore; + + while (digits[3] >= 1000) { + digits[0]++; + digits[3] -= 1000; + } + while (digits[3] >= 100) { + digits[1]++; + digits[3] -= 100; + } + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } + + loadChar = false; + for (i = 0; i < 4; i++) { + if (i == 3 || digits[i] != 0) { + loadChar = true; + } + if (loadChar) { + Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); + msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; + charTexIdx += FONT_CHAR_TEX_SIZE; + decodedBufPos++; + } + } + decodedBufPos--; + } else if (curChar == MESSAGE_TOKENS) { + // Convert the current number of collected gold skulltula tokens to digits and + // add the digits to the decoded buffer in place of the control character. + // "Total number of gold stars" + PRINTF("\n金スタ合計数 = %d", gSaveContext.save.info.inventory.gsTokens); + digits[0] = digits[1] = 0; + digits[2] = gSaveContext.save.info.inventory.gsTokens; + + while (digits[2] >= 100) { + digits[0]++; + digits[2] -= 100; + } + while (digits[2] >= 10) { + digits[1]++; + digits[2] -= 10; + } + + loadChar = false; + for (i = 0; i < 3; i++) { + if (i == 2 || digits[i] != 0) { + loadChar = true; + } + if (loadChar) { Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); charTexIdx += FONT_CHAR_TEX_SIZE; msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; + PRINTF("%x(%x) ", digits[i] + '0' - ' ', digits[i]); decodedBufPos++; - if (i == 1) { - Font_LoadChar(font, '"' - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = '"'; - decodedBufPos++; - } else if (i == 3) { - Font_LoadChar(font, '"' - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = '"'; - } } - break; - } - } else if (curChar == MESSAGE_TIME) { - // "Zelda time" - PRINTF("\nゼルダ時間 = "); - digits[0] = 0; - timeInSeconds = gSaveContext.save.dayTime * (24.0f * 60.0f / 0x10000); + } + decodedBufPos--; + } else if (curChar == MESSAGE_FISH_INFO) { + // "Fishing hole fish size" + PRINTF("\n釣り堀魚サイズ = "); + digits[0] = 0; + digits[1] = gSaveContext.minigameScore; - digits[1] = timeInSeconds / 60.0f; - while (digits[1] >= 10) { - digits[0]++; - digits[1] -= 10; - } - digits[2] = 0; - digits[3] = (s16)timeInSeconds % 60; - while (digits[3] >= 10) { - digits[2]++; - digits[3] -= 10; - } + while (digits[1] >= 10) { + digits[0]++; + digits[1] -= 10; + } - for (i = 0; i < 4; i++) { - Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; - decodedBufPos++; - if (i == 1) { - Font_LoadChar(font, ':' - ' ', charTexIdx); + for (i = 0; i < 2; i++) { + if (i == 1 || digits[i] != 0) { + Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; + PRINTF("%x(%x) ", digits[i] + '0' - ' ', digits[i]); + decodedBufPos++; + } + } + decodedBufPos--; + } else if (curChar == MESSAGE_HIGHSCORE) { + value = HIGH_SCORE((u8)font->msgBuf[++msgCtx->msgBufPos]); + // "Highscore" + PRINTF("ランキング=%d\n", font->msgBuf[msgCtx->msgBufPos]); + if ((font->msgBuf[msgCtx->msgBufPos] & 0xFF) == 2) { + if (LINK_AGE_IN_YEARS == YEARS_CHILD) { + value &= 0x7F; + } else { + PRINTF("HI_SCORE( kanfont->mbuff.nes_mes_buf[message->rdp] & 0xff000000 ) = %x\n", + HIGH_SCORE(font->msgBufWide[msgCtx->msgBufPos] & 0xFF000000)); + value = ((HIGH_SCORE((u8)font->msgBuf[msgCtx->msgBufPos]) & 0xFF000000) >> 0x18) & 0x7F; + } + value = SQ((f32)value) * 0.0036f + 0.5f; + PRINTF("score=%d\n", value); + } + switch (font->msgBuf[msgCtx->msgBufPos] & 0xFF) { + case HS_HBA: + case HS_POE_POINTS: + case HS_FISHING: + digits[0] = digits[1] = digits[2] = 0; + digits[3] = value; + + while (digits[3] >= 1000) { + digits[0]++; + digits[3] -= 1000; + } + while (digits[3] >= 100) { + digits[1]++; + digits[3] -= 100; + } + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } + + loadChar = false; + for (i = 0; i < 4; i++) { + if (i == 3 || digits[i] != 0) { + loadChar = true; + } + if (loadChar) { + Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); + msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; + charTexIdx += FONT_CHAR_TEX_SIZE; + decodedBufPos++; + } + } + decodedBufPos--; + break; + case HS_UNK_05: + break; + case HS_HORSE_RACE: + case HS_MARATHON: + case HS_DAMPE_RACE: + digits[0] = digits[1] = digits[2] = 0; + digits[3] = value; + + while (digits[3] >= 60) { + digits[1]++; + if (digits[1] >= 10) { + digits[0]++; + digits[1] -= 10; + } + digits[3] -= 60; + } + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } + + for (i = 0; i < 4; i++) { + Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; + decodedBufPos++; + if (i == 1) { + Font_LoadChar(font, '"' - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecoded[decodedBufPos] = '"'; + decodedBufPos++; + } else if (i == 3) { + Font_LoadChar(font, '"' - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecoded[decodedBufPos] = '"'; + } + } + break; + } + } else if (curChar == MESSAGE_TIME) { + // "Zelda time" + PRINTF("\nゼルダ時間 = "); + digits[0] = 0; + timeInSeconds = gSaveContext.save.dayTime * (24.0f * 60.0f / 0x10000); + + digits[1] = timeInSeconds / 60.0f; + while (digits[1] >= 10) { + digits[0]++; + digits[1] -= 10; + } + digits[2] = 0; + digits[3] = (s16)timeInSeconds % 60; + while (digits[3] >= 10) { + digits[2]++; + digits[3] -= 10; + } + + for (i = 0; i < 4; i++) { + Font_LoadChar(font, digits[i] + '0' - ' ', charTexIdx); charTexIdx += FONT_CHAR_TEX_SIZE; - msgCtx->msgBufDecoded[decodedBufPos] = ':'; + msgCtx->msgBufDecoded[decodedBufPos] = digits[i] + '0'; decodedBufPos++; + if (i == 1) { + Font_LoadChar(font, ':' - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; + msgCtx->msgBufDecoded[decodedBufPos] = ':'; + decodedBufPos++; + } + } + decodedBufPos--; + } else if (curChar == MESSAGE_ITEM_ICON) { + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[msgCtx->msgBufPos + 1]; + PRINTF("ITEM_NO=(%d) (%d)\n", msgCtx->msgBufDecoded[decodedBufPos], + font->msgBuf[msgCtx->msgBufPos + 1]); + Message_LoadItemIcon(play, font->msgBuf[msgCtx->msgBufPos + 1], R_TEXTBOX_Y + 10); + } else if (curChar == MESSAGE_BACKGROUND) { + msgCtx->textboxBackgroundIdx = font->msgBuf[msgCtx->msgBufPos + 1] * 2; + msgCtx->textboxBackgroundForeColorIdx = (font->msgBuf[msgCtx->msgBufPos + 2] & 0xF0) >> 4; + msgCtx->textboxBackgroundBackColorIdx = font->msgBuf[msgCtx->msgBufPos + 2] & 0xF; + msgCtx->textboxBackgroundYOffsetIdx = (font->msgBuf[msgCtx->msgBufPos + 3] & 0xF0) >> 4; + msgCtx->textboxBackgroundUnkArg = font->msgBuf[msgCtx->msgBufPos + 3] & 0xF; + DMA_REQUEST_SYNC(msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE, + (uintptr_t)_message_texture_staticSegmentRomStart + + msgCtx->textboxBackgroundIdx * MESSAGE_TEXTURE_STATIC_TEX_SIZE, + MESSAGE_TEXTURE_STATIC_TEX_SIZE, "../z_message_PAL.c", 1830); + DMA_REQUEST_SYNC(msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE + MESSAGE_TEXTURE_STATIC_TEX_SIZE, + (uintptr_t)_message_texture_staticSegmentRomStart + + (msgCtx->textboxBackgroundIdx + 1) * MESSAGE_TEXTURE_STATIC_TEX_SIZE, + MESSAGE_TEXTURE_STATIC_TEX_SIZE, "../z_message_PAL.c", 1834); + msgCtx->msgBufPos += 3; + R_TEXTBOX_BG_YPOS = R_TEXTBOX_Y + 8; + numLines = 2; +#if OOT_PAL + R_TEXT_INIT_XPOS = 50; +#endif + } else if (curChar == MESSAGE_COLOR) { + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; + } else if (curChar == MESSAGE_NEWLINE) { + numLines++; + } else if (curChar != MESSAGE_QUICKTEXT_ENABLE && curChar != MESSAGE_QUICKTEXT_DISABLE && + curChar != MESSAGE_AWAIT_BUTTON_PRESS && curChar != MESSAGE_OCARINA && + curChar != MESSAGE_PERSISTENT && curChar != MESSAGE_UNSKIPPABLE) { + if (curChar == MESSAGE_FADE) { + sTextFade = true; + PRINTF("NZ_TIMER_END (key_off_flag=%d)\n", sTextFade); + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; + } else if (curChar == MESSAGE_FADE2) { + sTextFade = true; + PRINTF("NZ_BGM (key_off_flag=%d)\n", sTextFade); + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; + } else if (curChar == MESSAGE_SHIFT || curChar == MESSAGE_TEXT_SPEED) { + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos] & 0xFF; + } else if (curChar == MESSAGE_SFX) { + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; + msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; + } else if (curChar == MESSAGE_TWO_CHOICE) { + msgCtx->choiceNum = 2; + } else if (curChar == MESSAGE_THREE_CHOICE) { + msgCtx->choiceNum = 3; + } else if (curChar != MESSAGE_CHAR_SPACE) { + Font_LoadChar(font, curChar - ' ', charTexIdx); + charTexIdx += FONT_CHAR_TEX_SIZE; } } - decodedBufPos--; - } else if (curChar == MESSAGE_ITEM_ICON) { - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[msgCtx->msgBufPos + 1]; - PRINTF("ITEM_NO=(%d) (%d)\n", msgCtx->msgBufDecoded[decodedBufPos], font->msgBuf[msgCtx->msgBufPos + 1]); - Message_LoadItemIcon(play, font->msgBuf[msgCtx->msgBufPos + 1], R_TEXTBOX_Y + 10); - } else if (curChar == MESSAGE_BACKGROUND) { - msgCtx->textboxBackgroundIdx = font->msgBuf[msgCtx->msgBufPos + 1] * 2; - msgCtx->textboxBackgroundForeColorIdx = (font->msgBuf[msgCtx->msgBufPos + 2] & 0xF0) >> 4; - msgCtx->textboxBackgroundBackColorIdx = font->msgBuf[msgCtx->msgBufPos + 2] & 0xF; - msgCtx->textboxBackgroundYOffsetIdx = (font->msgBuf[msgCtx->msgBufPos + 3] & 0xF0) >> 4; - msgCtx->textboxBackgroundUnkArg = font->msgBuf[msgCtx->msgBufPos + 3] & 0xF; - DMA_REQUEST_SYNC(msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE, - (uintptr_t)_message_texture_staticSegmentRomStart + - msgCtx->textboxBackgroundIdx * MESSAGE_TEXTURE_STATIC_TEX_SIZE, - MESSAGE_TEXTURE_STATIC_TEX_SIZE, "../z_message_PAL.c", 1830); - DMA_REQUEST_SYNC(msgCtx->textboxSegment + MESSAGE_STATIC_TEX_SIZE + MESSAGE_TEXTURE_STATIC_TEX_SIZE, - (uintptr_t)_message_texture_staticSegmentRomStart + - (msgCtx->textboxBackgroundIdx + 1) * MESSAGE_TEXTURE_STATIC_TEX_SIZE, - MESSAGE_TEXTURE_STATIC_TEX_SIZE, "../z_message_PAL.c", 1834); - msgCtx->msgBufPos += 3; - R_TEXTBOX_BG_YPOS = R_TEXTBOX_Y + 8; - numLines = 2; - R_TEXT_INIT_XPOS = 50; - } else if (curChar == MESSAGE_COLOR) { - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; - } else if (curChar == MESSAGE_NEWLINE) { - numLines++; - } else if (curChar != MESSAGE_QUICKTEXT_ENABLE && curChar != MESSAGE_QUICKTEXT_DISABLE && - curChar != MESSAGE_AWAIT_BUTTON_PRESS && curChar != MESSAGE_OCARINA && - curChar != MESSAGE_PERSISTENT && curChar != MESSAGE_UNSKIPPABLE) { - if (curChar == MESSAGE_FADE) { - sTextFade = true; - PRINTF("NZ_TIMER_END (key_off_flag=%d)\n", sTextFade); - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; - } else if (curChar == MESSAGE_FADE2) { - sTextFade = true; - PRINTF("NZ_BGM (key_off_flag=%d)\n", sTextFade); - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; - } else if (curChar == MESSAGE_SHIFT || curChar == MESSAGE_TEXT_SPEED) { - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos] & 0xFF; - } else if (curChar == MESSAGE_SFX) { - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; - msgCtx->msgBufDecoded[++decodedBufPos] = font->msgBuf[++msgCtx->msgBufPos]; - } else if (curChar == MESSAGE_TWO_CHOICE) { - msgCtx->choiceNum = 2; - } else if (curChar == MESSAGE_THREE_CHOICE) { - msgCtx->choiceNum = 3; - } else if (curChar != ' ') { - Font_LoadChar(font, curChar - ' ', charTexIdx); - charTexIdx += FONT_CHAR_TEX_SIZE; - } + decodedBufPos++; + msgCtx->msgBufPos++; } - decodedBufPos++; - msgCtx->msgBufPos++; +#if OOT_NTSC } +#endif } void Message_OpenText(PlayState* play, u16 textId) { @@ -1661,6 +2402,12 @@ void Message_OpenText(PlayState* play, u16 textId) { R_TEXT_LINE_SPACING = 6; R_TEXT_INIT_XPOS = 20; YREG(1) = 48; +#if OOT_NTSC + } else if (gSaveContext.language == LANGUAGE_JPN) { + R_TEXT_CHAR_SCALE = 88; + R_TEXT_LINE_SPACING = 18; + R_TEXT_INIT_XPOS = 50; +#endif } else { R_TEXT_CHAR_SCALE = 75; R_TEXT_LINE_SPACING = 12; @@ -1698,19 +2445,31 @@ void Message_OpenText(PlayState* play, u16 textId) { DMA_REQUEST_SYNC(font->msgBuf, (uintptr_t)_staff_message_data_staticSegmentRomStart + font->msgOffset, font->msgLength, "../z_message_PAL.c", 1954); } else { -#if OOT_PAL // TODO: implement NTSC version +#if OOT_NTSC + if (gSaveContext.language == LANGUAGE_JPN) { + Message_FindMessageJPN(play, textId); + msgCtx->msgLength = font->msgLength; + DmaMgr_RequestSync(font->msgBuf, (uintptr_t)_jpn_message_data_staticSegmentRomStart + font->msgOffset, + font->msgLength); + } else { + Message_FindMessageNES(play, textId); + msgCtx->msgLength = font->msgLength; + DmaMgr_RequestSync(font->msgBuf, (uintptr_t)_nes_message_data_staticSegmentRomStart + font->msgOffset, + font->msgLength); + } +#else if (gSaveContext.language == LANGUAGE_ENG) { - Message_FindMessage(play, textId); + Message_FindMessagePAL(play, textId); msgCtx->msgLength = font->msgLength; DMA_REQUEST_SYNC(font->msgBuf, (uintptr_t)_nes_message_data_staticSegmentRomStart + font->msgOffset, font->msgLength, "../z_message_PAL.c", 1966); } else if (gSaveContext.language == LANGUAGE_GER) { - Message_FindMessage(play, textId); + Message_FindMessagePAL(play, textId); msgCtx->msgLength = font->msgLength; DMA_REQUEST_SYNC(font->msgBuf, (uintptr_t)_ger_message_data_staticSegmentRomStart + font->msgOffset, font->msgLength, "../z_message_PAL.c", 1978); } else { - Message_FindMessage(play, textId); + Message_FindMessagePAL(play, textId); msgCtx->msgLength = font->msgLength; DMA_REQUEST_SYNC(font->msgBuf, (uintptr_t)_fra_message_data_staticSegmentRomStart + font->msgOffset, font->msgLength, "../z_message_PAL.c", 1990); @@ -1932,8 +2691,8 @@ void Message_StartOcarinaImpl(PlayState* play, u16 ocarinaActionId) { gSaveContext.hudVisibilityMode = HUD_VISIBILITY_NO_CHANGE; Interface_ChangeHudVisibilityMode(HUD_VISIBILITY_NOTHING); } - for (k = 0, j = 0; j < 48; j++, k += 0x80) { - func_8006EE50(&play->msgCtx.font, 0x8140, k); + for (k = 0, j = 0; j < 48; j++, k += FONT_CHAR_TEX_SIZE) { + Font_LoadCharWide(&play->msgCtx.font, MESSAGE_WIDE_CHAR_SPACE, k); } } @@ -2028,6 +2787,18 @@ void Message_SetView(View* view) { View_ApplyOrthoToOverlay(view); } +#if OOT_NTSC +#define DRAW_TEXT(play, gfx, isCredits) \ + if (gSaveContext.language == LANGUAGE_JPN && !(isCredits)) { \ + Message_DrawTextWide(play, gfx); \ + } else { \ + Message_DrawText(play, gfx); \ + } \ + (void)0 +#else +#define DRAW_TEXT(play, gfx, isCredits) Message_DrawText(play, gfx) +#endif + /** * Draws the textbox in full and updates ocarina state */ @@ -2107,19 +2878,19 @@ void Message_DrawMain(PlayState* play, Gfx** p) { break; case MSGMODE_TEXT_CONTINUING: if (msgCtx->stateTimer == 1) { - for (j = 0, i = 0; i < 48; i++, j += 0x80) { - func_8006EE50(&play->msgCtx.font, 0x8140, j); + for (j = 0, i = 0; i < 48; i++, j += FONT_CHAR_TEX_SIZE) { + Font_LoadCharWide(&play->msgCtx.font, MESSAGE_WIDE_CHAR_SPACE, j); } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, sTextIsCredits); } break; case MSGMODE_TEXT_DISPLAYING: case MSGMODE_TEXT_DELAYED_BREAK: - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, sTextIsCredits); break; case MSGMODE_TEXT_AWAIT_INPUT: case MSGMODE_TEXT_AWAIT_NEXT: - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, sTextIsCredits); Message_DrawTextboxIcon(play, &gfx, R_TEXTBOX_END_XPOS, R_TEXTBOX_END_YPOS); break; case MSGMODE_OCARINA_STARTING: @@ -2162,7 +2933,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { } if (msgCtx->ocarinaAction != OCARINA_ACTION_FREE_PLAY && msgCtx->ocarinaAction != OCARINA_ACTION_CHECK_NOWARP) { - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, sTextIsCredits); } break; case MSGMODE_OCARINA_PLAYING: @@ -2241,6 +3012,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } + if (msgCtx->ocarinaStaff == NULL) {} // fake Interface_ChangeHudVisibilityMode(HUD_VISIBILITY_NOTHING); } else { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); @@ -2261,7 +3033,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { } if (msgCtx->ocarinaAction != OCARINA_ACTION_FREE_PLAY && msgCtx->ocarinaAction != OCARINA_ACTION_CHECK_NOWARP) { - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, sTextIsCredits); } break; case MSGMODE_OCARINA_CORRECT_PLAYBACK: @@ -2402,11 +3174,11 @@ void Message_DrawMain(PlayState* play, Gfx** p) { play->msgCtx.ocarinaMode = OCARINA_MODE_03; } } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_OCARINA_FAIL: case MSGMODE_SONG_PLAYBACK_FAIL: - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); FALLTHROUGH; case MSGMODE_OCARINA_FAIL_NO_TEXT: msgCtx->stateTimer--; @@ -2468,7 +3240,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { } break; case MSGMODE_SETUP_DISPLAY_SONG_PLAYED: - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_DEFAULT); AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_DEFAULT); AudioOcarina_SetPlaybackSong(msgCtx->lastPlayedSong + 1, 1); @@ -2508,28 +3280,28 @@ void Message_DrawMain(PlayState* play, Gfx** p) { sOcarinaButtonIndexBufPos = 0; msgCtx->msgMode = MSGMODE_SONG_DEMONSTRATION; } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_DISPLAY_SONG_PLAYED_TEXT_BEGIN: Message_ContinueTextbox(play, msgCtx->lastPlayedSong + 0x893); // You played [song name] Message_Decode(play); msgCtx->msgMode = MSGMODE_DISPLAY_SONG_PLAYED_TEXT; msgCtx->stateTimer = 20; - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_DISPLAY_SONG_PLAYED_TEXT: msgCtx->stateTimer--; if (msgCtx->stateTimer == 0) { msgCtx->msgMode = MSGMODE_SONG_PLAYED_ACT_BEGIN; } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_SONG_PLAYED_ACT_BEGIN: AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); Message_ResetOcarinaNoteState(); msgCtx->msgMode = MSGMODE_SONG_PLAYED_ACT; msgCtx->stateTimer = 2; - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_SONG_PLAYED_ACT: msgCtx->stateTimer--; @@ -2609,7 +3381,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { } FALLTHROUGH; case MSGMODE_SONG_DEMONSTRATION_DONE: - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_SONG_PLAYBACK: msgCtx->ocarinaStaff = AudioOcarina_GetPlayingStaff(); @@ -2638,10 +3410,10 @@ void Message_DrawMain(PlayState* play, Gfx** p) { msgCtx->stateTimer = 10; msgCtx->msgMode = MSGMODE_SONG_PLAYBACK_FAIL; } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_OCARINA_AWAIT_INPUT: - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); if (Message_ShouldAdvance(play)) { Message_StartOcarina(play, msgCtx->ocarinaAction); } @@ -2656,7 +3428,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { sOcarinaButtonIndexBufLen = 0; Message_ResetOcarinaNoteState(); msgCtx->msgMode = MSGMODE_SCARECROW_LONG_RECORDING_ONGOING; - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_SCARECROW_LONG_RECORDING_ONGOING: msgCtx->ocarinaStaff = AudioOcarina_GetRecordingStaff(); @@ -2706,7 +3478,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { PRINTF(VT_RST); PRINTF("\n====================================================================\n"); } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_SCARECROW_LONG_PLAYBACK: case MSGMODE_SCARECROW_SPAWN_PLAYBACK: @@ -2743,7 +3515,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { AudioOcarina_SetRecordingState(OCARINA_RECORD_SCARECROW_SPAWN); AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_DEFAULT); msgCtx->msgMode = MSGMODE_SCARECROW_SPAWN_RECORDING_ONGOING; - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_SCARECROW_SPAWN_RECORDING_ONGOING: msgCtx->ocarinaStaff = AudioOcarina_GetRecordingStaff(); @@ -2781,7 +3553,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { Message_CloseTextbox(play); msgCtx->msgMode = MSGMODE_SCARECROW_SPAWN_RECORDING_FAILED; } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_SCARECROW_SPAWN_RECORDING_FAILED: PRINTF("cccccccccccc\n"); @@ -2862,7 +3634,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { msgCtx->msgMode = MSGMODE_MEMORY_GAME_ROUND_SUCCESS; msgCtx->stateTimer = 30; } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_MEMORY_GAME_ROUND_SUCCESS: msgCtx->ocarinaStaff = AudioOcarina_GetPlayingStaff(); @@ -2885,7 +3657,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { play->msgCtx.ocarinaMode = OCARINA_MODE_0F; } } - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, false); break; case MSGMODE_MEMORY_GAME_START_NEXT_ROUND: if (!Audio_IsSfxPlaying(NA_SE_SY_METRONOME)) { @@ -2917,7 +3689,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { case MSGMODE_FROGS_WAITING: break; case MSGMODE_TEXT_DONE: - Message_DrawText(play, &gfx); + DRAW_TEXT(play, &gfx, sTextIsCredits); switch (msgCtx->textboxEndType) { case TEXTBOX_ENDTYPE_2_CHOICE: @@ -3239,9 +4011,22 @@ void Message_Update(PlayState* play) { R_TEXTBOX_X_TARGET = sTextboxXPositions[var]; R_TEXTBOX_END_YPOS = sTextboxEndIconYOffset[var] + R_TEXTBOX_Y_TARGET; +#if OOT_NTSC + if (gSaveContext.language == LANGUAGE_JPN && !sTextIsCredits) { + R_TEXT_CHOICE_YPOS(0) = R_TEXTBOX_Y_TARGET + 7; + R_TEXT_CHOICE_YPOS(1) = R_TEXTBOX_Y_TARGET + 25; + R_TEXT_CHOICE_YPOS(2) = R_TEXTBOX_Y_TARGET + 43; + + } else { + R_TEXT_CHOICE_YPOS(0) = R_TEXTBOX_Y_TARGET + 20; + R_TEXT_CHOICE_YPOS(1) = R_TEXTBOX_Y_TARGET + 32; + R_TEXT_CHOICE_YPOS(2) = R_TEXTBOX_Y_TARGET + 44; + } +#else R_TEXT_CHOICE_YPOS(0) = R_TEXTBOX_Y_TARGET + 20; R_TEXT_CHOICE_YPOS(1) = R_TEXTBOX_Y_TARGET + 32; R_TEXT_CHOICE_YPOS(2) = R_TEXTBOX_Y_TARGET + 44; +#endif PRINTF("message->msg_disp_type=%x\n", msgCtx->textBoxProperties & 0xF0); if (msgCtx->textBoxType == TEXTBOX_TYPE_NONE_BOTTOM || msgCtx->textBoxType == TEXTBOX_TYPE_NONE_NO_SHADOW) { @@ -3334,7 +4119,15 @@ void Message_Update(PlayState* play) { if (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_HAS_NEXT) { Audio_PlaySfxGeneral(NA_SE_SY_MESSAGE_PASS, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); +#if OOT_NTSC + if (gSaveContext.language == LANGUAGE_JPN && !sTextIsCredits) { + Message_ContinueTextbox(play, msgCtx->msgBufDecodedWide[msgCtx->textDrawPos]); + } else { + Message_ContinueTextbox(play, sNextTextId); + } +#else Message_ContinueTextbox(play, sNextTextId); +#endif } else { Audio_PlaySfxGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); diff --git a/src/overlays/actors/ovl_Fishing/z_fishing.c b/src/overlays/actors/ovl_Fishing/z_fishing.c index d1a18134c..49ff3b5f1 100644 --- a/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -12,7 +12,7 @@ #include "terminal.h" // For retail BSS ordering, the block number of sStreamSfxProjectedPos must be 0. -#pragma increment_block_number 208 +#pragma increment_block_number 206 #define FLAGS ACTOR_FLAG_4 diff --git a/tools/disasm/gc-us/functions.txt b/tools/disasm/gc-us/functions.txt index 6a84ee67b..5300b4ed5 100644 --- a/tools/disasm/gc-us/functions.txt +++ b/tools/disasm/gc-us/functions.txt @@ -1169,7 +1169,7 @@ Jpeg_Decode = 0x8005B1AC; // type:func KaleidoSetup_Update = 0x8005B4E0; // type:func KaleidoSetup_Init = 0x8005B74C; // type:func KaleidoSetup_Destroy = 0x8005B8A0; // type:func -func_8006EE50 = 0x8005B8B0; // type:func +Font_LoadCharWide = 0x8005B8B0; // type:func Font_LoadChar = 0x8005B904; // type:func Font_LoadMessageBoxIcon = 0x8005B954; // type:func Font_LoadOrderedFont = 0x8005B998; // type:func @@ -3072,8 +3072,8 @@ Message_SetTextColor = 0x800D7514; // type:func Message_DrawTextboxIcon = 0x800D77C8; // type:func Message_DrawItemIcon = 0x800D7F0C; // type:func Message_HandleOcarina = 0x800D8258; // type:func -Message_DrawTextJPN = 0x800D8468; // type:func -Message_DrawTextNES = 0x800D985C; // type:func +Message_DrawTextWide = 0x800D8468; // type:func +Message_DrawText = 0x800D985C; // type:func Message_LoadItemIcon = 0x800DAAD4; // type:func Message_Decode = 0x800DAC74; // type:func Message_OpenText = 0x800DD19C; // type:func From 7244cd62a5eaa9df53cb7fb0836abd8886232968 Mon Sep 17 00:00:00 2001 From: Tharo <17233964+Thar0@users.noreply.github.com> Date: Tue, 23 Jul 2024 23:47:00 +0100 Subject: [PATCH 06/14] Restore makefile rules for building asset files out of the assets directory (#2002) * Re-add makefile rules for building asset files out of the assets directory * Fix ASSET_FILES_OUT --- Makefile | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 47e0960e2..c73d6fddc 100644 --- a/Makefile +++ b/Makefile @@ -220,22 +220,29 @@ endif # create extracted directories $(shell mkdir -p $(EXTRACTED_DIR) $(EXTRACTED_DIR)/assets $(EXTRACTED_DIR)/text) -ASSET_BIN_DIRS := $(shell find $(EXTRACTED_DIR)/assets -type d) -ASSET_FILES_BIN := $(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.bin)) -ASSET_FILES_OUT := $(foreach f,$(ASSET_FILES_BIN:.bin=.bin.inc.c),$(f:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%)) \ - $(foreach f,$(wildcard assets/text/*.c),$(BUILD_DIR)/$(f:.c=.o)) +ASSET_BIN_DIRS_EXTRACTED := $(shell find $(EXTRACTED_DIR)/assets -type d) +ASSET_BIN_DIRS_COMMITTED := $(shell find assets -type d -not -path "assets/xml*" -not -path assets/text) +ASSET_BIN_DIRS := $(ASSET_BIN_DIRS_EXTRACTED) $(ASSET_BIN_DIRS_COMMITTED) + +ASSET_FILES_BIN_EXTRACTED := $(foreach dir,$(ASSET_BIN_DIRS_EXTRACTED),$(wildcard $(dir)/*.bin)) +ASSET_FILES_BIN_COMMITTED := $(foreach dir,$(ASSET_BIN_DIRS_COMMITTED),$(wildcard $(dir)/*.bin)) +ASSET_FILES_OUT := $(foreach f,$(ASSET_FILES_BIN_EXTRACTED:.bin=.bin.inc.c),$(f:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%)) \ + $(foreach f,$(ASSET_FILES_BIN_COMMITTED:.bin=.bin.inc.c),$(BUILD_DIR)/$f) \ + $(foreach f,$(wildcard assets/text/*.c),$(BUILD_DIR)/$(f:.c=.o)) UNDECOMPILED_DATA_DIRS := $(shell find data -type d) BASEROM_BIN_FILES := $(wildcard $(EXTRACTED_DIR)/baserom/*) # source files +ASSET_C_FILES_EXTRACTED := $(filter-out %.inc.c,$(foreach dir,$(ASSET_BIN_DIRS_EXTRACTED),$(wildcard $(dir)/*.c))) +ASSET_C_FILES_COMMITTED := $(filter-out %.inc.c,$(foreach dir,$(ASSET_BIN_DIRS_COMMITTED),$(wildcard $(dir)/*.c))) SRC_C_FILES := $(filter-out %.inc.c,$(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))) -ASSET_C_FILES := $(filter-out %.inc.c,$(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.c))) S_FILES := $(foreach dir,$(SRC_DIRS) $(UNDECOMPILED_DATA_DIRS),$(wildcard $(dir)/*.s)) O_FILES := $(foreach f,$(S_FILES:.s=.o),$(BUILD_DIR)/$f) \ $(foreach f,$(SRC_C_FILES:.c=.o),$(BUILD_DIR)/$f) \ - $(foreach f,$(ASSET_C_FILES:.c=.o),$(f:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%)) \ + $(foreach f,$(ASSET_C_FILES_EXTRACTED:.c=.o),$(f:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%)) \ + $(foreach f,$(ASSET_C_FILES_COMMITTED:.c=.o),$(BUILD_DIR)/$f) \ $(foreach f,$(BASEROM_BIN_FILES),$(BUILD_DIR)/baserom/$(notdir $f).o) OVL_RELOC_FILES := $(shell $(CPP) $(CPPFLAGS) $(SPEC) | $(SPEC_REPLACE_VARS) | grep -o '[^"]*_reloc.o' ) @@ -245,10 +252,14 @@ OVL_RELOC_FILES := $(shell $(CPP) $(CPPFLAGS) $(SPEC) | $(SPEC_REPLACE_VARS) | g DEP_FILES := $(O_FILES:.o=.asmproc.d) $(OVL_RELOC_FILES:.o=.d) -TEXTURE_FILES_PNG := $(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.png)) -TEXTURE_FILES_JPG := $(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.jpg)) -TEXTURE_FILES_OUT := $(foreach f,$(TEXTURE_FILES_PNG:.png=.inc.c),$(f:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%)) \ - $(foreach f,$(TEXTURE_FILES_JPG:.jpg=.jpg.inc.c),$(f:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%)) +TEXTURE_FILES_PNG_EXTRACTED := $(foreach dir,$(ASSET_BIN_DIRS_EXTRACTED),$(wildcard $(dir)/*.png)) +TEXTURE_FILES_PNG_COMMITTED := $(foreach dir,$(ASSET_BIN_DIRS_COMMITTED),$(wildcard $(dir)/*.png)) +TEXTURE_FILES_JPG_EXTRACTED := $(foreach dir,$(ASSET_BIN_DIRS_EXTRACTED),$(wildcard $(dir)/*.jpg)) +TEXTURE_FILES_JPG_COMMITTED := $(foreach dir,$(ASSET_BIN_DIRS_COMMITTED),$(wildcard $(dir)/*.jpg)) +TEXTURE_FILES_OUT := $(foreach f,$(TEXTURE_FILES_PNG_EXTRACTED:.png=.inc.c),$(f:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%)) \ + $(foreach f,$(TEXTURE_FILES_PNG_COMMITTED:.png=.inc.c),$(BUILD_DIR)/$f) \ + $(foreach f,$(TEXTURE_FILES_JPG_EXTRACTED:.jpg=.jpg.inc.c),$(f:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%)) \ + $(foreach f,$(TEXTURE_FILES_JPG_COMMITTED:.jpg=.jpg.inc.c),$(BUILD_DIR)/$f) # create build directories $(shell mkdir -p $(BUILD_DIR)/baserom $(BUILD_DIR)/assets/text $(foreach dir,$(SRC_DIRS) $(UNDECOMPILED_DATA_DIRS),$(BUILD_DIR)/$(dir)) $(foreach dir,$(ASSET_BIN_DIRS),$(dir:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%))) @@ -464,6 +475,10 @@ else endif $(OBJCOPY) -O binary -j.rodata $@ $@.bin +$(BUILD_DIR)/assets/%.o: assets/%.c + $(CC) -c $(CFLAGS) $(MIPS_VERSION) $(OPTFLAGS) -o $@ $< + $(OBJCOPY) -O binary $@ $@.bin + $(BUILD_DIR)/assets/%.o: $(EXTRACTED_DIR)/assets/%.c $(CC) -c $(CFLAGS) $(MIPS_VERSION) $(OPTFLAGS) -o $@ $< $(OBJCOPY) -O binary $@ $@.bin @@ -515,12 +530,21 @@ $(BUILD_DIR)/src/overlays/%_reloc.o: $(BUILD_DIR)/$(SPEC) $(FADO) $$(tools/reloc_prereq $< $(notdir $*)) -n $(notdir $*) -o $(@:.o=.s) -M $(@:.o=.d) $(AS) $(ASFLAGS) $(@:.o=.s) -o $@ +$(BUILD_DIR)/assets/%.inc.c: assets/%.png + $(ZAPD) btex -eh -tt $(subst .,,$(suffix $*)) -i $< -o $@ + $(BUILD_DIR)/assets/%.inc.c: $(EXTRACTED_DIR)/assets/%.png $(ZAPD) btex -eh -tt $(subst .,,$(suffix $*)) -i $< -o $@ +$(BUILD_DIR)/assets/%.bin.inc.c: assets/%.bin + $(ZAPD) bblb -eh -i $< -o $@ + $(BUILD_DIR)/assets/%.bin.inc.c: $(EXTRACTED_DIR)/assets/%.bin $(ZAPD) bblb -eh -i $< -o $@ +$(BUILD_DIR)/assets/%.jpg.inc.c: assets/%.jpg + $(ZAPD) bren -eh -i $< -o $@ + $(BUILD_DIR)/assets/%.jpg.inc.c: $(EXTRACTED_DIR)/assets/%.jpg $(ZAPD) bren -eh -i $< -o $@ From 294da9e355b71a80987cf3b85388eadd5e94b8e7 Mon Sep 17 00:00:00 2001 From: cadmic Date: Sat, 27 Jul 2024 19:29:15 -0700 Subject: [PATCH 07/14] Detect shifted .bss sections in check_ordering.py (#1992) * Restrict check_ordering.py to .bss sections by default * Detect shifted .bss sections in check_ordering.py --- tools/check_ordering.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/tools/check_ordering.py b/tools/check_ordering.py index 83eecfacb..0af2d9a94 100755 --- a/tools/check_ordering.py +++ b/tools/check_ordering.py @@ -94,7 +94,7 @@ def read_s16(f: BinaryIO, offset: int) -> int: def main(): parser = argparse.ArgumentParser( - description="Report data/bss reorderings between the baserom and the current build " + description="Report bss reorderings between the baserom and the current build " "by parsing relocations from the built object files and comparing their final values " "between the baserom and the current build. " "Assumes that the only differences are due to ordering and that the text sections of the " @@ -112,6 +112,11 @@ def main(): type=str, help="ROM segment to check, e.g. 'boot', 'code', or 'ovl_player_actor' (default: all)", ) + parser.add_argument( + "--all-sections", + action="store_true", + help="Check ordering for all section types, not just .bss", + ) args = parser.parse_args() version = args.oot_version @@ -176,10 +181,9 @@ def main(): else: assert False, "Invalid relocation" - if base_value != build_value: - pointers.append( - Pointer(reloc.name, reloc.addend, base_value, build_value) - ) + pointers.append( + Pointer(reloc.name, reloc.addend, base_value, build_value) + ) # Remove duplicates and sort by baserom address pointers = list({p.base_value: p for p in pointers}.values()) @@ -188,6 +192,9 @@ def main(): # Go through sections and report differences for mapfile_segment in source_code_segments: for file in mapfile_segment: + if not args.all_sections and not file.sectionType == ".bss": + continue + pointers_in_section = [ p for p in pointers @@ -196,6 +203,17 @@ def main(): if not pointers_in_section: continue + # Try to detect if the section is shifted by comparing the lowest + # address among any pointer into the section between base and build + base_min_address = min(p.base_value for p in pointers_in_section) + build_min_address = min(p.build_value for p in pointers_in_section) + section_shift = build_min_address - base_min_address + if all( + p.build_value == p.base_value + section_shift + for p in pointers_in_section + ): + continue + print(f"{file.filepath} {file.sectionType} is reordered:") for i, p in enumerate(pointers_in_section): if p.addend > 0: From d905e08daf48db00a8383b6c8855277977a0f4d6 Mon Sep 17 00:00:00 2001 From: fig02 Date: Sat, 27 Jul 2024 23:16:00 -0400 Subject: [PATCH 08/14] Document bottle color bug (#2000) * bottle color bug * adjust wording * format * small thing * reword * missed a letter --- src/code/z_player_lib.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 80d4c210d..1c05d26f9 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -1522,6 +1522,11 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve func_80090A28(this, spE4); func_800906D4(play, this, spE4); } else if ((*dList != NULL) && (this->leftHandType == PLAYER_MODELTYPE_LH_BOTTLE)) { + //! @bug When Player is actively using shield, the `itemAction` value will be set to -1. + //! If shield is used at the same time a bottle is in hand, `Player_ActionToBottle` will + //! return -1, which results in an out of bounds access behind the `sBottleColors` array. + //! A value of -1 happens to access `gLinkChildBottleDL` (0x06018478). The last 3 bytes of + //! this pointer are read as a color, which results in a dark teal color used for the bottle. Color_RGB8* bottleColor = &sBottleColors[Player_ActionToBottle(this, this->itemAction)]; OPEN_DISPS(play->state.gfxCtx, "../z_player_lib.c", 2710); From 7fcbf3f4b280e26284a8f62dbcb5b72d0e24dcc4 Mon Sep 17 00:00:00 2001 From: fig02 Date: Sat, 27 Jul 2024 23:47:58 -0400 Subject: [PATCH 09/14] Document `ANIM_FLAG_PLAYER_2` as `ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT` (#2001) * name ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT * reword * typo --- include/z64animation.h | 13 ++- src/code/z_player_lib.c | 5 +- .../actors/ovl_player_actor/z_player.c | 84 +++++++++++-------- 3 files changed, 60 insertions(+), 42 deletions(-) diff --git a/include/z64animation.h b/include/z64animation.h index 782380ad2..ff4df48a2 100644 --- a/include/z64animation.h +++ b/include/z64animation.h @@ -106,8 +106,15 @@ typedef enum { // An option is to implement and use `ANIM_FLAG_OVERRIDE_MOVEMENT`. #define ANIM_FLAG_UPDATE_Y (1 << 1) -// (player-only) Related to scaling an animation from/to child/adult -#define ANIM_FLAG_PLAYER_2 (1 << 2) +// When this flag is set, Player's root limb position adjustment as child is disabled. +// Many of Player's animations are originally created for Adult Link. When playing those +// animations as Child Link without any adjustment, he will appear to be floating in the air. +// To fix this, Child Link's root position is scaled down by default to fit his smaller size. +// However, if an animation is created specifically for Child Link, it is desirable to disable +// this scaling of the root position by using this flag. +// Note that this flag will be ignored if `ANIM_FLAG_UPDATE_XZ` or `ANIM_FLAG_UPDATE_Y` are also +// set. The adjustment will be applied in this case regardless of this flag being enabled. +#define ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT (1 << 2) // (player-only) Call AnimTaskQueue_AddActorMove #define ANIM_FLAG_PLAYER_SETMOVE (1 << 3) @@ -123,7 +130,7 @@ typedef enum { // Some animations have translation data that does not begin at the "origin". This is common when a // longer sequence of animation is broken up into different parts as seperate animations. // In this case, when one animation starts its translation at the same position where a different animation -// left off, resetting `prevTransl` is not desireable. This will cause the actor's position to noticeably change +// left off, resetting `prevTransl` is not desirable. This will cause the actor's position to noticeably change // when the translation data from the first frame of the new animation is applied. // // When this flag is used during a transition between two animations, the first frame of movement is not applied. diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 1c05d26f9..7b90a1e35 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -1125,13 +1125,14 @@ s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx** sCurBodyPartPos = &this->bodyPartsPos[0] - 1; if (!LINK_IS_ADULT) { - if (!(this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) || + if (!(this->skelAnime.moveFlags & ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT) || (this->skelAnime.moveFlags & ANIM_FLAG_UPDATE_XZ)) { pos->x *= 0.64f; pos->z *= 0.64f; } - if (!(this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) || (this->skelAnime.moveFlags & ANIM_FLAG_UPDATE_Y)) { + if (!(this->skelAnime.moveFlags & ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT) || + (this->skelAnime.moveFlags & ANIM_FLAG_UPDATE_Y)) { pos->y *= 0.64f; } } diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 9ac957cc0..0073b5d76 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -2008,7 +2008,8 @@ void Player_AnimReplacePlayOnceAdjusted(PlayState* play, Player* this, LinkAnima void Player_AnimReplaceNormalPlayOnceAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) { Player_AnimReplacePlayOnceAdjusted(play, this, anim, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_ADJUST_STARTING_POS); } void Player_AnimReplacePlayLoopSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, @@ -2027,7 +2028,8 @@ void Player_AnimReplacePlayLoopAdjusted(PlayState* play, Player* this, LinkAnima void Player_AnimReplaceNormalPlayLoopAdjusted(PlayState* play, Player* this, LinkAnimationHeader* anim) { Player_AnimReplacePlayLoopAdjusted(play, this, anim, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_ADJUST_STARTING_POS); } void Player_ProcessControlStick(PlayState* play, Player* this) { @@ -5056,7 +5058,7 @@ s32 Player_ActionChange_1(Player* this, PlayState* play) { func_80832224(this); Player_AnimReplaceApplyFlags(play, this, ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); // If this door is the second half of a double door (spawned as child) @@ -5367,9 +5369,9 @@ s32 func_8083A6AC(Player* this, PlayState* play) { this->stateFlags1 |= PLAYER_STATE1_21; Player_AnimReplaceApplyFlags(play, this, - ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 | - ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | - ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); this->av2.actionVar2 = -1; this->av1.actionVar1 = sp50; @@ -6062,7 +6064,7 @@ s32 Player_ActionChange_11(Player* this, PlayState* play) { LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, frame, frame, ANIMMODE_ONCE, 0.0f); if (Player_IsChildWithHylianShield(this)) { - Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_PLAYER_2); + Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT); } Player_PlaySfx(this, NA_SE_IT_SHIELD_POSTURE); @@ -6892,8 +6894,8 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_98); Player_AnimReplaceApplyFlags(play, this, ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); chest->unk_1F4 = 1; Camera_RequestSetting(Play_GetCamera(play, CAM_ID_MAIN), CAM_SET_SLOW_CHEST_CS); } else { @@ -7069,10 +7071,10 @@ s32 func_8083EC18(Player* this, PlayState* play, u32 wallFlags) { func_80832224(this); Math_Vec3f_Copy(&this->actor.prevPos, &this->actor.world.pos); Player_AnimPlayOnce(play, this, anim); - Player_AnimReplaceApplyFlags(play, this, - ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 | - ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | - ANIM_FLAG_OVERRIDE_MOVEMENT); + Player_AnimReplaceApplyFlags( + play, this, + ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); return true; } @@ -7152,8 +7154,9 @@ s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWall this->actor.prevPos = this->actor.world.pos; Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start); Player_AnimReplaceApplyFlags(play, this, - ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | + ANIM_FLAG_OVERRIDE_MOVEMENT); return true; } @@ -7242,8 +7245,9 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end); Player_AnimReplaceApplyFlags(play, this, - ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | + ANIM_FLAG_OVERRIDE_MOVEMENT); OnePointCutscene_Init(play, 9601, 999, NULL, CAM_ID_MAIN); } else { // Leaving a crawlspace backwards @@ -7252,8 +7256,9 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, 0.0f); Player_AnimReplaceApplyFlags(play, this, - ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | + ANIM_FLAG_OVERRIDE_MOVEMENT); OnePointCutscene_Init(play, 9602, 999, NULL, CAM_ID_MAIN); } @@ -8661,7 +8666,7 @@ void Player_Action_80843188(Player* this, PlayState* play) { LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_clink_normal_defense_ALL, 1.0f, Animation_GetLastFrame(&gPlayerAnim_clink_normal_defense_ALL), 0.0f, ANIMMODE_ONCE, 0.0f); - Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_PLAYER_2); + Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT); } else { if (this->itemAction < 0) { func_8008EC70(this); @@ -9972,7 +9977,8 @@ void func_808467D4(PlayState* play, Player* this) { 0.0f); Player_AnimReplaceApplyFlags(play, this, ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_OVERRIDE_MOVEMENT); if (LINK_IS_ADULT) { func_80846720(play, this, 0); } @@ -11350,8 +11356,9 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { if (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_SETMOVE) { AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, - (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) ? 1.0f - : this->ageProperties->unk_08); + (this->skelAnime.moveFlags & ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT) + ? 1.0f + : this->ageProperties->unk_08); } Player_UpdateShapeYaw(this, play); @@ -14549,8 +14556,8 @@ void func_808510D4(PlayState* play, Player* this, void* anim) { void func_808510F4(PlayState* play, Player* this, void* anim) { Player_AnimReplacePlayOnce(play, this, anim, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | - ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); } void func_80851114(PlayState* play, Player* this, void* anim) { @@ -14559,8 +14566,8 @@ void func_80851114(PlayState* play, Player* this, void* anim) { void func_80851134(PlayState* play, Player* this, void* anim) { Player_AnimReplacePlayLoop(play, this, anim, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | - ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); } void func_80851154(PlayState* play, Player* this, void* anim) { @@ -14807,7 +14814,8 @@ void func_808519EC(PlayState* play, Player* this, CsCmdActorCue* cue) { Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_9C); Player_AnimReplaceApplyFlags(play, this, ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_OVERRIDE_MOVEMENT); } static struct_808551A4 D_808551A4[] = { @@ -14924,16 +14932,16 @@ void func_80851E64(PlayState* play, Player* this, CsCmdActorCue* cue) { void func_80851E90(PlayState* play, Player* this, CsCmdActorCue* cue) { Player_AnimReplacePlayOnce(play, this, &gPlayerAnim_clink_op3_negaeri, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | - ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); func_80832698(this, NA_SE_VO_LI_GROAN); } void func_80851ECC(PlayState* play, Player* this, CsCmdActorCue* cue) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimReplacePlayLoop(play, this, &gPlayerAnim_clink_op3_wait2, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | - ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); } } @@ -14960,8 +14968,8 @@ static AnimSfxEntry D_808551BC[] = { void func_80851FB0(PlayState* play, Player* this, CsCmdActorCue* cue) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimReplacePlayLoop(play, this, &gPlayerAnim_clink_op3_wait3, - ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | - ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | ANIM_FLAG_PLAYER_SETMOVE | + ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); this->av2.actionVar2 = 1; } else if (this->av2.actionVar2 == 0) { Player_ProcessAnimSfxList(this, D_808551BC); @@ -14985,8 +14993,9 @@ void func_80852048(PlayState* play, Player* this, CsCmdActorCue* cue) { void func_80852080(PlayState* play, Player* this, CsCmdActorCue* cue) { Player_AnimReplacePlayOnceAdjusted(play, this, &gPlayerAnim_clink_demo_futtobi, - ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | - ANIM_FLAG_ADJUST_STARTING_POS | ANIM_FLAG_OVERRIDE_MOVEMENT); + ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT | + ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_ADJUST_STARTING_POS | + ANIM_FLAG_OVERRIDE_MOVEMENT); func_80832698(this, NA_SE_VO_LI_FALL_L); } @@ -15273,7 +15282,8 @@ void func_80852B4C(PlayState* play, Player* this, CsCmdActorCue* cue, struct_808 arg3->func(play, this, cue); } - if ((D_80858AA0 & ANIM_FLAG_PLAYER_2) && !(this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2)) { + if ((D_80858AA0 & ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT) && + !(this->skelAnime.moveFlags & ANIM_FLAG_DISABLE_CHILD_ROOT_ADJUSTMENT)) { this->skelAnime.morphTable[0].y /= this->ageProperties->unk_08; D_80858AA0 = 0; } From 067d06bb56f2acb3436c24150e16487437dbf7c1 Mon Sep 17 00:00:00 2001 From: cadmic Date: Sat, 27 Jul 2024 21:09:05 -0700 Subject: [PATCH 10/14] Match NTSC loose ends (#2004) * Match NTSC loose ends * Add comment about giObjectSegment size --- src/code/z_actor.c | 10 +++++++++- src/code/z_common_data.c | 3 +++ src/code/z_play.c | 4 ++++ src/overlays/actors/ovl_Fishing/z_fishing.c | 12 +++++++++++- src/overlays/actors/ovl_player_actor/z_player.c | 6 +++++- 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 6afae4f1f..890a05a68 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -689,7 +689,7 @@ void TitleCard_InitPlaceName(PlayState* play, TitleCardContext* titleCtx, void* SceneTableEntry* loadedScene = play->loadedScene; u32 size = loadedScene->titleFile.vromEnd - loadedScene->titleFile.vromStart; - if ((size != 0) && (size <= 0x3000)) { + if ((size != 0) && (size <= 0x1000 * LANGUAGE_MAX)) { DMA_REQUEST_SYNC(texture, loadedScene->titleFile.vromStart, size, "../z_actor.c", 2765); } @@ -733,7 +733,15 @@ void TitleCard_Draw(PlayState* play, TitleCardContext* titleCtx) { OPEN_DISPS(play->state.gfxCtx, "../z_actor.c", 2824); +#if OOT_NTSC + if (gSaveContext.language == LANGUAGE_JPN) { + textureLanguageOffset = 0; + } else { + textureLanguageOffset = width * height; + } +#else textureLanguageOffset = width * height * gSaveContext.language; +#endif height = (width * height > 0x1000) ? 0x1000 / width : height; titleSecondY = titleY + (height * 4); diff --git a/src/code/z_common_data.c b/src/code/z_common_data.c index 47aecd9e6..a0588d929 100644 --- a/src/code/z_common_data.c +++ b/src/code/z_common_data.c @@ -24,4 +24,7 @@ void SaveContext_Init(void) { gSaveContext.dogIsLost = true; gSaveContext.nextTransitionType = TRANS_NEXT_TYPE_DEFAULT; gSaveContext.prevHudVisibilityMode = HUD_VISIBILITY_ALL; +#if OOT_NTSC + gSaveContext.language = LANGUAGE_ENG; +#endif } diff --git a/src/code/z_play.c b/src/code/z_play.c index 7abd6705c..4f536524f 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -168,7 +168,11 @@ void Play_SetupTransition(PlayState* this, s32 transitionType) { break; default: +#if OOT_NTSC + HUNGUP_AND_CRASH("../z_play.c", 2287); +#else HUNGUP_AND_CRASH("../z_play.c", 2290); +#endif break; } } diff --git a/src/overlays/actors/ovl_Fishing/z_fishing.c b/src/overlays/actors/ovl_Fishing/z_fishing.c index 49ff3b5f1..34876f792 100644 --- a/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -5759,8 +5759,18 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &sStreamSfxPos, &sStreamSfxProjectedPos, &sProjectedW); Sfx_PlaySfxAtPos(&sStreamSfxProjectedPos, NA_SE_EV_WATER_WALL - SFX_FLAG); - // convert length to weight. Theoretical max of 59 lbs (127^2*.0036+.5) + +#if OOT_NTSC + if (gSaveContext.language == LANGUAGE_JPN) { + gSaveContext.minigameScore = sFishLengthToWeigh; + } else { + // Convert length to weight. Theoretical max of 59 lbs (127^2*.0036+.5) + gSaveContext.minigameScore = (SQ((f32)sFishLengthToWeigh) * 0.0036f) + 0.5f; + } +#else + // Same as above, but for PAL gSaveContext.minigameScore = (SQ((f32)sFishLengthToWeigh) * 0.0036f) + 0.5f; +#endif #if OOT_DEBUG if (BREG(26) != 0) { diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 0073b5d76..aac7839a9 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -10113,7 +10113,11 @@ void Player_Init(Actor* thisx, PlayState* play2) { Player_SetEquipmentData(play, this); this->prevBoots = this->currentBoots; Player_InitCommon(this, play, gPlayerSkelHeaders[((void)0, gSaveContext.save.linkAge)]); - this->giObjectSegment = (void*)(((uintptr_t)ZELDA_ARENA_MALLOC(0x3008, "../z_player.c", 17175) + 8) & ~0xF); + // `giObjectSegment` is used for both "get item" objects and title cards. The maximum size for + // get item objects is 0x2000 (see the assert in func_8083AE40), and the maximum size for + // title cards is 0x1000 * LANGUAGE_MAX since each title card image includes all languages. + this->giObjectSegment = + (void*)(((uintptr_t)ZELDA_ARENA_MALLOC(0x1000 * LANGUAGE_MAX + 8, "../z_player.c", 17175) + 8) & ~0xF); respawnFlag = gSaveContext.respawnFlag; From 5515aa170567f1dd52b625a5adae7619ccdde291 Mon Sep 17 00:00:00 2001 From: cadmic Date: Sat, 27 Jul 2024 21:24:13 -0700 Subject: [PATCH 11/14] Configure incbins in version config instead of using the Debug ROM (#2005) * Run CPP for data/*.s * Configure incbins in version config instead of using the Debug ROM --- Makefile | 5 ++- baseroms/gc-eu-mq-dbg/config.yml | 65 ++++++++++++++++++++++++++++++++ baseroms/gc-eu-mq/config.yml | 57 ++++++++++++++++++++++++++++ baseroms/gc-eu/config.yml | 57 ++++++++++++++++++++++++++++ baseroms/gc-us/config.yml | 57 ++++++++++++++++++++++++++++ data/audio_tables.rodata.s | 16 ++++---- data/rsp.rodata.s | 18 ++++----- data/rsp.text.s | 14 +++---- data/rsp_boot.text.s | 10 ++--- data/unk_800093F0.data.s | 15 ++++---- data/unk_80009410.data.s | 10 ++--- data/unk_8012ABC0.data.s | 10 ++--- data/z_text.data.s | 16 ++++---- docs/tutorial/data.md | 8 ++-- src/makerom/ipl3.s | 2 +- tools/extract_incbins.py | 54 ++++++++++++++++++++++++++ tools/version_config.py | 19 ++++++++++ 17 files changed, 373 insertions(+), 60 deletions(-) create mode 100755 tools/extract_incbins.py diff --git a/Makefile b/Makefile index c73d6fddc..eedf572cf 100644 --- a/Makefile +++ b/Makefile @@ -170,7 +170,7 @@ endif CFLAGS += $(GBI_DEFINES) -ASFLAGS := -march=vr4300 -32 -no-pad-sections -Iinclude +ASFLAGS := -march=vr4300 -32 -no-pad-sections -Iinclude -I$(EXTRACTED_DIR) ifeq ($(COMPILER),gcc) CFLAGS += -G 0 -nostdinc $(INC) -march=vr4300 -mfix4300 -mabi=32 -mno-abicalls -mdivide-breaks -fno-PIC -fno-common -ffreestanding -fbuiltin -fno-builtin-sinf -fno-builtin-cosf $(CHECK_WARNINGS) -funsigned-char @@ -394,6 +394,7 @@ setup: venv $(MAKE) -C tools $(PYTHON) tools/decompress_baserom.py $(VERSION) $(PYTHON) tools/extract_baserom.py $(BASEROM_DIR)/baserom-decompressed.z64 --oot-version $(VERSION) -o $(EXTRACTED_DIR)/baserom + $(PYTHON) tools/extract_incbins.py $(EXTRACTED_DIR)/baserom --oot-version $(VERSION) -o $(EXTRACTED_DIR)/incbin $(PYTHON) tools/msgdis.py $(VERSION) $(PYTHON) extract_assets.py -v $(VERSION) -j$(N_THREADS) @@ -448,7 +449,7 @@ $(BUILD_DIR)/baserom/%.o: $(EXTRACTED_DIR)/baserom/% $(OBJCOPY) -I binary -O elf32-big $< $@ $(BUILD_DIR)/data/%.o: data/%.s - $(AS) $(ASFLAGS) $< -o $@ + $(CPP) $(CPPFLAGS) -Iinclude $< | $(AS) $(ASFLAGS) -o $@ $(BUILD_DIR)/assets/text/%.enc.jpn.h: assets/text/%.h $(EXTRACTED_DIR)/text/%.h assets/text/charmap.txt $(CPP) $(CPPFLAGS) -I$(EXTRACTED_DIR) $< | $(PYTHON) tools/msgenc.py --encoding jpn --charmap assets/text/charmap.txt - $@ diff --git a/baseroms/gc-eu-mq-dbg/config.yml b/baseroms/gc-eu-mq-dbg/config.yml index bd6c9bf6b..c5e301afa 100644 --- a/baseroms/gc-eu-mq-dbg/config.yml +++ b/baseroms/gc-eu-mq-dbg/config.yml @@ -1,5 +1,70 @@ dmadata_start: 0x12F70 text_lang_pal: true +incbins: + - name: ipl3 + segment: makerom + vram: 0x80000040 + size: 0xFC0 + - name: rspbootText + segment: boot + vram: 0x80009320 + size: 0xD0 + - name: aspMainText + segment: code + vram: 0x801120C0 + size: 0xFB0 + - name: gspS2DEX2d_fifoText + segment: code + vram: 0x80113070 + size: 0x18C0 + - name: njpgdspMainText + segment: code + vram: 0x80114930 + size: 0xAF0 + - name: gMojiFontTLUTs + segment: code + vram: 0x8012A740 + size: 0x80 + - name: gMojiFontTex + segment: code + vram: 0x8012A7C0 + size: 0x400 + - name: gSoundFontTable + segment: code + vram: 0x801550D0 + size: 0x270 + - name: gSequenceFontTable + segment: code + vram: 0x80155340 + size: 0x1C0 + - name: gSequenceTable + segment: code + vram: 0x80155500 + size: 0x6F0 + - name: gSampleBankTable + segment: code + vram: 0x80155BF0 + size: 0x80 + - name: aspMainData + segment: code + vram: 0x80155C70 + size: 0x2E0 + - name: gspF3DZEX2_NoN_PosLight_fifoText + segment: code + vram: 0x80155F50 + size: 0x1630 + - name: gspF3DZEX2_NoN_PosLight_fifoData + segment: code + vram: 0x80157580 + size: 0x420 + - name: gspS2DEX2d_fifoData + segment: code + vram: 0x801579A0 + size: 0x390 + - name: njpgdspMainData + segment: code + vram: 0x80157D30 + size: 0x60 variables: gMtxClear: 0x8012DB20 sNesMessageEntryTable: 0x8014B320 diff --git a/baseroms/gc-eu-mq/config.yml b/baseroms/gc-eu-mq/config.yml index e04429d0a..34c5cbe9c 100644 --- a/baseroms/gc-eu-mq/config.yml +++ b/baseroms/gc-eu-mq/config.yml @@ -1,5 +1,62 @@ dmadata_start: 0x7170 text_lang_pal: true +incbins: + - name: ipl3 + segment: makerom + vram: 0x80000040 + size: 0xFC0 + - name: rspbootText + segment: boot + vram: 0x80005FC0 + size: 0xD0 + - name: aspMainText + segment: code + vram: 0x800E11A0 + size: 0xFB0 + - name: gspS2DEX2d_fifoText + segment: code + vram: 0x800E2150 + size: 0x18C0 + - name: njpgdspMainText + segment: code + vram: 0x800E3A10 + size: 0xAF0 + - name: gSoundFontTable + segment: code + vram: 0x80110470 + size: 0x270 + - name: gSequenceFontTable + segment: code + vram: 0x801106E0 + size: 0x1C0 + - name: gSequenceTable + segment: code + vram: 0x801108A0 + size: 0x6F0 + - name: gSampleBankTable + segment: code + vram: 0x80110F90 + size: 0x80 + - name: aspMainData + segment: code + vram: 0x80111010 + size: 0x2E0 + - name: gspF3DZEX2_NoN_PosLight_fifoText + segment: code + vram: 0x801112F0 + size: 0x1630 + - name: gspF3DZEX2_NoN_PosLight_fifoData + segment: code + vram: 0x80112920 + size: 0x420 + - name: gspS2DEX2d_fifoData + segment: code + vram: 0x80112D40 + size: 0x390 + - name: njpgdspMainData + segment: code + vram: 0x801130D0 + size: 0x60 variables: gMtxClear: 0x800FBC00 sNesMessageEntryTable: 0x801077F0 diff --git a/baseroms/gc-eu/config.yml b/baseroms/gc-eu/config.yml index 6f48daec7..90712dc3f 100644 --- a/baseroms/gc-eu/config.yml +++ b/baseroms/gc-eu/config.yml @@ -1,5 +1,62 @@ dmadata_start: 0x7170 text_lang_pal: true +incbins: + - name: ipl3 + segment: makerom + vram: 0x80000040 + size: 0xFC0 + - name: rspbootText + segment: boot + vram: 0x80005FC0 + size: 0xD0 + - name: aspMainText + segment: code + vram: 0x800E11C0 + size: 0xFB0 + - name: gspS2DEX2d_fifoText + segment: code + vram: 0x800E2170 + size: 0x18C0 + - name: njpgdspMainText + segment: code + vram: 0x800E3A30 + size: 0xAF0 + - name: gSoundFontTable + segment: code + vram: 0x80110490 + size: 0x270 + - name: gSequenceFontTable + segment: code + vram: 0x80110700 + size: 0x1C0 + - name: gSequenceTable + segment: code + vram: 0x801108C0 + size: 0x6F0 + - name: gSampleBankTable + segment: code + vram: 0x80110FB0 + size: 0x80 + - name: aspMainData + segment: code + vram: 0x80111030 + size: 0x2E0 + - name: gspF3DZEX2_NoN_PosLight_fifoText + segment: code + vram: 0x80111310 + size: 0x1630 + - name: gspF3DZEX2_NoN_PosLight_fifoData + segment: code + vram: 0x80112940 + size: 0x420 + - name: gspS2DEX2d_fifoData + segment: code + vram: 0x80112D60 + size: 0x390 + - name: njpgdspMainData + segment: code + vram: 0x801130F0 + size: 0x60 variables: gMtxClear: 0x800FBC20 sNesMessageEntryTable: 0x80107810 diff --git a/baseroms/gc-us/config.yml b/baseroms/gc-us/config.yml index 0d6acafc3..54498f9a2 100644 --- a/baseroms/gc-us/config.yml +++ b/baseroms/gc-us/config.yml @@ -1,5 +1,62 @@ dmadata_start: 0x7170 text_lang_pal: false +incbins: + - name: ipl3 + segment: makerom + vram: 0x80000040 + size: 0xFC0 + - name: rspbootText + segment: boot + vram: 0x80005FC0 + size: 0xD0 + - name: aspMainText + segment: code + vram: 0x800E3840 + size: 0xFB0 + - name: gspS2DEX2d_fifoText + segment: code + vram: 0x800E47F0 + size: 0x18C0 + - name: njpgdspMainText + segment: code + vram: 0x800E60B0 + size: 0xAF0 + - name: gSoundFontTable + segment: code + vram: 0x80112C80 + size: 0x270 + - name: gSequenceFontTable + segment: code + vram: 0x80112EF0 + size: 0x1C0 + - name: gSequenceTable + segment: code + vram: 0x801130B0 + size: 0x6F0 + - name: gSampleBankTable + segment: code + vram: 0x801137A0 + size: 0x80 + - name: aspMainData + segment: code + vram: 0x80113820 + size: 0x2E0 + - name: gspF3DZEX2_NoN_PosLight_fifoText + segment: code + vram: 0x80113B00 + size: 0x1630 + - name: gspF3DZEX2_NoN_PosLight_fifoData + segment: code + vram: 0x80115130 + size: 0x420 + - name: gspS2DEX2d_fifoData + segment: code + vram: 0x80115550 + size: 0x390 + - name: njpgdspMainData + segment: code + vram: 0x801158E0 + size: 0x60 variables: gMtxClear: 0x800FE2A0 sJpnMessageEntryTable: 0x80109E8C diff --git a/data/audio_tables.rodata.s b/data/audio_tables.rodata.s index 5e76a127b..4f6655c86 100644 --- a/data/audio_tables.rodata.s +++ b/data/audio_tables.rodata.s @@ -1,22 +1,22 @@ .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 +/* 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 .rodata .balign 16 glabel gSoundFontTable - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCC270, 0x270 + .incbin "incbin/gSoundFontTable" glabel gSequenceFontTable - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCC4E0, 0x1C0 + .incbin "incbin/gSequenceFontTable" glabel gSequenceTable - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCC6A0, 0x6F0 + .incbin "incbin/gSequenceTable" glabel gSampleBankTable - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCCD90, 0x80 + .incbin "incbin/gSampleBankTable" diff --git a/data/rsp.rodata.s b/data/rsp.rodata.s index f3df8983f..bdb9fe991 100644 --- a/data/rsp.rodata.s +++ b/data/rsp.rodata.s @@ -1,30 +1,30 @@ .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 +/* 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 .rodata .balign 16 glabel aspMainDataStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCCE10, 0x2E0 + .incbin "incbin/aspMainData" glabel aspMainDataEnd glabel gspF3DZEX2_NoN_PosLight_fifoTextStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCD0F0, 0x1630 + .incbin "incbin/gspF3DZEX2_NoN_PosLight_fifoText" glabel gspF3DZEX2_NoN_PosLight_fifoTextEnd glabel gspF3DZEX2_NoN_PosLight_fifoDataStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCE720, 0x420 + .incbin "incbin/gspF3DZEX2_NoN_PosLight_fifoData" glabel gspF3DZEX2_NoN_PosLight_fifoDataEnd glabel gspS2DEX2d_fifoDataStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCEB40, 0x390 + .incbin "incbin/gspS2DEX2d_fifoData" glabel gspS2DEX2d_fifoDataEnd glabel njpgdspMainDataStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBCEED0, 0x60 + .incbin "incbin/njpgdspMainData" glabel njpgdspMainDataEnd diff --git a/data/rsp.text.s b/data/rsp.text.s index 045d8d614..fcf48a251 100644 --- a/data/rsp.text.s +++ b/data/rsp.text.s @@ -1,22 +1,22 @@ .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 +/* 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 .text .balign 16 glabel aspMainTextStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xB89260, 0xFB0 + .incbin "incbin/aspMainText" glabel aspMainTextEnd glabel gspS2DEX2d_fifoTextStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xB8A210, 0x18C0 + .incbin "incbin/gspS2DEX2d_fifoText" glabel gspS2DEX2d_fifoTextEnd glabel njpgdspMainTextStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xB8BAD0, 0xAF0 + .incbin "incbin/njpgdspMainText" glabel njpgdspMainTextEnd diff --git a/data/rsp_boot.text.s b/data/rsp_boot.text.s index 01fe3f0a7..59c9ffc27 100644 --- a/data/rsp_boot.text.s +++ b/data/rsp_boot.text.s @@ -1,14 +1,14 @@ .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 +/* 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 .text .balign 16 glabel rspbootTextStart - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0x9F20, 0xD0 + .incbin "incbin/rspbootText" glabel rspbootTextEnd diff --git a/data/unk_800093F0.data.s b/data/unk_800093F0.data.s index 380dbe64b..bf8a636c0 100644 --- a/data/unk_800093F0.data.s +++ b/data/unk_800093F0.data.s @@ -1,17 +1,18 @@ .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 +/* 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 .data .balign 16 -# Unused. -# This appears to be RSP code, however it is not part of -# rspboot as rspbootTextEnd is at this symbol +/* Unused. + * This appears to be RSP code, however it is not part of + * rspboot as rspbootTextEnd is at this symbol. + */ glabel D_800093F0 .word 0xE80C2001 # sqv $v12[0], 0x10($zero) .word 0x34014000 # li $1, 0x4000 diff --git a/data/unk_80009410.data.s b/data/unk_80009410.data.s index d2bded6c3..8ff273e22 100644 --- a/data/unk_80009410.data.s +++ b/data/unk_80009410.data.s @@ -1,15 +1,15 @@ .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 +/* 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 .data .balign 16 -# Unused +/* Unused */ glabel D_80009410 .word osStopThread .word __osSetHWIntrRoutine diff --git a/data/unk_8012ABC0.data.s b/data/unk_8012ABC0.data.s index 31e03580e..7f99d09e0 100644 --- a/data/unk_8012ABC0.data.s +++ b/data/unk_8012ABC0.data.s @@ -1,15 +1,15 @@ .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 +/* 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 .data .balign 16 -# Unused +/* Unused */ glabel D_8012ABC0 .word fmodf .word guScale diff --git a/data/z_text.data.s b/data/z_text.data.s index 3fe890cdb..d2a76e0b8 100644 --- a/data/z_text.data.s +++ b/data/z_text.data.s @@ -1,18 +1,20 @@ .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 +/* 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 .data .balign 16 -# temporary file name, rename to something more appropriate when decompiled +/* temporary file name, rename to something more appropriate when decompiled */ +#if OOT_DEBUG glabel gMojiFontTLUTs - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBA18E0, 0x80 + .incbin "incbin/gMojiFontTLUTs" glabel gMojiFontTex - .incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0xBA1960, 0x400 + .incbin "incbin/gMojiFontTex" +#endif diff --git a/docs/tutorial/data.md b/docs/tutorial/data.md index a96d26d84..bc3bf0765 100644 --- a/docs/tutorial/data.md +++ b/docs/tutorial/data.md @@ -37,10 +37,10 @@ Large code block, click to show ``` .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 + /* 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 .data diff --git a/src/makerom/ipl3.s b/src/makerom/ipl3.s index be02f7e2f..45f1c8e6f 100644 --- a/src/makerom/ipl3.s +++ b/src/makerom/ipl3.s @@ -1,4 +1,4 @@ .section .text -.incbin "baseroms/gc-eu-mq-dbg/baserom-decompressed.z64", 0x40, 0xFC0 +.incbin "incbin/ipl3" diff --git a/tools/extract_incbins.py b/tools/extract_incbins.py new file mode 100755 index 000000000..c76129ca4 --- /dev/null +++ b/tools/extract_incbins.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: © 2024 ZeldaRET +# SPDX-License-Identifier: CC0-1.0 + +from __future__ import annotations + +import argparse +from pathlib import Path +import sys + +import dmadata +import version_config + + +def main(): + parser = argparse.ArgumentParser( + description="Extract incbin pieces from an uncompressed ROM." + ) + parser.add_argument( + "baserom_dir", metavar="BASEROM_DIR", type=Path, help="Directory of uncompressed ROM segments" + ) + parser.add_argument( + "-v", + "--oot-version", + required=True, + help="OOT version", + ) + parser.add_argument( + "-o", + "--output-dir", + type=Path, + required=True, + help="Output directory for incbin pieces", + ) + + args = parser.parse_args() + + config = version_config.load_version_config(args.oot_version) + + args.output_dir.mkdir(parents=True, exist_ok=True) + for incbin in config.incbins: + incbin_path = args.output_dir / incbin.name + with open(args.baserom_dir / incbin.segment, "rb") as f: + offset = incbin.vram - config.dmadata_segments[incbin.segment].vram + f.seek(offset) + incbin_data = f.read(incbin.size) + incbin_path.write_bytes(incbin_data) + + print(f"Extracted {len(config.incbins)} incbin pieces to {args.output_dir}") + + +if __name__ == "__main__": + main() diff --git a/tools/version_config.py b/tools/version_config.py index 6ca203fd5..f1666d145 100644 --- a/tools/version_config.py +++ b/tools/version_config.py @@ -26,6 +26,8 @@ class VersionConfig: text_lang_pal: bool # DMA segment information, in ROM order dmadata_segments: OrderedDict[str, SegmentInfo] + # ROM pieces that are copied directly into the build with .incbin + incbins: list[IncbinConfig] # Addresses of important variables needed for asset extraction variables: dict[str, int] # Assets to extract @@ -38,6 +40,14 @@ class SegmentInfo: vram: Optional[int] +@dataclasses.dataclass +class IncbinConfig: + name: str + segment: str + vram: int + size: int + + @dataclasses.dataclass class AssetConfig: name: str @@ -61,6 +71,14 @@ def load_version_config(version: str) -> VersionConfig: with open(PROJECT_ROOT / f"baseroms/{version}/config.yml", "r") as f: config = yaml.load(f, Loader=yaml.Loader) + incbins = [] + for incbin in config["incbins"]: + incbins.append( + IncbinConfig( + incbin["name"], incbin["segment"], incbin["vram"], incbin["size"] + ) + ) + assets = [] for asset in config["assets"]: name = asset["name"] @@ -74,6 +92,7 @@ def load_version_config(version: str) -> VersionConfig: dmadata_start=config["dmadata_start"], text_lang_pal=config["text_lang_pal"], dmadata_segments=load_dmadata_segments(version), + incbins=incbins, variables=config["variables"], assets=assets, ) From ec5068c58d3c40d188c9a59791e5562bff38ce3e Mon Sep 17 00:00:00 2001 From: cadmic Date: Sat, 27 Jul 2024 21:46:55 -0700 Subject: [PATCH 12/14] Introduce OOT_VERSION and OOT_REGION defines for build info and ROM header (#2003) * Use version defines for build info and ROM header * Use existing REGION_ defines for OOT_REGION instead --- Makefile | 35 +++++++++++++++++++++++++++++------ include/macros.h | 10 ++++++++++ include/region.h | 9 +++++++++ include/z64.h | 8 -------- src/boot/build.c | 13 +++++++++---- src/boot/z_locale.c | 7 ++++--- src/makerom/rom_header.s | 11 +++++++++++ 7 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 include/region.h diff --git a/Makefile b/Makefile index eedf572cf..163311086 100644 --- a/Makefile +++ b/Makefile @@ -53,18 +53,25 @@ endif # Version-specific settings ifeq ($(VERSION),gc-us) + REGION := US + PAL := 0 + MQ := 0 DEBUG := 0 - COMPARE := 0 - CPP_DEFINES += -DOOT_NTSC=1 -DOOT_PAL=0 -DOOT_MQ=0 else ifeq ($(VERSION),gc-eu) + REGION := EU + PAL := 1 + MQ := 0 DEBUG := 0 - CPP_DEFINES += -DOOT_NTSC=0 -DOOT_PAL=1 -DOOT_MQ=0 else ifeq ($(VERSION),gc-eu-mq) + REGION := EU + PAL := 1 + MQ := 1 DEBUG := 0 - CPP_DEFINES += -DOOT_NTSC=0 -DOOT_PAL=1 -DOOT_MQ=1 else ifeq ($(VERSION),gc-eu-mq-dbg) + REGION := EU + PAL := 1 + MQ := 1 DEBUG := 1 - CPP_DEFINES += -DOOT_NTSC=0 -DOOT_PAL=1 -DOOT_MQ=1 else $(error Unsupported version $(VERSION)) endif @@ -79,11 +86,27 @@ VENV := .venv MAKE = make CPPFLAGS += -P -xc -fno-dollars-in-identifiers +# Converts e.g. ntsc-1.0 to OOT_NTSC_1_0 +CPP_DEFINES += -DOOT_VERSION=OOT_$(shell echo $(VERSION) | tr a-z-. A-Z__) +CPP_DEFINES += -DOOT_REGION=REGION_$(REGION) + +ifeq ($(PAL),0) + CPP_DEFINES += -DOOT_NTSC=1 +else + CPP_DEFINES += -DOOT_PAL=1 +endif + +ifeq ($(MQ),0) + CPP_DEFINES += -DOOT_MQ=0 +else + CPP_DEFINES += -DOOT_MQ=1 +endif + ifeq ($(DEBUG),1) CPP_DEFINES += -DOOT_DEBUG=1 OPTFLAGS := -O2 else - CPP_DEFINES += -DNDEBUG -DOOT_DEBUG=0 + CPP_DEFINES += -DOOT_DEBUG=0 -DNDEBUG OPTFLAGS := -O2 -g3 endif diff --git a/include/macros.h b/include/macros.h index e13593406..ed67abc4a 100644 --- a/include/macros.h +++ b/include/macros.h @@ -1,6 +1,16 @@ #ifndef MACROS_H #define MACROS_H +// OOT versions in build order +#define OOT_GC_JP 1 +#define OOT_GC_JP_MQ 2 +#define OOT_GC_US 3 +#define OOT_GC_US_MQ 4 +#define OOT_GC_EU_MQ_DBG 5 +#define OOT_GC_EU 6 +#define OOT_GC_EU_MQ 7 +#define OOT_GC_JP_CE 8 + #ifndef AVOID_UB #define BAD_RETURN(type) type #else diff --git a/include/region.h b/include/region.h new file mode 100644 index 000000000..b33375e6f --- /dev/null +++ b/include/region.h @@ -0,0 +1,9 @@ +#ifndef REGION_H +#define REGION_H + +#define REGION_NULL 0 +#define REGION_JP 1 +#define REGION_US 2 +#define REGION_EU 3 + +#endif diff --git a/include/z64.h b/include/z64.h index 03ef633b7..7e0b60ee5 100644 --- a/include/z64.h +++ b/include/z64.h @@ -70,11 +70,6 @@ #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 -#define REGION_NULL 0 -#define REGION_JP 1 -#define REGION_US 2 -#define REGION_EU 3 - #define THREAD_PRI_IDLE_INIT 10 #define THREAD_PRI_MAIN_INIT 10 #define THREAD_PRI_DMAMGR_LOW 10 // Used when decompressing files @@ -104,9 +99,6 @@ #define STACK_TOP(stack) \ ((u8*)(stack) + sizeof(stack)) -// NOTE: Once we start supporting other builds, this can be changed with an ifdef -#define REGION_NATIVE REGION_EU - typedef struct { /* 0x00 */ void* loadedRamAddr; /* 0x04 */ RomFile file; diff --git a/src/boot/build.c b/src/boot/build.c index d2fb891c0..a69c28d1f 100644 --- a/src/boot/build.c +++ b/src/boot/build.c @@ -1,12 +1,17 @@ +#include "macros.h" + const char gBuildTeam[] = "zelda@srd022j"; -// TODO: Use per-version preprocessor defines -#if OOT_DEBUG // gc-eu-mq-dbg +#if OOT_VERSION == OOT_GC_US +const char gBuildDate[] = "02-12-19 13:28:09"; +#elif OOT_VERSION == OOT_GC_EU_MQ_DBG const char gBuildDate[] = "03-02-21 00:16:31"; -#elif !OOT_MQ // gc-eu +#elif OOT_VERSION == OOT_GC_EU const char gBuildDate[] = "03-02-21 20:12:23"; -#else // gc-eu-mq +#elif OOT_VERSION == OOT_GC_EU_MQ const char gBuildDate[] = "03-02-21 20:37:19"; +#else +#error "Unsupported OOT_VERSION" #endif const char gBuildMakeOption[] = ""; diff --git a/src/boot/z_locale.c b/src/boot/z_locale.c index abff2ba77..acd151ce4 100644 --- a/src/boot/z_locale.c +++ b/src/boot/z_locale.c @@ -1,4 +1,5 @@ #include "global.h" +#include "region.h" #include "terminal.h" u32 gCurrentRegion = 0; @@ -35,7 +36,7 @@ void Locale_ResetRegion(void) { #if OOT_DEBUG u32 func_80001F48(void) { - if (gCurrentRegion == REGION_NATIVE) { + if (gCurrentRegion == OOT_REGION) { return 0; } @@ -47,7 +48,7 @@ u32 func_80001F48(void) { } u32 func_80001F8C(void) { - if (gCurrentRegion == REGION_NATIVE) { + if (gCurrentRegion == OOT_REGION) { return 0; } @@ -60,6 +61,6 @@ u32 func_80001F8C(void) { // This function appears to be unused? u32 Locale_IsRegionNative(void) { - return gCurrentRegion == REGION_NATIVE; + return gCurrentRegion == OOT_REGION; } #endif diff --git a/src/makerom/rom_header.s b/src/makerom/rom_header.s index ec243cc9c..06694ae35 100644 --- a/src/makerom/rom_header.s +++ b/src/makerom/rom_header.s @@ -1,4 +1,5 @@ #include "rom_header.h" +#include "region.h" /* 0x00 */ ENDIAN_IDENTIFIER /* 0x01 */ PI_DOMAIN_1_CFG(64, 18, 7, 3) @@ -9,7 +10,17 @@ /* 0x18 */ PADDING(8) /* 0x20 */ ROM_NAME("THE LEGEND OF ZELDA") /* 0x34 */ PADDING(7) +#if OOT_NTSC +/* 0x3B */ MEDIUM(CARTRIDGE_EXPANDABLE) +#else /* 0x3B */ MEDIUM(CARTRIDGE) +#endif /* 0x3C */ GAME_ID("ZL") +#if OOT_REGION == REGION_US +/* 0x3E */ REGION(US) +#elif OOT_REGION == REGION_JP +/* 0x3E */ REGION(JP) +#elif OOT_REGION == REGION_EU /* 0x3E */ REGION(PAL) +#endif /* 0x3F */ GAME_REVISION(15) From 0db9e7275f72d404106dee86f17208fd8a35acbc Mon Sep 17 00:00:00 2001 From: cadmic Date: Mon, 29 Jul 2024 12:57:35 -0700 Subject: [PATCH 13/14] Fix Makefile performance regression with OOT_VERSION define (#2006) --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 163311086..9ffbc5c41 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,8 @@ MAKE = make CPPFLAGS += -P -xc -fno-dollars-in-identifiers # Converts e.g. ntsc-1.0 to OOT_NTSC_1_0 -CPP_DEFINES += -DOOT_VERSION=OOT_$(shell echo $(VERSION) | tr a-z-. A-Z__) +VERSION_MACRO := OOT_$(shell echo $(VERSION) | tr a-z-. A-Z__) +CPP_DEFINES += -DOOT_VERSION=$(VERSION_MACRO) CPP_DEFINES += -DOOT_REGION=REGION_$(REGION) ifeq ($(PAL),0) From 8ee485d2e7b237a785ac0cf3870117944c923a07 Mon Sep 17 00:00:00 2001 From: Tharo <17233964+Thar0@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:16:53 +0100 Subject: [PATCH 14/14] Create build directories for committed assets (#2007) --- Makefile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9ffbc5c41..11a960949 100644 --- a/Makefile +++ b/Makefile @@ -286,7 +286,16 @@ TEXTURE_FILES_OUT := $(foreach f,$(TEXTURE_FILES_PNG_EXTRACTED:.png=.inc.c),$(f: $(foreach f,$(TEXTURE_FILES_JPG_COMMITTED:.jpg=.jpg.inc.c),$(BUILD_DIR)/$f) # create build directories -$(shell mkdir -p $(BUILD_DIR)/baserom $(BUILD_DIR)/assets/text $(foreach dir,$(SRC_DIRS) $(UNDECOMPILED_DATA_DIRS),$(BUILD_DIR)/$(dir)) $(foreach dir,$(ASSET_BIN_DIRS),$(dir:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%))) +$(shell mkdir -p $(BUILD_DIR)/baserom \ + $(BUILD_DIR)/assets/text \ + $(foreach dir, \ + $(SRC_DIRS) \ + $(UNDECOMPILED_DATA_DIRS) \ + $(ASSET_BIN_DIRS_COMMITTED), \ + $(BUILD_DIR)/$(dir)) \ + $(foreach dir, \ + $(ASSET_BIN_DIRS_EXTRACTED), \ + $(dir:$(EXTRACTED_DIR)/%=$(BUILD_DIR)/%))) ifeq ($(COMPILER),ido) $(BUILD_DIR)/src/boot/stackcheck.o: OPTFLAGS := -O2