diff --git a/include/z64cutscene.h b/include/z64cutscene.h index 026071d52b..9bb5558089 100644 --- a/include/z64cutscene.h +++ b/include/z64cutscene.h @@ -344,14 +344,19 @@ typedef enum CutsceneDestination { /* 0x77 */ CS_DEST_ZELDAS_COURTYARD_RECEIVE_LETTER } CutsceneDestination; -// the primary purpose of these values is to select `gSaveContext.sceneLayer` -// CS_INDEX_AUTO: [SCENE_LAYER_CHILD_DAY .. SCENE_LAYER_ADULT_NIGHT] -// CS_INDEX_[0 .. A]: GET_CUTSCENE_LAYER(cutscene_index) -// normally `z_play.c` does this task, while the rest of the code -// schedules that by assigning one of the listed values to either of +// values `< 0xFFF0` indicate a "manual" cutscene; can be assigned to // - `gSaveContext.save.cutsceneIndex` // - `gSaveContext.nextCutsceneIndex` +// using them implies an intention to have `z_play.c` set `gSaveContext.sceneLayer` based on age and day time +// see enum values [`SCENE_LAYER_CHILD_DAY` .. `SCENE_LAYER_ADULT_NIGHT`] #define CS_INDEX_AUTO 0x0000 +#define CS_INDEX_UNK_8000 0x8000 + +// values `>= 0xFFF0` indicate a "scripted" cutscene; can be assigned to +// - `gSaveContext.save.cutsceneIndex` +// - `gSaveContext.nextCutsceneIndex` +// using them implies an intention to have `z_play.c` set `gSaveContext.sceneLayer` directly by index +// see `GET_CUTSCENE_LAYER(index)` #define CS_INDEX_0 0xFFF0 #define CS_INDEX_1 0xFFF1 #define CS_INDEX_2 0xFFF2 @@ -364,16 +369,16 @@ typedef enum CutsceneDestination { #define CS_INDEX_9 0xFFF9 #define CS_INDEX_A 0xFFFA -// then there are two different sentinel values -// it is not strictly required to wait until a field is empty before setting it -// albeit there are some cases besides `z_play.c` which do check for these values -// either to sequence actions properly or to drive their internal logic -#define CS_INDEX_EMPTY 0xFFFD // marks `cutsceneIndex` as free -#define CS_INDEX_NEXT_EMPTY 0xFFEF // marks `nextCutsceneIndex` as free +// it's "out of range" even for the largest set of `entrance_table.h` +// but `z_demo.c` immediately sets `CS_STATE_STOP` state +#define CS_INDEX_UNK_FFFF 0xFFFF -// finally two more, but they're not meaningful for the normal gameplay -#define CS_INDEX_8000 0x8000 // unused; set in CS_DEST_DEATH_MOUNTAIN_TRAIL or `z_select.c` -#define CS_INDEX_FFFF 0xFFFF // unused; set in CS_DEST_GANONS_CASTLE_DISPEL_BARRIER_CONDITONAL +// sentinel value used for `cutsceneIndex` to indicate that it should be reset to "auto" +#define CS_INDEX_EMPTY 0xFFFD + +// sentinel value used for `nextCutsceneIndex` to indicate that it is empty +// otherwise its value will be copied to `cutsceneIndex` +#define CS_INDEX_NEXT_EMPTY 0xFFEF typedef union CsCmdCam { struct { diff --git a/src/code/z_demo.c b/src/code/z_demo.c index 43d17883cf..cc78a46f03 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -746,7 +746,7 @@ void CutsceneCmd_Destination(PlayState* play, CutsceneContext* csCtx, CsCmdDesti play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_BLACK_FAST; - gSaveContext.save.cutsceneIndex = CS_INDEX_8000; + gSaveContext.save.cutsceneIndex = CS_INDEX_UNK_8000; break; case CS_DEST_LAKE_HYLIA_WATER_RESTORED: @@ -1367,10 +1367,10 @@ void CutsceneCmd_Destination(PlayState* play, CutsceneContext* csCtx, CsCmdDesti play->csCtx.script = SEGMENTED_TO_VIRTUAL(gTowerBarrierCs); play->csCtx.curFrame = 0; gSaveContext.cutsceneTrigger = 1; - gSaveContext.save.cutsceneIndex = CS_INDEX_FFFF; + gSaveContext.save.cutsceneIndex = CS_INDEX_UNK_FFFF; csCtx->state = CS_STATE_STOP; } else { - gSaveContext.save.cutsceneIndex = CS_INDEX_FFFF; + gSaveContext.save.cutsceneIndex = CS_INDEX_UNK_FFFF; csCtx->state = CS_STATE_STOP; } break; diff --git a/src/overlays/gamestates/ovl_select/z_select.c b/src/overlays/gamestates/ovl_select/z_select.c index 5144648b0a..1336d20078 100644 --- a/src/overlays/gamestates/ovl_select/z_select.c +++ b/src/overlays/gamestates/ovl_select/z_select.c @@ -295,7 +295,7 @@ void MapSelect_UpdateMenu(MapSelectState* this) { } if (CHECK_BTN_ALL(input->press.button, BTN_Z)) { - if (gSaveContext.save.cutsceneIndex == CS_INDEX_8000) { + if (gSaveContext.save.cutsceneIndex == CS_INDEX_UNK_8000) { gSaveContext.save.cutsceneIndex = CS_INDEX_AUTO; } else if (gSaveContext.save.cutsceneIndex == CS_INDEX_AUTO) { gSaveContext.save.cutsceneIndex = CS_INDEX_0; @@ -320,13 +320,13 @@ void MapSelect_UpdateMenu(MapSelectState* this) { } else if (gSaveContext.save.cutsceneIndex == CS_INDEX_9) { gSaveContext.save.cutsceneIndex = CS_INDEX_A; } else if (gSaveContext.save.cutsceneIndex == CS_INDEX_A) { - gSaveContext.save.cutsceneIndex = CS_INDEX_8000; + gSaveContext.save.cutsceneIndex = CS_INDEX_UNK_8000; } } else if (CHECK_BTN_ALL(input->press.button, BTN_R)) { - if (gSaveContext.save.cutsceneIndex == CS_INDEX_8000) { + if (gSaveContext.save.cutsceneIndex == CS_INDEX_UNK_8000) { gSaveContext.save.cutsceneIndex = CS_INDEX_A; } else if (gSaveContext.save.cutsceneIndex == CS_INDEX_AUTO) { - gSaveContext.save.cutsceneIndex = CS_INDEX_8000; + gSaveContext.save.cutsceneIndex = CS_INDEX_UNK_8000; } else if (gSaveContext.save.cutsceneIndex == CS_INDEX_0) { gSaveContext.save.cutsceneIndex = CS_INDEX_AUTO; } else if (gSaveContext.save.cutsceneIndex == CS_INDEX_1) { @@ -560,7 +560,7 @@ void MapSelect_PrintCutsceneSetting(MapSelectState* this, GfxPrint* printer, u16 label = T(GFXP_HIRAGANA " ヨル " GFXP_KATAKANA "ゴロン", "Night"); gSaveContext.save.dayTime = CLOCK_TIME(0, 0); break; - case CS_INDEX_8000: + case CS_INDEX_UNK_8000: // clang-format off gSaveContext.save.dayTime = CLOCK_TIME(12, 0); label = T(GFXP_HIRAGANA "オヒル " GFXP_KATAKANA "ジャラ", "Day"); // clang-format on @@ -727,6 +727,6 @@ void MapSelect_Init(GameState* thisx) { DMA_REQUEST_SYNC(this->staticSegment, (uintptr_t)_z_select_staticSegmentRomStart, size, "../z_select.c", 1115); } - gSaveContext.save.cutsceneIndex = CS_INDEX_8000; + gSaveContext.save.cutsceneIndex = CS_INDEX_UNK_8000; gSaveContext.save.linkAge = LINK_AGE_CHILD; }