Saya memutuskan untuk mencuba menggunakan Golang pada PSP dan meneroka beberapa pendekatan, termasuk mengalihkan Clang, menggunakan TinyGo dan menyusun Golang ke JavaScript dengan GopherJS. Kemudian, saya terjumpa pengguna bernama aethiopicuschan pada PSP homebrew Discord, yang mencuba matlamat yang sama menggunakan WebAssembly. Contoh beliau berfungsi pada PPSSPP tetapi bukan pada perkakasan sebenar.
Apa pun, saya terpaksa menangguhkan projek saya kerana peperiksaan akan datang. Tetapi, beberapa bulan kemudian, saya menemui artikel di mana aethiopicuschan berjaya menyusun Golang ke WASM dan menjalankannya pada PSP menggunakan penterjemah WASM.
Pendekatannya menggunakan penterjemah Wasm yang dipanggil Wasm3 untuk menjalankan kod, tetapi saya tahu saya boleh melakukan yang lebih baik. Saya tahu tentang projek seperti Wasm2C yang menukar binari Wasm anda kepada C.
Teruja, saya mendalami topik ini dan menemui artikel tentang menyusun WebAssembly kepada kod C mudah alih. Mereka menggunakan pengkompil dipanggil w2c2, yang saya rasa adalah sekuelnya.
Selepas berjam-jam bermain-main dengan CMake, saya berjaya mencipta contoh yang berkesan menggunakan TinyGo dan menyasarkan WASI. Saya juga membungkus fungsi raylib, InitWindow (psp mempunyai port raylib), dengan matlamat mengalihkan pengikatan raylib-go ke platform WASM-to-C ini. Contoh berjaya mengikat fungsi C InitWindow kepada kod WASM yang disusun.
Seperti yang anda lihat, ia kelihatan seperti mana-mana kod golang lain
package main import "time" import rl "github.com/gen2brain/raylib-go/raylib" func main() { rl.InitWindow(480, 272, "Psp test") for { time.Sleep(time.Millisecond * 16) } }
tetapi dalam pakej rl, kami mengimport fungsi C, kami memberikannya tandatangan fungsi juga. Ingatlah.
package rl //go:wasmimport rl InitWindow func c_InitWindow(width int32, height int32, title string) // InitWindow - Initialize Window and OpenGL Graphics func InitWindow(width int32, height int32, title string) { c_InitWindow(width, height, title) }
mari pecahkan kod ini langkah demi langkah.
#define __GLIBC_USE #include <raylib.h> #include <stdio.h> #include <time.h> #include <pspkernel.h> PSP_MODULE_INFO("WasiExample", 0, 1, 0); PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER); #include "pspdebug.h" #define printf pspDebugScreenPrintf
di sini kami mengimport apl modul yang disusun.h
kami juga mengimport "runtime" wasi yang disediakan oleh w2c2
// // the compiled wasm -> C code #include "app.h" // // wasi runtime #include "w2c2_base.h" #include "wasi.h" extern wasmMemory* e_memory; // the WASM memory. void trap(Trap trap) { fprintf(stderr, "TRAP: %s\n", trapDescription(trap)); abort(); } wasmMemory* wasiMemory(void* instance) { return app_memory((appInstance*)instance); } extern char** environ;
Fungsi perangkap ialah plat dandang,
fungsi wasiMemory ialah fungsi pembantu yang saya buat untuk fungsi pembantu yang lain
char* getCStringFromMemory(void* memoryptr, U32 offset, U32 length) { wasmMemory* memory = wasiMemory(memoryptr); char* str = (char*)(memory->data + offset); char* result = (char*)malloc( length + 1); // Allocate space for the string + null terminator if (result == NULL) { fprintf(stderr, "Memory allocation failed\n"); return NULL; } // Copy the string from WASI memory to local memory for (U32 i = 0; i < length; ++i) { result[i] = str[i]; } result[length] = '<pre class="brush:php;toolbar:false">void rl__InitWindow( void* memoryptr, U32 width, U32 height, U32 offset, U32 length) { char* title = getCStringFromMemory(memoryptr, offset, length); InitWindow(width, height, title); bool ready = IsWindowReady(); if (ready) { // this will print to the psp screen. printf("Window was created"); } }
ini ialah fungsi C yang kami panggil dari kod golang kami, saya terpaksa mentakrifkannya sendiri.
int main(int argc, char* argv[]) { pspDebugScreenInit(); appInstance i; appInstantiate(&i, NULL); if (!wasiInit(argc, argv, environ)) { fprintf(stderr, "failed to initialize WASI\n"); return 1; } app__start(&i); appFreeInstance(&i); return 0; }
kami sedang membaca args yang dilalui oleh wasm yang ditranspilkan, dan menyampaikannya kepada raylib.
ini adalah beberapa lagi boilerplate, yang kami lakukan hanyalah menjalankan fungsi utama kod golang, yang dieksport sebagai app_start()
Ini ialah tangkapan skrin psp ?emulator?.
tetapi ia juga berfungsi pada perkakasan asal.
Tinggalkan sebarang soalan di ruangan komen!
Atas ialah kandungan terperinci Golang pada PSP (dan bahasa lain). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!