From 136f42b116d70499c954c0015200e02a6e2fd6cc Mon Sep 17 00:00:00 2001 From: NISZOgen Date: Thu, 2 Apr 2026 17:15:36 +0200 Subject: [PATCH 1/2] wasm port --- Makefile | 4 +- kula/Makefile.wasm | 51 ++++++ kula/src/constants.h | 7 - kula/src/main.c | 330 ++++++++++++++++++++++--------------- kula/src/structs.h | 4 - kula/src/utils.h | 2 +- kula3D/Makefile.wasm | 51 ++++++ kula3D/src/constants.h | 8 - kula3D/src/main.c | 357 +++++++++++++++++++++++----------------- kula3D/src/structs.h | 4 - kula3D/src/utils.h | 2 +- kulatwo/Makefile.wasm | 52 ++++++ kulatwo/src/constants.h | 5 - kulatwo/src/main.c | 332 ++++++++++++++++++++++--------------- kulatwo/src/structs.h | 4 - kulatwo/src/utils.h | 2 +- 16 files changed, 756 insertions(+), 459 deletions(-) create mode 100644 kula/Makefile.wasm create mode 100644 kula3D/Makefile.wasm create mode 100644 kulatwo/Makefile.wasm diff --git a/Makefile b/Makefile index 08ffe0e..52e43cb 100644 --- a/Makefile +++ b/Makefile @@ -8,11 +8,11 @@ GAME_TARGETS = kula kula3D kulatwo all: $(GAME_TARGETS) $(GAME_TARGETS): %: %/assets - $(MAKE) $(if $(WINDOWS),-C $@ -f Makefile.win,-C $@) $(filter-out $@,$(MAKECMDGOALS)) + $(MAKE) -C $@ -f Makefile.wasm $(filter-out $@,$(MAKECMDGOALS)) %/assets: python tools/copy_assets_to_game.py $* # empty rule to avoid "No rule to make target" errors %: - @: \ No newline at end of file + @: diff --git a/kula/Makefile.wasm b/kula/Makefile.wasm new file mode 100644 index 0000000..4c5f19a --- /dev/null +++ b/kula/Makefile.wasm @@ -0,0 +1,51 @@ +# constants +CC = emcc +CFLAGS = -Wall -fms-extensions -O2 \ + -sUSE_SDL=2 \ + -sUSE_SDL_IMAGE=2 \ + -sSDL2_IMAGE_FORMATS=png \ + -sUSE_SDL_MIXER=2 \ + -sSDL2_MIXER_FORMATS=mp3,ogg \ + -sUSE_SDL_TTF=2 \ + -sUSE_FREETYPE=1 +LDFLAGS = $(CFLAGS) \ + -sALLOW_MEMORY_GROWTH=1 \ + --use-preload-plugins \ + --preload-file $(ASSETS_DIR)@/assets \ + --shell-file ../web/shell.html + +SRC_DIR = src +ASSETS_DIR = assets +BUILD_DIR = ../build/kula +export EM_CACHE ?= $(abspath ../build/.emcache) + +SOURCES = $(wildcard $(SRC_DIR)/*.c) +HEADERS = $(wildcard $(SRC_DIR)/*.h) +OBJECTS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.wasm.o,$(SOURCES)) + +EXECUTABLE = index.html + +# phony +.PHONY: all clean distclean run + +# targets +all: $(BUILD_DIR)/$(EXECUTABLE) + +clean: + $(RM) -r $(BUILD_DIR) + +distclean: clean + $(RM) -r $(ASSETS_DIR) + +run: $(BUILD_DIR)/$(EXECUTABLE) + emrun $< + +# rules +$(BUILD_DIR)/$(EXECUTABLE): $(OBJECTS) | $(BUILD_DIR) + $(CC) $(OBJECTS) $(LDFLAGS) -o $@ + +$(BUILD_DIR)/%.wasm.o: $(SRC_DIR)/%.c | $(HEADERS) $(BUILD_DIR) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR): + mkdir -p $@ diff --git a/kula/src/constants.h b/kula/src/constants.h index b396def..2e3448a 100644 --- a/kula/src/constants.h +++ b/kula/src/constants.h @@ -21,13 +21,6 @@ #define ENEMY_OPEN_PATH "/dev_hdd0/game/KULA00001/USRDIR/assets/fiende01.png" #define FONT_PATH "/dev_hdd0/game/KULA00001/USRDIR/assets/skrifttype.ttf" #define PLAYER_PATH "/dev_hdd0/game/KULA00001/USRDIR/assets/kula.png" -#elif defined(__3DS__) - #define BACKGROUND_PATH "romfs:/kulabakgrunn.png" - #define BGM_PATH "romfs:/mortietunes.mp3" - #define ENEMY_CLOSED_PATH "romfs:/fiende02.png" - #define ENEMY_OPEN_PATH "romfs:/fiende01.png" - #define FONT_PATH "romfs:/skrifttype.ttf" - #define PLAYER_PATH "romfs:/kula.png" #else #define BACKGROUND_PATH "assets/kulabakgrunn.png" #define BGM_PATH "assets/mortietunes.mp3" diff --git a/kula/src/main.c b/kula/src/main.c index 906efc2..410ea48 100644 --- a/kula/src/main.c +++ b/kula/src/main.c @@ -6,11 +6,6 @@ #include #include "../../mixer/mixer.h" -#elif defined(__3DS__) - #include - #include - #include - #include #else #include #include @@ -18,12 +13,31 @@ #include #endif +#include + #include #include "constants.h" #include "structs.h" #include "utils.h" +struct App { + SDL_Window* window; + SDL_Renderer* renderer; + SDL_GameController* controller; + + GameState state; + GameAssets assets; + + bool loop; + bool audioStarted; + + int screenWidth; + int screenHeight; +}; + +typedef struct App App; + void GameLogic(GameState* state) { if (!state->player.glideState.active) { if (state->controls & 1 << 0) { @@ -126,39 +140,8 @@ void GameRender(SDL_Renderer* renderer, GameState* state, GameAssets* assets) { RenderScore(renderer, assets->font, state->score); } -int main(int argc, char* argv[]) { - #if defined(NXDK) - XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); - #endif - - SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER); - IMG_Init(IMG_INIT_PNG); - TTF_Init(); - Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048); - - SDL_Window* window = SDL_CreateWindow( - WINDOW_TITLE, - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - #if defined(__wii__) || defined(NXDK) - 640, 480, - #elif defined(__vita__) - 960, 544, - #elif defined(PSP) - 480, 272, - #elif defined(__PPU__) - 1280, 720, - #elif defined(__3DS__) - 400, 240, - #else - GAME_WIDTH, GAME_HEIGHT, - #endif - SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE - ); - SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); - SDL_GameController* controller = NULL; - SDL_Event event; - - GameState state = { +static GameState GameStateCreate(void) { + return (GameState) { .score = 0, .scoreTimer = 0, @@ -198,7 +181,10 @@ int main(int argc, char* argv[]) { .controls = 0 }; - GameAssets assets = { +} + +static GameAssets GameAssetsLoad(SDL_Renderer* renderer) { + return (GameAssets) { .background = IMG_LoadTexture(renderer, BACKGROUND_PATH), .music = Mix_LoadMUS(BGM_PATH), .font = TTF_OpenFont(FONT_PATH, SCORE_SIZE), @@ -207,131 +193,128 @@ int main(int argc, char* argv[]) { .enemyOpen = IMG_LoadTexture(renderer, ENEMY_OPEN_PATH), .enemyClosed = IMG_LoadTexture(renderer, ENEMY_CLOSED_PATH) }; +} - bool loop = true; +static void AppUpdateRenderScale(App* app, int width, int height) { + app->screenWidth = width; + app->screenHeight = height; - int screenWidth; - int screenHeight; - - SDL_GetWindowSize(window, &screenWidth, &screenHeight); - SDL_RenderSetScale(renderer, - (float)screenWidth / GAME_WIDTH, - (float)screenHeight / GAME_HEIGHT + SDL_RenderSetScale( + app->renderer, + (float)width / GAME_WIDTH, + (float)height / GAME_HEIGHT ); +} - #if defined(__wii__) - SDL_ShowCursor(SDL_DISABLE); - #endif +static void AppStartMusic(App* app) { + if (app->audioStarted || app->assets.music == NULL) { + return; + } - Mix_PlayMusic(assets.music, -1); + Mix_PlayMusic(app->assets.music, -1); + app->audioStarted = true; +} - while (loop) { - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_QUIT: - loop = false; break; +static void AppHandleEvent(App* app, const SDL_Event* event) { + switch (event->type) { + case SDL_QUIT: + app->loop = false; break; - case SDL_WINDOWEVENT: - if (event.window.event == SDL_WINDOWEVENT_RESIZED) { - SDL_RenderSetScale(renderer, - (float)event.window.data1 / GAME_WIDTH, - (float)event.window.data2 / GAME_HEIGHT - ); - } + case SDL_WINDOWEVENT: + if (event->window.event == SDL_WINDOWEVENT_RESIZED) { + AppUpdateRenderScale(app, event->window.data1, event->window.data2); + } - break; + break; - case SDL_KEYDOWN: - if (event.key.repeat) break; + case SDL_KEYDOWN: + if (event->key.repeat) break; - switch (event.key.keysym.scancode) { - case SDL_SCANCODE_LEFT: - state.controls |= 1 << 0; break; - case SDL_SCANCODE_RIGHT: - state.controls |= 1 << 1; break; - case SDL_SCANCODE_SPACE: - state.controls |= 1 << 2; break; - default: - break; - } + AppStartMusic(app); + switch (event->key.keysym.scancode) { + case SDL_SCANCODE_LEFT: + app->state.controls |= 1 << 0; break; + case SDL_SCANCODE_RIGHT: + app->state.controls |= 1 << 1; break; + case SDL_SCANCODE_SPACE: + app->state.controls |= 1 << 2; break; + default: break; + } - case SDL_KEYUP: - switch (event.key.keysym.scancode) { - case SDL_SCANCODE_LEFT: - state.controls &= ~(1 << 0); break; - case SDL_SCANCODE_RIGHT: - state.controls &= ~(1 << 1); break; - case SDL_SCANCODE_SPACE: - state.controls &= ~(1 << 2); break; - default: - break; - } - + break; + + case SDL_KEYUP: + switch (event->key.keysym.scancode) { + case SDL_SCANCODE_LEFT: + app->state.controls &= ~(1 << 0); break; + case SDL_SCANCODE_RIGHT: + app->state.controls &= ~(1 << 1); break; + case SDL_SCANCODE_SPACE: + app->state.controls &= ~(1 << 2); break; + default: break; + } - case SDL_CONTROLLERDEVICEADDED: - if (controller == NULL) { - controller = SDL_GameControllerOpen(event.cdevice.which); - } - - break; + break; - case SDL_CONTROLLERDEVICEREMOVED: - if (SDL_GameControllerFromInstanceID(event.cdevice.which) == controller) { - SDL_GameControllerClose(controller); controller = NULL; - } + case SDL_CONTROLLERDEVICEADDED: + if (app->controller == NULL) { + app->controller = SDL_GameControllerOpen(event->cdevice.which); + } - break; + break; - case SDL_CONTROLLERBUTTONDOWN: - switch (event.cbutton.button) { - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - state.controls |= 1 << 0; break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - state.controls |= 1 << 1; break; - case SDL_CONTROLLER_BUTTON_A: - state.controls |= 1 << 2; break; - case SDL_CONTROLLER_BUTTON_BACK: - loop = false; break; - } + case SDL_CONTROLLERDEVICEREMOVED: + if (SDL_GameControllerFromInstanceID(event->cdevice.which) == app->controller) { + SDL_GameControllerClose(app->controller); + app->controller = NULL; + } - break; + break; - case SDL_CONTROLLERBUTTONUP: - switch (event.cbutton.button) { - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - state.controls &= ~(1 << 0); break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - state.controls &= ~(1 << 1); break; - case SDL_CONTROLLER_BUTTON_A: - state.controls &= ~(1 << 2); break; - } + case SDL_CONTROLLERBUTTONDOWN: + AppStartMusic(app); - break; + switch (event->cbutton.button) { + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + app->state.controls |= 1 << 0; break; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + app->state.controls |= 1 << 1; break; + case SDL_CONTROLLER_BUTTON_A: + app->state.controls |= 1 << 2; break; + case SDL_CONTROLLER_BUTTON_BACK: + app->loop = false; break; } - } - SDL_RenderClear(renderer); + break; - GameLogic(&state); - GameRender(renderer, &state, &assets); + case SDL_CONTROLLERBUTTONUP: + switch (event->cbutton.button) { + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + app->state.controls &= ~(1 << 0); break; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + app->state.controls &= ~(1 << 1); break; + case SDL_CONTROLLER_BUTTON_A: + app->state.controls &= ~(1 << 2); break; + } - SDL_RenderPresent(renderer); - SDL_Delay(1000 / FPS); + break; } +} - SDL_DestroyTexture(assets.background); - Mix_FreeMusic(assets.music); - TTF_CloseFont(assets.font); - SDL_DestroyTexture(assets.player); - SDL_DestroyTexture(assets.enemyOpen); - SDL_DestroyTexture(assets.enemyClosed); +static void AppShutdown(App* app) { + SDL_DestroyTexture(app->assets.background); + Mix_FreeMusic(app->assets.music); + TTF_CloseFont(app->assets.font); + SDL_DestroyTexture(app->assets.player); + SDL_DestroyTexture(app->assets.enemyOpen); + SDL_DestroyTexture(app->assets.enemyClosed); - if (controller != NULL) SDL_GameControllerClose(controller); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); + if (app->controller != NULL) SDL_GameControllerClose(app->controller); + SDL_DestroyRenderer(app->renderer); + SDL_DestroyWindow(app->window); Mix_CloseAudio(); Mix_Quit(); @@ -339,6 +322,79 @@ int main(int argc, char* argv[]) { TTF_Quit(); IMG_Quit(); SDL_Quit(); +} + +static void AppTick(void* userdata) { + App* app = userdata; + SDL_Event event; + + while (SDL_PollEvent(&event)) { + AppHandleEvent(app, &event); + } + + if (!app->loop) { + emscripten_cancel_main_loop(); + AppShutdown(app); + + return; + } + + SDL_RenderClear(app->renderer); + + GameLogic(&app->state); + GameRender(app->renderer, &app->state, &app->assets); + + SDL_RenderPresent(app->renderer); +} + +int main(int argc, char* argv[]) { + #if defined(NXDK) + XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); + #endif + + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER); + IMG_Init(IMG_INIT_PNG); + TTF_Init(); + Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048); + + SDL_Window* window = SDL_CreateWindow( + WINDOW_TITLE, + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + #if defined(__wii__) || defined(NXDK) + 640, 480, + #elif defined(__vita__) + 960, 544, + #elif defined(PSP) + 480, 272, + #elif defined(__PPU__) + 1280, 720, + #else + GAME_WIDTH, GAME_HEIGHT, + #endif + SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE + ); + SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); + + App app = { + .window = window, + .renderer = renderer, + .controller = NULL, + .state = GameStateCreate(), + .assets = GameAssetsLoad(renderer), + .loop = true, + .audioStarted = false, + .screenWidth = 0, + .screenHeight = 0 + }; + + SDL_GetWindowSize(window, &app.screenWidth, &app.screenHeight); + AppUpdateRenderScale(&app, app.screenWidth, app.screenHeight); + + #if defined(__wii__) + SDL_ShowCursor(SDL_DISABLE); + #endif + + emscripten_set_main_loop_arg(AppTick, &app, FPS, true); return 0; -} \ No newline at end of file +} diff --git a/kula/src/structs.h b/kula/src/structs.h index e884cea..9272d08 100644 --- a/kula/src/structs.h +++ b/kula/src/structs.h @@ -6,10 +6,6 @@ #include #include "../../mixer/mixer.h" -#elif defined(__3DS__) - #include - #include - #include #else #include #include diff --git a/kula/src/utils.h b/kula/src/utils.h index 61d3542..15429fb 100644 --- a/kula/src/utils.h +++ b/kula/src/utils.h @@ -1,7 +1,7 @@ #ifndef UTILS_H #define UTILS_H -#if defined(NXDK) || defined(__3DS__) +#if defined(NXDK) #include #include #else diff --git a/kula3D/Makefile.wasm b/kula3D/Makefile.wasm new file mode 100644 index 0000000..6a55244 --- /dev/null +++ b/kula3D/Makefile.wasm @@ -0,0 +1,51 @@ +# constants +CC = emcc +CFLAGS = -Wall -fms-extensions -O2 \ + -sUSE_SDL=2 \ + -sUSE_SDL_IMAGE=2 \ + -sSDL2_IMAGE_FORMATS=png \ + -sUSE_SDL_MIXER=2 \ + -sSDL2_MIXER_FORMATS=mp3,ogg \ + -sUSE_SDL_TTF=2 \ + -sUSE_FREETYPE=1 +LDFLAGS = $(CFLAGS) \ + -sALLOW_MEMORY_GROWTH=1 \ + --use-preload-plugins \ + --preload-file $(ASSETS_DIR)@/assets \ + --shell-file ../web/shell.html + +SRC_DIR = src +ASSETS_DIR = assets +BUILD_DIR = ../build/kula3D +export EM_CACHE ?= $(abspath ../build/.emcache) + +SOURCES = $(wildcard $(SRC_DIR)/*.c) +HEADERS = $(wildcard $(SRC_DIR)/*.h) +OBJECTS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.wasm.o,$(SOURCES)) + +EXECUTABLE = index.html + +# phony +.PHONY: all clean distclean run + +# targets +all: $(BUILD_DIR)/$(EXECUTABLE) + +clean: + $(RM) -r $(BUILD_DIR) + +distclean: clean + $(RM) -r $(ASSETS_DIR) + +run: $(BUILD_DIR)/$(EXECUTABLE) + emrun $< + +# rules +$(BUILD_DIR)/$(EXECUTABLE): $(OBJECTS) | $(BUILD_DIR) + $(CC) $(OBJECTS) $(LDFLAGS) -o $@ + +$(BUILD_DIR)/%.wasm.o: $(SRC_DIR)/%.c | $(HEADERS) $(BUILD_DIR) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR): + mkdir -p $@ diff --git a/kula3D/src/constants.h b/kula3D/src/constants.h index 14a4035..76e2d2a 100644 --- a/kula3D/src/constants.h +++ b/kula3D/src/constants.h @@ -23,14 +23,6 @@ #define FONT_PATH "/dev_hdd0/game/KULA00003/USRDIR/assets/skrifttype.ttf" #define LOGO_PATH "/dev_hdd0/game/KULA00003/USRDIR/assets/logo.png" #define PLAYER_PATH "/dev_hdd0/game/KULA00003/USRDIR/assets/kula.png" -#elif defined(__3DS__) - #define BACKGROUND_PATH "romfs:/background.png" - #define BGM_PATH "romfs:/mortietunes.mp3" - #define ENEMY_CLOSED_PATH "romfs:/trekant2.png" - #define ENEMY_OPEN_PATH "romfs:/trekant.png" - #define FONT_PATH "romfs:/skrifttype.ttf" - #define LOGO_PATH "romfs:/logo.png" - #define PLAYER_PATH "romfs:/kula.png" #else #define BACKGROUND_PATH "assets/background.png" #define BGM_PATH "assets/mortietunes.mp3" diff --git a/kula3D/src/main.c b/kula3D/src/main.c index 1304bf4..8b85655 100644 --- a/kula3D/src/main.c +++ b/kula3D/src/main.c @@ -6,11 +6,6 @@ #include #include "../../mixer/mixer.h" -#elif defined(__3DS__) - #include - #include - #include - #include #else #include #include @@ -18,13 +13,32 @@ #include #endif +#include + #include #include "constants.h" #include "structs.h" #include "utils.h" -void GameReset(GameState* state) { +struct App { + SDL_Window* window; + SDL_Renderer* renderer; + SDL_GameController* controller; + + GameState state; + GameAssets assets; + + bool loop; + bool audioStarted; + + int screenWidth; + int screenHeight; +}; + +typedef struct App App; + +void GameReset(GameState* state, bool resumeMusic) { state->player.rect = (SDL_Rect)PLAYER_INITIAL_RECT; state->player.active = true; state->player.hidden = false; @@ -45,8 +59,10 @@ void GameReset(GameState* state) { state->score = 0; - Mix_SetMusicPosition(0); - Mix_ResumeMusic(); + if (resumeMusic) { + Mix_SetMusicPosition(0); + Mix_ResumeMusic(); + } } void GameLogic(GameState* state) { @@ -168,39 +184,8 @@ void GameRender(SDL_Renderer* renderer, GameState* state, GameAssets* assets) { if (!state->player.active) RenderGameOver(renderer, assets->font); } -int main(int argc, char* argv[]) { - #if defined(NXDK) - XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); - #endif - - SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER); - IMG_Init(IMG_INIT_PNG); - TTF_Init(); - Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048); - - SDL_Window* window = SDL_CreateWindow( - WINDOW_TITLE, - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - #if defined(__wii__) || defined(NXDK) - 640, 480, - #elif defined(__vita__) - 960, 544, - #elif defined(PSP) - 480, 272, - #elif defined(__PPU__) - 1280, 720, - #elif defined(__3DS__) - 400, 240, - #else - GAME_WIDTH, GAME_HEIGHT, - #endif - SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE - ); - SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); - SDL_GameController* controller = NULL; - SDL_Event event; - - GameState state = { +static GameState GameStateCreate(void) { + return (GameState) { .score = 0, .player = { @@ -220,7 +205,10 @@ int main(int argc, char* argv[]) { .controls = 0 }; - GameAssets assets = { +} + +static GameAssets GameAssetsLoad(SDL_Renderer* renderer) { + return (GameAssets) { .background = IMG_LoadTexture(renderer, BACKGROUND_PATH), .logo = IMG_LoadTexture(renderer, LOGO_PATH), .music = Mix_LoadMUS(BGM_PATH), @@ -230,143 +218,141 @@ int main(int argc, char* argv[]) { .enemyOpen = IMG_LoadTexture(renderer, ENEMY_OPEN_PATH), .enemyClosed = IMG_LoadTexture(renderer, ENEMY_CLOSED_PATH) }; +} - bool loop = true; - - int screenWidth; - int screenHeight; +static void AppUpdateRenderScale(App* app, int width, int height) { + app->screenWidth = width; + app->screenHeight = height; - SDL_GetWindowSize(window, &screenWidth, &screenHeight); - SDL_RenderSetScale(renderer, - (float)screenWidth / GAME_WIDTH, - (float)screenHeight / GAME_HEIGHT + SDL_RenderSetScale( + app->renderer, + (float)width / GAME_WIDTH, + (float)height / GAME_HEIGHT ); +} - #if defined(__wii__) - SDL_ShowCursor(SDL_DISABLE); - #endif +static void AppStartMusic(App* app) { + if (app->audioStarted || app->assets.music == NULL) { + return; + } - Mix_PlayMusic(assets.music, -1); + Mix_PlayMusic(app->assets.music, -1); + app->audioStarted = true; +} - while (loop) { - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_QUIT: - loop = false; break; +static void AppHandleEvent(App* app, const SDL_Event* event) { + switch (event->type) { + case SDL_QUIT: + app->loop = false; break; - case SDL_WINDOWEVENT: - if (event.window.event == SDL_WINDOWEVENT_RESIZED) { - SDL_RenderSetScale(renderer, - (float)event.window.data1 / GAME_WIDTH, - (float)event.window.data2 / GAME_HEIGHT - ); - } + case SDL_WINDOWEVENT: + if (event->window.event == SDL_WINDOWEVENT_RESIZED) { + AppUpdateRenderScale(app, event->window.data1, event->window.data2); + } - break; + break; - case SDL_KEYDOWN: - if (event.key.repeat) break; - - switch (event.key.keysym.scancode) { - case SDL_SCANCODE_LEFT: - state.controls |= 1 << 0; break; - case SDL_SCANCODE_RIGHT: - state.controls |= 1 << 1; break; - case SDL_SCANCODE_SPACE: - state.controls |= 1 << 2; break; - case SDL_SCANCODE_RETURN: - if (!state.player.active) { - GameReset(&state); - } - - break; - default: - break; - } + case SDL_KEYDOWN: + if (event->key.repeat) break; - break; + AppStartMusic(app); - case SDL_KEYUP: - switch (event.key.keysym.scancode) { - case SDL_SCANCODE_LEFT: - state.controls &= ~(1 << 0); break; - case SDL_SCANCODE_RIGHT: - state.controls &= ~(1 << 1); break; - case SDL_SCANCODE_SPACE: - state.controls &= ~(1 << 2); break; - default: - break; + switch (event->key.keysym.scancode) { + case SDL_SCANCODE_LEFT: + app->state.controls |= 1 << 0; break; + case SDL_SCANCODE_RIGHT: + app->state.controls |= 1 << 1; break; + case SDL_SCANCODE_SPACE: + app->state.controls |= 1 << 2; break; + case SDL_SCANCODE_RETURN: + if (!app->state.player.active) { + GameReset(&app->state, app->audioStarted); } break; + default: + break; + } - case SDL_CONTROLLERDEVICEADDED: - if (controller == NULL) { - controller = SDL_GameControllerOpen(event.cdevice.which); - } - + break; + + case SDL_KEYUP: + switch (event->key.keysym.scancode) { + case SDL_SCANCODE_LEFT: + app->state.controls &= ~(1 << 0); break; + case SDL_SCANCODE_RIGHT: + app->state.controls &= ~(1 << 1); break; + case SDL_SCANCODE_SPACE: + app->state.controls &= ~(1 << 2); break; + default: break; + } - case SDL_CONTROLLERDEVICEREMOVED: - if (SDL_GameControllerFromInstanceID(event.cdevice.which) == controller) { - SDL_GameControllerClose(controller); controller = NULL; - } + break; - break; + case SDL_CONTROLLERDEVICEADDED: + if (app->controller == NULL) { + app->controller = SDL_GameControllerOpen(event->cdevice.which); + } - case SDL_CONTROLLERBUTTONDOWN: - switch (event.cbutton.button) { - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - state.controls |= 1 << 0; break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - state.controls |= 1 << 1; break; - case SDL_CONTROLLER_BUTTON_A: - state.controls |= 1 << 2; break; - case SDL_CONTROLLER_BUTTON_START: - if (!state.player.active) { - GameReset(&state); - } - - break; - case SDL_CONTROLLER_BUTTON_BACK: - loop = false; break; - } + break; - break; + case SDL_CONTROLLERDEVICEREMOVED: + if (SDL_GameControllerFromInstanceID(event->cdevice.which) == app->controller) { + SDL_GameControllerClose(app->controller); + app->controller = NULL; + } - case SDL_CONTROLLERBUTTONUP: - switch (event.cbutton.button) { - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - state.controls &= ~(1 << 0); break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - state.controls &= ~(1 << 1); break; - case SDL_CONTROLLER_BUTTON_A: - state.controls &= ~(1 << 2); break; + break; + + case SDL_CONTROLLERBUTTONDOWN: + AppStartMusic(app); + + switch (event->cbutton.button) { + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + app->state.controls |= 1 << 0; break; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + app->state.controls |= 1 << 1; break; + case SDL_CONTROLLER_BUTTON_A: + app->state.controls |= 1 << 2; break; + case SDL_CONTROLLER_BUTTON_START: + if (!app->state.player.active) { + GameReset(&app->state, app->audioStarted); } break; + case SDL_CONTROLLER_BUTTON_BACK: + app->loop = false; break; } - } - SDL_RenderClear(renderer); + break; - GameLogic(&state); - GameRender(renderer, &state, &assets); + case SDL_CONTROLLERBUTTONUP: + switch (event->cbutton.button) { + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + app->state.controls &= ~(1 << 0); break; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + app->state.controls &= ~(1 << 1); break; + case SDL_CONTROLLER_BUTTON_A: + app->state.controls &= ~(1 << 2); break; + } - SDL_RenderPresent(renderer); - SDL_Delay(1000 / FPS); + break; } +} - SDL_DestroyTexture(assets.background); - Mix_FreeMusic(assets.music); - TTF_CloseFont(assets.font); - SDL_DestroyTexture(assets.player); - SDL_DestroyTexture(assets.enemyOpen); - SDL_DestroyTexture(assets.enemyClosed); +static void AppShutdown(App* app) { + SDL_DestroyTexture(app->assets.background); + SDL_DestroyTexture(app->assets.logo); + Mix_FreeMusic(app->assets.music); + TTF_CloseFont(app->assets.font); + SDL_DestroyTexture(app->assets.player); + SDL_DestroyTexture(app->assets.enemyOpen); + SDL_DestroyTexture(app->assets.enemyClosed); - if (controller != NULL) SDL_GameControllerClose(controller); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); + if (app->controller != NULL) SDL_GameControllerClose(app->controller); + SDL_DestroyRenderer(app->renderer); + SDL_DestroyWindow(app->window); Mix_CloseAudio(); Mix_Quit(); @@ -374,6 +360,79 @@ int main(int argc, char* argv[]) { TTF_Quit(); IMG_Quit(); SDL_Quit(); +} + +static void AppTick(void* userdata) { + App* app = userdata; + SDL_Event event; + + while (SDL_PollEvent(&event)) { + AppHandleEvent(app, &event); + } + + if (!app->loop) { + emscripten_cancel_main_loop(); + AppShutdown(app); + + return; + } + + SDL_RenderClear(app->renderer); + + GameLogic(&app->state); + GameRender(app->renderer, &app->state, &app->assets); + + SDL_RenderPresent(app->renderer); +} + +int main(int argc, char* argv[]) { + #if defined(NXDK) + XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); + #endif + + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER); + IMG_Init(IMG_INIT_PNG); + TTF_Init(); + Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048); + + SDL_Window* window = SDL_CreateWindow( + WINDOW_TITLE, + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + #if defined(__wii__) || defined(NXDK) + 640, 480, + #elif defined(__vita__) + 960, 544, + #elif defined(PSP) + 480, 272, + #elif defined(__PPU__) + 1280, 720, + #else + GAME_WIDTH, GAME_HEIGHT, + #endif + SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE + ); + SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); + + App app = { + .window = window, + .renderer = renderer, + .controller = NULL, + .state = GameStateCreate(), + .assets = GameAssetsLoad(renderer), + .loop = true, + .audioStarted = false, + .screenWidth = 0, + .screenHeight = 0 + }; + + SDL_GetWindowSize(window, &app.screenWidth, &app.screenHeight); + AppUpdateRenderScale(&app, app.screenWidth, app.screenHeight); + + #if defined(__wii__) + SDL_ShowCursor(SDL_DISABLE); + #endif + + emscripten_set_main_loop_arg(AppTick, &app, FPS, true); return 0; -} \ No newline at end of file +} diff --git a/kula3D/src/structs.h b/kula3D/src/structs.h index 6ee4ba5..cbf01b0 100644 --- a/kula3D/src/structs.h +++ b/kula3D/src/structs.h @@ -6,10 +6,6 @@ #include #include "../../mixer/mixer.h" -#elif defined(__3DS__) - #include - #include - #include #else #include #include diff --git a/kula3D/src/utils.h b/kula3D/src/utils.h index 98d3e54..fd69156 100644 --- a/kula3D/src/utils.h +++ b/kula3D/src/utils.h @@ -1,7 +1,7 @@ #ifndef UTILS_H #define UTILS_H -#if defined(NXDK) || defined(__3DS__) +#if defined(NXDK) #include #include #else diff --git a/kulatwo/Makefile.wasm b/kulatwo/Makefile.wasm new file mode 100644 index 0000000..9e939a6 --- /dev/null +++ b/kulatwo/Makefile.wasm @@ -0,0 +1,52 @@ +# constants +CC = emcc +CFLAGS = -Wall -fms-extensions -O2 \ + -sUSE_SDL=2 \ + -sUSE_SDL_IMAGE=2 \ + -sSDL2_IMAGE_FORMATS=png \ + -sUSE_SDL_MIXER=2 \ + -sSDL2_MIXER_FORMATS=mp3,ogg \ + -sUSE_SDL_TTF=2 \ + -sUSE_FREETYPE=1 +LDFLAGS = $(CFLAGS) \ + -sALLOW_MEMORY_GROWTH=1 \ + --use-preload-plugins \ + --preload-file $(ASSETS_DIR)@/assets \ + --shell-file ../web/shell.html \ + -lm + +SRC_DIR = src +ASSETS_DIR = assets +BUILD_DIR = ../build/kulatwo +export EM_CACHE ?= $(abspath ../build/.emcache) + +SOURCES = $(wildcard $(SRC_DIR)/*.c) +HEADERS = $(wildcard $(SRC_DIR)/*.h) +OBJECTS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.wasm.o,$(SOURCES)) + +EXECUTABLE = index.html + +# phony +.PHONY: all clean distclean run + +# targets +all: $(BUILD_DIR)/$(EXECUTABLE) + +clean: + $(RM) -r $(BUILD_DIR) + +distclean: clean + $(RM) -r $(ASSETS_DIR) + +run: $(BUILD_DIR)/$(EXECUTABLE) + emrun $< + +# rules +$(BUILD_DIR)/$(EXECUTABLE): $(OBJECTS) | $(BUILD_DIR) + $(CC) $(OBJECTS) $(LDFLAGS) -o $@ + +$(BUILD_DIR)/%.wasm.o: $(SRC_DIR)/%.c | $(HEADERS) $(BUILD_DIR) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR): + mkdir -p $@ diff --git a/kulatwo/src/constants.h b/kulatwo/src/constants.h index 19cbd04..b859704 100644 --- a/kulatwo/src/constants.h +++ b/kulatwo/src/constants.h @@ -17,11 +17,6 @@ #define BALL_PATH "/dev_hdd0/game/KULA00002/USRDIR/assets/drakt1.png" #define FONT_PATH "/dev_hdd0/game/KULA00002/USRDIR/assets/skrifttype.ttf" #define MUSIC_PATH "/dev_hdd0/game/KULA00002/USRDIR/assets/mortietunes.mp3" -#elif defined(__3DS__) - #define BACKGROUND_PATH "romfs:/blue_sky.png" - #define BALL_PATH "romfs:/drakt1.png" - #define FONT_PATH "romfs:/skrifttype.ttf" - #define MUSIC_PATH "romfs:/mortietunes.mp3" #else #define BACKGROUND_PATH "assets/blue_sky.png" #define BALL_PATH "assets/drakt1.png" diff --git a/kulatwo/src/main.c b/kulatwo/src/main.c index 86efa46..86baf74 100644 --- a/kulatwo/src/main.c +++ b/kulatwo/src/main.c @@ -8,11 +8,6 @@ #include #include "../../mixer/mixer.h" -#elif defined(__3DS__) - #include - #include - #include - #include #else #include #include @@ -20,6 +15,8 @@ #include #endif +#include + #include #include #include @@ -29,6 +26,23 @@ #include "structs.h" #include "utils.h" +struct App { + SDL_Window* window; + SDL_Renderer* renderer; + SDL_GameController* controller; + + GameState state; + GameAssets assets; + + bool loop; + bool audioStarted; + + int screenWidth; + int screenHeight; +}; + +typedef struct App App; + void GameLogic(GameState* state) { if (state->controls & 1 << 0) { if (state->paddle.rect.x + (state->paddle.rect.w / 2) > 0) { @@ -111,41 +125,8 @@ void GameRender(SDL_Renderer* renderer, GameState* state, GameAssets* assets) { RenderScore(renderer, assets->font, state->score); } -int main(int argc, char* argv[]) { - #if defined(NXDK) - XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); - #endif - - SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER); - IMG_Init(0); - TTF_Init(); - Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048); - - srand(time(NULL)); - - SDL_Window* window = SDL_CreateWindow( - WINDOW_TITLE, - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - #if defined(__wii__) || defined(NXDK) - 640, 480, - #elif defined(__vita__) - 960, 544, - #elif defined(PSP) - 480, 272, - #elif defined(__PPU__) - 1280, 720, - #elif defined(__3DS__) - 400, 240, - #else - GAME_WIDTH, GAME_HEIGHT, - #endif - SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE - ); - SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); - SDL_GameController* controller = NULL; - SDL_Event event; - - GameState state = { +static GameState GameStateCreate(void) { + return (GameState) { .score = 0, .paddle = { @@ -179,139 +160,143 @@ int main(int argc, char* argv[]) { .controls = 0 }; - GameAssets assets = { +} + +static GameAssets GameAssetsLoad(SDL_Renderer* renderer) { + return (GameAssets) { .background = IMG_LoadTexture(renderer, BACKGROUND_PATH), .music = Mix_LoadMUS(MUSIC_PATH), .font = TTF_OpenFont(FONT_PATH, SCORE_SIZE), .ball = IMG_LoadTexture(renderer, BALL_PATH) }; +} - bool loop = true; - - int screenWidth; - int screenHeight; +static void AppUpdateRenderScale(App* app, int width, int height) { + app->screenWidth = width; + app->screenHeight = height; - SDL_GetWindowSize(window, &screenWidth, &screenHeight); - SDL_RenderSetScale(renderer, - (float)screenWidth / GAME_WIDTH, - (float)screenHeight / GAME_HEIGHT + SDL_RenderSetScale( + app->renderer, + (float)width / GAME_WIDTH, + (float)height / GAME_HEIGHT ); +} - #if defined(__wii__) - SDL_ShowCursor(SDL_DISABLE); - #endif - - Mix_PlayMusic(assets.music, -1); +static void AppStartMusic(App* app) { + if (app->audioStarted || app->assets.music == NULL) { + return; + } - while (loop) { - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_QUIT: - loop = false; break; + Mix_PlayMusic(app->assets.music, -1); + app->audioStarted = true; +} - case SDL_WINDOWEVENT: - if (event.window.event == SDL_WINDOWEVENT_RESIZED) { - screenWidth = event.window.data1; - screenHeight = event.window.data2; +static void AppHandleEvent(App* app, const SDL_Event* event) { + switch (event->type) { + case SDL_QUIT: + app->loop = false; break; - SDL_RenderSetScale(renderer, - (float)screenWidth / GAME_WIDTH, - (float)screenHeight / GAME_HEIGHT - ); - } + case SDL_WINDOWEVENT: + if (event->window.event == SDL_WINDOWEVENT_RESIZED) { + AppUpdateRenderScale(app, event->window.data1, event->window.data2); + } - break; + break; - case SDL_KEYDOWN: - if (event.key.repeat) break; + case SDL_KEYDOWN: + if (event->key.repeat) break; - switch (event.key.keysym.scancode) { - case SDL_SCANCODE_LEFT: - state.controls |= 1 << 0; break; - case SDL_SCANCODE_RIGHT: - state.controls |= 1 << 1; break; - default: - break; - } + AppStartMusic(app); + switch (event->key.keysym.scancode) { + case SDL_SCANCODE_LEFT: + app->state.controls |= 1 << 0; break; + case SDL_SCANCODE_RIGHT: + app->state.controls |= 1 << 1; break; + default: break; + } - case SDL_KEYUP: - switch (event.key.keysym.scancode) { - case SDL_SCANCODE_LEFT: - state.controls &= ~(1 << 0); break; - case SDL_SCANCODE_RIGHT: - state.controls &= ~(1 << 1); break; - default: - break; - } + break; + case SDL_KEYUP: + switch (event->key.keysym.scancode) { + case SDL_SCANCODE_LEFT: + app->state.controls &= ~(1 << 0); break; + case SDL_SCANCODE_RIGHT: + app->state.controls &= ~(1 << 1); break; + default: break; + } - case SDL_MOUSEMOTION: - state.paddle.rect.x = (event.motion.x / (float)screenWidth * GAME_WIDTH) - (state.paddle.rect.w / 2); break; + break; - case SDL_CONTROLLERDEVICEADDED: - if (controller == NULL) { - controller = SDL_GameControllerOpen(event.cdevice.which); - } + case SDL_MOUSEBUTTONDOWN: + AppStartMusic(app); + break; - break; + case SDL_MOUSEMOTION: + app->state.paddle.rect.x = (event->motion.x / (float)app->screenWidth * GAME_WIDTH) - (app->state.paddle.rect.w / 2); break; - case SDL_CONTROLLERDEVICEREMOVED: - if (SDL_GameControllerFromInstanceID(event.cdevice.which) == controller) { - SDL_GameControllerClose(controller); controller = NULL; - } + case SDL_CONTROLLERDEVICEADDED: + if (app->controller == NULL) { + app->controller = SDL_GameControllerOpen(event->cdevice.which); + } - break; + break; - case SDL_CONTROLLERBUTTONDOWN: - switch (event.cbutton.button) { - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - state.controls |= 1 << 0; break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - state.controls |= 1 << 1; break; - case SDL_CONTROLLER_BUTTON_BACK: - loop = false; break; - } + case SDL_CONTROLLERDEVICEREMOVED: + if (SDL_GameControllerFromInstanceID(event->cdevice.which) == app->controller) { + SDL_GameControllerClose(app->controller); + app->controller = NULL; + } - break; + break; - case SDL_CONTROLLERBUTTONUP: - switch (event.cbutton.button) { - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - state.controls &= ~(1 << 0); break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - state.controls &= ~(1 << 1); break; - } + case SDL_CONTROLLERBUTTONDOWN: + AppStartMusic(app); - break; + switch (event->cbutton.button) { + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + app->state.controls |= 1 << 0; break; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + app->state.controls |= 1 << 1; break; + case SDL_CONTROLLER_BUTTON_BACK: + app->loop = false; break; + } - case SDL_FINGERDOWN: - case SDL_FINGERMOTION: - case SDL_FINGERUP: - state.paddle.rect.x = (event.tfinger.x * GAME_WIDTH) - (state.paddle.rect.w / 2); break; + break; + + case SDL_CONTROLLERBUTTONUP: + switch (event->cbutton.button) { + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + app->state.controls &= ~(1 << 0); break; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + app->state.controls &= ~(1 << 1); break; } - } - SDL_RenderClear(renderer); + break; - GameLogic(&state); - GameRender(renderer, &state, &assets); + case SDL_FINGERDOWN: + AppStartMusic(app); + app->state.paddle.rect.x = (event->tfinger.x * GAME_WIDTH) - (app->state.paddle.rect.w / 2); break; - SDL_RenderPresent(renderer); - SDL_Delay(1000 / FPS); + case SDL_FINGERMOTION: + case SDL_FINGERUP: + app->state.paddle.rect.x = (event->tfinger.x * GAME_WIDTH) - (app->state.paddle.rect.w / 2); break; } +} - SDL_DestroyTexture(assets.background); - Mix_FreeMusic(assets.music); - TTF_CloseFont(assets.font); - SDL_DestroyTexture(assets.ball); +static void AppShutdown(App* app) { + SDL_DestroyTexture(app->assets.background); + Mix_FreeMusic(app->assets.music); + TTF_CloseFont(app->assets.font); + SDL_DestroyTexture(app->assets.ball); - if (controller != NULL) SDL_GameControllerClose(controller); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); + if (app->controller != NULL) SDL_GameControllerClose(app->controller); + SDL_DestroyRenderer(app->renderer); + SDL_DestroyWindow(app->window); Mix_CloseAudio(); Mix_Quit(); @@ -319,6 +304,81 @@ int main(int argc, char* argv[]) { TTF_Quit(); IMG_Quit(); SDL_Quit(); +} + +static void AppTick(void* userdata) { + App* app = userdata; + SDL_Event event; + + while (SDL_PollEvent(&event)) { + AppHandleEvent(app, &event); + } + + if (!app->loop) { + emscripten_cancel_main_loop(); + AppShutdown(app); + + return; + } + + SDL_RenderClear(app->renderer); + + GameLogic(&app->state); + GameRender(app->renderer, &app->state, &app->assets); + + SDL_RenderPresent(app->renderer); +} + +int main(int argc, char* argv[]) { + #if defined(NXDK) + XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); + #endif + + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER); + IMG_Init(0); + TTF_Init(); + Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048); + + srand(time(NULL)); + + SDL_Window* window = SDL_CreateWindow( + WINDOW_TITLE, + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + #if defined(__wii__) || defined(NXDK) + 640, 480, + #elif defined(__vita__) + 960, 544, + #elif defined(PSP) + 480, 272, + #elif defined(__PPU__) + 1280, 720, + #else + GAME_WIDTH, GAME_HEIGHT, + #endif + SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE + ); + SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); + + App app = { + .window = window, + .renderer = renderer, + .controller = NULL, + .state = GameStateCreate(), + .assets = GameAssetsLoad(renderer), + .loop = true, + .audioStarted = false, + .screenWidth = 0, + .screenHeight = 0 + }; + + SDL_GetWindowSize(window, &app.screenWidth, &app.screenHeight); + AppUpdateRenderScale(&app, app.screenWidth, app.screenHeight); + + #if defined(__wii__) + SDL_ShowCursor(SDL_DISABLE); + #endif + + emscripten_set_main_loop_arg(AppTick, &app, FPS, true); return 0; -} \ No newline at end of file +} diff --git a/kulatwo/src/structs.h b/kulatwo/src/structs.h index adbe890..8af5dfb 100644 --- a/kulatwo/src/structs.h +++ b/kulatwo/src/structs.h @@ -6,10 +6,6 @@ #include #include "../../mixer/mixer.h" -#elif defined(__3DS__) - #include - #include - #include #else #include #include diff --git a/kulatwo/src/utils.h b/kulatwo/src/utils.h index 61d3542..15429fb 100644 --- a/kulatwo/src/utils.h +++ b/kulatwo/src/utils.h @@ -1,7 +1,7 @@ #ifndef UTILS_H #define UTILS_H -#if defined(NXDK) || defined(__3DS__) +#if defined(NXDK) #include #include #else From 1f52d39aaa0a217fb96d972089ae3adebde6beec Mon Sep 17 00:00:00 2001 From: NISZOgen <43617163+niszogen@users.noreply.github.com> Date: Thu, 2 Apr 2026 17:22:45 +0200 Subject: [PATCH 2/2] Update README with Emscripten SDK Added information about Emscripten SDK for WebAssembly builds and browser audio interaction. --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b76b65e..ff16618 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ OpenKula has been ported to and tested on various platforms, with varying levels - [PlayStation Portable](https://github.com/bemxio/OpenKula/tree/psp) (text rendering issues) - [PlayStation Vita](https://github.com/bemxio/OpenKula/tree/vita) - [Xbox](https://github.com/bemxio/OpenKula/tree/xbox) (major performance issues) +- [WASM](https://github.com/bemxio/OpenKula/tree/wasm)