golang实现任天堂Game Boy Color模拟器插件GoBoy的使用

GoBoy - 用Golang实现的任天堂Game Boy Color模拟器插件

概述

GoBoy是一个用Go语言编写的多平台任天堂GameBoy和GameBoy Color模拟器。这个模拟器可以运行大多数GB游戏和一些CGB游戏,支持彩色显示和声音输出。

塞尔达传说:梦之岛DX 精灵宝可梦:金

该程序包含调试功能,对于理解模拟器工作原理和自行开发模拟器很有帮助。这些功能包括:

  • 在每一步将操作码和寄存器值打印到控制台(会显著减慢模拟速度)
  • 单独开关各个声音通道

安装

从源码构建

安装GoBoy到Go二进制目录:

go get github.com/Humpheh/goboy/cmd/goboy

或者使用Go 1.11及以上版本:

git clone https://github.com/Humpheh/goboy.git
cd goboy
go build -o goboy cmd/goboy/main.go

GoBoy兼容MacOS、Windows和Linux。在Windows 10上构建需要MinGW,在Linux上需要安装gtk。

GoBoy使用像素库(pixel)进行控制绑定和图形渲染,需要OpenGL支持。

使用

goboy zelda.gb

控制键:

  • 方向键:← ↑ ↓ →
  • 按键:Z X Enter Backspace
  • 在DMG模式下按"="循环切换调色板
  • 按"F"全屏显示

其他选项:

  -dmg      # 强制设置为DMG模式
  -mute     # 静音输出

调试或实验性选项:

  -cpuprofile string  # 将CPU配置文件写入文件(调试用)
  -disableVsync       # 禁用垂直同步(调试用)
  -stepthrough        # 逐步执行操作码(调试用)
  -unlocked           # 解除CPU速度限制(调试用)

调试

有几个键盘快捷键对调试很有用:

  • Q - 强制切换背景
  • W - 强制切换精灵
  • A - 打印GB背景调色板数据(CGB)
  • S - 打印精灵调色板数据(CGB)
  • D - 将背景地图打印到日志
  • E - 切换将操作码打印到控制台(会减慢执行速度)
  • 7,8,9,0 - 开关声音通道1到4

保存

如果加载的ROM支持电池,会在ROM文件旁边创建一个<rom-name>.sav文件(例如zelda.gb.sav),包含从卡带中导出的RAM数据。程序会在游戏运行时每秒更新这个保存文件。

测试

GoBoy目前通过了Blargg的cpu_instrsinstr_timing测试ROM中的所有测试。

CPU指令测试 指令时序测试

这些ROM包含在源代码中,并有测试来检查输出是否符合预期(instructions_test.gotiming_test.go)。这些测试也会在每次提交时运行。

示例代码

以下是使用GoBoy API的简单示例:

package main

import (
	"github.com/Humpheh/goboy/pkg/goboy"
)

func main() {
	// 创建新的Game Boy实例
	gb := goboy.NewGameboy()

	// 加载ROM文件
	err := gb.LoadROM("zelda.gb")
	if err != nil {
		panic(err)
	}

	// 设置模拟器选项
	gb.SetDMGMode(false)  // 设置为GBC模式
	gb.SetMute(false)     // 不静音

	// 运行模拟器
	gb.Run()
}

已知问题和TODO列表

已完成:

  • [x] 屏幕边缘附近的精灵不绘制
  • [x] 顶部屏幕消失的精灵上半部分
  • [x] 小精灵行故障
  • [x] BG瓦片窗口偏移问题

待完成:

  • [ ] 精灵Z轴绘制错误
  • [ ] 轻微的APU时序问题
  • [ ] 更好的APU缓冲
  • [ ] 停止抖动
  • [ ] MBC3时钟支持
  • [ ] 加速CPU和PPU

更多游戏截图 更多游戏截图

资源

开发过程中参考了多种资源来理解和测试GameBoy硬件,包括:

  • Game Boy编程手册
  • 各种测试ROM
  • BGB模拟器(调试非常有用)
  • 其他开源Game Boy模拟器项目

更多关于golang实现任天堂Game Boy Color模拟器插件GoBoy的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现任天堂Game Boy Color模拟器插件GoBoy的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


GoBoy - 一个用Go实现的Game Boy Color模拟器插件

