isle-portable/ISLE/emscripten/filesystem.cpp
foxtacles 7e4a86fb39
Some checks failed
CI / clang-format (push) Has been cancelled
CI / ${{ matrix.name }} (false, --toolchain /usr/local/vitasdk/share/vita.toolchain.cmake, false, false, Ninja, Vita, ubuntu-latest, true, true) (push) Has been cancelled
CI / ${{ matrix.name }} (false, -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.26100.0, false, false, Visual Studio 17 2022, true, Xbox One, windows-latest, amd64, false, true) (push) Has been cancelled
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake, false, devkitpro/devkitarm:latest, false, Ninja, true, Nintendo 3DS, ubuntu-latest, true) (push) Has been cancelled
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake, false, devkitpro/devkita64:latest, false, Ninja, Nintendo Switch, true, ubuntu-latest, true) (push) Has been cancelled
CI / ${{ matrix.name }} (false, emcmake, false, false, true, Ninja, Emscripten, ubuntu-latest, true) (push) Has been cancelled
CI / ${{ matrix.name }} (false, false, false, Ninja, true, MSVC (arm64), windows-latest, amd64_arm64, false) (push) Has been cancelled
CI / ${{ matrix.name }} (false, false, true, Ninja, true, MSVC (x86), windows-latest, amd64_x86, false) (push) Has been cancelled
CI / ${{ matrix.name }} (false, true, false, Ninja, true, MSVC (x64), windows-latest, amd64, false) (push) Has been cancelled
CI / ${{ matrix.name }} (false, true, true, false, Ninja, true, MSVC (x64 Debug), windows-latest, amd64, false) (push) Has been cancelled
CI / ${{ matrix.name }} (true, false, -DCMAKE_SYSTEM_NAME=iOS, false, false, Xcode, true, iOS, macos-15, true) (push) Has been cancelled
CI / ${{ matrix.name }} (true, false, false, false, Ninja, Android, ubuntu-latest, true) (push) Has been cancelled
CI / ${{ matrix.name }} (true, false, true, false, Ninja, macOS, macos-latest, true) (push) Has been cancelled
CI / ${{ matrix.name }} (true, true, false, Ninja, true, mingw-w64-x86_64, mingw64, msys2 mingw64, windows-latest, msys2 {0}, true) (push) Has been cancelled
CI / ${{ matrix.name }} (true, true, true, false, Ninja, true, Linux (Debug), ubuntu-latest, true) (push) Has been cancelled
CI / ${{ matrix.name }} (true, true, true, false, Ninja, true, Linux, ubuntu-latest, true) (push) Has been cancelled
CI / Flatpak (${{ matrix.arch }}) (aarch64, ubuntu-22.04-arm) (push) Has been cancelled
CI / Flatpak (${{ matrix.arch }}) (x86_64, ubuntu-latest) (push) Has been cancelled
CI / C++ (push) Has been cancelled
Docker / Publish web port (push) Has been cancelled
CI / Release (push) Has been cancelled
Add third person camera extension (#786)
Introduces a third person camera system with orbit camera, input handling
(mouse/keyboard/touch/gamepad), display actor cloning, and camera-relative
movement. Includes shared character utilities (animator, cloner, customizer)
and an IExtraAnimHandler interface for optional animation extensions.
Also includes generic base game fixes and extension system improvements.
2026-03-31 01:00:07 +02:00

139 lines
3.9 KiB
C++

#include "filesystem.h"
#include "events.h"
#include "extensions/siloader.h"
#include "extensions/textureloader.h"
#include "legogamestate.h"
#include "misc.h"
#include "mxmain.h"
#include <SDL3/SDL_filesystem.h>
#include <SDL3/SDL_log.h>
#include <emscripten.h>
#include <emscripten/wasmfs.h>
static backend_t opfs = nullptr;
static backend_t fetchfs = nullptr;
extern const char* g_files[46];
extern const char* g_textures[120];
bool Emscripten_OPFSDisabled()
{
return MAIN_THREAD_EM_ASM_INT({return !!Module["disableOpfs"]});
}
bool Emscripten_SetupConfig(const char* p_iniConfig)
{
if (Emscripten_OPFSDisabled()) {
SDL_Log("OPFS is disabled; ignoring .ini path");
return false;
}
opfs = wasmfs_create_opfs_backend();
MxString iniConfig = p_iniConfig;
char* parse = iniConfig.GetData();
while ((parse = SDL_strchr(++parse, '/'))) {
*parse = '\0';
wasmfs_create_directory(iniConfig.GetData(), 0644, opfs);
*parse = '/';
}
return true;
}
void Emscripten_SetupFilesystem()
{
fetchfs = wasmfs_create_fetch_backend((MxString(Emscripten_streamHost) + "/LEGO").GetData(), 512 * 1024);
wasmfs_create_directory("/LEGO", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Act2", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Act3", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Build", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Garage", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Hospital", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Infocntr", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Isle", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Police", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Race", 0644, fetchfs);
wasmfs_create_directory("/LEGO/data", 0644, fetchfs);
const auto registerFile = [](const char* p_path) {
MxString path = MxString(Emscripten_bundledPath) + MxString(p_path);
path.MapPathToFilesystem();
if (SDL_GetPathInfo(path.GetData(), NULL)) {
SDL_Log("File %s is bundled and won't be streamed", p_path);
}
else {
wasmfs_create_file(p_path, 0644, fetchfs);
MxOmni::GetCDFiles().emplace_back(p_path);
SDL_Log("File %s set up for streaming", p_path);
}
};
const auto preloadFile = [](const char* p_path) -> bool {
size_t length = 0;
void* data = SDL_LoadFile(p_path, &length);
if (data) {
SDL_free(data);
}
return length > 0;
};
for (const char* file : g_files) {
registerFile(file);
}
#ifdef EXTENSIONS
if (Extensions::TextureLoaderExt::enabled) {
MxString directory =
MxString("/LEGO") + Extensions::TextureLoaderExt::options["texture loader:texture path"].c_str();
Extensions::TextureLoaderExt::options["texture loader:texture path"] = directory.GetData();
wasmfs_create_directory(directory.GetData(), 0644, fetchfs);
MxU32 i = 0;
Emscripten_SendExtensionProgress("HD Textures", 0);
for (const char* file : g_textures) {
MxString path = directory + "/" + file + ".bmp";
registerFile(path.GetData());
if (!preloadFile(path.GetData())) {
Extensions::TextureLoaderExt::AddExcludedFile(file);
}
Emscripten_SendExtensionProgress("HD Textures", (++i * 100) / sizeOfArray(g_textures));
}
}
if (Extensions::SiLoaderExt::enabled) {
wasmfs_create_directory("/LEGO/extra", 0644, fetchfs);
for (const auto& file : Extensions::SiLoaderExt::GetFiles()) {
registerFile(file.c_str());
}
}
#endif
if (GameState()->GetSavePath() && *GameState()->GetSavePath() && !Emscripten_OPFSDisabled()) {
if (!opfs) {
opfs = wasmfs_create_opfs_backend();
}
MxString savePath = GameState()->GetSavePath();
if (savePath.GetData()[savePath.GetLength() - 1] != '/') {
savePath += "/";
}
char* parse = savePath.GetData();
while ((parse = SDL_strchr(++parse, '/'))) {
*parse = '\0';
wasmfs_create_directory(savePath.GetData(), 0644, opfs);
*parse = '/';
}
}
}