-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.cpp
143 lines (112 loc) · 3.29 KB
/
main.cpp
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <cstdlib>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#endif
#ifndef __EMSCRIPTEN__
#define SDL_MAIN_USE_CALLBACKS
#endif
#include <SDL3/SDL_main.h>
#include "frontend.h"
#ifdef __EMSCRIPTEN__
static double next_time;
static double time_delta;
static void Terminate()
{
Frontend::Deinitialise();
emscripten_cancel_main_loop();
// Deinitialise persistent storage.
EM_ASM({
FS.syncfs(false, function (err) {});
}, 0);
}
static void FrameRateCallback(const bool pal_mode)
{
time_delta = pal_mode ? Frontend::DivideByPALFramerate(1000.0) : Frontend::DivideByNTSCFramerate(1000.0);
}
static bool EventFilter(void* /*const userdata*/, SDL_Event* const event)
{
// The event loop will never have time to catch this, so we
// must use this callback to intercept it as soon as possible.
if (event->type == SDL_EVENT_TERMINATING)
Terminate();
return 0;
}
extern "C" EMSCRIPTEN_KEEPALIVE void StorageLoaded()
{
const auto callback = []()
{
const double current_time = emscripten_get_now();
if (current_time >= next_time)
{
// If massively delayed, resynchronise to avoid fast-forwarding.
if (current_time >= next_time + 100.0)
next_time = current_time;
next_time += time_delta;
SDL_Event event;
while (SDL_PollEvent(&event))
Frontend::HandleEvent(event);
Frontend::Update();
if (Frontend::WantsToQuit())
Terminate();
}
};
next_time = emscripten_get_now();
emscripten_set_main_loop(callback, 0, 0);
if (Frontend::Initialise(0, nullptr, FrameRateCallback))
SDL_AddEventWatch(EventFilter, nullptr);
}
int main([[maybe_unused]] const int argc, [[maybe_unused]] char** const argv)
{
// Initialise persistent storage.
EM_ASM({
FS.mount(IDBFS, {}, UTF8ToString($0));
FS.syncfs(true, function(err) {
Module._StorageLoaded();
});
}, Frontend::GetConfigurationDirectoryPath().u8string().c_str());
return EXIT_SUCCESS;
}
#else
static Uint64 time_delta;
static constexpr Uint64 one_second_in_nanoseconds = 1'000'000'000;
static void FrameRateCallback(const bool pal_mode)
{
if (pal_mode)
{
// Run at 50FPS
time_delta = Frontend::DivideByPALFramerate(one_second_in_nanoseconds);
}
else
{
// Run at roughly 59.94FPS (60 divided by 1.001)
time_delta = Frontend::DivideByNTSCFramerate(one_second_in_nanoseconds);
}
}
SDL_AppResult SDL_AppInit([[maybe_unused]] void** const appstate, const int argc, char** const argv)
{
return Frontend::Initialise(argc, argv, FrameRateCallback) ? SDL_APP_CONTINUE : SDL_APP_FAILURE;
}
SDL_AppResult SDL_AppIterate([[maybe_unused]] void* const appstate)
{
static Uint64 next_time;
const Uint64 current_time = SDL_GetTicksNS();
if (current_time < next_time)
return SDL_APP_CONTINUE;
// If massively delayed, resynchronise to avoid fast-forwarding.
if (current_time >= next_time + one_second_in_nanoseconds / 10)
next_time = current_time;
next_time += time_delta;
Frontend::Update();
return Frontend::WantsToQuit() ? SDL_APP_SUCCESS : SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppEvent([[maybe_unused]] void* const appstate, SDL_Event* const event)
{
Frontend::HandleEvent(*event);
return Frontend::WantsToQuit() ? SDL_APP_SUCCESS : SDL_APP_CONTINUE;
}
void SDL_AppQuit([[maybe_unused]] void* const appstate, [[maybe_unused]] const SDL_AppResult result)
{
Frontend::Deinitialise();
}
#endif