GoBoy是一个用Go语言实现的Game Boy Color模拟器核心,可以作为插件集成到更大的项目中。下面我将介绍如何使用GoBoy以及一些基本示例代码。

安装GoBoy

首先,你需要安装GoBoy库:

go get github.com/HFO4/goboy

基本使用方法

1. 创建模拟器实例

package main

import (
	"github.com/HFO4/goboy/pkg/goboy"
)

func main() {
	// 创建新的Game Boy模拟器实例
	gb := goboy.NewGameBoy()

	// 加载ROM文件
	err := gb.LoadCartridge("game.gbc") // 替换为你的ROM文件路径
	if err != nil {
		panic(err)
	}

	// 运行模拟器
	gb.Start()
}

2. 自定义显示和输入

GoBoy允许你自定义显示输出和输入处理:

package main

import (
	"image"
	"github.com/HFO4/goboy/pkg/goboy"
)

type CustomDisplay struct{}

func (d *CustomDisplay) Render(screen *image.RGBA) {
	// 在这里处理屏幕渲染
	// screen包含了160x144像素的Game Boy屏幕数据
}

func main() {
	gb := goboy.NewGameBoy()
	
	// 设置自定义显示
	gb.SetDisplay(&CustomDisplay{})
	
	// 加载ROM并运行
	gb.LoadCartridge("game.gbc")
	gb.Start()
}

3. 处理按键输入

package main

import (
	"github.com/HFO4/goboy/pkg/goboy"
	"github.com/HFO4/goboy/pkg/constants"
)

func main() {
	gb := goboy.NewGameBoy()
	gb.LoadCartridge("game.gbc")

	// 模拟按键按下
	gb.KeyDown(constants.KeyA)
	
	// 模拟按键释放
	gb.KeyUp(constants.KeyA)

	gb.Start()
}

高级功能

1. 保存和加载游戏状态

// 保存游戏状态
saveData, err := gb.SaveState()
if err != nil {
	panic(err)
}

// 加载游戏状态
err = gb.LoadState(saveData)
if err != nil {
	panic(err)
}

2. 自定义音频输出

type CustomAudio struct{}

func (a *CustomAudio) Play(left, right float32) {
	// 处理音频输出
	// left和right是左右声道的音频样本
}

func main() {
	gb := goboy.NewGameBoy()
	gb.SetAudio(&CustomAudio{})
	// ...
}

集成到GUI应用示例

以下是一个使用GoBoy和ebiten创建简单GUI模拟器的示例:

package main

import (
	"image"
	"log"

	"github.com/HFO4/goboy/pkg/goboy"
	"github.com/hajimehoshi/ebiten/v2"
)

type Game struct {
	gb *goboy.GameBoy
	screen *ebiten.Image
}

func (g *Game) Update() error {
	// 处理输入
	if ebiten.IsKeyPressed(ebiten.KeyZ) {
		g.gb.KeyDown(goboy.KeyA)
	} else {
		g.gb.KeyUp(goboy.KeyA)
	}
	// 其他按键处理...

	// 运行一帧
	g.gb.RunNextFrame()
	return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
	// 获取Game Boy屏幕数据
	img := g.gb.GetScreenImage()
	g.screen = ebiten.NewImageFromImage(img)
	
	// 绘制到窗口
	screen.DrawImage(g.screen, nil)
}

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
	return 160, 144
}

func main() {
	gb := goboy.NewGameBoy()
	err := gb.LoadCartridge("game.gbc")
	if err != nil {
		log.Fatal(err)
	}

	game := &Game{gb: gb}
	
	ebiten.SetWindowSize(640, 576)
	ebiten.SetWindowTitle("GoBoy Emulator")
	if err := ebiten.RunGame(game); err != nil {
		log.Fatal(err)
	}
}

注意事项

  1. 出于法律原因,你需要拥有合法的ROM文件才能使用模拟器
  2. GoBoy仍在开发中,可能不支持所有游戏
  3. 性能可能不如C/C++实现的模拟器

GoBoy提供了Game Boy Color模拟的核心功能,你可以根据需要扩展它或集成到自己的项目中。这个库特别适合需要Go语言实现的场景,或者作为学习模拟器开发的起点。

希望这些示例能帮助你开始使用GoBoy!如需更高级的功能,建议查看项目的GitHub仓库和文档。

回到顶部