Emscripten build fixes, merge Emscripten backend into shared backend

This commit is contained in:
ROllerozxa 2025-03-10 22:05:42 +01:00
commit 07e7921719
5 changed files with 184 additions and 428 deletions

View file

@ -172,9 +172,6 @@ if(ANDROID)
set(BACKEND_SRC main_android.cc)
elseif(SCREENSHOT_BUILD)
set(BACKEND_SRC main_screenshotter.cc)
elseif(EMSCRIPTEN)
set(CMAKE_EXECUTABLE_SUFFIX ".html")
set(BACKEND_SRC main_emscripten.cc)
else()
set(BACKEND_SRC main.cc)
list(APPEND SRCS src/tms/backend/pipe.cc)
@ -273,6 +270,13 @@ add_definitions(-DTMS_BACKEND_${TMS_FORMFACTOR} -DTMS_BACKEND_${TMS_BACKEND})
# Use a safe subset of fast math flags
set(COMMON_FLAGS "-fno-math-errno -fno-trapping-math -fno-signed-zeros")
if(EMSCRIPTEN)
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "--preload-file ../data/")
string(APPEND COMMON_FLAGS " -sUSE_SDL=2 -pthread")
set(CMAKE_EXE_LINKER_FLAGS " -sUSE_SDL=2 -pthread -sPTHREAD_POOL_SIZE=20 -sINITIAL_MEMORY=2013265920 -sALLOW_MEMORY_GROWTH=1 -sTOTAL_STACK=16Mb")
set(CMAKE_EXECUTABLE_SUFFIX ".html")
endif()
set(COMMON_FLAGS_DEBUG "${COMMON_FLAGS} -O0 -ggdb -DDEBUG=1")
set(COMMON_FLAGS_RELEASE "${COMMON_FLAGS} -DNDEBUG=1 -fomit-frame-pointer")
@ -300,11 +304,6 @@ endif()
# Installation
# ------------
if(EMSCRIPTEN)
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "--preload-file ../data/")
target_link_libraries(${PROJECT_NAME} -lemsocket -lssl -lcrypto)
endif()
if(APPLE)
set(BUNDLE_NAME ${PROJECT_NAME}.app)
set(BUNDLE_PATH "${BUNDLE_NAME}")

View file

@ -1,7 +1,7 @@
set(DEPS "${CMAKE_SOURCE_DIR}/build_web/deps/")
set(CURL_INCLUDE_DIR ${DEPS}/include/curl)
set(CURL_LIBRARY ${DEPS}/lib/libcurl.a)
set(CURL_LIBRARY ${DEPS}/lib/libcurl.a;${DEPS}/lib/libcrypto.a;${DEPS}/lib/libemsocket.a;${DEPS}/lib/libssl.a)
set(FREETYPE_INCLUDE_DIR_ft2build ${DEPS}/include/freetype2)
set(FREETYPE_INCLUDE_DIR_freetype2 ${FREETYPE_INCLUDE_DIR_ft2build}/freetype)
set(FREETYPE_LIBRARY ${DEPS}/lib/libfreetype.a)
@ -9,3 +9,5 @@ set(JPEG_INCLUDE_DIR ${DEPS}/include)
set(JPEG_LIBRARY ${DEPS}/lib/libjpeg.a)
set(PNG_PNG_INCLUDE_DIR ${DEPS}/include/libpng16) #what
set(PNG_LIBRARY ${DEPS}/lib/libpng16.a)
set(ZLIB_INCLUDE_DIR ${DEPS}/include)
set(ZLIB_LIBRARY ${DEPS}/lib/libz.a)

View file

