Maison >développement back-end >Golang >Golang sur PSP (et autres langues)
J'ai décidé d'essayer d'utiliser Golang sur la PSP et j'ai exploré plusieurs approches, notamment le portage de Clang, l'utilisation de TinyGo et la compilation de Golang en JavaScript avec GopherJS. Ensuite, je suis tombé sur un utilisateur nommé aethiopicuschan sur le homebrew Discord PSP, qui tentait le même objectif en utilisant WebAssembly. Son exemple fonctionnait sur PPSSPP mais pas sur le matériel réel.
Quoi qu'il en soit, j'ai dû suspendre mon projet à cause des examens à venir. Mais, quelques mois plus tard, j'ai trouvé un article dans lequel aethiopicuschan avait réussi à compiler Golang en WASM et à l'exécuter sur la PSP à l'aide d'un interpréteur WASM.
Son approche utilisait un interpréteur Wasm appelé Wasm3 pour exécuter le code, mais je savais que je pouvais faire mieux. Je connaissais des projets comme Wasm2C qui convertissent vos binaires Wasm en C.
Enthousiasmé, j'ai approfondi le sujet et découvert un article sur la compilation de WebAssembly en code C portable. Ils ont utilisé un compilateur appelé w2c2, qui, je suppose, est la suite.
Après des heures de bricolage avec CMake, j'ai réussi à créer un exemple fonctionnel en utilisant TinyGo et en ciblant WASI. J'ai également enveloppé une fonction raylib, InitWindow (la psp a d'ailleurs un port raylib), dans le but de porter les liaisons raylib-go sur cette plateforme WASM-to-C. L'exemple lie avec succès la fonction C InitWindow au code WASM compilé.
Comme vous pouvez le voir, cela ressemble à n'importe quel autre code Golang
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) } }
mais dans le package rl, nous importons une fonction C, nous lui donnons également une signature de fonction. Gardez cela à l’esprit.
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) }
Décomposons ce code étape par étape.
#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
ici nous importons le module compilé app.h
nous importons également le "runtime" wasi qui est fourni par 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;
La fonction piège est une plaque chauffante,
la fonction wasiMemory est une fonction d'assistance que j'ai créée pour une autre fonction d'assistance
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"); } }'; // Null-terminate the string return result; }
c'est la fonction C que nous appelons depuis notre code golang, j'ai dû la définir moi-même.
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; }
nous lisons les arguments transmis par le wasm transpilé et les transmettons à Raylib.
c'est encore un passe-partout, tout ce que nous faisons est d'exécuter la fonction principale du code golang, qui est exporté sous app_start()
Ceci est une capture d'écran d'un émulateur PSP.
mais cela fonctionne également sur le matériel d'origine.
Laissez vos questions dans la section commentaires !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!