🎮
Wasm3 + TinyGo on PSP!
本題
以前 PSP上でWASMを実行するデモ という記事を書きましたが、これはエミュレータでは動きますが実機では以下のようなエラーになってしまうという問題がありました。
これについていろいろと試しましたが解決しないため、別のアプローチを取ったところ、うまくいきました。今回はそれに関する記事です。
先に成果物からお見せしますと、以下のコードをTinyGoでWASMにして、C言語 + Wasm3で作ったランタイムで実行しました。
package main
import "unsafe"
//go:wasmimport debug println
func println(ptr unsafe.Pointer, len int32)
//export start
func start() {
main()
}
func main() {
message := "Hello, WebAssembly, from Golang!"
println(unsafe.Pointer(unsafe.StringData(message)), int32(len(message)))
}
実機での動作は以下のようになっています。
しっかりと出力できていますね。
ランタイム側では以下のように定義しています。
#define printf pspDebugScreenPrintf
static const void* host_debug_println(IM3Runtime runtime, IM3ImportContext ctx, uint64_t *stack, void *mem)
{
uint32_t ptr = (uint32_t) stack[0];
uint32_t length = (uint32_t) stack[1];
uint8_t* bytes = (uint8_t*)mem + ptr;
char buffer[256];
if (length >= sizeof(buffer)) {
length = sizeof(buffer)-1;
}
memcpy(buffer, bytes, length);
buffer[length] = '\0';
printf("%s\n", buffer);
return NULL;
}
今回はデモということでpspDebugScreenPrintf
のみですが、その他の関数も同じようにラップしてWASM側に渡せば、理論上TinyGoでのPSPアプリケーション開発が可能になるはずです。今後はその方向で開発を進めたいと思います。
その他細かいことはGitHubリポジトリを参照してください。
おまけ(1) Wasm3をフォークした
Wasm3をフォークしてPSP向けに改造しました。これを使うと環境構築が多少楽になります。
おまけ(2) ハマったところ
-
Wasm3のクロスコンパイル。ChatGPTのおかげでうまいこといけました。
-
TinyGoに渡す引数。最終的に
tinygo build -o hello.wasm -target=wasm -no-debug main.go
となりましたが、-target=wasi
だとうまくいかないとか-no-debug
が無いとエラーになったりとか模索に模索を重ねました。 -
main関数をラップしてexportすること。
target=wasi
だと_start
という名前でexportしてくれるが、今回のようにtarget=wasm
の場合は一工夫いる。
以上!
Discussion