SCHEDULE_TIME (#1438)

* SCHEDULE_CALC_TIME_ALT

* add s32 cast to avoid f32 -> u16 direct cast

* SCHEDULE_TIME

* remove the alts

* Update explanation about the script
This commit is contained in:
Anghelo Carvajal 2023-10-22 02:52:40 -03:00 committed by GitHub
parent 425238fd5d
commit ec86f10b0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 124 additions and 40 deletions

View File

@ -28,10 +28,13 @@
*/
// Macro to convert the time format used in the save struct into the format used in Schedule
#define SCHEDULE_CONVERT_TIME(time) ((u16)((time) - 0x10000 / 360 * 90))
#define SCHEDULE_CONVERT_TIME(time) ((s32)((time) - 0x10000 / 360 * 90))
#define SCHEDULE_TIME(hour, minute) SCHEDULE_CONVERT_TIME((((hour)*60.0f) + (minute)) * (0x10000 / 60 / 24.0f))
#define SCHEDULE_TIME_NOW SCHEDULE_CONVERT_TIME(gSaveContext.save.time)
typedef enum {
typedef enum ScheduleCommandId {
/* 0x00 */ SCHEDULE_CMD_ID_CHECK_FLAG_S, // Checks if a weekEventReg flag is set and branches if so, short range branch
/* 0x01 */ SCHEDULE_CMD_ID_CHECK_FLAG_L, // Checks if a weekEventReg flag is set and branches if so, long range branch
/* 0x02 */ SCHEDULE_CMD_ID_CHECK_TIME_RANGE_S, // Checks if the current time is within the range of the two provided times and branches if so, short range branch

View File

@ -702,9 +702,35 @@ s32 Environment_IsSceneUpsideDown(PlayState* play) {
#pragma GLOBAL_ASM("asm/non_matchings/code/z_kankyo/Environment_UpdateSun.s")
void func_800F88C4(u16 weekEventFlag);
#pragma GLOBAL_ASM("asm/non_matchings/code/z_kankyo/func_800F88C4.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/z_kankyo/func_800F8970.s")
void func_800F8970(void) {
if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_27_40) && (SCHEDULE_TIME_NOW >= SCHEDULE_TIME(9, 31))) {
SET_WEEKEVENTREG(WEEKEVENTREG_27_40);
func_800F88C4(WEEKEVENTREG_DEPOSITED_LETTER_TO_KAFEI_SOUTH_UPPER_CLOCKTOWN);
}
if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_27_80) && (SCHEDULE_TIME_NOW >= SCHEDULE_TIME(10, 3))) {
SET_WEEKEVENTREG(WEEKEVENTREG_27_80);
func_800F88C4(WEEKEVENTREG_DEPOSITED_LETTER_TO_KAFEI_NORTH_CLOCKTOWN);
}
if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_28_01) && (SCHEDULE_TIME_NOW >= SCHEDULE_TIME(10, 35))) {
SET_WEEKEVENTREG(WEEKEVENTREG_28_01);
func_800F88C4(WEEKEVENTREG_DEPOSITED_LETTER_TO_KAFEI_EAST_UPPER_CLOCKTOWN);
}
if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_28_02) && (SCHEDULE_TIME_NOW >= SCHEDULE_TIME(10, 53))) {
SET_WEEKEVENTREG(WEEKEVENTREG_28_02);
func_800F88C4(WEEKEVENTREG_DEPOSITED_LETTER_TO_KAFEI_EAST_LOWER_CLOCKTOWN);
}
if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_28_04) && (SCHEDULE_TIME_NOW >= SCHEDULE_TIME(11, 25))) {
SET_WEEKEVENTREG(WEEKEVENTREG_28_04);
func_800F88C4(WEEKEVENTREG_DEPOSITED_LETTER_TO_KAFEI_SOUTH_LOWER_CLOCKTOWN);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_kankyo/Environment_UpdatePostmanEvents.s")

View File

@ -4,7 +4,7 @@
(temp) = (hour)*60.0f; \
(temp) += (minute); \
(dest) = (temp) * (0x10000 / 60 / 24.0f); \
(dest) = SCHEDULE_CONVERT_TIME(dest);
(dest) = SCHEDULE_CONVERT_TIME(dest)
s32 Schedule_CheckFlagS(PlayState* play, u8** script, ScheduleOutput* output) {
ScheduleCmdCheckFlagS* cmd = (ScheduleCmdCheckFlagS*)*script;
@ -239,34 +239,50 @@ s32 Schedule_BranchL(PlayState* play, u8** script, ScheduleOutput* output) {
return false;
}
static s32 (*sScheduleCmdFuncs[])(PlayState*, u8**, ScheduleOutput*) = {
Schedule_CheckFlagS, Schedule_CheckFlagL, Schedule_CheckTimeRangeS, Schedule_CheckTimeRangeL,
Schedule_ReturnValueL, Schedule_ReturnNone, Schedule_ReturnEmpty, Schedule_Nop,
Schedule_CheckMiscS, Schedule_ReturnValueS, Schedule_CheckNotInSceneS, Schedule_CheckNotInSceneL,
Schedule_CheckNotInDayS, Schedule_CheckNotInDayL, Schedule_ReturnTime, Schedule_CheckBeforeTimeS,
Schedule_CheckBeforeTimeL, Schedule_BranchS, Schedule_BranchL,
typedef s32 (*ScheduleCmdFunc)(PlayState*, u8**, ScheduleOutput*);
static ScheduleCmdFunc sScheduleCmdFuncs[] = {
Schedule_CheckFlagS, // SCHEDULE_CMD_ID_CHECK_FLAG_S
Schedule_CheckFlagL, // SCHEDULE_CMD_ID_CHECK_FLAG_L
Schedule_CheckTimeRangeS, // SCHEDULE_CMD_ID_CHECK_TIME_RANGE_S
Schedule_CheckTimeRangeL, // SCHEDULE_CMD_ID_CHECK_TIME_RANGE_L
Schedule_ReturnValueL, // SCHEDULE_CMD_ID_RET_VAL_L
Schedule_ReturnNone, // SCHEDULE_CMD_ID_RET_NONE
Schedule_ReturnEmpty, // SCHEDULE_CMD_ID_RET_EMPTY
Schedule_Nop, // SCHEDULE_CMD_ID_NOP
Schedule_CheckMiscS, // SCHEDULE_CMD_ID_CHECK_MISC_S
Schedule_ReturnValueS, // SCHEDULE_CMD_ID_RET_VAL_S
Schedule_CheckNotInSceneS, // SCHEDULE_CMD_ID_CHECK_NOT_IN_SCENE_S
Schedule_CheckNotInSceneL, // SCHEDULE_CMD_ID_CHECK_NOT_IN_SCENE_L
Schedule_CheckNotInDayS, // SCHEDULE_CMD_ID_CHECK_NOT_IN_DAY_S
Schedule_CheckNotInDayL, // SCHEDULE_CMD_ID_CHECK_NOT_IN_DAY_L
Schedule_ReturnTime, // SCHEDULE_CMD_ID_RET_TIME
Schedule_CheckBeforeTimeS, // SCHEDULE_CMD_ID_CHECK_BEFORE_TIME_S
Schedule_CheckBeforeTimeL, // SCHEDULE_CMD_ID_CHECK_BEFORE_TIME_L
Schedule_BranchS, // SCHEDULE_CMD_ID_BRANCH_S
Schedule_BranchL, // SCHEDULE_CMD_ID_BRANCH_L
};
static u8 sScheduleCmdSizes[] = {
sizeof(ScheduleCmdCheckFlagS),
sizeof(ScheduleCmdCheckFlagL),
sizeof(ScheduleCmdCheckTimeRangeS),
sizeof(ScheduleCmdCheckTimeRangeL),
sizeof(ScheduleCmdReturnValueL),
sizeof(ScheduleCmdBase),
sizeof(ScheduleCmdBase),
sizeof(ScheduleCmdNop),
sizeof(ScheduleCmdCheckMiscS),
sizeof(ScheduleCmdReturnValueS),
sizeof(ScheduleCmdCheckNotInSceneS),
sizeof(ScheduleCmdCheckNotInSceneL),
sizeof(ScheduleCmdCheckNotInDayS),
sizeof(ScheduleCmdCheckNotInDayL),
sizeof(ScheduleCmdReturnTime),
sizeof(ScheduleCmdCheckBeforeTimeS),
sizeof(ScheduleCmdCheckBeforeTimeL),
sizeof(ScheduleCmdBranchS),
sizeof(ScheduleCmdBranchL),
sizeof(ScheduleCmdCheckFlagS), // SCHEDULE_CMD_ID_CHECK_FLAG_S
sizeof(ScheduleCmdCheckFlagL), // SCHEDULE_CMD_ID_CHECK_FLAG_L
sizeof(ScheduleCmdCheckTimeRangeS), // SCHEDULE_CMD_ID_CHECK_TIME_RANGE_S
sizeof(ScheduleCmdCheckTimeRangeL), // SCHEDULE_CMD_ID_CHECK_TIME_RANGE_L
sizeof(ScheduleCmdReturnValueL), // SCHEDULE_CMD_ID_RET_VAL_L
sizeof(ScheduleCmdBase), // SCHEDULE_CMD_ID_RET_NONE
sizeof(ScheduleCmdBase), // SCHEDULE_CMD_ID_RET_EMPTY
sizeof(ScheduleCmdNop), // SCHEDULE_CMD_ID_NOP
sizeof(ScheduleCmdCheckMiscS), // SCHEDULE_CMD_ID_CHECK_MISC_S
sizeof(ScheduleCmdReturnValueS), // SCHEDULE_CMD_ID_RET_VAL_S
sizeof(ScheduleCmdCheckNotInSceneS), // SCHEDULE_CMD_ID_CHECK_NOT_IN_SCENE_S
sizeof(ScheduleCmdCheckNotInSceneL), // SCHEDULE_CMD_ID_CHECK_NOT_IN_SCENE_L
sizeof(ScheduleCmdCheckNotInDayS), // SCHEDULE_CMD_ID_CHECK_NOT_IN_DAY_S
sizeof(ScheduleCmdCheckNotInDayL), // SCHEDULE_CMD_ID_CHECK_NOT_IN_DAY_L
sizeof(ScheduleCmdReturnTime), // SCHEDULE_CMD_ID_RET_TIME
sizeof(ScheduleCmdCheckBeforeTimeS), // SCHEDULE_CMD_ID_CHECK_BEFORE_TIME_S
sizeof(ScheduleCmdCheckBeforeTimeL), // SCHEDULE_CMD_ID_CHECK_BEFORE_TIME_L
sizeof(ScheduleCmdBranchS), // SCHEDULE_CMD_ID_BRANCH_S
sizeof(ScheduleCmdBranchL), // SCHEDULE_CMD_ID_BRANCH_L
};
s32 Schedule_RunScript(PlayState* play, u8* script, ScheduleOutput* output) {
@ -275,7 +291,7 @@ s32 Schedule_RunScript(PlayState* play, u8* script, ScheduleOutput* output) {
do {
size = sScheduleCmdSizes[*script];
stop = (*sScheduleCmdFuncs[*script])(play, &script, output);
stop = sScheduleCmdFuncs[*script](play, &script, output);
script += size;
} while (!stop);

View File

@ -187,10 +187,12 @@ s32* func_80C22880(DmTag* this, PlayState* play) {
switch (this->unk_18E) {
case 1:
time = gSaveContext.save.time - 0x3FFC;
if ((time >= 0xA54B) && (time < 0xB54A) && (gSaveContext.save.day == 2)) {
this->msgEventCallback = func_80C227E8;
return D_80C22BF0;
time = SCHEDULE_TIME_NOW;
if ((time >= SCHEDULE_TIME(21, 30)) && (time < SCHEDULE_TIME(23, 0))) {
if (gSaveContext.save.day == 2) {
this->msgEventCallback = func_80C227E8;
return D_80C22BF0;
}
}
return D_80C22C30;
@ -201,6 +203,7 @@ s32* func_80C22880(DmTag* this, PlayState* play) {
default:
break;
}
return NULL;
}

View File

@ -581,7 +581,7 @@ s32 func_80AF7BAC(EnPm* this) {
case 2:
if (CHECK_WEEKEVENTREG(WEEKEVENTREG_89_40)) {
D_801F4E78 = 0;
D_801F4E78 = CLOCK_TIME(0, 0);
this->unk_38C++;
}
break;

View File

@ -188,7 +188,7 @@ u16 EnSob1_GetTalkOption(EnSob1* this, PlayState* play) {
Player* player = GET_PLAYER(play);
if (this->shopType == BOMB_SHOP) {
if ((gSaveContext.save.day == 1) && (gSaveContext.save.time >= CLOCK_TIME(6, 00))) {
if ((gSaveContext.save.day == 1) && (gSaveContext.save.time >= CLOCK_TIME(6, 0))) {
return 0x648;
} else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_RECOVERED_STOLEN_BOMB_BAG)) {
return 0x649;

View File

@ -701,7 +701,7 @@ s32 func_80A3F9A4(EnTest3* this, PlayState* play) {
}
s32 func_80A3F9E4(EnTest3* this, PlayState* play, struct_80A41828* arg2, ScheduleOutput* scheduleOutput) {
scheduleOutput->time0 = SCHEDULE_TIME_NOW;
scheduleOutput->time0 = (u16)SCHEDULE_TIME_NOW;
scheduleOutput->time1 = (u16)(scheduleOutput->time0 + 70);
func_80A40098(this, play, arg2, scheduleOutput);
if (this->player.actor.xzDistToPlayer < 300.0f) {
@ -729,7 +729,7 @@ s32 func_80A3FA58(EnTest3* this, PlayState* play) {
if (cond || this->unk_D8A <= 0) {
func_80A3F114(this, play);
sp40.unk_1_0 = 5;
scheduleOutput.time0 = SCHEDULE_TIME_NOW;
scheduleOutput.time0 = (u16)SCHEDULE_TIME_NOW;
scheduleOutput.time1 = (u16)(scheduleOutput.time0 + (cond ? 80 : 140));
func_80A40098(this, play, &sp40, &scheduleOutput);
@ -805,7 +805,7 @@ s32 func_80A3FE20(EnTest3* this, PlayState* play) {
if (D_80A41D64 == 0) {
if (func_80A3E9DC(this, play)) {
sp2C.unk_1_0 = 2;
scheduleOutput.time0 = SCHEDULE_TIME_NOW;
scheduleOutput.time0 = (u16)SCHEDULE_TIME_NOW;
scheduleOutput.time1 = (u16)(scheduleOutput.time0 + 1000);
func_80A40098(this, play, &sp2C, &scheduleOutput);
D_80A41D64 = 1;

View File

@ -2484,7 +2484,7 @@ void FileSelect_InitContext(GameState* thisx) {
ShrinkWindow_Letterbox_SetSizeTarget(0);
gSaveContext.skyboxTime = 0;
gSaveContext.save.time = 0;
gSaveContext.save.time = CLOCK_TIME(0, 0);
Skybox_Init(&this->state, &this->skyboxCtx, 1);
R_TIME_SPEED = 10;

36
tools/schedule_timeconv.py Executable file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: © 2023 ZeldaRET
# SPDX-License-Identifier: MIT
# Convert time values such as 0x1AA9 to their schedule clock time, i.e. 8,30
from __future__ import annotations
import sys
def u16(x: int|float) -> int:
return int(x) & 0xFFFF
def SCHEDULE_CONVERT_TIME(time: int|float) -> int:
return u16(time - 0x10000 // 360 * 90)
def SCHEDULE_UNCONVERT_TIME(time: int) -> int:
return time + 0x10000 // 360 * 90
time = sys.argv[1]
time = int(time, 0)
minutes = round(((24 * 60) / 0x10000) * SCHEDULE_UNCONVERT_TIME(time))
hours = int(minutes // 60)
minutes = round(minutes - 60 * hours)
# Since multiple values are mapped to the same clock time, check that it
# still matches once converted. If it doesn't match as it is, print a warning.
macro_val = SCHEDULE_CONVERT_TIME((hours * 60.0 + minutes) * ((0x10000 // 60) / 24.0))
print(f"{hours},{minutes:02} -> 0x{macro_val:04X}")
print(f"SCHEDULE_TIME({hours}, {minutes})")
if time != macro_val:
print("Warning: Result does not match as-is")