From 70d5e117194d1643c1fb2140190944cf94a2260f Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Sun, 4 May 2025 18:08:28 +0200 Subject: [PATCH] Add emscripten --- HTMLshell.html | 95 +++++++++++++++++++++++++++++++++++++++ TODO.txt | 1 + frontend_sdl.c | 120 ++++++++++++++++++++++++++++++++++--------------- make.sh | 12 +++-- 4 files changed, 189 insertions(+), 39 deletions(-) create mode 100644 HTMLshell.html diff --git a/HTMLshell.html b/HTMLshell.html new file mode 100644 index 0000000..3af5da2 --- /dev/null +++ b/HTMLshell.html @@ -0,0 +1,95 @@ + + + + + + + + + game + + + + + + + + + + {{{ SCRIPT }}} + + + + + +
+ + + diff --git a/TODO.txt b/TODO.txt index b0bff28..ea6ee6f 100644 --- a/TODO.txt +++ b/TODO.txt @@ -2,6 +2,7 @@ fuck issue trackers :D =========== GENERAL ============== +- 640x480 with resolution subdiv has bad sized menu item highlight - LOD blocks in lower res look too small - hitting ramps at higher speed still often bugs, try to fiddle with physics again (reshape iterations, tension, ...) diff --git a/frontend_sdl.c b/frontend_sdl.c index beaf2ce..aee6773 100644 --- a/frontend_sdl.c +++ b/frontend_sdl.c @@ -11,6 +11,15 @@ #define LCR_FPS_GET_MS SDL_GetTicks() // uncomment for FPS measuring +#ifdef __EMSCRIPTEN__ + #define LCR_SETTING_RESOLUTION_X 640 + #define LCR_SETTING_RESOLUTION_Y 480 + #define LCR_SETTING_MUSIC 0 + #define LCR_SETTING_CAR_SHADOW 0 + #define LCR_SETTING_TEXTURE_SUBSAMPLE 4 + #define LCR_SETTING_RESOLUTION_SUBDIVIDE 2 +#endif + #include "game.h" SDL_Window *window; @@ -18,6 +27,8 @@ SDL_Renderer *renderer; SDL_Texture *texture; SDL_Surface *screenSurface; +uint8_t running = 1, fullscreen = 1; + #if LCR_SETTING_332_COLOR uint8_t #else @@ -30,6 +41,9 @@ FILE *dataFile = 0; char LCR_getNextDataFileChar(void) { +#ifdef __EMSCRIPTEN__ + return 0; +#else if (!dataFile) return 0; @@ -42,10 +56,12 @@ char LCR_getNextDataFileChar(void) } return c; +#endif } void LCR_appendDataStr(const char *str) { +#ifndef __EMSCRIPTEN__ if (!dataFile) return; @@ -68,6 +84,9 @@ void LCR_appendDataStr(const char *str) dataFile = fopen(DATA_FILE_NAME,"r"); } } +#else + printf("%s",str); +#endif } void audioFillCallback(void *userdata, uint8_t *s, int l) @@ -116,11 +135,26 @@ uint8_t LCR_keyPressed(uint8_t key) return 0; } +#ifdef __EMSCRIPTEN__ +typedef void (*em_callback_func)(void); +void emscripten_set_main_loop( + em_callback_func func, int fps, int simulate_infinite_loop); +#endif + void LCR_sleep(uint16_t timeMs) { +#ifndef __EMSCRIPTEN__ SDL_Delay(timeMs); +#endif } +#ifdef __EMSCRIPTEN__ +void webButton(uint8_t key, uint8_t down) // HTML button pressed +{ + // TODO +} +#endif + void LCR_drawPixel(unsigned long index, uint16_t color) { screen[index] = color; @@ -140,10 +174,36 @@ void printHelp(void) LCR_ARG_HELP_STR); } +void mainLoopIteration(void) +{ + SDL_Event event; + + running = 1; + + while (SDL_PollEvent(&event)) + if (event.type == SDL_QUIT) + running = 0; + + keyboardState = SDL_GetKeyboardState(NULL); + + running &= LCR_gameStep(SDL_GetTicks()); + + SDL_UpdateTexture(texture,NULL,screen, + LCR_SETTING_RESOLUTION_X * sizeof( +#if LCR_SETTING_332_COLOR + uint8_t +#else + uint16_t +#endif + )); + + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer,texture,NULL,NULL); + SDL_RenderPresent(renderer); +} + int main(int argc, char *argv[]) { - uint8_t running = 1, fullscreen = 1; - for (int i = 0; i < argc; ++i) if (argv[i][0] == '-') switch (argv[i][1]) @@ -160,11 +220,20 @@ int main(int argc, char *argv[]) default: break; } +#ifdef __EMSCRIPTEN__ + fullscreen = 0; +#else dataFile = fopen(DATA_FILE_NAME,"r"); if (!dataFile) LCR_log("couldn't open data file"); + musicFile = fopen("assets/music","rb"); + + if (!musicFile) + fputs("could not open music file",stderr); +#endif + LCR_log("initializing game"); LCR_gameInit(argc,(const char **) argv); @@ -173,23 +242,23 @@ int main(int argc, char *argv[]) LCR_log("initializing audio"); SDL_AudioSpec audioSpec; - SDL_memset(&audioSpec, 0, sizeof(audioSpec)); + SDL_memset(&audioSpec,0,sizeof(audioSpec)); audioSpec.callback = audioFillCallback; + audioSpec.channels = 1; audioSpec.freq = 8000; audioSpec.format = AUDIO_U8; - audioSpec.channels = 1; + +#ifdef __EMSCRIPTEN__ + audioSpec.samples = 1024; +#else audioSpec.samples = 64; +#endif if (SDL_OpenAudio(&audioSpec,NULL) < 0) fputs("could not initialize audio",stderr); - + SDL_PauseAudio(0); - musicFile = fopen("assets/music","rb"); - - if (!musicFile) - fputs("could not open music file",stderr); - window = SDL_CreateWindow("Licar", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, LCR_SETTING_RESOLUTION_X, LCR_SETTING_RESOLUTION_Y, @@ -237,41 +306,22 @@ int main(int argc, char *argv[]) LCR_log("starting game loop"); - while (running) - { - SDL_Event event; - - running = 1; - - while (SDL_PollEvent(&event)) - if (event.type == SDL_QUIT) - running = 0; - - keyboardState = SDL_GetKeyboardState(NULL); - - running &= LCR_gameStep(SDL_GetTicks()); - - SDL_UpdateTexture(texture,NULL,screen, - LCR_SETTING_RESOLUTION_X * sizeof( -#if LCR_SETTING_332_COLOR - uint8_t +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(mainLoopIteration,0,1); #else - uint16_t + while (running) + mainLoopIteration(); #endif - )); - - SDL_RenderClear(renderer); - SDL_RenderCopy(renderer,texture,NULL,NULL); - SDL_RenderPresent(renderer); - } LCR_log("ending"); if (musicFile) fclose(musicFile); +#ifndef __EMSCRIPTEN__ if (dataFile) fclose(dataFile); +#endif SDL_PauseAudio(1); SDL_CloseAudio(); diff --git a/make.sh b/make.sh index ff48594..be35b8a 100755 --- a/make.sh +++ b/make.sh @@ -35,10 +35,14 @@ if [ $PLATFORM = "sdl" ]; then # - SDL2 (dev) package SDL_FLAGS=`sdl2-config --cflags --libs` - COMMAND="${COMPILER} ${C_FLAGS} frontend_sdl.c -I/usr/local/include ${SDL_FLAGS}" + ${COMPILER} ${C_FLAGS} frontend_sdl.c -I/usr/local/include ${SDL_FLAGS} +elif [ $PLATFORM = "emscripten" ]; then + # emscripten (browser Javascript) build, requires: + # - emscripten +# COMMAND="../emsdk/upstream/emscripten/emcc ./frontend_sdl.c -s USE_SDL=2 -O3 -lopenal --shell-file HTMLshell.html -o licar.html -s EXPORTED_FUNCTIONS=\'[\"_main\",\"_webButton\"]\' -s EXPORTED_RUNTIME_METHODS=\'[\"ccall\",\"cwrap\"]\'" + ../emsdk/upstream/emscripten/emcc ./frontend_sdl.c -s USE_SDL=2 -O3 -lopenal --shell-file HTMLshell.html -o licar.html -s EXPORTED_FUNCTIONS='["_main","_webButton"]' -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' +else + echo "unknown frontend" fi -echo ${COMMAND} -${COMMAND} - echo "done"