On this page
  1. Related
  2. Mechanics
  3. References
  4. Sources

The atlas reads Majora’s Mask through the Zelda Reverse Engineering Team’s decompilation, C that rebuilds the Nintendo 64’s US 1.0 ROM. Names and comments quoted here are theirs. Nothing has been measured in the game yet.

The clock counts a day as 65,536 units and adds the scene’s time speed on each update, except while the game is paused, a cutscene runs, or most textboxes are open1. Before Link has his ocarina, any scene where time moves runs at 5 units an update, and the game updates once every 3 video frames: about 11 minutes a day, computed at NTSC’s 59.94 frames a second2. Once accepted, the Inverted Song of Time takes 2 units off each update where time moves2.

At the third dawn the moon falls: the day counter goes to 4 and the game fades to Termina Field3. The Song of Time heads it off by resetting the cycle: Link loses his rupees, ammo, keys, and what his bottles hold, but the bank balance stays4. Where the clock goes back to the first dawn is untraced. The Song of Double Time jumps the clock to the next 6:00 or 18:00, though not on the last night5.

Mechanics

MechanicKindHow
Time of dayTime loopa 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 game, by concept (5)
Time of dayIn 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.Code
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.Code
In 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.Code
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.Code
In 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.Code

References

  1. ^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 claim ledger

  2. ^ abcIn 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 swap
    
    include/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.

    In the claim ledger

  3. ^In 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.

    In the claim ledger

  4. ^In 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 claim ledger

  5. ^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.

    In the claim ledger

Sources

Code