Skip to content

Commit ce84578

Browse files
committed
working on actions
1 parent 277a4da commit ce84578

File tree

11 files changed

+172
-11
lines changed

11 files changed

+172
-11
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
.DS_Store
22
.vscode
33
build
4-
*.null0
5-
*.wasm

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ function (BUILD_CART_C name cart_dir)
1414
target_include_directories(${name}_c_wasm PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/c")
1515
add_custom_target(${name} ALL
1616
COMMAND ${CMAKE_COMMAND} -E make_directory "${CART_TEMP}"
17+
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_SOURCE_DIR}/webroot/"
1718
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:${name}_c_wasm>" "${CART_TEMP}/main.wasm"
1819
COMMAND ${CMAKE_COMMAND} -E copy_directory "${cart_dir}" "${CART_TEMP}"
1920
COMMAND ${CMAKE_COMMAND} -E rm -f "${CART_TEMP}/*.c"
2021
COMMAND ${CMAKE_COMMAND} -E rm -f "${CART_TEMP}/*.h"
2122
COMMAND ${CMAKE_COMMAND} -E chdir "${CART_TEMP}" ${CMAKE_COMMAND} -E tar "cf" "${CMAKE_CURRENT_BINARY_DIR}/${name}.null0" --format=zip .
2223
COMMAND ${CMAKE_COMMAND} -E rm -rf "${CART_TEMP}"
23-
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${name}.null0" "${CMAKE_CURRENT_SOURCE_DIR}"
24+
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${name}.null0" "${CMAKE_CURRENT_SOURCE_DIR}/webroot/"
2425
DEPENDS ${name}_c_wasm
2526
COMMENT "Creating cart ${name}.null0"
2627
)

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ Then you can do this:
2222
```sh
2323
$WASI_SDK_PATH/bin/clang src/main.c -o src/main.wasm
2424
cd src
25-
zip -r ../mygame.null0 . -x '*.h' '*.c'
25+
zip -r ../webroot/mygame.null0 . -x '*.h' '*.c'
2626
```
2727

2828
You can also use cmake (recommended) to build a complete cart:
2929
src/
3030

3131
```sh
32-
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake -DCMAKE_BUILD_TYPE=Release
32+
cmake -B build -DCMAKE_TOOLCHAIN_FILE="${WASI_SDK_PATH}/share/cmake/wasi-sdk.cmake" -DCMAKE_BUILD_TYPE=Release
3333
cmake --build build
3434
```

webroot/favicon.ico

15 KB
Binary file not shown.

