Skip to content

Commit

Permalink
feat: Emscripten build
Browse files Browse the repository at this point in the history
Related #112
  • Loading branch information
carstene1ns committed Sep 19, 2024
1 parent efb7440 commit aabc4c6
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 1 deletion.
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,40 @@ jobs:
name: openjazz-windows-mingw-x86_64
path: OJ-*/

web-emscripten:
name: Build (Emscripten)
needs: prepare
runs-on: emscripten/emsdk
steps:
- name: Install dependencies
run: |
sudo apt-get update -yqq
sudo apt-get install -yqq build-essential cmake ninja-build \
asciidoctor w3m
- name: Checkout
uses: actions/checkout@v4

- name: Build OpenJazz
run: |
emcmake cmake --workflow --preset release -DDATAPATH=/data -DNETWORK=OFF
touch build-release/data.js # dummy data
ls -l build-release
- name: Prepare artifact
env:
OJ_VERSION: ${{ needs.prepare.outputs.oj_version }}
run: |
mkdir OJ-${OJ_VERSION}
builds/ci/adoc2txt ${OJ_VERSION} < res/unix/OpenJazz.6.adoc > OJ-${OJ_VERSION}/Manual.txt
cp build-release/*.{wasm,js,html,data} README.md COPYING licenses.txt OJ-${OJ_VERSION}/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: openjazz-web
path: OJ-*/

nintendo-devkitpro:
strategy:
fail-fast: false
Expand Down
17 changes: 16 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,12 @@ endif()

# libraries

if(LEGACY_SDL)
if(EMSCRIPTEN)
# emscripten ships a "port" of SDL2
set(OJ_LIBS_SDL "SDL2")
set(SDL_STATUS "SDL2 (emscripten port)")
target_compile_options(OpenJazz PRIVATE "--use-port=sdl2;-flto;-fexceptions")
elseif(LEGACY_SDL)
find_package(SDL REQUIRED)
target_include_directories(OpenJazz PRIVATE ${SDL_INCLUDE_DIR})
set(OJ_LIBS_SDL ${SDL_LIBRARY})
Expand Down Expand Up @@ -260,6 +265,16 @@ if(WIN32)
set_target_properties(OpenJazz PROPERTIES WIN32_EXECUTABLE $<$<NOT:$<CONFIG:Debug>>:TRUE>)
# add icon
target_sources(OpenJazz PRIVATE res/windows/OpenJazz.rc)
elseif(EMSCRIPTEN)
set_target_properties(OpenJazz PROPERTIES SUFFIX ".html")
set(JS_SHELL "${CMAKE_CURRENT_SOURCE_DIR}/res/emscripten/shell.html")

set_property(TARGET OpenJazz PROPERTY LINK_FLAGS
"--shell-file ${JS_SHELL} -sMINIFY_HTML=0 -flto --use-port=sdl2
-sFORCE_FILESYSTEM -sEXIT_RUNTIME=1 -sASYNCIFY
-sENVIRONMENT=web --closure 1 -sEXPORTED_RUNTIME_METHODS=['allocate']
-sASSERTIONS -sNO_DISABLE_EXCEPTION_CATCHING")
set_source_files_properties("src/main.cpp" PROPERTIES OBJECT_DEPENDS "${JS_SHELL}")
elseif(RISCOS)
target_sources(OpenJazz PRIVATE
src/platforms/riscos.cpp
Expand Down
4 changes: 4 additions & 0 deletions builds/cmake/Platform-Helpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ elseif(HAIKU)
list(APPEND PLATFORM_LIST ${OJ_HOST})
elseif(WIN32)
set(OJ_LIBS_NET "-lws2_32")
elseif(EMSCRIPTEN)
add_compile_definitions(EMSCRIPTEN)
set(OJ_HOST "Web")
set(OJ_ALLOW_SCALE OFF)
elseif(PSP)
set(OJ_HOST "PSP")
set(OJ_ALLOW_SCALE OFF)
Expand Down
162 changes: 162 additions & 0 deletions res/emscripten/shell.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>OpenJazz</title>
<style>
body {
font-family: arial;
margin: 0;
padding: none;
background-color: rgb(23, 23, 123);
}

.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas.emscripten { border: 0px none; background-color: black; }

.spinner {
height: 30px;
width: 30px;
margin: 0;
margin-top: 20px;
margin-left: 20px;
display: inline-block;
vertical-align: top;

-webkit-animation: rotation .8s linear infinite;
-moz-animation: rotation .8s linear infinite;
-o-animation: rotation .8s linear infinite;
animation: rotation 0.8s linear infinite;

border-left: 5px solid rgb(235, 235, 235);
border-right: 5px solid rgb(235, 235, 235);
border-bottom: 5px solid rgb(235, 235, 235);
border-top: 5px solid rgb(120, 120, 120);

border-radius: 100%;
background-color: rgb(189, 215, 46);
}

@-webkit-keyframes rotation {
from {-webkit-transform: rotate(0deg);}
to {-webkit-transform: rotate(360deg);}
}
@-moz-keyframes rotation {
from {-moz-transform: rotate(0deg);}
to {-moz-transform: rotate(360deg);}
}
@-o-keyframes rotation {
from {-o-transform: rotate(0deg);}
to {-o-transform: rotate(360deg);}
}
@keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}

#status {
display: inline-block;
vertical-align: top;
margin-top: 30px;
margin-left: 20px;
font-weight: bold;
color: rgb(120, 120, 120);
}

