En_Gakufu OK and Documented + Related Audio Functions (#662)

* Gakufu OK, copy progress from audio WIP

* Extraction

* import wip in prep for audio data import

* Add in `code_8019AF00.c` functions

* Finish docs

* Spacing

* Add enum

* Many PR suggestions

* Another enum

* PR Suggestions

* Fix bss

* Move comment higher

* Fix bss

Co-authored-by: angie <angheloalf95@gmail.com>
This commit is contained in:
engineer124
2022-03-28 01:52:43 +11:00
committed by GitHub
parent 928acac500
commit 02cb971616
13 changed files with 488 additions and 101 deletions
+1 -1
View File
@@ -76,6 +76,6 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_80194568.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_80194668.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/Audio_NextRandom.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/Audio_InitMesgQueues.s")
+161 -21
View File
@@ -45,7 +45,7 @@ typedef enum {
/* 0xD */ SFX_CHANNEL_OCARINA, // SfxOcarinaBank
/* 0xE */ SFX_CHANNEL_VOICE0, // SfxVoiceBank
/* 0xF */ SFX_CHANNEL_VOICE1
} SfxChannelIdx; // playerIdx = 2
} SfxChannelIndex; // playerIndex = 2
// Global IO ports for sequences, 8 global ports per seqPlayer
typedef enum {
@@ -66,6 +66,7 @@ typedef struct {
/* 0xC */ s32 remainingFrames;
} FreqLerp; // size = 0x10
s32 AudioOcarina_MemoryGameGenerateNotes(void);
s32 Audio_SetGanonsTowerBgmVolume(u8 targetVolume);
void func_801A3238(s8 playerIndex, u16 seqId, u8 fadeTimer, s8 arg3, u8 arg4);
@@ -107,7 +108,7 @@ u8 sIsFinalHoursOrSoaring;
u8 sObjSoundFanfareSeqId;
u8 sObjSoundFanfareRequested;
Vec3f sObjSoundFanfarePos;
u8 sObjSoundPlayerIdx;
u8 sObjSoundPlayerIndex;
Vec3f sObjSoundPos;
s16 sObjSoundFlags;
f32 sObjSoundMinDist;
@@ -122,7 +123,7 @@ u8 sSpatialSeqFlags;
u8 D_801FD432;
u8 sSpatialSubBgmFadeTimer;
u8 D_801FD434;
u8 sSpatialSeqPlayerIdx;
u8 sSpatialSeqPlayerIndex;
u8 sSpatialSeqFadeTimer;
u16 D_801FD438;
@@ -139,8 +140,8 @@ s32 sOcaInputBtnPress;
u8 sOcarinaResetDelay;
u8 sOcarinaResetUnused;
u8 sOcarinaHasStartedSong;
u8 sFirstOcarinaSongIdx;
u8 sLastOcarinaSongIdx;
u8 sFirstOcarinaSongIndex;
u8 sLastOcarinaSongIndex;
u32 sOcarinaAvailSongs;
u8 sOcarinaStaffPlayingPos;
u16 sMusicStaffPos[OCARINA_SONG_MAX];
@@ -987,11 +988,11 @@ u8 sIsOcarinaInputEnabled = false;
s8 sOcarinaInstrumentId = OCARINA_INSTRUMENT_OFF;
u8 sCurOcarinaPitch = OCARINA_PITCH_NONE;
u8 sPrevOcarinaPitch = 0;
u8 sCurOcarinaButtonIdx = 0;
u8 sCurOcarinaButtonIndex = 0;
u8 sMusicStaffPrevPitch = 0;
f32 sCurOcarinaBendFreq = 1.0f;
f32 sDefaultOcarinaVolume = 0.68503935f;
s8 sCurOcarinaBendIdx = 0;
s8 sCurOcarinaBendIndex = 0;
s8 sCurOcarinaVolume = 0x57;
s8 sCurOcarinaVibrato = 0;
u8 sPlaybackState = 0;
@@ -1017,7 +1018,7 @@ u8 sCurOcarinaSong[8] = {
u8 sOcarinaSongAppendPos = 0;
u8 sOcarinaSongStartingPos = 0;
u8 sButtonToNoteMap[5] = {
u8 sButtonToPitchMap[5] = {
OCARINA_PITCH_D4, // OCARINA_BTN_A
OCARINA_PITCH_F4, // OCARINA_BTN_C_DOWN
OCARINA_PITCH_A4, // OCARINA_BTN_C_RIGHT
@@ -1025,7 +1026,7 @@ u8 sButtonToNoteMap[5] = {
OCARINA_PITCH_D5, // OCARINA_BTN_C_UP
};
u8 sOcaMemoryGameAppendPos = 0;
u8 sOcarinaMemoryGameAppendPos = 0;
u8 sOcaMemoryGameEndPos = 0;
u8 sOcaMemoryGameNumNotes[] = { 5, 6, 8 };
OcarinaNote sOcarinaSongNotes[OCARINA_SONG_MAX][20] = {
@@ -1446,9 +1447,9 @@ u32 sOcarinaRecordTaskStart = 0;
u8 sRecordOcarinaPitch = 0;
u8 sRecordOcarinaVolume = 0;
u8 sRecordOcarinaVibrato = 0;
s8 sRecordOcarinaBendIdx = 0;
u8 sRecordOcarinaButtonIdx = 0;
u8 sPlayedOcarinaSongIdxPlusOne = 0;
s8 sRecordOcarinaBendIndex = 0;
u8 sRecordOcarinaButtonIndex = 0;
u8 sPlayedOcarinaSongIndexPlusOne = 0;
u8 sMusicStaffNumNotesPerTest = 0;
u8 D_801D8530 = false;
u32 D_801D8534 = 0;
@@ -1463,7 +1464,7 @@ OcarinaNote* gScarecrowLongSongPtr = sScarecrowsLongSongNotes;
u8* gScarecrowSpawnSongPtr = (u8*)&sOcarinaSongNotes[OCARINA_SONG_SCARECROW];
OcarinaNote* sTerminaWallSongPtr = sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL];
u8 sNoteToButtonMap[16] = {
u8 sPitchToButtonMap[16] = {
OCARINA_BTN_A, // OCARINA_PITCH_C4
OCARINA_BTN_A, // OCARINA_PITCH_DFLAT4
OCARINA_BTN_A, // OCARINA_PITCH_D4
@@ -1852,6 +1853,7 @@ const u16 gAudioEnvironmentalSfx[] = {
NA_SE_EV_WAVE_S - SFX_FLAG, NA_SE_EV_WAVE_S - SFX_FLAG,
};
extern const u8 sIsOcarinaSongReserved[OCARINA_SONG_MAX];
/**
const u8 sIsOcarinaSongReserved[OCARINA_SONG_MAX] = {
true, // OCARINA_SONG_SONATA
@@ -1889,7 +1891,8 @@ const u8 sIsOcarinaSongReserved[OCARINA_SONG_MAX] = {
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019B02C.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019B074.s")
void AudioOcarina_MapSongFromNotesToButtons(u8 noteSongIndex, u8 buttonSongIndex, u8 numButtons);
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/AudioOcarina_MapSongFromNotesToButtons.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019B144.s")
@@ -1901,7 +1904,7 @@ const u8 sIsOcarinaSongReserved[OCARINA_SONG_MAX] = {
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019B4B8.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019B544.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/AudioOcarina_StartDefault.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019B568.s")
@@ -1927,7 +1930,7 @@ const u8 sIsOcarinaSongReserved[OCARINA_SONG_MAX] = {
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019C2E4.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019C300.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/AudioOcarina_SetInstrumentId.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019C398.s")
@@ -1956,17 +1959,154 @@ const char sAudioOcarinaUnusedText7[] = "check is over!!! %d %d %d\n";
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019CF78.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019CF9C.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/AudioOcarina_GetPlaybackStaff.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019CFA8.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019D134.s")
/**
* Tests to see if the notes from songIndex contain identical notes
* within its song to any of the reserved songIndex from 0 up to maxSongIndex
*/
s32 AudioOcarina_TerminaWallValidateNotes(u8 songIndex, u8 maxSongIndex) {
u8 curSongIndex;
u8 j;
u8 k;
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019D26C.s")
// loop through all possible songs up to maxSongIndex
for (curSongIndex = 0; curSongIndex < maxSongIndex; curSongIndex++) {
// check to see if the song is reserved or not
if (sIsOcarinaSongReserved[curSongIndex]) {
// starting index to test the song
for (j = 0; j < (9 - gOcarinaSongButtons[curSongIndex].numButtons); j++) {
// loop through each note in the song
for (k = 0; (k < gOcarinaSongButtons[curSongIndex].numButtons) && ((k + j) < 8) &&
(gOcarinaSongButtons[curSongIndex].buttonIndex[k] ==
gOcarinaSongButtons[songIndex].buttonIndex[(k + j)]);
k++) {
continue;
}
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019D488.s")
if (k == gOcarinaSongButtons[curSongIndex].numButtons) {
// failure: songIndex is identical to curSongIndex.
return -1;
}
}
}
}
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019D4F8.s")
// success: notes are accepted and used
return 0;
}
/**
* Generates the notes displayed on the Termina Field wall of musical notes
* Song generation loop alternates between 8 random notes and a random song from Ocarina of Time (OoT).
* Will check to see that the notes are valid by ensuring no playable song is within the selected notes
* All OoT songs are valid, so the outer loop will run a maxiumum of two times.
* i.e. if random notes fails, then the next set of notes will be from a valid OoT song
*/
void AudioOcarina_TerminaWallGenerateNotes(void) {
OcarinaNote* ocarinaNote;
u8 randButtonIndex;
u8 i;
u8 j;
do {
i = 0;
if (sOcarinaWallCounter++ % 2) {
j = 0;
for (; i < 8; i++) {
randButtonIndex = Audio_NextRandom() % ARRAY_COUNT(sButtonToPitchMap);
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].pitch = sButtonToPitchMap[randButtonIndex];
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].length = 19;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].volume = 80;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].bend = 0;
j++;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].length = 3;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].volume = 0;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].bend = 0;
j++;
}
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j - 2].length = 90;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j - 1].length = 22;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j + 1].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j + 1].length = 0;
AudioOcarina_MapSongFromNotesToButtons(OCARINA_SONG_TERMINA_WALL, OCARINA_SONG_TERMINA_WALL, 8);
} else {
j = Audio_NextRandom() % ARRAY_COUNT(sOoTOcarinaSongNotes);
ocarinaNote = sOoTOcarinaSongNotes[j];
for (; ocarinaNote[i].length != 0; i++) {
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][i] = ocarinaNote[i];
}
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][i].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][i].length = 0;
AudioOcarina_MapSongFromNotesToButtons(OCARINA_SONG_TERMINA_WALL, OCARINA_SONG_TERMINA_WALL,
sOoTOcarinaSongsNumNotes[j]);
}
} while (AudioOcarina_TerminaWallValidateNotes(OCARINA_SONG_TERMINA_WALL, OCARINA_SONG_TERMINA_WALL) != 0);
}
/**
* Unused remnant of OoT
*/
void AudioOcarina_MemoryGameSetNumNotes(u8 minigameRound) {
u8 i;
if (minigameRound > 2) {
minigameRound = 2;
}
sOcarinaMemoryGameAppendPos = 0;
sOcaMemoryGameEndPos = sOcaMemoryGameNumNotes[minigameRound];
for (i = 0; i < 3; i++) {
AudioOcarina_MemoryGameGenerateNotes();
}
}
/**
* Unused remnant of OoT, Id 14 now represent Goron Lullaby Intro instead of the OoT ocarina memory game
* //! @bug calling this function in MM will overwrite Goron Lullaby Intro
*/
#define OCARINA_SONG_MEMORYGAME 14
s32 AudioOcarina_MemoryGameGenerateNotes(void) {
u32 randButtonIndex;
u8 randPitch;
if (sOcarinaMemoryGameAppendPos == sOcaMemoryGameEndPos) {
return true;
}
randButtonIndex = Audio_NextRandom();
randPitch = sButtonToPitchMap[randButtonIndex % ARRAY_COUNT(sButtonToPitchMap)];
if (sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos - 1].pitch == randPitch) {
randPitch = sButtonToPitchMap[(randButtonIndex + 1) % ARRAY_COUNT(sButtonToPitchMap)];
}
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos].pitch = randPitch;
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos].length = 45;
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos].volume = 0x50;
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos].bend = 0;
sOcarinaMemoryGameAppendPos++;
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos].length = 0;
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos + 1].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_MEMORYGAME][sOcarinaMemoryGameAppendPos + 1].length = 0;
if (1) {}
return false;
}
#undef OCARINA_SONG_MEMORYGAME
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019D600.s")
+251 -19
View File
@@ -5,6 +5,7 @@
*/
#include "z_en_gakufu.h"
#include "interface/parameter_static/parameter_static.h"
#define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_2000000)
@@ -15,13 +16,15 @@ void EnGakufu_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnGakufu_Update(Actor* thisx, GlobalContext* globalCtx);
void EnGakufu_Draw(Actor* thisx, GlobalContext* globalCtx);
void func_80AFCB94(EnGakufu* this, GlobalContext* globalCtx);
void func_80AFCBD4(EnGakufu* this, GlobalContext* globalCtx);
void func_80AFCC14(EnGakufu* this, GlobalContext* globalCtx);
void func_80AFCD44(EnGakufu* this, GlobalContext* globalCtx);
void func_80AFCDC8(EnGakufu* this, GlobalContext* globalCtx);
void EnGakufu_ProcessNotes(EnGakufu* this);
s32 EnGakufu_IsPlayerInRange(EnGakufu* this, GlobalContext* globalCtx);
void EnGakufu_DisplayOnTimer(EnGakufu* this, GlobalContext* globalCtx);
void EnGakufu_WaitForTimer(EnGakufu* this, GlobalContext* globalCtx);
void EnGakufu_DoNothing(EnGakufu* this, GlobalContext* globalCtx);
void EnGakufu_GiveReward(EnGakufu* this, GlobalContext* globalCtx);
void EnGakufu_PlayRewardCutscene(EnGakufu* this, GlobalContext* globalCtx);
void EnGakufu_WaitForSong(EnGakufu* this, GlobalContext* globalCtx);
#if 0
const ActorInit En_Gakufu_InitVars = {
ACTOR_EN_GAKUFU,
ACTORCAT_ITEMACTION,
@@ -34,28 +37,257 @@ const ActorInit En_Gakufu_InitVars = {
(ActorFunc)EnGakufu_Draw,
};
#endif
Vec3f sRewardDropsSpawnTerminaFieldPos = {
-710.0f,
-123.0f,
-3528.0f,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/func_80AFC960.s")
/**
* Determines which set of `sRewardDrops` to collect when successfully playing the notes on the wall.
* Rewards come in batches of three, and the reward you get depends on the time of day.
*/
u8 sRewardDropsIndex[] = {
3, // CLOCK_TIME(0, 0) to CLOCKTIME(1, 0)
12, // CLOCK_TIME(1, 0) to CLOCKTIME(2, 0)
6, // CLOCK_TIME(2, 0) to CLOCKTIME(3, 0)
12, // CLOCK_TIME(3, 0) to CLOCKTIME(4, 0)
9, // CLOCK_TIME(4, 0) to CLOCKTIME(5, 0)
12, // CLOCK_TIME(5, 0) to CLOCKTIME(6, 0)
0, // CLOCK_TIME(6, 0) to CLOCKTIME(7, 0)
12, // CLOCK_TIME(7, 0) to CLOCKTIME(8, 0)
3, // CLOCK_TIME(8, 0) to CLOCKTIME(9, 0)
12, // CLOCK_TIME(9, 0) to CLOCKTIME(10, 0)
6, // CLOCK_TIME(10, 0) to CLOCKTIME(11, 0)
12, // CLOCK_TIME(11, 0) to CLOCKTIME(12, 0)
3, // CLOCK_TIME(12, 0) to CLOCKTIME(13, 0)
12, // CLOCK_TIME(13, 0) to CLOCKTIME(14, 0)
6, // CLOCK_TIME(14, 0) to CLOCKTIME(15, 0)
12, // CLOCK_TIME(15, 0) to CLOCKTIME(16, 0)
3, // CLOCK_TIME(16, 0) to CLOCKTIME(17, 0)
12, // CLOCK_TIME(17, 0) to CLOCKTIME(18, 0)
6, // CLOCK_TIME(18, 0) to CLOCKTIME(19, 0)
12, // CLOCK_TIME(19, 0) to CLOCKTIME(20, 0)
9, // CLOCK_TIME(20, 0) to CLOCKTIME(21, 0)
12, // CLOCK_TIME(21, 0) to CLOCKTIME(22, 0)
6, // CLOCK_TIME(22, 0) to CLOCKTIME(23, 0)
12, // CLOCK_TIME(23, 0) to CLOCKTIME(0, 0)
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/EnGakufu_Init.s")
/**
* The set of rewards when the song notes on the wall are played.
* Should be thought of as a 2D array: sRewardDrops[5][3]
* i.e. there are 5 sets of possible rewards. And each set gives out three rewards
*/
u8 sRewardDrops[] = {
ITEM00_RUPEE_RED, ITEM00_RUPEE_RED, ITEM00_RUPEE_RED, // Set 1 (index 0)
ITEM00_RUPEE_RED, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, // Set 2 (index 3)
ITEM00_RUPEE_BLUE, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_BLUE, // Set 3 (index 6)
ITEM00_RUPEE_RED, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_BLUE, // Set 4 (index 9)
ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, // Set 5 (index 12)
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/EnGakufu_Destroy.s")
// y-offsets of ocarina buttons drawn on wall
f32 sOcarinaBtnWallYOffsets[] = {
-4.0f, -2.0f, 0.0f, 1.0f, 3.0f,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/func_80AFCB94.s")
TexturePtr sOcarinaBtnWallTextures[] = {
gOcarinaATex, gOcarinaCDownTex, gOcarinaCRightTex, gOcarinaCLeftTex, gOcarinaCUpTex,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/func_80AFCBD4.s")
#include "overlays/ovl_En_Gakufu/ovl_En_Gakufu.c"
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/func_80AFCC14.s")
void EnGakufu_ProcessNotes(EnGakufu* this) {
OcarinaStaff* playbackStaff;
OcarinaSongButtons* ocarinaSongButtons;
s32 songNumButtons;
s32 i;
s32 songIndex;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/func_80AFCC24.s")
AudioOcarina_TerminaWallGenerateNotes();
AudioOcarina_SetInstrumentId(OCARINA_INSTRUMENT_DEFAULT);
AudioOcarina_StartDefault((1 << this->songIndex) | 0x80000000);
playbackStaff = AudioOcarina_GetPlaybackStaff();
playbackStaff->pos = 0;
playbackStaff->state = 0xFF;
AudioOcarina_SetInstrumentId(OCARINA_INSTRUMENT_OFF);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/func_80AFCC58.s")
songIndex = this->songIndex;
ocarinaSongButtons = &gOcarinaSongButtons[songIndex];
songNumButtons = gOcarinaSongButtons[this->songIndex].numButtons;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/func_80AFCD44.s")
for (i = 0; i < songNumButtons; i++) {
this->buttonIndex[i] = ocarinaSongButtons->buttonIndex[i];
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/func_80AFCDC8.s")
for (; i < ARRAY_COUNT(this->buttonIndex); i++) {
this->buttonIndex[i] = OCARINA_BTN_INVALID;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/EnGakufu_Update.s")
void EnGakufu_Init(Actor* thisx, GlobalContext* globalCtx) {
EnGakufu* this = THIS;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gakufu/EnGakufu_Draw.s")
this->songIndex = OCARINA_SONG_TERMINA_WALL;
EnGakufu_ProcessNotes(this);
Actor_SetScale(&this->actor, 1.0f);
if (GAKUFU_GET_TYPE(&this->actor) == GAKUFU_MILK_BAR) {
this->actor.draw = NULL;
this->actionFunc = EnGakufu_WaitForTimer;
return;
}
this->actor.flags &= ~ACTOR_FLAG_2000000;
if (EnGakufu_IsPlayerInRange(this, globalCtx)) {
gSaveContext.eventInf[3] |= 2;
} else {
gSaveContext.eventInf[3] &= (u8)~2;
}
this->actionFunc = EnGakufu_WaitForSong;
gSaveContext.eventInf[3] &= (u8)~4;
}
void EnGakufu_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnGakufu* this = THIS;
if (GAKUFU_GET_TYPE(&this->actor) != GAKUFU_MILK_BAR) {
gSaveContext.eventInf[3] &= (u8)~2;
}
}
/**
* Special behaviour for the Milk Bar:
* this->actor.home.rot.x acts as a timer. Draws the notes on the back of the stage
* until the timer runs out
*/
void EnGakufu_DisplayOnTimer(EnGakufu* this, GlobalContext* globalCtx) {
if (this->actor.home.rot.x > 0) {
this->actor.draw = EnGakufu_Draw;
this->actor.home.rot.x--;
} else {
this->actor.draw = NULL;
this->actor.home.rot.x = 0;
this->actionFunc = EnGakufu_WaitForTimer;
}
}
/**
* Special behaviour for the Milk Bar:
* this->actor.home.rot.x acts as a timer. Waits for this timer to be set,
* then rerolls the notes and start displaying the notes
*/
void EnGakufu_WaitForTimer(EnGakufu* this, GlobalContext* globalCtx) {
if (this->actor.home.rot.x > 0) {
EnGakufu_ProcessNotes(this);
this->actionFunc = EnGakufu_DisplayOnTimer;
}
}
void EnGakufu_DoNothing(EnGakufu* this, GlobalContext* globalCtx) {
}
s32 EnGakufu_IsPlayerInRange(EnGakufu* this, GlobalContext* globalCtx) {
if (this->actor.xzDistToPlayer < 600.0f) {
return true;
} else {
return false;
}
}
/**
* Reward the player with three item drops depending on the time of day
*/
void EnGakufu_GiveReward(EnGakufu* this, GlobalContext* globalCtx) {
s32 hour;
s32 i;
play_sound(NA_SE_SY_CORRECT_CHIME);
hour = gSaveContext.time * (24.0f / 0x10000);
for (i = 0; i < 3; i++) {
Item_DropCollectible(globalCtx, &sRewardDropsSpawnTerminaFieldPos, sRewardDrops[i + sRewardDropsIndex[hour]]);
}
this->actionFunc = EnGakufu_DoNothing;
}
void EnGakufu_PlayRewardCutscene(EnGakufu* this, GlobalContext* globalCtx) {
if (this->actor.cutscene == -1) {
EnGakufu_GiveReward(this, globalCtx);
} else if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) {
ActorCutscene_StartAndSetUnkLinkFields(this->actor.cutscene, &this->actor);
EnGakufu_GiveReward(this, globalCtx);
} else {
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
}
}
/**
* Waits for the notes on the wall to be played and updates the corresponding flags
* (gSaveContext.eventInf[3] & 2) is checking if Player is within range of the wall
* (gSaveContext.eventInf[3] & 4) is checking if Player has played the notes of the wall
*/
void EnGakufu_WaitForSong(EnGakufu* this, GlobalContext* globalCtx) {
if (gSaveContext.eventInf[3] & 2) {
if (gSaveContext.eventInf[3] & 4) {
gSaveContext.eventInf[3] &= (u8)~2;
gSaveContext.eventInf[3] &= (u8)~4;
this->actionFunc = EnGakufu_PlayRewardCutscene;
EnGakufu_PlayRewardCutscene(this, globalCtx);
this->actor.draw = NULL;
} else if (!EnGakufu_IsPlayerInRange(this, globalCtx)) {
gSaveContext.eventInf[3] &= (u8)~2;
}
} else if (EnGakufu_IsPlayerInRange(this, globalCtx)) {
gSaveContext.eventInf[3] |= 2;
}
}
void EnGakufu_Update(Actor* thisx, GlobalContext* globalCtx) {
EnGakufu* this = THIS;
this->actionFunc(this, globalCtx);
}
void EnGakufu_Draw(Actor* thisx, GlobalContext* globalCtx) {
s32 i;
s32 pad;
EnGakufu* this = THIS;
OPEN_DISPS(globalCtx->state.gfxCtx);
gDPPipeSync(POLY_XLU_DISP++);
gSPSegment(POLY_XLU_DISP++, 0x02, globalCtx->interfaceCtx.parameterSegment);
for (i = 0; (i < ARRAY_COUNT(this->buttonIndex)) && (this->buttonIndex[i] != OCARINA_BTN_INVALID); i++) {
Matrix_StatePush();
Matrix_InsertTranslation(30 * i - 105, sOcarinaBtnWallYOffsets[this->buttonIndex[i]] * 7.5f, 1.0f,
MTXMODE_APPLY);
Matrix_Scale(0.6f, 0.6f, 0.6f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetTextureLUT(POLY_XLU_DISP++, G_TT_NONE);
gDPLoadTextureBlock(POLY_XLU_DISP++, sOcarinaBtnWallTextures[this->buttonIndex[i]], G_IM_FMT_IA, G_IM_SIZ_8b,
16, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD,
G_TX_NOLOD);
if (this->buttonIndex[i] == OCARINA_BTN_A) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 80, 150, 255, 200);
} else {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 50, 200);
}
gSPDisplayList(POLY_XLU_DISP++, gGakufuButtonIndexDL);
Matrix_StatePop();
}
gSPSegment(POLY_XLU_DISP++, 0x02, globalCtx->sceneSegment);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
@@ -7,10 +7,18 @@ struct EnGakufu;
typedef void (*EnGakufuActionFunc)(struct EnGakufu*, GlobalContext*);
#define GAKUFU_GET_TYPE(thisx) ((thisx)->params & 0xF)
typedef enum {
/* 0x00 */ GAKUFU_TERMINA_FIELD,
/* 0x01 */ GAKUFU_MILK_BAR
} GakufuType;
typedef struct EnGakufu {
/* 0x0000 */ Actor actor;
/* 0x0144 */ char unk_144[0xC];
/* 0x0150 */ EnGakufuActionFunc actionFunc;
/* 0x000 */ Actor actor;
/* 0x144 */ s32 songIndex;
/* 0x148 */ u8 buttonIndex[8];
/* 0x150 */ EnGakufuActionFunc actionFunc;
} EnGakufu; // size = 0x154
extern const ActorInit En_Gakufu_InitVars;
+3 -3
View File
@@ -1104,14 +1104,14 @@ void func_80B98AD0(EnZot* this, GlobalContext* globalCtx) {
func_801477B4(globalCtx);
this->actionFunc = func_80B98CA8;
gSaveContext.weekEventReg[41] &= (u8)~0x20;
func_8019C300(0);
AudioOcarina_SetInstrumentId(OCARINA_INSTRUMENT_OFF);
break;
case 0x12BA:
func_801477B4(globalCtx);
this->actionFunc = func_80B98CA8;
gSaveContext.weekEventReg[41] |= 0x20;
func_8019C300(0);
AudioOcarina_SetInstrumentId(OCARINA_INSTRUMENT_OFF);
break;
default:
@@ -1140,7 +1140,7 @@ void func_80B98BF4(EnZot* this, GlobalContext* globalCtx) {
void func_80B98CA8(EnZot* this, GlobalContext* globalCtx) {
if (func_800B8718(&this->actor, &globalCtx->state)) {
globalCtx->msgCtx.ocarinaMode = 4;
func_8019B544(0xFFFF);
AudioOcarina_StartDefault(0xFFFF);
this->actionFunc = func_80B98BF4;
this->actor.flags |= ACTOR_FLAG_10000;
func_800B8614(&this->actor, globalCtx, 120.0f);