Time of day
A clock whose time changes what a game contains or how it behaves.
Time-of-day systems use an external real-time clock or advance a clock inside the game1,2. They can divide a day into named periods, trigger scheduled updates, or impose a deadline that resets a cycle1,3,4.
- Pokémon Crystal (2000). Morning, day, and night rates for wild encounters, as in Gold and Silver.5
- External clockPokémon Gold and Silver (1999). Morning, day, and night from the cartridge clock's hour.1,6Animal Crossing (2001). The daily update compares the clock with the last update's time; the day turns over at 6:00, and one update makes up for every 6:00 missed.3,7Pokémon HeartGold and SoulSilver (2009). Platinum's five periods from the DS clock's hour, folded to three for wild Pokémon; night starts at 20:00.8,9
- Game clockCastlevania II: Simon's Quest (1987). A running clock turns day to night and back, and at night most enemies have double hit points.2,10Harvest Moon 64 (1999). 10 game seconds per loop step on maps where time flows, at most 10 game minutes per real second.11Pikmin (2001). A day runs from 7:00 to 19:00 on a clock paced by a parameter file, and at sunset, outside challenge mode, the tutorial, and the ending, every Pikmin not following the captain, at an Onion, or in free mode near an Onion or the ship is lost.12,13The Legend of Zelda: The Wind Waker (2002). A day is 360 units, 15 an hour, advancing 0.02 an update where time passes; elsewhere it creeps only to 11:00 or 23:00.14
- Time loopThe Legend of Zelda: Majora's Mask (2000). A day is 65,536 clock units; the moon falls at the third dawn unless the Song of Time resets the cycle to the first, keeping the bank but not Link's wallet.15,16,17,18,4
#Clock source and advancement
Pokémon Gold and Silver read morning, day, and night from the cartridge clock1. Pokémon Crystal keeps those periods’ wild-encounter rates5. HeartGold and SoulSilver read five periods from the Nintendo DS clock and fold them into three for wild Pokémon8,9. Night starts at 20:00 in HeartGold and SoulSilver, later than in Gold and Silver8,1.
Other games advance their own clock. Castlevania II: Simon’s Quest advances one game minute every 15 frames2. Harvest Moon 64 adds 10 seconds per eligible loop step on maps where time flows11. The Legend of Zelda: The Wind Waker advances by 0.02 units per update when its conditions permit; in other rooms, it advances only to 11:00 or 23:0014. Pikmin paces its clock from a parameter file and ends the day at 19:0012.
Animal Crossing compares the clock with the time of its last town update. It runs a daily pass at the first 6:00 after that update, or a back-in-time pass if the clock was set earlier3. The daily pass adds weeds in proportion to the number of 6:00 intervals missed7. The Legend of Zelda: Majora’s Mask advances through a three-day cycle; when the clock crosses 6:00 on day 3, the moon-crash sequence starts and sets the clock to 6:00 plus 10 units and the day counter to 44. The Song of Time calls the cycle-reset routine, which clears some saved progress and preserves other fields17.
#What the clock controls
Gold and Silver use the time period to change wild encounter rates6. Crystal retains period-specific encounter rates5. HeartGold and SoulSilver choose wild species by the folded period, and clock-bound evolution methods check whether it is day or night9.
The clock also gates world updates and consequences. Simon’s Quest doubles the hit points of enemies placed at night, with exceptions for some object types and mansions10. Animal Crossing’s daily pass adds up to 5 weeds per missed 6:00, subject to available spaces7. At sunset, Pikmin can lose any Pikmin left outside the specified safe states and areas13. In Majora’s Mask, the third dawn starts the moon crash4.
Games
| Game | Year | How | Note |
|---|---|---|---|
| Pokémon Crystal | 2000 | morning, day, and night rates for wild encounters, as in Gold and Silver | |
| Pokémon Gold and Silver | 1999 | External clock | morning, day, and night from the cartridge clock's hour |
| Animal Crossing | 2001 | External clock | the daily update compares the clock with the last update's time; the day turns over at 6:00, and one update makes up for every 6:00 missed |
| Pokémon HeartGold and SoulSilver | 2009 | External clock | Platinum's five periods from the DS clock's hour, folded to three for wild Pokémon; night starts at 20:00 |
| Castlevania II: Simon's Quest | 1987 | Game clock | a running clock turns day to night and back, and at night most enemies have double hit points |
| Dragon Warrior III | 1988 | Game clock | time passes as the party travels; at night castles shut, most shops close, and monsters come more often |
| Harvest Moon 64 | 1999 | Game clock | 10 game seconds per loop step on maps where time flows, at most 10 game minutes per real second |
| Pikmin | 2001 | Game clock | a day runs from 7:00 to 19:00 on a clock paced by a parameter file, and at sunset, outside challenge mode, the tutorial, and the ending, every Pikmin not following the captain, at an Onion, or in free mode near an Onion or the ship is lost |
| The Legend of Zelda: The Wind Waker | 2002 | Game clock | a day is 360 units, 15 an hour, advancing 0.02 an update where time passes; elsewhere it creeps only to 11:00 or 23:00 |
| Factorio | 2016 | Game clock | a seven-minute day that solar panels follow, with accumulators to cover the night |
| The Legend of Zelda: Majora's Mask | 2000 | Time loop | a day is 65,536 clock units; the moon falls at the third dawn unless the Song of Time resets the cycle to the first, keeping the bank but not Link's wallet |
Every claim about this mechanic, by game (18)
References
- ^ abcdeGold and Silver set the time of day from the cartridge clock's hour, morning from 4:00 to 9:59, day from 10:00 to 17:59, and night from 18:00 to 3:59.Codepret/pokegold
How we know
25GetTimeOfDay:: 26; get time of day based on the current hour 27 ldh a, [hHours] ; hour 28 ld hl, TimesOfDay ⋮ 42; get time of day ⋮ 48TimesOfDay: 49; hours for the time of day 50; 0400-0959 morn | 1000-1759 day | 1800-0359 nite 51 db MORN_HOUR, NITE_F 52 db DAY_HOUR, MORN_F 53 db NITE_HOUR, DAY_F
engine/rtc/rtc.asm lines 25–55 at fc702b6 · upstream ↗ 37DEF MORN_HOUR EQU 4 ; 4 AM 38DEF DAY_HOUR EQU 10 ; 10 AM 39DEF NITE_HOUR EQU 18 ; 6 PM
constants/misc_constants.asm lines 37–39 at fc702b6 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abcdSimon's Quest keeps a clock of days, hours, and minutes in BCD that advances one minute every 15 frames outside the stopped cases, and when the hour reaches 6 or 18 it starts the day-night transition; a day is 24 hours.Code“Castlevania II - Simon's Quest (USA)”
How we know
In the cartridge (“Castlevania II - Simon's Quest (USA)”): bank 7 $D767-$D7C9: no tick in map type 5, in Simon's action $0B, while $34 is set, or while $8F stops time; else a counter $84 to 15, then minute $85 + 1 to 60, hour $86 + 1 to 24 (then day $83 + 1, up to 99); hour 6 or 18 jumps to the transition; bank 7 $CED8-$CEDD, in the transition, IsNightTime $82 flipped with XOR 1. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abcIn the USA GameCube release (
GAFE01_00, ACreTeam/ac-decomp), the town's daily update (mAGrw_RenewalFgItem_ovl) runs when the outdoor town scene is built and no event notice is showing, and compares the clock with the time of the last update. If the clock is earlier than that time, it runs a back-in-time pass (mAGrw_GROW_FIRST_FORCE; the decompilers' comment says "Used when you go back in time"). Otherwise it runs the daily pass only once the clock reaches the first 6:00 after the last update: 6:00 the same day if that update came before 6:00, or the next day's. Either pass then records the clock as the last update.CodeACreTeam/ac-decompHow we know
3075 if (Save_Get(scene_no) == SCENE_FG) { ⋮ 3086 if (Common_Get(event_notification_active) != TRUE) { ⋮ 3088 is_over_time = lbRTC_IsOverTime(last_grow_time, now_time); ⋮ 3090 if (is_grow_time_equal == TRUE || is_over_time == lbRTC_LESS) { ⋮ 3095 proc_type = mAGrw_GROW_FIRST_FORCE; ⋮ 3117 if (grow_time.hour >= 6) { 3118 lbRTC_Add_DD(&grow_time, 1); ⋮ 3126 grow_time.hour = 6; ⋮ 3128 if (lbRTC_IsOverTime(&grow_time, now_time) == lbRTC_OVER) {
src/game/m_all_grow_ovl.c lines 3075–3128 at 09ca8e8 · upstream ↗ 3110 lbRTC_TimeCopy(last_grow_time, now_time);src/game/m_all_grow_ovl.c line 3110 at 09ca8e8 · upstream ↗ 3150 lbRTC_TimeCopy(last_grow_time, now_time);src/game/m_all_grow_ovl.c line 3150 at 09ca8e8 · upstream ↗ 30 mAGrw_GROW_FIRST_FORCE, /* Used when you go back in time */include/m_all_grow_ovl.h lines 27–37 at 09ca8e8 · upstream ↗ 421 if (t1->year < t0->year) { 422 return lbRTC_LESS; ⋮ 435 return lbRTC_LESS; ⋮ 439 return lbRTC_LESS; ⋮ 443 return lbRTC_LESS; ⋮ 447 return lbRTC_LESS; ⋮ 451 return lbRTC_LESS; ⋮ 455 return lbRTC_OVER;
src/lb_rtc.c lines 420–456 at 09ca8e8 · upstream ↗ 1196extern void mFM_FieldInit(GAME_PLAY* play) { ⋮ 1220 mAGrw_RenewalFgItem(Common_GetPointer(time.rtc_time));
src/game/m_field_make.c lines 1196–1220 at 09ca8e8 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abcdIn the N64 US 1.0 code, the actor En_Test4, which its file's comment describes as "Three-Day Events: day-night transitions", compares each update the clock with the next transition time (6:00 by night, 18:00 by day) by multiplying the 16-bit differences of the current and previous times from it and treating a product of 0 or less as a crossing (the atlas's reading of the test), unless a transition, a cutscene, setup actors, a room load, or the debug camera is under way. When the clock crosses 6:00 with the day counter at 3, it calls Interface_StartMoonCrash, which sets the day to 4 and the clock to 6:00 plus 10 units and starts a white fade to a Termina Field entrance. On days 1 and 2 the same crossing adds a day when no transition cutscene is set or the telescope is on; the other branch (z_en_test4.c L446-L470), which sets a flag the decomp names EVENTINF_TRIGGER_DAYTELOP for the Dawn of a New Day screen, is untraced. Play_Init spawns this actor in dungeon and boss rooms on any day but 0; elsewhere it comes from scene data the atlas hasn't read.Codezeldaret/mmrevised
How we know
4 * Description: Three-Day Events: day-night transitions, shrink screen before next day,src/overlays/actors/ovl_En_Test4/z_en_test4.c line 4 at 710e1a7 · upstream ↗ 404void EnTest4_HandleEvents(EnTest4* this, PlayState* play) { 405 static u16 sDayNightTransitionTimes[THREEDAY_DAYTIME_MAX] = { 406 CLOCK_TIME(6, 0), // THREEDAY_DAYTIME_NIGHT 407 CLOCK_TIME(18, 0), // THREEDAY_DAYTIME_DAY ⋮ 411 if ((play->transitionMode == TRANS_MODE_OFF) && !Play_InCsMode(play) && (play->numSetupActors <= 0) && 412 (play->roomCtx.status == 0) && !Play_IsDebugCamEnabled()) { 413 u16 transitionTime = sDayNightTransitionTimes[this->daytimeIndex]; ⋮ 419 curTimeUntilTransition = CURRENT_TIME - transitionTime; 420 prevTimeUntilTransition = this->prevTime - transitionTime; ⋮ 429 if ((curTimeUntilTransition * prevTimeUntilTransition) <= 0) { ⋮ 439 } else if (transitionTime == CLOCK_TIME(6, 0)) { 440 // previously night, turning day ⋮
src/overlays/actors/ovl_En_Test4/z_en_test4.c lines 404–445 at 710e1a7 · upstream ↗ 446 } else if (((sCsIdList[this->daytimeIndex] <= CS_ID_NONE) || 447 (play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) && 448 (CURRENT_DAY != 3)) { 449 // Turn day without cutscene 450 EnTest4_HandleDayNightSwap(this, play); 451 } else { ⋮ 463 } else { ⋮ 470 SET_EVENTINF(EVENTINF_TRIGGER_DAYTELOP);
src/overlays/actors/ovl_En_Test4/z_en_test4.c lines 446–470 at 710e1a7 · upstream ↗ 115 } else if ((sCsIdList[this->daytimeIndex] <= CS_ID_NONE) || (play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) { 116 // Previously night, turning day, without a cutscene 117 Sram_IncrementDay(); 118 gSaveContext.save.time = CLOCK_TIME(6, 0);
src/overlays/actors/ovl_En_Test4/z_en_test4.c lines 115–118 at 710e1a7 · upstream ↗ 655void Sram_IncrementDay(void) { 656 if (CURRENT_DAY <= 3) { 657 gSaveContext.save.day++; 658 gSaveContext.save.eventDayCount++;
src/code/z_sram_NES.c lines 655–658 at 710e1a7 · upstream ↗ 5612void Interface_StartMoonCrash(PlayState* play) { ⋮ 5617 gSaveContext.save.day = 4; 5618 gSaveContext.save.eventDayCount = 4; 5619 gSaveContext.save.time = CLOCK_TIME(6, 0) + 10; 5620 play->nextEntrance = ENTRANCE(TERMINA_FIELD, 12); 5621 gSaveContext.nextCutsceneIndex = 0; 5622 play->transitionTrigger = TRANS_TRIGGER_START; 5623 play->transitionType = TRANS_TYPE_FADE_WHITE;
src/code/z_parameter.c lines 5612–5623 at 710e1a7 · upstream ↗ 2316 if ((CURRENT_DAY != 0) && 2317 ((this->roomCtx.curRoom.type == ROOM_TYPE_DUNGEON) || (this->roomCtx.curRoom.type == ROOM_TYPE_BOSS))) { 2318 Actor_Spawn(&this->actorCtx, this, ACTOR_EN_TEST4, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0);
src/code/z_play.c lines 2316–2318 at 710e1a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abcOn each step,
TryWildEncounterstarts a battle whenRandomis below the map's rate for the time of day (morning, day, or night) or its water rate; the Pokémon March or Ruins of Alph radio doubles the rate, and the Pokémon Lullaby or a Cleanse Tag in the party halves it.Codepret/pokecrystalHow we know
195.EncounterRate: 196 call GetMapEncounterRate 197 call ApplyMusicEffectOnEncounterRate 198 call ApplyCleanseTagEffectOnEncounterRate 199 call Random 200 cp b 201 ret ⋮ 214 ret ⋮ 217; Pokemon March and Ruins of Alph signal double encounter rate. 218; Pokemon Lullaby halves encounter rate. ⋮ 227 ret ⋮ 231 ret ⋮
engine/overworld/wildmons.asm lines 195–250 at 97187cd · upstream ↗ 1237 def_grass_wildmons ROUTE_29 1238 db 10 percent, 10 percent, 10 percent ; encounter rates: morn/day/nite
data/wild/johto_grass.asm lines 1237–1238 at 97187cd · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abOn each step, Gold and Silver's
TryWildEncounterreads the map's encounter rate for the current time of day (morning, day, or night), or its water rate, doubles it for the Pokémon March or Ruins of Alph radio, halves it for the Pokémon Lullaby or a Cleanse Tag, and starts a battle whenRandomis below it; Crystal keeps this unchanged.Codepret/pokegold · pret/pokecrystalHow we know
212.EncounterRate: 213 call GetMapEncounterRate 214 call ApplyMusicEffectOnEncounterRate 215 call ApplyCleanseTagEffectOnEncounterRate 216 call Random 217 cp b 218 ret ⋮ 220GetMapEncounterRate: 221 ld hl, wMornEncounterRate 222 call CheckOnWater 223 ld a, wWaterEncounterRate - wMornEncounterRate 224 jr z, .ok ⋮
engine/overworld/wildmons.asm lines 212–251 at fc702b6 · upstream ↗ engine/overworld/wildmons.asm#L176-L251 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abcIn the USA GameCube release (
GAFE01_00, ACreTeam/ac-decomp), the daily pass of the town update adds up to 5 weeds for each 6:00 passed since the last update (computed frommAGrw_GetGrassMax), with no cap on the days counted. Each weed goes on a random empty square, in a random town block that has one, that is plantable ground (mCoBG_PLANT4) and not marked off by the cancel map; weeds stop when no such square is left. The weed kinds cycle through a shuffled table of 12. Whileclear_grassis set (a decompilers' comment: "set by Wisp, removes all weeds"), the next update removes every weed, adds none, and clears the flag; the back-in-time pass adds none either.CodeACreTeam/ac-decompHow we know
2754 delta_days++; 2755 if (delta_days > 1 && now_time->hour < 6) { 2756 delta_days--; ⋮ 2759 return delta_days * mAGrw_GRASS_PER_DAY;
src/game/m_all_grow_ovl.c lines 2744–2760 at 09ca8e8 · upstream ↗ 19#define mAGrw_GRASS_TABLE_NUM 12 ⋮ 25#define mAGrw_GRASS_PER_DAY 5
include/m_all_grow_ovl.h lines 19–25 at 09ca8e8 · upstream ↗ 601 days += t1->day - 1; 602 days += total_days[over_leap][t1->month - 1];
src/lb_rtc.c lines 542–609 at 09ca8e8 · upstream ↗ 2778 if (((cancel[0] >> ut_x) & 1) != 1 && (items[0] == EMPTY_NO) && 2779 (mCoBG_Attribute2CheckPlant(col->data.unit_attribute, &wpos_temp) == mCoBG_PLANT4)) {
src/game/m_all_grow_ovl.c lines 2762–2792 at 09ca8e8 · upstream ↗ 2856 grass_max = mAGrw_GetGrassMax(now_time, grow_time); ⋮ 2876 for (i = 0; i < grass_max; i++) { 2877 if (candidate_blocks > 0) { ⋮ 2883 selected_block = RANDOM(candidate_blocks); ⋮ 2910 grass_table_idx++;
src/game/m_all_grow_ovl.c lines 2835–2918 at 09ca8e8 · upstream ↗ 3078 if (Save_Get(clear_grass)) { 3079 mAGrw_ClearGrass();
src/game/m_all_grow_ovl.c lines 3078–3080 at 09ca8e8 · upstream ↗ 2929 if (IS_ITEM_GRASS(items[0])) { 2930 items[0] = EMPTY_NO;
src/game/m_all_grow_ovl.c lines 2920–2936 at 09ca8e8 · upstream ↗ 3143 if (Save_Get(clear_grass) == FALSE) { 3144 mAGrw_SetGrass(now_time, &grow_time, l_cancel_ut); ⋮ 3155 Save_Set(clear_grass, FALSE);
src/game/m_all_grow_ovl.c lines 3143–3155 at 09ca8e8 · upstream ↗ 139 /* 0x021395 */ u8 clear_grass; /* set by Wisp, removes all weeds */include/m_common_data.h line 139 at 09ca8e8 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abcHeartGold and SoulSilver (the US releases, which share this code) split the clock's hour into five periods with a 24-entry table: morning from 4:00 to 9:59, day from 10:00 to 16:59, evening from 17:00 to 19:59, night from 20:00 to 23:59, and late night from 0:00 to 3:59. Platinum's table gives every hour the same period (its names are morning, day, twilight, night, and late night). Gold and Silver have three periods: morning from 4:00, day from 10:00, and night from 18:00.Codepret/pokeheartgold · pret/pokeplatinum · pret/pokegold
How we know
8typedef enum RTC_TimeOfDay { 9 RTC_TIMEOFDAY_MORN = 0, 10 RTC_TIMEOFDAY_DAY, 11 RTC_TIMEOFDAY_EVE, 12 RTC_TIMEOFDAY_NITE, 13 RTC_TIMEOFDAY_LATE,
include/gf_rtc.h lines 8–15 at 6988158 · upstream ↗ 164TIMEOFDAY GF_RTC_GetTimeOfDayByHour(s32 hour) { 165 static const u8 sTimeOfDayByHour[24] = { 166 RTC_TIMEOFDAY_LATE, 167 RTC_TIMEOFDAY_LATE, 168 RTC_TIMEOFDAY_LATE, 169 RTC_TIMEOFDAY_LATE, 170 RTC_TIMEOFDAY_MORN, 171 RTC_TIMEOFDAY_MORN, 172 RTC_TIMEOFDAY_MORN, 173 RTC_TIMEOFDAY_MORN, 174 RTC_TIMEOFDAY_MORN, 175 RTC_TIMEOFDAY_MORN, ⋮
src/gf_rtc.c lines 164–193 at 6988158 · upstream ↗ 153enum TimeOfDay TimeOfDayForHour(int hour) ⋮ 155 static const u8 lookup[24] = { 156 TIMEOFDAY_LATE_NIGHT, 157 TIMEOFDAY_LATE_NIGHT, 158 TIMEOFDAY_LATE_NIGHT, 159 TIMEOFDAY_LATE_NIGHT, 160 TIMEOFDAY_MORNING, 161 TIMEOFDAY_MORNING, 162 TIMEOFDAY_MORNING, 163 TIMEOFDAY_MORNING, 164 TIMEOFDAY_MORNING, 165 TIMEOFDAY_MORNING, ⋮
src/rtc.c lines 153–183 at 49f78f3 · upstream ↗ 37DEF MORN_HOUR EQU 4 ; 4 AM 38DEF DAY_HOUR EQU 10 ; 10 AM 39DEF NITE_HOUR EQU 18 ; 6 PM
constants/misc_constants.asm lines 37–39 at fc702b6 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abcHeartGold and SoulSilver fold the five periods into three for wild Pokémon (
GF_RTC_GetTimeOfDayWildParamByHour: morning; day or evening; night or late night), and grass encounters pick their species list the same way.IsNighttimeis true at night or late night, so from 20:00 to 3:59 (computed from the hour table), and the evolution methods tied to the clock read it: friendship of at least 220 by day (EVO_FRIENDSHIP_DAY) or by night (EVO_FRIENDSHIP_NIGHT), and a held item by day or by night (EVO_ITEM_DAY,EVO_ITEM_NIGHT).Codepret/pokeheartgoldHow we know
142BOOL IsNighttime(void) { 143 switch (GF_RTC_GetTimeOfDay()) { 144 case RTC_TIMEOFDAY_NITE: 145 case RTC_TIMEOFDAY_LATE: 146 return TRUE; 147 default: 148 return FALSE;
src/gf_rtc.c lines 142–150 at 6988158 · upstream ↗ 196TimeOfDayWildParam GF_RTC_GetTimeOfDayWildParamByHour(s32 hour) { 197 switch (GF_RTC_GetTimeOfDayByHour(hour)) { 198 case RTC_TIMEOFDAY_MORN: 199 return TIMEOFDAY_WILD_MORN; 200 case RTC_TIMEOFDAY_DAY: 201 case RTC_TIMEOFDAY_EVE: 202 return TIMEOFDAY_WILD_DAY; 203 default: 204 return TIMEOFDAY_WILD_NITE;
src/gf_rtc.c lines 196–205 at 6988158 · upstream ↗ 119static void EncSlotArray_Init_Land(const EncounterData *encData, EncounterSlot *encSlots) { 120 TIMEOFDAY timeOfDay = GF_RTC_GetTimeOfDay(); ⋮ 123 if (timeOfDay == RTC_TIMEOFDAY_MORN) { 124 slotSpecies = encData->landSlots.species_morn; 125 } else if (timeOfDay == RTC_TIMEOFDAY_DAY || timeOfDay == RTC_TIMEOFDAY_EVE) { 126 slotSpecies = encData->landSlots.species_day; 127 } else if (timeOfDay == RTC_TIMEOFDAY_NITE || timeOfDay == RTC_TIMEOFDAY_LATE) { 128 slotSpecies = encData->landSlots.species_nite;
src/field/encounter_check.c lines 119–130 at 6988158 · upstream ↗ 2829 case EVO_FRIENDSHIP_DAY: 2830 if (IsNighttime() == 0 && friendship >= 220) { ⋮ 2835 case EVO_FRIENDSHIP_NIGHT: 2836 if (IsNighttime() == 1 && friendship >= 220) {
src/pokemon.c lines 2829–2839 at 6988158 · upstream ↗ 2902 case EVO_ITEM_DAY: 2903 if (IsNighttime() == 0 && evoTable[i].param == heldItem) { ⋮ 2908 case EVO_ITEM_NIGHT: 2909 if (IsNighttime() == 1 && evoTable[i].param == heldItem) {
src/pokemon.c lines 2902–2909 at 6988158 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abIn Simon's Quest an enemy placed while it's night starts with double the hit points its level data gives, except a few object types and in the mansions.Code“Castlevania II - Simon's Quest (USA)” · FoxCunning/Castlevania2
How we know
In the cartridge (“Castlevania II - Simon's Quest (USA)”): bank 1 $810D-$814C: if IsNightTime ($82), and the type isn't $21, $22, $25-$27, $2D-$2F, or $34, and map type ($30) isn't 1, the HP byte is shifted left once before it's stored in $04C2. We don't reproduce the bytes.
531LevelData_Stairs_1_Mansions_2_3_11_12:bank_2.asm line 531 at 2abe12c · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abIn the US release, each step of the gameplay loop adds 10 to the clock's seconds, as long as the map's
LEVEL_TIME_FLOWSflag is set, no animation has suspended time, and the player entity passescheckEntityMapSpaceDependentand isn't paused; 60 seconds make a minute. So a game minute is 6 steps and a game hour 360. The main loop steps at most once per video retrace (mainLoopUpdateIntervalis 1), and the retrace callback counts 60 calls as its cycle. Assuming 60 retraces a second (NTSC's rate is about 59.94), the clock runs at most 10 game minutes per real second, an hour in 6 real seconds (computed under that assumption). The real rate depends on how many steps the game finishes each second, which the atlas hasn't measured.Codeharvestwhisperer/hm64-decomprevisedHow we know
48 if ((getLevelFlags(gBaseMapIndex) & LEVEL_TIME_FLOWS) && !checkDailyEventBit(SUSPEND_TIME_DURING_ANIMATION)) {src/game/time.c lines 46–50 at 9824b88 · upstream ↗ 107 gSeconds += 10;src/game/time.c lines 104–113 at 9824b88 · upstream ↗ 59 handleTimeUpdates();src/game/transition.c lines 50–59 at 9824b88 · upstream ↗ 165 mainLoopUpdateInterval = 1;src/mainproc.c lines 164–165 at 9824b88 · upstream ↗ 307 if ((vblankCounter % mainLoopUpdateInterval) == 0) {src/mainLoop.c lines 305–325 at 9824b88 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abThe clock advances by the frame's real time (
gsys->getFrameTime()), and a 24-hour game day lasts 60 ×daySpeed×day_multiplyreal seconds:daySpeed(p00) comes from parms/gamePrms.bin, with a code default of 20 minutes that a decompilation comment gives as 27 in the file, andday_multiplycomes from the stage file, 1 if it has none. Each day starts atstartHour(t00, default 7.0) and ends when the time of day reachesendHour(t01, default 19.0), so the playable span is 12 ÷ 24 of a game day (computed): withday_multiplyat 1, 10 real minutes at the code defaults and 13.5 at the comment's 27. The clock advances only while no reset is pending (gsys->resetPending()), no menu is open outside a cutscene, nothing is paused (mPauseAll), no window is over the screen (mIsUIOverlayActive), no cutscene plays, the section's update flags includeUPDATE_WORLD_CLOCK, and the game isn't in the tutorial (isTutorial()).CodeprojectPiki/pikminrevisedHow we know
599 , mStartHour(this, 7.0f, 0.0f, 0.0f, "t00", "startHour") 600 , mEndHour(this, 19.0f, 0.0f, 0.0f, "t01", "endHour") 601 , mRealMinutesPerGameDay(this, 20.0f, 0.0f, 0.0f, "p00", "daySpeed")
include/gameflow.h lines 599–601 at 9a21636 · upstream ↗ 619 Parm<f32> mRealMinutesPerGameDay; ///< _24, p00 - how many real-life minutes correspond to one (24-hr) in-game "day" - def: 27 mins.include/gameflow.h line 619 at 9a21636 · upstream ↗ 594 load("parms/", "gamePrms.bin", 1);src/plugPikiColin/gameflow.cpp line 594 at 9a21636 · upstream ↗ 737 gameflow.mWorldClock.mRealSecsPerGameDay = 60.0f * (gameflow.mTimeMultiplier * gameflow.mParameters->mRealMinutesPerGameDay()); 738 gameflow.mWorldClock.mRealSecsPerGameHour = gameflow.mWorldClock.mRealSecsPerGameDay / gameflow.mWorldClock.mHoursInDay;
include/gameflow.h lines 737–738 at 9a21636 · upstream ↗ 2226 gameflow.mTimeMultiplier = 1.0f; ⋮ 2236 } else if (stream->isToken("day_multiply")) { 2237 sscanf(stream->getToken(true), "%f", &gameflow.mTimeMultiplier);
src/plugPikiColin/newPikiGame.cpp lines 2226–2237 at 9a21636 · upstream ↗ 204 mRealSecsIntoHour += gsys->getFrameTime() * playRate; 205 if (mRealSecsIntoHour >= mRealSecsPerGameHour) { 206 mRealSecsIntoHour -= mRealSecsPerGameHour; 207 mCurrentGameHour++; ⋮ 215 mTimeOfDay = mCurrentGameHour + mRealSecsIntoHour / mRealSecsPerGameHour;
src/plugPikiColin/gameflow.cpp lines 204–215 at 9a21636 · upstream ↗ 2155 if (!gsys->resetPending() && (!mActiveMenu || gameflow.mMoviePlayer->mIsActive)) { 2156 if (!gameflow.mPauseAll && !gameflow.mIsUIOverlayActive) { 2157 if (!gameflow.mMoviePlayer->mIsActive && (mUpdateFlags & UPDATE_WORLD_CLOCK) && !playerState->isTutorial()) { ⋮ 2159 gameflow.mWorldClock.update(1.0f);
src/plugPikiColin/newPikiGame.cpp lines 2155–2159 at 9a21636 · upstream ↗ 286 // handle story mode world map screen if we've made a decision ⋮ 299 enterCourse(stage); ⋮ 302 gameflow.mWorldClock.setTime(gameflow.mParameters->mStartHour());
src/plugPikiColin/mapSelect.cpp lines 286–302 at 9a21636 · upstream ↗ 864 if (!gameflow.mIsDayEndActive && !gameflow.mMoviePlayer->mIsActive 865 && gameflow.mWorldClock.mTimeOfDay >= gameflow.mParameters->mEndHour()) { ⋮ 870 gameflow.mIsDayEndTriggered = TRUE;
src/plugPikiColin/newPikiGame.cpp lines 864–870 at 9a21636 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abWhen a day ends (
GameCoreSection::cleanupDayEnd), outside challenge mode, the tutorial, and the game's ending (isEnding(): the 30th day, or all 30 ship parts), every Pikmin is killed and counted as left behind unless it is entering or leaving an Onion, or in itsLookAtstate, or following the captain (formation mode) in a state other than drowning, burning, swallowed, bubbled, dying, or flicked, or in free mode (FreeMode, in any state) withinmSunsetSafetyRange(p60, "日没生き残り範囲", code default 200, read from parms/pikiMgr.bin) of an Onion or of the ship, measured byqdist2's ground-plane approximation (|dx| + |dz| − ½ min). Pikmin with mushroom heads die too. If any were left behind, the take-off cutscene plays its enemy-attack version. The survivors then all go into their color's Onion (exitDayEnd), and a Pikmin with no Onion of its color is killed.CodeprojectPiki/pikminrevisedHow we know
598 PRINT("STEP (2) : remove objects (teki/boss/pellet/free pikis)\n"); ⋮ 600 if (!playerState->isChallengeMode() && !playerState->isTutorial() && !playerState->isEnding()) { ⋮ 607 if (piki->isKinoko()) { ⋮ 614 piki->kill(false);
src/plugPikiKando/gameCoreSection.cpp lines 598–618 at 9a21636 · upstream ↗ 630 if (mode == PikiMode::FormationMode) { 631 if (state == PIKISTATE_Drown || state == PIKISTATE_Fired || state == PIKISTATE_Dead || state == PIKISTATE_Swallowed 632 || state == PIKISTATE_Bubble || state == PIKISTATE_Dying || state == PIKISTATE_Flick || !piki->isAlive()) { 633 // do nothing 634 } else { 635 continue; ⋮ 638 if (mode == PikiMode::ExitMode || mode == PikiMode::EnterMode) { 639 continue; 640 } else if (state == PIKISTATE_LookAt) { 641 continue; ⋮ 645 if (piki->mMode == PikiMode::FreeMode) { ⋮ 650 <= pikiMgr->mPikiParms->mPikiParms.mSunsetSafetyRange()) { ⋮
src/plugPikiKando/gameCoreSection.cpp lines 629–676 at 9a21636 · upstream ↗ 112 , mSunsetSafetyRange(this, 200.0f, 0.0f, 5000.0f, "p60", "日没生き残り範囲")include/PikiMgr.h line 112 at 9a21636 · upstream ↗ 81 load("parms/", "pikiMgr.bin", 1);src/plugPikiKando/pikiMgr.cpp line 81 at 9a21636 · upstream ↗ 511 if (x1 > y1) { 512 min = y1; 513 } else { 514 min = x1; ⋮ 517 return (x1 + y1) - (0.5f * min);
src/sysCommon/sysMath.cpp lines 511–517 at 9a21636 · upstream ↗ 110bool PlayerState::isEnding() ⋮ 112 if (getCurrDay() >= (MAX_DAYS - 1)) { 113 // we've hit our 30-day limit 114 return true; ⋮ 116 } else if (getCurrParts() >= MAX_UFO_PARTS) { ⋮ 118 return true;
src/plugPikiKando/playerState.cpp lines 110–118 at 9a21636 · upstream ↗ 1507 if (dayEndObjFlags == 0) { 1508 // no dead pikmin! use correct (frustrated/neutral) animation 1509 dayEndObjFlags |= CAF_DayEndEnemyNoDeaths; 1510 } else { 1511 // dead pikmin :( use killing animation 1512 dayEndObjFlags |= CAF_DayEndEnemyAttack;
src/plugPikiColin/newPikiGame.cpp lines 1507–1512 at 9a21636 · upstream ↗ 362 if (piki->isAlive()) { 363 GoalItem* item = itemMgr->getContainer(piki->mColor); 364 if (item) { 365 item->enterGoal(piki); 366 entered++; 367 } else { 368 piki->kill(false);
src/plugPikiKando/gameCoreSection.cpp lines 362–369 at 9a21636 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abIn the USA build, the time of day is a float from 0 to 360, 15 to an hour (dKy_getdaytime_hour divides by 15); dKy_daynight_check calls 6:00 to 17:59 day. The environment's setup sets the advance mTimeAdv to 0.02, which dKy_custom_timeset can change. Each setDaytime call adds it only when no event-night stop is set, the save's get-item flag (2, 0) is set, no event runs, and (USA and PAL only) Link isn't on stage "sea" room 14 with stage layer 2 or 3. In rooms that pass time (getTimePass) the clock wraps from 360 to 0 and the day of the week goes up by one; in other rooms it advances only by day before 165 (11:00) and by night from 270 (18:00) to 345 (23:00). At 0.02 a day is 18,000 setDaytime calls (computed).Codezeldaret/tww
How we know
476 g_env_light.mTimeAdv = 0.02f;src/d/d_kankyo.cpp line 476 at cb24f55 · upstream ↗ 502void dScnKy_env_light_c::setDaytime() { ⋮ 504#if VERSION > VERSION_DEMO ⋮ 506#endif ⋮ 510#if VERSION > VERSION_JPN 511 if (strcmp(dComIfGp_getStartStageName(), "sea") == 0 && dComIfGp_roomControl_getStayNo() == 14) ⋮ 513 if (dComIfGp_getStartStageLayer() == 2 || dComIfGp_getStartStageLayer() == 3) { 514 var_r30 = true; ⋮ 517#endif ⋮ 519 if (!dKy_checkEventNightStop() && dComIfGs_isGetItem(2, 0) && dComIfGp_event_runCheck() == FALSE 520#if VERSION > VERSION_DEMO 521 && !var_r30 522#endif ⋮
src/d/d_kankyo.cpp lines 502–538 at cb24f55 · upstream ↗ 614int dKy_getdaytime_hour() { 615 return dComIfGs_getTime() / 15.0f; ⋮ 625int dKy_daynight_check() { 626 s32 hour = dKy_getdaytime_hour(); ⋮ 628 if (hour >= 6 && hour < 18) { 629 return dKy_TIME_DAY_e;
src/d/d_kankyo.cpp lines 614–631 at cb24f55 · upstream ↗ 3361void dKy_custom_timeset(f32 i_speed) { 3362 g_env_light.mTimeAdv = i_speed;
src/d/d_kankyo.cpp lines 3361–3362 at cb24f55 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^In the N64 US 1.0 code the clock is a 16-bit count in which a day is 0x10000 units, so a game minute is about 45.5 units (computed; the macro CLOCK_TIME_MINUTE truncates it to 45). Each play update, Environment_UpdateTime adds the time speed R_TIME_SPEED and then, if that speed isn't 0, the save's timeSpeedOffset. It adds only when time isn't stopped, the game isn't paused or over, no textbox is open (or its message id is 0xF7, 0x20D2, 0x140C, or 0x100 through 0x200, or the game mode is the end credits), the debug frame advance (FrameAdvance_IsEnabled) is off, no transition is under way (transitionMode off, or a game mode other than normal) and none has been triggered, and no cutscene runs. From 18:00 until 6:00 it sets the save's isNight flag.Codezeldaret/mmrevised
How we know
23#define CLOCK_TIME(hr, min) (s32)(((hr) * 60 + (min)) * 0x10000 / (24 * 60)) 24#define CLOCK_TIME_MINUTE (CLOCK_TIME(0, 1)) 25#define CLOCK_TIME_HOUR (CLOCK_TIME(1, 0)) 26#define DAY_LENGTH (CLOCK_TIME(24, 0))
include/macros.h lines 23–26 at 710e1a7 · upstream ↗ 334 /* 0x0C */ u16 time; // "zelda_time" ⋮ 336 /* 0x10 */ s32 isNight; // "asahiru_fg" 337 /* 0x14 */ s32 timeSpeedOffset; // "change_zelda_time" 338 /* 0x18 */ s32 day; // "totalday"
include/z64save.h lines 334–338 at 710e1a7 · upstream ↗ 1203 if (!sEnvIsTimeStopped && (pauseCtx->state == PAUSE_STATE_OFF) && (gameOverCtx->state == GAMEOVER_INACTIVE)) { 1204 if ((msgCtx->msgMode == MSGMODE_NONE) || (msgCtx->currentTextId == 0xF7) || (msgCtx->currentTextId == 0x20D2) || 1205 (msgCtx->currentTextId == 0x140C) || 1206 ((msgCtx->currentTextId >= 0x100) && (msgCtx->currentTextId <= 0x200)) || 1207 (gSaveContext.gameMode == GAMEMODE_END_CREDITS)) { 1208 if (!FrameAdvance_IsEnabled(play) && 1209 ((play->transitionMode == TRANS_MODE_OFF) || (gSaveContext.gameMode != GAMEMODE_NORMAL))) { 1210 if (play->transitionTrigger == TRANS_TRIGGER_OFF) { 1211 if ((CutsceneManager_GetCurrentCsId() == CS_ID_NONE) && !Play_InCsMode(play)) { 1212 gSaveContext.save.time = CURRENT_TIME + (u16)R_TIME_SPEED; 1213 if (R_TIME_SPEED != 0) { 1214 gSaveContext.save.time = CURRENT_TIME + (u16)((void)0, gSaveContext.save.timeSpeedOffset);
src/code/z_kankyo.c lines 1203–1214 at 710e1a7 · upstream ↗ 1227 time = CURRENT_TIME; ⋮ 1229 if ((time >= CLOCK_TIME(18, 0)) || (time < CLOCK_TIME(6, 0))) { 1230 gSaveContext.save.isNight = true;
src/code/z_kankyo.c lines 1227–1230 at 710e1a7 · upstream ↗ 1774 if (pauseCtx->state == PAUSE_STATE_OFF) { ⋮ 1779 Environment_UpdateTime(play, envCtx, pauseCtx, msgCtx, gameOverCtx);
src/code/z_kankyo.c lines 1774–1779 at 710e1a7 · upstream ↗ 1051 Environment_Update(this, &this->envCtx, &this->lightCtx, &this->pauseCtx, &this->msgCtx, &this->gameOverCtx,src/code/z_play.c line 1051 at 710e1a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^In the N64 US 1.0 code each scene's header sets its time speed, and a header value of 0xFF gives 0, a scene where time stands still. While Link's ocarina slot is empty, a nonzero scene speed becomes 5, under a decompilers' comment that reads "Increase time speed during first cycle"; the scene's speed becomes R_TIME_SPEED only while Sun's Song is inactive. The Inverted Song of Time is offered only where the scene's restriction flags allow it (otherwise text 0x1B95 and nothing) and the speed isn't 0; accepting it sets the offset to −2, or back to 0 if it was already set, and the update adds the offset only while the speed isn't 0. The game updates once every 3 video frames, set by GameState_SetFramerateDivisor(3) into a field whose comment reads "how many VIs should elapse before next swap". Assuming NTSC's 59.94 video frames a second (the atlas's assumption, not in the code), that is about 20 updates a second, and at speed 5 a game minute takes about 0.46 s, a day about 656 s, and the three days about 33 minutes (computed). The usual speed of a scene is in its header, ROM data the decompilation doesn't hold.Codezeldaret/mmrevised
How we know
393 if (cmd->timeSettings.timeSpeed != 0xFF) { 394 play->envCtx.sceneTimeSpeed = cmd->timeSettings.timeSpeed; 395 } else { 396 play->envCtx.sceneTimeSpeed = 0; ⋮ 399 // Increase time speed during first cycle 400 if ((gSaveContext.save.saveInfo.inventory.items[SLOT_OCARINA] == ITEM_NONE) && (play->envCtx.sceneTimeSpeed != 0)) { 401 play->envCtx.sceneTimeSpeed = 5; ⋮ 404 if (gSaveContext.sunsSongState == SUNSSONG_INACTIVE) { 405 R_TIME_SPEED = play->envCtx.sceneTimeSpeed;
src/code/z_scene.c lines 393–406 at 710e1a7 · upstream ↗ 5890 } else if (sLastPlayedSong == OCARINA_SONG_INVERTED_TIME) { 5891 if (interfaceCtx->restrictions.invSongOfTime == 0) { 5892 if (R_TIME_SPEED != 0) { ⋮ 5895 } else { ⋮ 5898 play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_INVERTED_TIME; 5899 } else { 5900 Message_StartTextbox(play, 0x1B8B, NULL); 5901 play->msgCtx.ocarinaMode = OCARINA_MODE_END; ⋮ 5903 } else { 5904 sLastPlayedSong = 0xFF; 5905 Message_StartTextbox(play, 0x1B95, NULL); 5906 play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_RESTRICTED_SONG;
src/code/z_message.c lines 5890–5906 at 710e1a7 · upstream ↗ 1212 gSaveContext.save.time = CURRENT_TIME + (u16)R_TIME_SPEED; 1213 if (R_TIME_SPEED != 0) { 1214 gSaveContext.save.time = CURRENT_TIME + (u16)((void)0, gSaveContext.save.timeSpeedOffset);
src/code/z_kankyo.c lines 1212–1214 at 710e1a7 · upstream ↗ 5683 } else if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_TWO_CHOICE) && 5684 (play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_INVERTED_TIME)) { 5685 if (Message_ShouldAdvance(play)) { 5686 if (msgCtx->choiceIndex == 0) { 5687 Audio_PlaySfx_MessageDecide(); 5688 if (gSaveContext.save.timeSpeedOffset == 0) { 5689 play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_INV_SOT_SLOW; 5690 gSaveContext.save.timeSpeedOffset = -2; 5691 } else { 5692 play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_INV_SOT_FAST; 5693 gSaveContext.save.timeSpeedOffset = 0;
src/code/z_message.c lines 5683–5694 at 710e1a7 · upstream ↗ 40void GameState_SetFramerateDivisor(GameState* gameState, s32 divisor) { 41 R_UPDATE_RATE = divisor; 42 gameState->framerateDivisor = divisor; 43 GameState_UpdateFramerateDivisors(divisor);
src/code/game.c lines 40–43 at 710e1a7 · upstream ↗ 243 GameState_SetFramerateDivisor(gameState, 3);src/code/game.c line 243 at 710e1a7 · upstream ↗ 236 cfb->updateRate = gameState->framerateDivisor;src/code/graph.c line 236 at 710e1a7 · upstream ↗ 25 /* 0x11 */ s8 updateRate; // how many VIs should elapse before next swapinclude/scheduler.h line 25 at 710e1a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abIn the N64 US 1.0 code, answering yes to the Song of Time's prompt runs Sram_SaveEndOfCycle, whose comment says it is "Used by Song of Time (when clicking "Yes") and (indirectly) by the "Dawn of the New Day" cutscene". The function sets the day counter to 0 and the clock one unit before 6:00, clears the Inverted Song's offset, and adds one to a reset count capped at 999, but on the song's path the message code saves the day, the time, and the cutscene index before the call and puts them back right after it; where the cycle returns to the first dawn is untraced. It sets the rupees Link carries to 0 and every ammo count to 0 except the pictograph box's, and turns any bottle holding an item from ITEM_POTION_RED through ITEM_OBABA_DRINK back into an empty bottle. It sets a sword at or below the Razor Sword back to the Kokiri Sword (or the Gilded Sword if a stolen-item slot holds it), removes dungeon keys, boss keys, stray fairies, and the pictograph, and clears the event-info flags. Scene flags (switches, chests, collectibles) and week-event flags survive only where a per-scene or per-flag persistence table marks them. Among the rest, it resets five minigame high scores and the three Deku Playground scores, but not the bank balance, which is kept in the high-score slot HS_BANK_RUPEES.Codezeldaret/mmrevised
How we know
5881 if (sLastPlayedSong == OCARINA_SONG_TIME) { 5882 if (interfaceCtx->restrictions.songOfTime == 0) { 5883 Message_StartTextbox(play, 0x1B8A, NULL); 5884 play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_SOT;
src/code/z_message.c lines 5881–5884 at 710e1a7 · upstream ↗ 5668 } else if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_TWO_CHOICE) && 5669 (play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_SOT)) { 5670 if (Message_ShouldAdvance(play)) { 5671 if (msgCtx->choiceIndex == 0) { 5672 Audio_PlaySfx_MessageDecide(); 5673 msgCtx->msgMode = MSGMODE_NEW_CYCLE_0;
src/code/z_message.c lines 5668–5673 at 710e1a7 · upstream ↗ 6022 case MSGMODE_NEW_CYCLE_0: 6023 play->state.unk_A3 = 1; 6024 sp44 = gSaveContext.save.cutsceneIndex; 6025 sp3E = CURRENT_TIME; 6026 sp40 = gSaveContext.save.day; ⋮ 6028 Sram_SaveEndOfCycle(play); 6029 gSaveContext.timerStates[TIMER_ID_MOON_CRASH] = TIMER_STATE_OFF; 6030 func_8014546C(&play->sramCtx); ⋮ 6032 gSaveContext.save.day = sp40; 6033 gSaveContext.save.time = sp3E; 6034 gSaveContext.save.cutsceneIndex = sp44;
src/code/z_message.c lines 6022–6034 at 710e1a7 · upstream ↗ 428 * Used by Song of Time (when clicking "Yes") and (indirectly) by the "Dawn of the New Day" cutscene ⋮ 430void Sram_SaveEndOfCycle(PlayState* play) { ⋮ 437 gSaveContext.save.timeSpeedOffset = 0; 438 gSaveContext.save.eventDayCount = 0; 439 gSaveContext.save.day = 0; 440 gSaveContext.save.time = CLOCK_TIME(6, 0) - 1; ⋮ 442 gSaveContext.save.saveInfo.playerData.threeDayResetCount++; 443 if (gSaveContext.save.saveInfo.playerData.threeDayResetCount > 999) { 444 gSaveContext.save.saveInfo.playerData.threeDayResetCount = 999;
src/code/z_sram_NES.c lines 427–444 at 710e1a7 · upstream ↗ 450 play->actorCtx.sceneFlags.chest &= sPersistentCycleSceneFlags[sceneId].chest; ⋮ 456 for (i = 0; i < SCENE_MAX; i++) { 457 gSaveContext.cycleSceneFlags[i].switch0 = 458 ((void)0, gSaveContext.cycleSceneFlags[i].switch0) & sPersistentCycleSceneFlags[i].switch0;
src/code/z_sram_NES.c lines 450–464 at 710e1a7 · upstream ↗ 486 for (i = 0; i < ARRAY_COUNT(sPersistentCycleWeekEventRegs); i++) { 487 u16 isPersistentBits = sPersistentCycleWeekEventRegs[i]; ⋮ 490 if (!(isPersistentBits & 3)) { 491 gSaveContext.save.saveInfo.weekEventReg[i] = 492 ((void)0, gSaveContext.save.saveInfo.weekEventReg[i]) & (0xFF ^ sBitFlags8[j]); ⋮ 498 for (i = 0; i < ARRAY_COUNT(gSaveContext.eventInf); i++) { 499 gSaveContext.eventInf[i] = 0;
src/code/z_sram_NES.c lines 486–499 at 710e1a7 · upstream ↗ 537 for (i = 0; i < ITEM_NUM_SLOTS; i++) { 538 if (gAmmoItems[i] != ITEM_NONE) { 539 if ((gSaveContext.save.saveInfo.inventory.items[i] != ITEM_NONE) && (i != SLOT_PICTOGRAPH_BOX)) { 540 item = gSaveContext.save.saveInfo.inventory.items[i]; 541 AMMO(item) = 0; ⋮ 546 for (i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_6; i++) { 547 // Check for all bottled items 548 if (gSaveContext.save.saveInfo.inventory.items[i] >= ITEM_POTION_RED) { 549 if (gSaveContext.save.saveInfo.inventory.items[i] <= ITEM_OBABA_DRINK) { ⋮ 556 gSaveContext.save.saveInfo.inventory.items[i] = ITEM_BOTTLE;
src/code/z_sram_NES.c lines 536–556 at 710e1a7 · upstream ↗ 561 REMOVE_QUEST_ITEM(QUEST_PICTOGRAPH); ⋮ 567 if (GET_CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) <= EQUIP_VALUE_SWORD_RAZOR) { 568 SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_KOKIRI); ⋮ 570 if (CUR_FORM == 0) { 571 if ((STOLEN_ITEM_1 >= ITEM_SWORD_GILDED) || (STOLEN_ITEM_2 >= ITEM_SWORD_GILDED)) { 572 CUR_FORM_EQUIP(EQUIP_SLOT_B) = ITEM_SWORD_GILDED; 573 SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_GILDED);
src/code/z_sram_NES.c lines 561–573 at 710e1a7 · upstream ↗ 637 Sram_ClearHighscores(); ⋮ 639 for (i = 0; i < 8; i++) { 640 gSaveContext.save.saveInfo.inventory.dungeonItems[i] &= (u8)~1; // remove boss key 641 DUNGEON_KEY_COUNT(i) = 0; 642 gSaveContext.save.saveInfo.inventory.strayFairies[i] = 0; ⋮ 645 gSaveContext.save.saveInfo.playerData.rupees = 0;
src/code/z_sram_NES.c lines 637–645 at 710e1a7 · upstream ↗ 404void Sram_ClearHighscores(void) { 405 HS_SET_BOAT_ARCHERY_HIGH_SCORE(19); 406 HS_SET_HIGH_SCORE_3_LOWER(10); 407 HS_SET_HORSE_BACK_BALLOON_TIME(SECONDS_TO_TIMER(60)); 408 HS_SET_TOWN_SHOOTING_GALLERY_HIGH_SCORE(39); 409 HS_SET_SWAMP_SHOOTING_GALLERY_HIGH_SCORE(10); ⋮ 411 gSaveContext.save.saveInfo.dekuPlaygroundHighScores[0] = SECONDS_TO_TIMER(75); 412 gSaveContext.save.saveInfo.dekuPlaygroundHighScores[1] = SECONDS_TO_TIMER(75); 413 gSaveContext.save.saveInfo.dekuPlaygroundHighScores[2] = SECONDS_TO_TIMER(76);
src/code/z_sram_NES.c lines 404–413 at 710e1a7 · upstream ↗ 613#define HS_GET_BANK_RUPEES() (HIGH_SCORE(HS_BANK_RUPEES) & 0xFFFF) 614#define HS_SET_BANK_RUPEES(rupees) (HIGH_SCORE(HS_BANK_RUPEES) = ((HIGH_SCORE(HS_BANK_RUPEES) & 0xFFFF0000) | (rupees)))
include/z64save.h lines 613–614 at 710e1a7 · upstream ↗ 694#if MM_VERSION >= N64_US 695 include "$(BUILD_DIR)/src/code/z_sram_NES.o" 696#endif
spec/spec lines 694–696 at 710e1a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^In the N64 US 1.0 code, accepting the Song of Double Time's prompt sets the clock to 6:00 if the save's isNight flag is set and to 18:00 if not, and turns off the moon's countdown timer; this code doesn't change the day counter. The three-day events actor (En_Test4) then sees the clock cross 6:00 and, in its no-cutscene branch, adds a day; that the jump to exactly 6:00 trips its crossing test is the atlas's reading. The song isn't offered on the third night (day 3 with isNight set) or where a scene's restriction flags forbid it.Codezeldaret/mmrevised
How we know
419 curTimeUntilTransition = CURRENT_TIME - transitionTime; 420 prevTimeUntilTransition = this->prevTime - transitionTime; ⋮ 429 if ((curTimeUntilTransition * prevTimeUntilTransition) <= 0) {
src/overlays/actors/ovl_En_Test4/z_en_test4.c lines 419–429 at 710e1a7 · upstream ↗ 115 } else if ((sCsIdList[this->daytimeIndex] <= CS_ID_NONE) || (play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) { 116 // Previously night, turning day, without a cutscene 117 Sram_IncrementDay(); 118 gSaveContext.save.time = CLOCK_TIME(6, 0);
src/overlays/actors/ovl_En_Test4/z_en_test4.c lines 115–118 at 710e1a7 · upstream ↗ 5908 } else if (sLastPlayedSong == OCARINA_SONG_DOUBLE_TIME) { 5909 if (interfaceCtx->restrictions.songOfDoubleTime == 0) { 5910 if ((CURRENT_DAY != 3) || (gSaveContext.save.isNight == 0)) { 5911 if (gSaveContext.save.isNight) { 5912 Message_StartTextbox(play, sDoubleTimeSkipToDayTextIds[CURRENT_DAY - 1], NULL); 5913 } else { 5914 Message_StartTextbox(play, sDoubleTimeSkipToNightTextIds[CURRENT_DAY - 1], NULL); ⋮ 5916 play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_DOUBLE_TIME; 5917 } else { 5918 Message_StartTextbox(play, 0x1B94, NULL); 5919 play->msgCtx.ocarinaMode = OCARINA_MODE_END;
src/code/z_message.c lines 5908–5919 at 710e1a7 · upstream ↗ 5702 } else if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_TWO_CHOICE) && 5703 (play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_DOUBLE_TIME)) { 5704 if (Message_ShouldAdvance(play)) { 5705 if (msgCtx->choiceIndex == 0) { 5706 Audio_PlaySfx_MessageDecide(); 5707 if (gSaveContext.save.isNight != 0) { 5708 gSaveContext.save.time = CLOCK_TIME(6, 0); 5709 } else { 5710 gSaveContext.save.time = CLOCK_TIME(18, 0); ⋮ 5712 play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_DOUBLE_SOT; 5713 gSaveContext.timerStates[TIMER_ID_MOON_CRASH] = TIMER_STATE_OFF;
src/code/z_message.c lines 5702–5713 at 710e1a7 · upstream ↗ 5305s16 sDoubleTimeSkipToNightTextIds[] = { 5306 0x1B91, // Night of 1st day 5307 0x1B90, // Night of 2nd day 5308 0x1B8F, // Night of final day ⋮ 5310s16 sDoubleTimeSkipToDayTextIds[] = { 5311 0x1B92, // Dawn of 2nd day 5312 0x1B8E, // Dawn of final day
src/code/z_message.c lines 5305–5313 at 710e1a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
Sources
Code
- pret contributors. 2026. “pokegold: disassembly of Pokémon Gold and Silver.” pret. Commit fc702b6. pret/pokegold @ fc702b6 · licence, all uses
- 1988. “Castlevania II - Simon's Quest (USA).” · licence, all uses
- ACreTeam contributors. 2026. “ac-decomp: a decompilation of Animal Crossing for the GameCube (ACreTeam/ac-decomp).” Commit 09ca8e8. ACreTeam/ac-decomp @ 09ca8e8 · licence, all uses
- zeldaret. 2026. “mm: a decompilation of The Legend of Zelda: Majora's Mask (zeldaret/mm).” Commit 710e1a7. zeldaret/mm @ 710e1a7 · licence, all uses
- pret contributors. 2026. “pokecrystal: disassembly of Pokémon Crystal.” pret. Commit 97187cd. pret/pokecrystal @ 97187cd · licence, all uses
- pret contributors. 2026. “pokeheartgold: decompilation of Pokémon HeartGold and SoulSilver.” pret. Commit 6988158. pret/pokeheartgold @ 6988158 · licence, all uses
- pret contributors. 2026. “pokeplatinum: decompilation of Pokémon Platinum.” pret. Commit 49f78f3. pret/pokeplatinum @ 49f78f3 · licence, all uses
- harvestwhisperer and hm64-decomp contributors. 2026. “hm64-decomp: a decompilation of Harvest Moon 64 (harvestwhisperer/hm64-decomp).” Commit 9824b88. harvestwhisperer/hm64-decomp @ 9824b88 · licence, all uses
- zeldaret. 2026. “tww: a decompilation of The Legend of Zelda: The Wind Waker (zeldaret/tww).” Commit cb24f55. zeldaret/tww @ cb24f55 · licence, all uses
- projectPiki. 2026. “pikmin: a decompilation of Pikmin (projectPiki/pikmin).” Commit 9a21636. projectPiki/pikmin @ 9a21636 · licence, all uses
- FoxCunning. 2022. “Castlevania 2 - Bloodlust: a full disassembly and hack of Castlevania II: Simon's Quest.” Commit 2abe12c. FoxCunning/Castlevania2 @ 2abe12c · licence, all uses