diff --git a/Buildscr b/Buildscr index 29d4e56..d9c9a96 100644 --- a/Buildscr +++ b/Buildscr @@ -131,19 +131,28 @@ endif # delegation. ifneq "$(NOJS)" yes then delegate emscripten - in puzzles do emcmake cmake -B build-emscripten -DCMAKE_BUILD_TYPE=Release $(web_unfinished_option) . + in puzzles do emcmake cmake -B build-emscripten $(web_unfinished_option) . in puzzles/build-emscripten do make -j$(nproc) VERBOSE=1 return puzzles/build-emscripten/*.js + return puzzles/build-emscripten/*.wasm return puzzles/build-emscripten/unfinished/group.js + return puzzles/build-emscripten/unfinished/group.wasm enddelegate # Build a set of wrapping HTML pages for easy testing of the - # Javascript puzzles. These aren't quite the same as the versions that - # will go on my live website, because those ones will substitute in a - # different footer, and not have to link to the .js files with the - # ../js/ prefix. But these ones should be good enough to just open - # using a file:// URL in a browser after running a build, and make - # sure the main functionality works. + # Javascript puzzles. + # + # These aren't quite the same as the HTML pages that will go on my + # live website. The live ones will substitute in a different footer + # that links back to the main puzzles page, and they'll have a + # different filesystem layout so that ther links to the .js files + # won't need the ../js/ prefix used below. + # + # But these test pages should be good enough to just open after + # running a build, to make sure the main functionality works. + # Unfortunately, due to some kind of WASM loading restriction, this + # can't be done using a file:// URL; you have to actually point an + # HTTP or HTTPS server at the build output directory. in puzzles do mkdir jstest in puzzles/jstest do ../html/jspage.pl --jspath=../js/ /dev/null ../html/*.html endif @@ -182,7 +191,9 @@ ifneq "$(NOJAVA)" yes then endif ifneq "$(NOJS)" yes then deliver puzzles/build-emscripten/*.js js/$@ + deliver puzzles/build-emscripten/*.wasm js/$@ deliver puzzles/build-emscripten/unfinished/*.js js/$@ + deliver puzzles/build-emscripten/unfinished/*.wasm js/$@ deliver puzzles/jstest/*.html jstest/$@ deliver puzzles/html/*.html html/$@ deliver puzzles/html/*.pl html/$@ diff --git a/cmake/platforms/emscripten.cmake b/cmake/platforms/emscripten.cmake index d923083..89223a5 100644 --- a/cmake/platforms/emscripten.cmake +++ b/cmake/platforms/emscripten.cmake @@ -29,7 +29,9 @@ set(emcc_export_list list(TRANSFORM emcc_export_list PREPEND \") list(TRANSFORM emcc_export_list APPEND \") string(JOIN "," emcc_export_string ${emcc_export_list}) -set(CMAKE_C_LINK_FLAGS "-s ASM_JS=1 -s EXPORTED_FUNCTIONS='[${emcc_export_string}]'") +set(CMAKE_C_LINK_FLAGS "\ +-s EXPORTED_FUNCTIONS='[${emcc_export_string}]' \ +-s EXTRA_EXPORTED_RUNTIME_METHODS='[cwrap,callMain]'") set(build_cli_programs FALSE) diff --git a/emcclib.js b/emcclib.js index 907dc19..c81c576 100644 --- a/emcclib.js +++ b/emcclib.js @@ -23,7 +23,7 @@ mergeInto(LibraryManager.library, { * Unused in production, but handy in development. */ js_debug: function(ptr) { - console.log(Pointer_stringify(ptr)); + console.log(UTF8ToString(ptr)); }, /* @@ -34,7 +34,7 @@ mergeInto(LibraryManager.library, { * in a configuration dialog). */ js_error_box: function(ptr) { - alert(Pointer_stringify(ptr)); + alert(UTF8ToString(ptr)); }, /* @@ -68,7 +68,7 @@ mergeInto(LibraryManager.library, { * clicked. */ js_add_preset: function(menuid, ptr, value) { - var name = Pointer_stringify(ptr); + var name = UTF8ToString(ptr); var item = document.createElement("li"); item.setAttribute("data-index", value); var tick = document.createElement("span"); @@ -96,7 +96,7 @@ mergeInto(LibraryManager.library, { * js_add_preset or this function. */ js_add_preset_submenu: function(menuid, ptr, value) { - var name = Pointer_stringify(ptr); + var name = UTF8ToString(ptr); var item = document.createElement("li"); // We still create a transparent tick element, even though it // won't ever be selected, to make submenu titles line up @@ -167,13 +167,13 @@ mergeInto(LibraryManager.library, { * the random seed permalink. */ js_update_permalinks: function(desc, seed) { - desc = Pointer_stringify(desc); + desc = UTF8ToString(desc); permalink_desc.href = "#" + desc; if (seed == 0) { permalink_seed.style.display = "none"; } else { - seed = Pointer_stringify(seed); + seed = UTF8ToString(seed); permalink_seed.href = "#" + seed; permalink_seed.style.display = "inline"; } @@ -277,7 +277,7 @@ mergeInto(LibraryManager.library, { * Draw a rectangle. */ js_canvas_draw_rect: function(x, y, w, h, colptr) { - ctx.fillStyle = Pointer_stringify(colptr); + ctx.fillStyle = UTF8ToString(colptr); ctx.fillRect(x, y, w, h); }, @@ -314,7 +314,7 @@ mergeInto(LibraryManager.library, { * Postscriptish drawing frameworks). */ js_canvas_draw_line: function(x1, y1, x2, y2, width, colour) { - colour = Pointer_stringify(colour); + colour = UTF8ToString(colour); ctx.beginPath(); ctx.moveTo(x1 + 0.5, y1 + 0.5); @@ -345,13 +345,13 @@ mergeInto(LibraryManager.library, { getValue(pointptr+8*i+4, 'i32') + 0.5); ctx.closePath(); if (fill != 0) { - ctx.fillStyle = Pointer_stringify(fill); + ctx.fillStyle = UTF8ToString(fill); ctx.fill(); } ctx.lineWidth = '1'; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; - ctx.strokeStyle = Pointer_stringify(outline); + ctx.strokeStyle = UTF8ToString(outline); ctx.stroke(); }, @@ -366,13 +366,13 @@ mergeInto(LibraryManager.library, { ctx.beginPath(); ctx.arc(x + 0.5, y + 0.5, r, 0, 2*Math.PI); if (fill != 0) { - ctx.fillStyle = Pointer_stringify(fill); + ctx.fillStyle = UTF8ToString(fill); ctx.fill(); } ctx.lineWidth = '1'; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; - ctx.strokeStyle = Pointer_stringify(outline); + ctx.strokeStyle = UTF8ToString(outline); ctx.stroke(); }, @@ -397,7 +397,7 @@ mergeInto(LibraryManager.library, { * per (font,height) pair. */ js_canvas_find_font_midpoint: function(height, font) { - font = Pointer_stringify(font); + font = UTF8ToString(font); // Reuse cached value if possible if (midpoint_cache[font] !== undefined) @@ -451,12 +451,12 @@ mergeInto(LibraryManager.library, { * function to do it for us with almost no extra effort. */ js_canvas_draw_text: function(x, y, halign, colptr, fontptr, text) { - ctx.font = Pointer_stringify(fontptr); - ctx.fillStyle = Pointer_stringify(colptr); + ctx.font = UTF8ToString(fontptr); + ctx.fillStyle = UTF8ToString(colptr); ctx.textAlign = (halign == 0 ? 'left' : halign == 1 ? 'center' : 'right'); ctx.textBaseline = 'alphabetic'; - ctx.fillText(Pointer_stringify(text), x, y); + ctx.fillText(UTF8ToString(text), x, y); }, /* @@ -542,7 +542,7 @@ mergeInto(LibraryManager.library, { * Set the text in the status bar. */ js_canvas_set_statusbar: function(ptr) { - var text = Pointer_stringify(ptr); + var text = UTF8ToString(ptr); statusbar.replaceChild(document.createTextNode(text), statusbar.lastChild); }, @@ -574,7 +574,7 @@ mergeInto(LibraryManager.library, { * overlay on top of the rest of the puzzle web page. */ js_dialog_init: function(titletext) { - dialog_init(Pointer_stringify(titletext)); + dialog_init(UTF8ToString(titletext)); }, /* @@ -584,10 +584,10 @@ mergeInto(LibraryManager.library, { * construction. */ js_dialog_string: function(index, title, initialtext) { - dlg_form.appendChild(document.createTextNode(Pointer_stringify(title))); + dlg_form.appendChild(document.createTextNode(UTF8ToString(title))); var editbox = document.createElement("input"); editbox.type = "text"; - editbox.value = Pointer_stringify(initialtext); + editbox.value = UTF8ToString(initialtext); dlg_form.appendChild(editbox); dlg_form.appendChild(document.createElement("br")); @@ -607,9 +607,9 @@ mergeInto(LibraryManager.library, { * gives the separator. */ js_dialog_choices: function(index, title, choicelist, initvalue) { - dlg_form.appendChild(document.createTextNode(Pointer_stringify(title))); + dlg_form.appendChild(document.createTextNode(UTF8ToString(title))); var dropdown = document.createElement("select"); - var choicestr = Pointer_stringify(choicelist); + var choicestr = UTF8ToString(choicelist); var items = choicestr.slice(1).split(choicestr[0]); var options = []; for (var i in items) { @@ -653,7 +653,7 @@ mergeInto(LibraryManager.library, { dlg_form.appendChild(checkbox); var checkboxlabel = document.createElement("label"); checkboxlabel.setAttribute("for", checkbox.id); - checkboxlabel.textContent = Pointer_stringify(title); + checkboxlabel.textContent = UTF8ToString(title); dlg_form.appendChild(checkboxlabel); dlg_form.appendChild(document.createElement("br")); diff --git a/emccpre.js b/emccpre.js index 56f6972..1579ead 100644 --- a/emccpre.js +++ b/emccpre.js @@ -486,15 +486,17 @@ function initPuzzle() { } }); - // Run the C setup function, passing argv[1] as the fragment - // identifier (so that permalinks of the form puzzle.html#game-id - // can launch the specified id). - Module.callMain([location.hash]); + Module.onRuntimeInitialized = function() { + // Run the C setup function, passing argv[1] as the fragment + // identifier (so that permalinks of the form puzzle.html#game-id + // can launch the specified id). + Module.callMain([location.hash]); - // And if we get here with everything having gone smoothly, i.e. - // we haven't crashed for one reason or another during setup, then - // it's probably safe to hide the 'sorry, no puzzle here' div and - // show the div containing the actual puzzle. - document.getElementById("apology").style.display = "none"; - document.getElementById("puzzle").style.display = "inline"; + // And if we get here with everything having gone smoothly, i.e. + // we haven't crashed for one reason or another during setup, then + // it's probably safe to hide the 'sorry, no puzzle here' div and + // show the div containing the actual puzzle. + document.getElementById("apology").style.display = "none"; + document.getElementById("puzzle").style.display = "inline"; + }; }