Open6

Emscripten pthread版DOSBox-xを動かしたい会

okuokuokuoku

JSPIあるしあんまり頑張らなくても良いか

https://v8.dev/blog/jspi

本当はupstreamするくらいまで作り込むつもりだったけど、そもそもJSPI使えばメインスレッドをblockingに書けるので、あと1、2年で不要になる考察で大改造をupstreamするのはちょっと良くないなと思い直した。(Asyncify=2がこれ専用のモードとして用意されている。)

一旦、現状のAsyncify前提のコードを分離して専用のifdefを付けるのが良いかな。このコミットで消したコードが該当する。

https://github.com/okuoku/dosbox-x/commit/5c7763e14be5eef7a64ca5eae41ffe14a38b1940

okuokuokuoku

オーディオサポートを一旦無効化

最初ChromeのAuto play規制で失敗してるのかと思ったけど、

https://developer.chrome.com/blog/autoplay/#web-audio

そもそもEmscriptenはオーディオをサブスレッドで実行できないようだ(Proxyが無い)。また、Emscripten Audio WorkletはJS的なWorkerで動作するのでpthreadから操作できない。

https://emscripten.org/docs/api_reference/wasm_audio_worklets.html

たぶんメインスレッドでオーディオ読み書きをするのが簡単だろう。とりあえず後回しにしてオーディオを無効化した。

https://github.com/okuoku/dosbox-x/commit/827fc5febb2305cd109e2af4fd638004fa5320e0

okuokuokuoku

COEPするWebサーバを用意する

Emscriptenのpthreadは動作に SharedArrayBuffer が必要なので適当にCOEPのhttpヘッダを設定する。

#!/usr/bin/env python3
from http import server # Python 3

class TheHandler(server.SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_my_headers()
        server.SimpleHTTPRequestHandler.end_headers(self)

    def send_my_headers(self):
        self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
        self.send_header("Cross-Origin-Opener-Policy", "same-origin")


server.test(HandlerClass=TheHandler, port=3000)

https://github.com/okuoku/dosbox-x/commit/b972c754096ec68fcaa62224b8b0a950b41aade6

coi-serviceworker とか組込むべきなのかねぇ。。(というか、これでワークアラウンドできちゃったらあんまり意味なくない。。?)

https://github.com/gzuidhof/coi-serviceworker

とりあえずHTTPサーバをローカルに立てて、あとはngrokで。

https://zenn.dev/okuoku/scraps/aea5d27efc94a7

ssh -R 443:localhost:3000 tunnel.jp.ngrok.com http
okuokuokuoku

クリック位置がズレる

window.devicePixelRatio != 1 の環境に対応していない。 ...一応DOSBox-xはhigh DPI awareなのでそちらを利用するように修正するのが良いだろう。

https://emscripten.org/docs/api_reference/emscripten.h.html#c.emscripten_get_device_pixel_ratio

Emscriptenは emscripten_get_device_pixel_ratio を提供している。

DPI関連が真面目に実装されるのはSDL3を待った方が良いんだろうか。。?ひとまず後回し。

okuokuokuoku

そこそこ動いた

まだ音が鳴らないけど。

ファイルシステムの投入

$EMSDK/upstream/emscripten/tools/file_packager pack.data --preload ./data@/data --js-output=data.js

こういう感じで data.js を作り、本体よりも前に <script> で読めばOK。

https://github.com/okuoku/dosbox-x/blob/6671c842fe73a42518c03e7931e309968ef11c50/html/shell.html#L1295-L1302

ついでにコマンドラインオプションも書いたけど、 callMain に渡さないといけないのが盲点だった。

https://github.com/okuoku/dosbox-x/blob/748b27f0883a9457e10f2bf5b6d6e53dd81b9078/html/shell.html#L1203