1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include "SavingEnhancements.h"
#include <libultraship/bridge/consolevariablebridge.h>
#include "BenPort.h"
#include "2s2h/GameInteractor/GameInteractor.h"
#include "2s2h/ShipInit.hpp"
#include "2s2h/CustomMessage/CustomMessage.h"
extern "C" {
#include <variables.h>
#include <functions.h>
}
#define CVAR_AUTOSAVE_NAME "gEnhancements.Saving.Autosave"
#define CVAR_AUTOSAVE CVarGetInteger(CVAR_AUTOSAVE_NAME, 0)
static uint32_t autosaveInterval = 0;
static uint32_t iconTimer = 0;
static uint64_t currentTimestamp = 0;
static uint64_t lastSaveTimestamp = GetUnixTimestamp();
void DrawAutosaveIcon() {
// 5 seconds (100 frames) of showing the owl save icon to signify autosave has happened.
if (iconTimer != 0) {
float opacity = 255.0;
// Fade in icon
if (iconTimer > 80) {
opacity = 255.0 - (((iconTimer - 80.0) / 20.0) * 255);
// Fade out icon
} else if (iconTimer < 20) {
opacity = (iconTimer / 20.0) * 255.0;
}
Interface_DrawAutosaveIcon(gPlayState, uint16_t(opacity));
iconTimer--;
}
}
void HandleAutoSave() {
// Check if the interval has passed in minutes.
autosaveInterval = CVarGetInteger("gEnhancements.Saving.AutosaveInterval", 5) * 60000;
currentTimestamp = GetUnixTimestamp();
if ((currentTimestamp - lastSaveTimestamp) < autosaveInterval) {
return;
}
Player* player = GET_PLAYER(gPlayState);
if (player == NULL) {
return;
}
// Time must be moving for autosave to work. Fixes an issue with Time Moves When You Move.
if (gSaveContext.save.timeSpeedOffset == -R_TIME_SPEED && R_TIME_SPEED != 0) {
return;
}
// If owl save available to create, do it and reset the interval.
if (SavingEnhancements_CanSave() && gPlayState->pauseCtx.state == 0) {
// Reset timestamp, set icon timer to show autosave icon for 5 seconds (100 frames)
lastSaveTimestamp = GetUnixTimestamp();
iconTimer = 100;
// Persist this in case the user is 0th daying
bool currentOwlSaveState = gSaveContext.save.isOwlSave;
// Create owl save
gSaveContext.save.isOwlSave = true;
SavingEnhancements_PersistSaveEntranceInfo();
SavingEnhancements_AdvancePlaytime();
Play_SaveCycleSceneFlags(gPlayState);
gSaveContext.save.saveInfo.playerData.savedSceneId = gPlayState->sceneId;
func_8014546C(&gPlayState->sramCtx);
Sram_SetFlashPagesOwlSave(&gPlayState->sramCtx,
gFlashOwlSaveStartPages[gSaveContext.fileNum * FLASH_SAVE_MAIN_MULTIPLIER],
gFlashOwlSaveNumPages[gSaveContext.fileNum * FLASH_SAVE_MAIN_MULTIPLIER]);
Sram_StartWriteToFlashOwlSave(&gPlayState->sramCtx);
gSaveContext.save.isOwlSave = currentOwlSaveState;
SavingEnhancements_ClearSaveEntranceInfo();
}
}
static RegisterShipInitFunc registerAutosave(
[]() {
COND_HOOK(OnGameStateUpdate, CVAR_AUTOSAVE, []() {
if (gPlayState == nullptr) {
return;
}
HandleAutoSave();
});
COND_HOOK(OnGameStateDrawFinish, CVAR_AUTOSAVE, []() {
if (gPlayState == nullptr) {
return;
}
DrawAutosaveIcon();
});
},
{ CVAR_AUTOSAVE_NAME });
|