首页 > 后端开发 > Golang > PSP(和其他语言)上的 Golang

PSP(和其他语言)上的 Golang

Linda Hamilton
发布: 2025-01-03 12:33:43
原创
1027 人浏览过

我决定尝试在 PSP 上使用 Golang,并探索了多种方法,包括移植 Clang、使用 TinyGo 以及使用 GopherJS 将 Golang 编译为 JavaScript。然后,我在 PSP 自制程序 Discord 上遇到了一位名为 aethiopicuschan 的用户,他正在使用 WebAssembly 尝试实现相同的目标。他的示例在 PPSSPP 上有效,但在实际硬件上无效。

无论如何,由于即将到来的考试,我不得不暂停我的项目。但是,几个月后,我发现一篇文章,aethiopicuschan 成功地将 Golang 编译为 WASM,并使用 WASM 解释器在 PSP 上运行它。
他的方法使用了一个名为 Wasm3 的 Wasm 解释器来运行代码,但我知道我可以做得更好。我知道像 Wasm2C 这样的项目,可以将 Wasm 二进制文件转换为 C。
我很兴奋,更深入地研究了这个主题,并发现了一篇有关将 WebAssembly 编译为可移植 C 代码的文章。他们使用了一个名为 w2c2 的编译器,我猜这是续集。

经过几个小时的修改 CMake,我成功地使用 TinyGo 并针对 WASI 创建了一个工作示例。我还封装了一个 raylib 函数 InitWindow(顺便说一下,psp 有一个 raylib 端口),目的是将 raylib-go 绑定移植到这个 WASM-to-C 平台。该示例成功将 C InitWindow 函数绑定到编译后的 WASM 代码。

如您所见,它看起来与任何其他 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)
    }
}
登录后复制

但是在 rl 包中,我们导入了一个 C 函数,我们也给它一个函数签名。请记住。


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)
}
登录后复制

让我们一步步分解这段代码。

#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

登录后复制

首先我们导入 psp 库,并设置样板,我们还导入 raylib 端口

这里我们导入编译后的模块app.h
我们还导入了 w2c2 提供的 wasi“运行时”

// // 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;

登录后复制

陷阱函数是样板,
wasiMemory 函数是我为另一个辅助函数制作的辅助函数

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; }

这个函数所做的就是获取字符串内存指针的内存指针(在 wasm 中,我们通过传递内存偏移量和字符串的长度来处理字符串),并使用偏移量和长度返回一个 C 字符串

这是我们从 golang 代码中调用的 C 函数,我必须自己定义它。

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;
}
登录后复制

我们正在读取转译的 wasm 传递的参数,并将它们传递给 raylib。


这是更多的样板文件,我们所做的就是运行 golang 代码的 main 函数,该函数导出为 app_start()

Golang on PSP (and other languages)

有用!

这是 psp 模拟器的屏幕截图。
但它也适用于原始硬件。

有任何问题请在评论区留言!

以上是PSP(和其他语言)上的 Golang的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板