#progress {
height: 20px;
width: 300px;
}

#infobox {
padding: 20px;
background-color: rgb(222, 222, 222);
}
</style>
</head>
<body>
<div class="spinner" id='spinner'></div>
<div class="emscripten" id="status">Downloading...</div>

<div class="emscripten">
<progress value="0" max="100" id="progress" hidden=1></progress>
</div>

<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>

<br> <br>

<div id="infobox">
This is <a href="http://alister.eu/jazz/oj/">OpenJazz</a> powered by <a href="http://emscripten.org">emscripten</a>.
</div>

<script type='text/javascript'>
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
var spinnerElement = document.getElementById('spinner');

var Module = {
print: (function() {
return (...args) => {
var text = args.join(' ');
console.log(text);
};
})(),
canvas: (() => {
var canvas = document.getElementById('canvas');

// As a default initial behavior, pop up an alert when webgl context is lost. To make your
// application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", (e) => { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);

return canvas;
})(),
setStatus: (text) => {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.last.text) return;
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var now = Date.now();
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
Module.setStatus.last.time = now;
Module.setStatus.last.text = text;
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = false;
spinnerElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
if (!text) spinnerElement.style.display = 'none';
}
statusElement.innerHTML = text;
},
totalDependencies: 0,
monitorRunDependencies: (left) => {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
},
onExit: (status) => {
Module.setStatus('OpenJazz has closed. Refresh the browser window to play again.');
}
};
Module.setStatus('Downloading...');
window.onerror = (event) => {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.setStatus('Exception thrown, see JavaScript console');
spinnerElement.style.display = 'none';
Module.setStatus = (text) => {
if (text) console.error('[post-exception status] ' + text);
};
};
</script>
<script async type="text/javascript" src=data.js></script>
{{{ SCRIPT }}}
</body>
</html>
5 changes: 5 additions & 0 deletions src/io/gfx/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@
#define NO_RESIZE

#define FULLSCREEN_FLAGS (SDL_FULLSCREEN | SDL_HWSURFACE)
#elif defined(EMSCRIPTEN)
#define DEFAULT_SCREEN_WIDTH 640
#define DEFAULT_SCREEN_HEIGHT 480

#define FULLSCREEN_FLAGS (SDL_FULLSCREEN | SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWPALETTE)
#else
#define DEFAULT_SCREEN_WIDTH SW
#define DEFAULT_SCREEN_HEIGHT SH
Expand Down
2 changes: 2 additions & 0 deletions src/io/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ void openAudio () {
(SDL_AUDIO_BITSIZE(audioSpec.format) != 8 && SDL_AUDIO_BITSIZE(audioSpec.format) != 16)) {
LOG_DEBUG("SDL audio format unsupported, letting SDL convert it.");

if(audioDevice) SDL_CloseAudioDevice(audioDevice);

audioDevice = SDL_OpenAudioDevice(nullptr, 0, &asDesired, &audioSpec, 0);
}
audioOk = (audioDevice != 0);
Expand Down

0 comments on commit aabc4c6

Please sign in to comment.