Emscripten: Support persistent storage
This commit is contained in:
parent
82bd834e05
commit
58229f49b2
@ -209,7 +209,10 @@ if host_platform == 'emscripten'
|
||||
'-s', 'WASM=1',
|
||||
'-s', 'ALLOW_MEMORY_GROWTH=1',
|
||||
'-s', 'FORCE_FILESYSTEM=1',
|
||||
'-s', 'EXIT_RUNTIME=1',
|
||||
'-s', 'EXIT_RUNTIME=0',
|
||||
'-s', 'EXPORTED_RUNTIME_METHODS=ccall,cwrap',
|
||||
'-s', 'FS_DEBUG',
|
||||
'-lidbfs.js',
|
||||
]
|
||||
emcc_args = [
|
||||
'-s', 'USE_SDL=2',
|
||||
|
@ -182,6 +182,11 @@ static std::unique_ptr<ExplicitSingletons> explicitSingletons;
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Platform::SetupCrt();
|
||||
return Platform::InvokeMain(argc, argv);
|
||||
}
|
||||
|
||||
int Main(int argc, char *argv[])
|
||||
{
|
||||
Platform::Atexit([]() {
|
||||
SaveWindowPosition();
|
||||
// Unregister dodgy error handlers so they don't try to show the blue screen when the window is closed
|
||||
@ -254,22 +259,22 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ddir = std::unique_ptr<char, decltype(&SDL_free)>(SDL_GetPrefPath(NULL, APPDATA), SDL_free);
|
||||
auto ddir = Platform::DefaultDdir();
|
||||
if (!Platform::FileExists("powder.pref"))
|
||||
{
|
||||
if (ddir)
|
||||
if (ddir.size())
|
||||
{
|
||||
if (!Platform::ChangeDir(ddir.get()))
|
||||
if (!Platform::ChangeDir(ddir))
|
||||
{
|
||||
perror("failed to chdir to default ddir");
|
||||
ddir.reset();
|
||||
ddir = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ddir)
|
||||
if (ddir.size())
|
||||
{
|
||||
Platform::sharedCwd = ddir.get();
|
||||
Platform::sharedCwd = ddir;
|
||||
}
|
||||
}
|
||||
// We're now in the correct directory, time to get prefs.
|
||||
|
@ -3,12 +3,23 @@
|
||||
#include <emscripten.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
void MaybeTriggerSyncFs();
|
||||
}
|
||||
|
||||
static void MainLoopBody()
|
||||
{
|
||||
EngineProcess();
|
||||
Platform::MaybeTriggerSyncFs();
|
||||
}
|
||||
|
||||
void SetFpsLimit(FpsLimit newFpsLimit)
|
||||
{
|
||||
static bool mainLoopSet = false;
|
||||
if (!mainLoopSet)
|
||||
{
|
||||
emscripten_set_main_loop(EngineProcess, 0, 0);
|
||||
emscripten_set_main_loop(MainLoopBody, 0, 0);
|
||||
mainLoopSet = true;
|
||||
}
|
||||
if (auto *fpsLimitVsync = std::get_if<FpsLimitVsync>(&newFpsLimit))
|
||||
@ -28,8 +39,9 @@ void SetFpsLimit(FpsLimit newFpsLimit)
|
||||
}
|
||||
}
|
||||
|
||||
// Is actually only called once at startup, the real main loop body is MainLoopBody.
|
||||
void MainLoop()
|
||||
{
|
||||
SetFpsLimit(ui::Engine::Ref().GetFpsLimit());
|
||||
EngineProcess();
|
||||
MainLoopBody();
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace http
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" void RequestManager_UpdateRequestStatusThunk(http::RequestHandleHttp *handle);
|
||||
EMSCRIPTEN_KEEPALIVE extern "C" void RequestManager_UpdateRequestStatusThunk(http::RequestHandleHttp *handle);
|
||||
|
||||
namespace http
|
||||
{
|
||||
|
@ -6,10 +6,6 @@ if not enable_http
|
||||
client_files += files('Null.cpp')
|
||||
elif host_platform == 'emscripten'
|
||||
client_files += files('Emscripten.cpp')
|
||||
project_link_args += [
|
||||
'-s', 'EXPORTED_FUNCTIONS=_main,_RequestManager_UpdateRequestStatusThunk',
|
||||
'-s', 'EXPORTED_RUNTIME_METHODS=cwrap',
|
||||
]
|
||||
else
|
||||
client_files += files('Libcurl.cpp')
|
||||
endif
|
||||
|
@ -24,4 +24,8 @@ bool CanUpdate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetupCrt()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -48,4 +48,8 @@ bool CanUpdate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetupCrt()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
14
src/common/platform/DdirCommon.cpp
Normal file
14
src/common/platform/DdirCommon.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "Platform.h"
|
||||
#include "common/String.h"
|
||||
#include "Config.h"
|
||||
#include <SDL.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
ByteString DefaultDdir()
|
||||
{
|
||||
auto ddir = std::unique_ptr<char, decltype(&SDL_free)>(SDL_GetPrefPath(NULL, APPDATA), SDL_free);
|
||||
return ddir.get();
|
||||
}
|
||||
}
|
@ -1,5 +1,17 @@
|
||||
#include "Platform.h"
|
||||
#include <ctime>
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/threading.h>
|
||||
#include <atomic>
|
||||
#include <iostream>
|
||||
|
||||
static std::atomic<bool> shouldSyncFs = false;
|
||||
static bool syncFsInFlight = false;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE extern "C" void Platform_SyncFsDone()
|
||||
{
|
||||
syncFsInFlight = false;
|
||||
}
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
@ -37,4 +49,84 @@ void Atexit(ExitFunc exitFunc)
|
||||
void Exit(int code)
|
||||
{
|
||||
}
|
||||
|
||||
ByteString DefaultDdir()
|
||||
{
|
||||
return "/powder";
|
||||
}
|
||||
|
||||
int InvokeMain(int argc, char *argv[])
|
||||
{
|
||||
EM_ASM({
|
||||
FS.syncfs(true, () => {
|
||||
Module.ccall('MainJs', 'number', [ 'number', 'number' ], [ $0, $1 ]);
|
||||
});
|
||||
}, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MaybeTriggerSyncFs()
|
||||
{
|
||||
if (!syncFsInFlight && shouldSyncFs.exchange(false, std::memory_order_relaxed))
|
||||
{
|
||||
std::cerr << "invoking FS.syncfs" << std::endl;
|
||||
syncFsInFlight = true;
|
||||
EM_ASM({
|
||||
FS.syncfs(false, err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
Module.ccall('Platform_SyncFsDone', null, [], []);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE extern "C" int MainJs(int argc, char *argv[])
|
||||
{
|
||||
return Main(argc, argv);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE extern "C" void Platform_ShouldSyncFs()
|
||||
{
|
||||
shouldSyncFs.store(true, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
void SetupCrt()
|
||||
{
|
||||
EM_ASM({
|
||||
let ddir = UTF8ToString($0);
|
||||
let prefix = ddir + '/';
|
||||
let shouldSyncFs = Module.cwrap(
|
||||
'Platform_ShouldSyncFs',
|
||||
null,
|
||||
[]
|
||||
);
|
||||
FS.trackingDelegate['onMovePath'] = function(oldpath, newpath) {
|
||||
if (oldpath.startsWith(prefix) || newpath.startsWith(prefix)) {
|
||||
shouldSyncFs();
|
||||
}
|
||||
};
|
||||
FS.trackingDelegate['onDeletePath'] = function(path) {
|
||||
if (path.startsWith(prefix)) {
|
||||
shouldSyncFs();
|
||||
}
|
||||
};
|
||||
FS.trackingDelegate['onWriteToFile'] = function(path, bytesWritten) {
|
||||
if (path.startsWith(prefix)) {
|
||||
shouldSyncFs();
|
||||
}
|
||||
};
|
||||
FS.trackingDelegate['onMakeDirectory'] = function(path, mode) {
|
||||
if (path.startsWith(prefix)) {
|
||||
shouldSyncFs();
|
||||
}
|
||||
};
|
||||
FS.mkdir(ddir);
|
||||
FS.mount(IDBFS, {}, ddir);
|
||||
}, DefaultDdir().c_str());
|
||||
}
|
||||
}
|
||||
|
@ -109,4 +109,8 @@ bool Install()
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void SetupCrt()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
9
src/common/platform/MainCommon.cpp
Normal file
9
src/common/platform/MainCommon.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "Platform.h"
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
int InvokeMain(int argc, char *argv[])
|
||||
{
|
||||
return Main(argc, argv);
|
||||
}
|
||||
}
|
@ -11,4 +11,8 @@ bool CanUpdate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetupCrt()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -62,4 +62,10 @@ namespace Platform
|
||||
using ExitFunc = void (*)();
|
||||
void Atexit(ExitFunc exitFunc);
|
||||
void Exit(int code);
|
||||
|
||||
ByteString DefaultDdir();
|
||||
|
||||
int InvokeMain(int argc, char *argv[]);
|
||||
}
|
||||
|
||||
extern "C" int Main(int argc, char *argv[]);
|
||||
|
@ -218,8 +218,4 @@ bool UpdateFinish()
|
||||
void UpdateCleanup()
|
||||
{
|
||||
}
|
||||
|
||||
void SetupCrt()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,10 @@ if host_platform == 'windows'
|
||||
'Windows.cpp',
|
||||
'ExitCommon.cpp',
|
||||
)
|
||||
powder_files += files(
|
||||
'MainCommon.cpp',
|
||||
'DdirCommon.cpp',
|
||||
)
|
||||
elif host_platform == 'darwin'
|
||||
can_install_enforce_no = true
|
||||
common_files += files(
|
||||
@ -19,6 +23,10 @@ elif host_platform == 'darwin'
|
||||
'Posix.cpp',
|
||||
'ExitCommon.cpp',
|
||||
)
|
||||
powder_files += files(
|
||||
'MainCommon.cpp',
|
||||
'DdirCommon.cpp',
|
||||
)
|
||||
elif host_platform == 'android'
|
||||
can_install_enforce_no = true
|
||||
common_files += files(
|
||||
@ -26,6 +34,10 @@ elif host_platform == 'android'
|
||||
'Posix.cpp',
|
||||
'ExitCommon.cpp',
|
||||
)
|
||||
powder_files += files(
|
||||
'MainCommon.cpp',
|
||||
'DdirCommon.cpp',
|
||||
)
|
||||
elif host_platform == 'emscripten'
|
||||
use_bluescreen = false
|
||||
can_install_enforce_no = true
|
||||
@ -41,6 +53,10 @@ elif host_platform == 'linux'
|
||||
'Posix.cpp',
|
||||
'ExitCommon.cpp',
|
||||
)
|
||||
powder_files += files(
|
||||
'MainCommon.cpp',
|
||||
'DdirCommon.cpp',
|
||||
)
|
||||
else
|
||||
can_install_enforce_no = true
|
||||
common_files += files(
|
||||
@ -48,6 +64,10 @@ else
|
||||
'Posix.cpp',
|
||||
'ExitCommon.cpp',
|
||||
)
|
||||
powder_files += files(
|
||||
'MainCommon.cpp',
|
||||
'DdirCommon.cpp',
|
||||
)
|
||||
endif
|
||||
conf_data.set('SET_WINDOW_ICON', set_window_icon ? 'true' : 'false')
|
||||
conf_data.set('PATH_SEP_CHAR', path_sep_char)
|
||||
|
Loading…
Reference in New Issue
Block a user