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"