@ -30,6 +30,10 @@
#include <pwd.h>
#endif
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include "pipe.hh"
FILE *_f_out = stdout;
@ -43,6 +47,7 @@ int mouse_down;
static char *_storage_path = 0;
static int T_intercept_input(SDL_Event ev);
static void mainloop();
extern "C" int tbackend_init_surface();
extern "C" const char *tbackend_get_storage_path(void);
@ -81,8 +86,7 @@ void print_log_header() {
int main(int argc, char **argv)
{
SDL_Event ev;
int done = 0;
int done = 0;
signal(SIGSEGV, _catch_signal);
@ -179,163 +183,13 @@ int main(int argc, char **argv)
if (_tms.screen == 0)
tms_fatalf("Context has no initial screen!");
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(mainloop, 0, 1);
#else
do {
int i;
for (i = 0; i < 235; ++i) {
if (keys[i] == 1) {
struct tms_event spec;
spec.type = TMS_EV_KEY_DOWN;
spec.data.key.keycode = i;
tms_event_push(spec);
}
}
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_QUIT:
_tms.state = TMS_STATE_QUITTING;
break;
case SDL_KEYDOWN:
T_intercept_input(ev);
keys[ev.key.keysym.scancode] = 1;
break;
case SDL_KEYUP:
T_intercept_input(ev);
keys[ev.key.keysym.scancode] = 0;
break;
case SDL_WINDOWEVENT:
switch (ev.window.event) {
case SDL_WINDOWEVENT_RESIZED: {
tms_infof("Window %d resized to %dx%d",
ev.window.windowID, ev.window.data1,
ev.window.data2);
int w = ev.window.data1;
int h = ev.window.data2;
_tms.window_width = _tms.opengl_width = w;
_tms.window_height = _tms.opengl_height = h;
tproject_window_size_changed();
} break;
case SDL_WINDOWEVENT_MAXIMIZED:
settings["window_maximized"]->v.b = true;
break;
case SDL_WINDOWEVENT_RESTORED:
settings["window_maximized"]->v.b = false;
break;
default:
break;
}
break;
case SDL_FINGERDOWN:
case SDL_FINGERUP:
case SDL_FINGERMOTION:
case SDL_MOUSEWHEEL:
T_intercept_input(ev);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEMOTION: {
if (settings["emulate_touch"]->is_false()) {
//tms_infof("from sdl mouse thing");
T_intercept_input(ev);
}
} break;
// XXX: is this necessary
#ifdef TMS_BACKEND_WINDOWS
case SDL_SYSWMEVENT: {
SDL_SysWMmsg *msg = (SDL_SysWMmsg*)ev.syswm.msg;
switch (msg->msg.win.msg) {
case WM_MOUSEMOVE: {
//tms_infof("MOUSE MOVE");
SDL_Event user_event;
user_event.type = SDL_MOUSEMOTION;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_LEFT;
T_intercept_input(user_event);
} break;
case WM_LBUTTONDOWN: {
//tms_infof("LBUTTON DOWN");
SDL_Event user_event;
user_event.type = SDL_MOUSEBUTTONDOWN;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_LEFT;
T_intercept_input(user_event);
} break;
case WM_LBUTTONUP: {
//tms_infof("LBUTTON UP");
SDL_Event user_event;
user_event.type = SDL_MOUSEBUTTONUP;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_LEFT;
T_intercept_input(user_event);
} break;
case WM_RBUTTONDOWN: {
//tms_infof("RBUTTON DOWN");
SDL_Event user_event;
user_event.type = SDL_MOUSEBUTTONDOWN;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_RIGHT;
T_intercept_input(user_event);
} break;
case WM_RBUTTONUP: {
//tms_infof("RBUTTON UP");
SDL_Event user_event;
user_event.type = SDL_MOUSEBUTTONUP;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_RIGHT;
T_intercept_input(user_event);
} break;
}
} break;
#endif
case SDL_TEXTINPUT:
T_intercept_input(ev);
break;
}
}
tms_step();
tms_begin_frame();
tms_render();
SDL_GL_SwapWindow(_window);
tms_end_frame();
if (settings["emulate_touch"]->is_true()) {
int x, y;
SDL_GetMouseState(&x, &y);
SDL_Event user_event;
user_event.type = SDL_MOUSEMOTION;
user_event.button.x = x;
user_event.button.y = y;
user_event.button.button = SDL_BUTTON_LEFT;
}
mainloop();
} while (_tms.state != TMS_STATE_QUITTING);
#endif
tproject_quit();
@ -344,6 +198,166 @@ int main(int argc, char **argv)
return 0;
}
static void mainloop()
{
SDL_Event ev;
int i;
for (i = 0; i < 235; ++i) {
if (keys[i] == 1) {
struct tms_event spec;
spec.type = TMS_EV_KEY_DOWN;
spec.data.key.keycode = i;
tms_event_push(spec);
}
}
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_QUIT:
_tms.state = TMS_STATE_QUITTING;
break;
case SDL_KEYDOWN:
T_intercept_input(ev);
keys[ev.key.keysym.scancode] = 1;
break;
case SDL_KEYUP:
T_intercept_input(ev);
keys[ev.key.keysym.scancode] = 0;
break;
case SDL_WINDOWEVENT:
switch (ev.window.event) {
case SDL_WINDOWEVENT_RESIZED: {
tms_infof("Window %d resized to %dx%d",
ev.window.windowID, ev.window.data1,
ev.window.data2);
int w = ev.window.data1;
int h = ev.window.data2;
_tms.window_width = _tms.opengl_width = w;
_tms.window_height = _tms.opengl_height = h;
tproject_window_size_changed();
} break;
case SDL_WINDOWEVENT_MAXIMIZED:
settings["window_maximized"]->v.b = true;
break;
case SDL_WINDOWEVENT_RESTORED:
settings["window_maximized"]->v.b = false;
break;
default:
break;
}
break;
case SDL_FINGERDOWN:
case SDL_FINGERUP:
case SDL_FINGERMOTION:
case SDL_MOUSEWHEEL:
T_intercept_input(ev);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEMOTION: {
if (settings["emulate_touch"]->is_false()) {
//tms_infof("from sdl mouse thing");
T_intercept_input(ev);
}
} break;
// XXX: is this necessary
#ifdef TMS_BACKEND_WINDOWS
case SDL_SYSWMEVENT: {
SDL_SysWMmsg *msg = (SDL_SysWMmsg*)ev.syswm.msg;
switch (msg->msg.win.msg) {
case WM_MOUSEMOVE: {
//tms_infof("MOUSE MOVE");
SDL_Event user_event;
user_event.type = SDL_MOUSEMOTION;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_LEFT;
T_intercept_input(user_event);
} break;
case WM_LBUTTONDOWN: {
//tms_infof("LBUTTON DOWN");
SDL_Event user_event;
user_event.type = SDL_MOUSEBUTTONDOWN;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_LEFT;
T_intercept_input(user_event);
} break;
case WM_LBUTTONUP: {
//tms_infof("LBUTTON UP");
SDL_Event user_event;
user_event.type = SDL_MOUSEBUTTONUP;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_LEFT;
T_intercept_input(user_event);
} break;
case WM_RBUTTONDOWN: {
//tms_infof("RBUTTON DOWN");
SDL_Event user_event;
user_event.type = SDL_MOUSEBUTTONDOWN;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_RIGHT;
T_intercept_input(user_event);
} break;
case WM_RBUTTONUP: {
//tms_infof("RBUTTON UP");
SDL_Event user_event;
user_event.type = SDL_MOUSEBUTTONUP;
user_event.button.x = GET_X_LPARAM(msg->msg.win.lParam);
user_event.button.y = GET_Y_LPARAM(msg->msg.win.lParam);
user_event.button.button = SDL_BUTTON_RIGHT;
T_intercept_input(user_event);
} break;
}
} break;
#endif
case SDL_TEXTINPUT:
T_intercept_input(ev);
break;
}
}
tms_step();
tms_begin_frame();
tms_render();
SDL_GL_SwapWindow(_window);
tms_end_frame();
if (settings["emulate_touch"]->is_true()) {
int x, y;
SDL_GetMouseState(&x, &y);
SDL_Event user_event;
user_event.type = SDL_MOUSEMOTION;
user_event.button.x = x;
user_event.button.y = y;
user_event.button.button = SDL_BUTTON_LEFT;
}
}
int
tbackend_init_surface()
{
@ -620,6 +634,10 @@ T_intercept_input(SDL_Event ev)
const char *tbackend_get_storage_path(void)
{
#ifdef __EMSCRIPTEN__
return SDL_GetPrefPath("Bithack", "Principia");
#endif
if (!_storage_path) {
char *path = (char*)malloc(512);

View file

@ -1,264 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <tms/core/project.h>
#include <tms/core/event.h>
#include <tms/core/tms.h>
#include <tms/backend/opengl.h>
#include <pwd.h>
#include <emscripten.h>
FILE *_f_out = stdout;
static int _storage_type = 0;
SDL_Window *_window;
int keys[235];
int mouse_down;
static char *_storage_path = 0;
static int T_intercept_input(SDL_Event ev);
extern "C" int tbackend_init_surface();
extern "C" const char *tbackend_get_storage_path(void);
static void mainloop(void)
{
SDL_Event ev;
int i;
for (i = 0; i < 235; ++i) {
if (keys[i] == 1) {
struct tms_event spec;
spec.type = TMS_EV_KEY_DOWN;
spec.data.key.keycode = i;
tms_event_push(spec);
}
}
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_QUIT:
_tms.state = TMS_STATE_QUITTING;
break;
case SDL_KEYDOWN:
T_intercept_input(ev);
keys[ev.key.keysym.scancode] = 1;
break;
case SDL_KEYUP:
T_intercept_input(ev);
keys[ev.key.keysym.scancode] = 0;
break;
case SDL_MOUSEWHEEL:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEMOTION:
case SDL_TEXTINPUT:
T_intercept_input(ev);
break;
default:
break;
}
}
tms_step();
tms_begin_frame();
tms_render();
SDL_GL_SwapWindow(_window);
tms_end_frame();
}
int main(int argc, char **argv)
{
int done = 0;
tms_infof("Initializing SDL...");
SDL_Init(SDL_INIT_VIDEO);
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(0, &mode);
_tms.window_width = 1280;
_tms.window_height = 720;
tproject_set_args(argc, argv);
tms_init();
if (_tms.screen == 0)
tms_fatalf("Context has no initial screen!");
emscripten_set_main_loop(mainloop, 0, 1);
tproject_quit();
SDL_Quit();
return 0;
}
int
tbackend_init_surface()
{
SDL_Init(SDL_INIT_VIDEO);
_window = SDL_CreateWindow("Principia", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
1280, 720,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (_window == NULL)
tms_fatalf("Could not create SDL Window: %s", SDL_GetError());
_tms._window = _window;
_tms.xppcm = 108.f/2.54f * 1.5f;
_tms.yppcm = 107.f/2.54f * 1.5f;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_CreateContext(_window);
return T_OK;
}
int
mouse_button_to_pointer_id(int button)
{
switch (button) {
case SDL_BUTTON_LEFT: return 0;
case SDL_BUTTON_RIGHT: return 1;
case SDL_BUTTON_MIDDLE: return 2;
default: return 4;
}
}
int
T_intercept_input(SDL_Event ev)
{
struct tms_event spec;
spec.type = -1;
int motion_y = _tms.window_height-ev.motion.y;
int button_y = _tms.window_height-ev.button.y;
switch (ev.type) {
case SDL_KEYDOWN:
if (ev.key.repeat)
spec.type = TMS_EV_KEY_REPEAT;
else
spec.type = TMS_EV_KEY_PRESS;
spec.data.key.keycode = ev.key.keysym.scancode;
spec.data.key.mod = ev.key.keysym.mod;
switch (spec.data.key.keycode) {
case TMS_KEY_LEFT_CTRL: spec.data.key.mod |= TMS_MOD_LCTRL; break;
case TMS_KEY_RIGHT_CTRL: spec.data.key.mod |= TMS_MOD_RCTRL; break;
case TMS_KEY_LEFT_SHIFT: spec.data.key.mod |= TMS_MOD_LSHIFT; break;
case TMS_KEY_RIGHT_SHIFT: spec.data.key.mod |= TMS_MOD_RSHIFT; break;
}
break;
case SDL_KEYUP:
spec.type = TMS_EV_KEY_UP;
spec.data.key.keycode = ev.key.keysym.scancode;
spec.data.key.mod = ev.key.keysym.mod;
break;
case SDL_MOUSEBUTTONDOWN:
if (ev.button.which == SDL_TOUCH_MOUSEID)
return T_OK;
spec.type = TMS_EV_POINTER_DOWN;
spec.data.button.pointer_id = mouse_button_to_pointer_id(ev.button.button);
spec.data.button.x = ev.button.x;
spec.data.button.y = button_y;
spec.data.button.button = ev.button.button;
if (mouse_down == 0)
mouse_down = ev.button.button;
break;
case SDL_MOUSEBUTTONUP:
if (ev.button.which == SDL_TOUCH_MOUSEID)
return T_OK;
spec.type = TMS_EV_POINTER_UP;
spec.data.button.pointer_id = mouse_button_to_pointer_id(ev.button.button);
spec.data.button.x = ev.button.x;
spec.data.button.y = button_y;
spec.data.button.button = ev.button.button;
if (mouse_down == ev.button.button)
mouse_down = 0;
break;
case SDL_MOUSEMOTION:
if (ev.button.which == SDL_TOUCH_MOUSEID)
return T_OK;
spec.data.button.pointer_id = mouse_button_to_pointer_id(ev.button.button);
if (mouse_down) {
spec.type = TMS_EV_POINTER_DRAG;
spec.data.button.x = ev.motion.x;
spec.data.button.y = button_y;
spec.data.button.button = mouse_down;
} else {
spec.type = TMS_EV_POINTER_MOVE;
spec.data.button.x = ev.motion.x;
spec.data.button.y = motion_y;
}
break;
case SDL_MOUSEWHEEL:
spec.type = TMS_EV_POINTER_SCROLL;
spec.data.scroll.x = ev.wheel.x;
spec.data.scroll.y = ev.wheel.y;
SDL_GetMouseState(&spec.data.scroll.mouse_x, &spec.data.scroll.mouse_y);
break;
case SDL_TEXTINPUT:
spec.type = TMS_EV_TEXT_INPUT;
std::copy(ev.text.text, ev.text.text + 32, spec.data.text.text);
break;
}
tms_event_push(spec);
return T_OK;
}
const char *tbackend_get_storage_path(void)
{
if (!_storage_path) {
char *path = (char*)malloc(512);
char* exedir = SDL_GetPrefPath("Bithack", "Principia");
strcpy(path, exedir);
strcat(path, "userdata");
_storage_path = path;
tms_infof("Storage path: %s", path);
}
return _storage_path;
}

View file

@ -64,9 +64,10 @@ int _pipe_listener(void *p)
return T_OK;
#elif defined(TMS_BACKEND_HAIKU)
#elif defined(TMS_BACKEND_HAIKU) || defined(TMS_BACKEND_EMSCRIPTEN)
// Unimplemented
return 0;
#else
@ -166,7 +167,7 @@ void setup_pipe(int argc, char **argv)
SDL_CreateThread(_pipe_listener, "_pipe_listener", 0);
}
#elif defined(TMS_BACKEND_HAIKU)
#elif defined(TMS_BACKEND_HAIKU) || defined(TMS_BACKEND_EMSCRIPTEN)
// Unimplemented