webroot/fflatefs.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// stupidly-minimal fs that uses fflate on the zip
2+
// it's just enough to load js carts, and read files, but not much else
3+
4+
import * as fflate from 'fflate' // https://esm.sh/fflate/esm/browser.js
5+
6+
const FILETYPE_REGULAR_FILE = 4
7+
const FILETYPE_DIRECTORY = 3
8+
9+
export default async function fflatefs(cartUrl) {
10+
const info = {}
11+
let ino = 4
12+
13+
const data = fflate.unzipSync(new Uint8Array(await fetch(cartUrl).then((r) => r.arrayBuffer())), {
14+
filter: (file) => {
15+
if (file.name != 'main.wasm' && !file.name.endsWith('.DS_Store')) {
16+
info[file.name] = file
17+
info[file.name].type = file.name.endsWith('/') ? FILETYPE_DIRECTORY : FILETYPE_REGULAR_FILE
18+
info[file.name].ino = ino++
19+
return true
20+
}
21+
}
22+
})
23+
24+
return {
25+
info,
26+
data,
27+
28+
statSync(path, options = {}) {
29+
const p = path.replace(/^\//g, '')
30+
const i = info[p]
31+
const now = Math.floor(Date.now() / 1000)
32+
33+
return {
34+
isFile: () => i?.type === FILETYPE_REGULAR_FILE,
35+
isDirectory: () => i?.type === FILETYPE_DIRECTORY,
36+
isSymbolicLink: () => false,
37+
isCharacterDevice: () => false,
38+
isBlockDevice: () => false,
39+
isFIFO: () => false,
40+
dev: 4,
41+
ino: i?.ino || 0,
42+
filetype: i?.type || 0,
43+
nlink: 0,
44+
size: i?.originalSize || 0,
45+
atimeMs: now,
46+
mtimeMs: now,
47+
ctimeMs: now
48+
}
49+
},
50+
51+
readFileSync(path) {
52+
const p = path.replace(/^\//g, '')
53+
return data[p]
54+
}
55+
}
56+
}

webroot/index.html

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
1-
<head>
2-
<title>null0</title>
3-
</head>
4-
<body>
5-
NULL0 cart here.
6-
</body>
1+
<html>
2+
<head>
3+
<title>null0</title>
4+
<script type="importmap">
5+
{
6+
"imports": {
7+
"@easywasm/wasi": "https://esm.sh/@easywasm/wasi",
8+
"fflate": "https://esm.sh/fflate/esm/browser.js"
9+
}
10+
}
11+
</script>
12+
<script type="module" src="null0-cart.js"></script>
13+
</head>
14+
<body>
15+
<null0-cart src="carts/c/mygame.null0"></null0-cart>
16+
</body>
17+
</body>
18+
</html>

webroot/mygame.null0

15.6 KB
Binary file not shown.

webroot/null0-cart.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// simpler web-component
2+
3+
import loadCart from './null0.js'
4+
5+
class Null0Cart extends HTMLElement {
6+
static get observedAttributes() {
7+
return ['src']
8+
}
9+
10+
constructor() {
11+
super()
12+
const shadow = this.attachShadow({ mode: 'open' })
13+
this.canvas = document.createElement('canvas')
14+
shadow.appendChild(this.canvas)
15+
}
16+
17+
connectedCallback() {}
18+
disconnectedCallback() {}
19+
20+
attributeChangedCallback(name, oldValue, newValue) {
21+
if (name === 'src') {
22+
loadCart(newValue, this.canvas).then((cart) => {
23+
this.cart = cart
24+
})
25+
}
26+
}
27+
}
28+
29+
customElements.define('null0-cart', Null0Cart)

webroot/null0.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import WasiPreview1 from '@easywasm/wasi'
2+
import fflatefs from './fflatefs.js'
3+
4+
// this is output from emscripten
5+
import loadHost from './wbuild/host/null0.mjs'
6+
7+
const debug = false
8+
9+
export default async function loadCart(cartUrl, canvas) {
10+
const cartName = cartUrl.split('/').pop()
11+
const fs = await fflatefs(cartUrl)
12+
13+
return await loadHost({
14+
canvas,
15+
arguments: [cartName],
16+
preRun(h) {
17+
h.FS.createPreloadedFile('', cartName, cartUrl, true, false)
18+
19+
// this is called at startup by emscripten-code
20+
h.cart_callback_init = (wasmBytesPtr, wasmSize) => {
21+
const wasmBytes = h.HEAPU8.subarray(wasmBytesPtr, wasmBytesPtr + wasmSize)
22+
23+
const wasi_snapshot_preview1 = new WasiPreview1({ fs })
24+
const imports = { wasi_snapshot_preview1, null0: {} }
25+
26+
// expose host-functions that are named _host_whatever as null0.whatever
27+
for (const f of Object.keys(h)) {
28+
if (f.startsWith('_host_')) {
29+
const func = f.replace(/^_host_/, '')
30+
imports.null0[func] = (...args) => {
31+
if (debug) {
32+
console.log(func, args)
33+
}
34+
return h[f](...args)
35+
}
36+
}
37+
}
38+
39+
WebAssembly.instantiate(wasmBytes, imports).then(({ instance }) => {
40+
h.cart = instance.exports
41+
fs.wasm = h
42+
wasi_snapshot_preview1.start(h.cart)
43+
if (h.cart.load) {
44+
h.cart.load()
45+
}
46+
})
47+
return true
48+
}
49+
}
50+
})
51+
}

webroot/wbuild/host/null0.mjs

Lines changed: 14 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)