McRogueFace/deps/platform/linux/platform.h
John McCardle 8c3128e29c WASM Python integration milestone - game.py runs in browser
Major milestone for issue #158 (Emscripten/WebAssembly build target):
- Python 3.14 successfully initializes and runs in WASM
- mcrfpy module loads and works correctly
- Game scripts execute with full level generation
- Entities (boulders, rats, cyclops, spawn points) placed correctly

Key changes:
- CMakeLists.txt: Add 2MB stack, Emscripten link options, preload files
- platform.h: Add WASM-specific implementations for executable paths
- HeadlessTypes.h: Make Texture/Font/Sound stubs return success
- CommandLineParser.cpp: Guard filesystem operations for WASM
- McRFPy_API.cpp: Add WASM path configuration, debug output
- game.py: Make 'code' module import optional (not available in WASM)
- wasm_stdlib/: Add minimal Python stdlib for WASM (~4MB)

Build with: emmake make (from build-emscripten/)
Test with: node mcrogueface.js

Next steps:
- Integrate VRSFML for actual WebGL rendering
- Create HTML page to host WASM build
- Test in actual browsers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 05:15:11 -05:00

90 lines
2.3 KiB
C++

#ifndef __PLATFORM
#define __PLATFORM
#define __PLATFORM_SET_PYTHON_SEARCH_PATHS 1
#ifdef __EMSCRIPTEN__
// WASM/Emscripten platform - no /proc filesystem, limited std::filesystem support
std::wstring executable_path()
{
// In WASM, the executable is at the root of the virtual filesystem
return L"/";
}
std::wstring executable_filename()
{
// In WASM, we use a fixed executable name
return L"/mcrogueface";
}
std::wstring working_path()
{
// In WASM, working directory is root of virtual filesystem
return L"/";
}
std::string narrow_string(std::wstring convertme)
{
// Simple conversion for ASCII/UTF-8 compatible strings
std::string result;
result.reserve(convertme.size());
for (wchar_t wc : convertme) {
if (wc < 128) {
result.push_back(static_cast<char>(wc));
} else {
// For non-ASCII, use a simple UTF-8 encoding
if (wc < 0x800) {
result.push_back(static_cast<char>(0xC0 | (wc >> 6)));
result.push_back(static_cast<char>(0x80 | (wc & 0x3F)));
} else {
result.push_back(static_cast<char>(0xE0 | (wc >> 12)));
result.push_back(static_cast<char>(0x80 | ((wc >> 6) & 0x3F)));
result.push_back(static_cast<char>(0x80 | (wc & 0x3F)));
}
}
}
return result;
}
#else
// Native Linux platform
std::wstring executable_path()
{
/*
wchar_t buffer[MAX_PATH];
GetModuleFileName(NULL, buffer, MAX_PATH);
std::wstring exec_path = buffer;
*/
auto exec_path = std::filesystem::canonical("/proc/self/exe").parent_path();
return exec_path.wstring();
//size_t path_index = exec_path.find_last_of('/');
//return exec_path.substr(0, path_index);
}
std::wstring executable_filename()
{
auto exec_path = std::filesystem::canonical("/proc/self/exe");
return exec_path.wstring();
}
std::wstring working_path()
{
auto cwd = std::filesystem::current_path();
return cwd.wstring();
}
std::string narrow_string(std::wstring convertme)
{
//setup converter
using convert_type = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_type, wchar_t> converter;
//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
return converter.to_bytes(convertme);
}
#endif // __EMSCRIPTEN__
#endif // __PLATFORM