GameBoy 程序开发-macOS 下环境搭建

03 年的时候家里有一部联想的笔电,让我打开了新世界的大门,那时候接家里的座机电话线上网,一些应用程序普遍都是几百 KB 的,根本想象不到现在动不动一个应用能占用十几个 G(点名某信)。总之当时就让我对电子产品开始感兴趣,刚好 05 年的时候让我接触到 GameBoy,当时玩到两个游戏,一个是牧场物语,另一个是口袋妖怪•黄(精灵宝可梦•黄),然后就有个想法,我一定要给这种掌上游戏机设备开发程序,从此就走上了一条不归路。

那么第一步先把开发环境搭起来。

个人设备情况

当前设备

  1. MacBook Pro 2016 年款 13 吋,系统 macOS 10.14.6;
  2. Mac mini 2020 年 Apple Silicon 芯片款,系统 macOS 14.1.1。

主要是说明这套环境配置笔记涵盖新版跟旧版两种环境。

开始安装

首先把设备安装好 homebrew,根据 homebrew 官网的说明操作即可,相信用 Mac 的没有几个没装这个(当然也可能有因为用过 FreeBSD 所以选择使用 MacPorts 的人,不过我没研究怎么用 MacPorts 配置 GBDK)。

Apple Silicon 芯片设备

第二步,如果是 Apple Silicon 芯片的设备,就执行下面的命令(旧款 x86_64 的设备我没测试这个开发套件),主要用于安装一个针对 GameBoy 芯片指令的 C 编译器及 GameBoy 开发相关的套件(GBDK 2020)。

shell 复制代码
brew tap limitLiu/formulae
brew update
brew install gbdk2020

然后再在 .zshrc 配置如下环境变量

shell 复制代码
export GBDKDIR=/opt/homebrew/opt/gbdk2020/
相关工具

接着是安装一个支持 32 位 Windows 程序的 wine-crossover 应用,主要方案引用自
macOS wine 32/64-bit Setup,目前(2023 年 11 月底,有高于 10.14 系统的 Intel 芯片 Mac 用户也可以试一下,)亲测可用。

shell 复制代码
brew tap gcenx/wine
brew install --cask --no-quarantine wine-crossover

有了以上这个工具,还需要相关的调试工具,譬如 GameBoy emulator,比较好使的就是 BGB,点击链接进到它的官网找下载地址即可,可能需要科学,实在下载不了就找个普通的 GameBoy Advance(后面称其为 GBA)仿真器代替下,譬如 mGBA,这个是有多个平台的版本 GBA 仿真器有原生适配 macOS 的程序包,通常情况下市面上的 GBA 仿真器都是向下兼容 GameBoy 程序的。

总之 BGB 这个软件非常小,虽然是 Windows 程序,不过基于刚才安装的 wine-crossover 就可以执行。接着就是跟 GameBoy 贴图相关的两个工具 GBTD、GBMB,点击到 GBTD 跟 GBMB 的 GitHub 托管地址下载,同样是 win32 的程序,直接用 wine-crossover 打开即可。

Intel 芯片设备

前段时间想找个 x86_64 设备学 5.1 版本的 Swift,就从家里翻了一部旧款机器,然后给它装上一个 macOS 10.14.6 的系统,刚好这个版本也是最后一个不需要特殊手段直接支持 32 位程序的系统。

接下来就是基本的安装 GBDK(算是 GBDK 2020 的前身,年久失修,刚好适合旧设备) 环节

shell 复制代码
brew tap mistydemeo/formulae
brew update
brew install gbdk

这个版本的 GBDK 是不需要配置环境变量的,所以跳过配置环境变量环节,直接装上就能用啦。

相关工具

因为这个设备是 Intel 芯片的 10.14 系统,所以可以直接用 homebrew 安装 wine-stable

shell 复制代码
brew install wine-stable --cask

有了 wine-stable 后,再下载兼容旧版 GBDKGBTD(1999 年用 Delphi 写得程序),当然 BGB 直接下载解压双击 .exe 程序会自动用 wine 打开(只要安装 wine 打开过一趟,也就是初始化过 wine),亲测也是可用的,我给这台设备上装得是 32 位。

wine 注意事项

如果碰到打开 wine 提示损坏,那就用鼠标右键点击并选择打开选项,后续看对话框打开就能用啦。

hello world

make 方式

现在来写个简单的程序压压惊,需要用到 make 工具,幸好 macOS 只要装上 Xcode 就能用 make。

Makefile 内容如下,主打一个简单问题复杂化。

makefile 复制代码
CC = /usr/local/bin/lcc -Wa-l -Wl-m -Wl-j

BIN = main.gb

main: $(BIN)

%.gb: %.o
	@$(CC) -o $@ $^

%.o: %.c
	@$(CC) -c -o $@ $<

.PHONY: clean
clean:
	-rm *.o *.gb *.lst *.map *.sym *.rel *.sav

这边先简单解释下,第一行第二行表示定义两个变量(类似 C 语言宏行为的"变量"),用 $CC 表示把它替换成 = 右边的内容,因为是类似 C 语言的宏,所以建议用 $(CC) $(BIN) 这种带括号形式的使用方式。

后面的 main: $(BIN) 进行宏展开后就是 main: main.gb,然后它就会去找 main.gb,因为我用得是通配符的形式 %.gb,所以就会到 %.gb: %.o 这行,它下面跟着实际是

makefile 复制代码
    @/usr/local/bin/lcc -Wa-l -Wl-m -Wl-j -o main.gb main.o

注意开头必须是 <Tab> 制表键表示的符号,不能是空格,后面第一个 @ 表示这行命令静默执行,也就是不会先打印再执行。因为解析 %.gb: %.o 后会变成 main.gb: main.o,后续的 @ ^ 是自动变量,既然是"变量",所以用 $ 处理替换,$@ 表示目标文件,$^ 表示所有依赖文件,于是就变成了上面的样子。

接着下的这两行

makefile 复制代码
%.o: %.c
	@$(CC) -c -o $@ $<

其实表达得是

makefile 复制代码
main.o: main.c
	@/usr/local/bin/lcc -Wa-l -Wl-m -Wl-j -c -o main.o main.c

< 也是一个自动变量,$< 取出变量后表示第一个依赖,这里对应的就是 %.c 解析后的 main.c。 说白了整个过程就是用 lcc 编译构建生成 gb 文件,既然如此,那就在 Makefile 同级目录下创建 main.c 文件,内容如下

c 复制代码
#include <stdio.h>
#include <gb/gb.h>

int main(void) {
  printf("Hello, world!\n");
  waitpad(J_START);
  printf("End.\n");
  return 0;
}

接着就是直接执行 make,就会看到一个 main.gb 的文件,用仿真器打开它,你就会看到

我们看到源码里有一行这个

c 复制代码
waitpad(J_START);

那我们按一下仿真器对应 GameBoy 的 start 键,于是就看到

至此,一个可以执行的 GameBoy 程序完成啦。

cmake 方式

上面的方式对于开发者而言比较麻烦,基本上等同于在裸写 C 程序的代码。如果结合 CLion 跟 cmake 的方式,就能让开发体验上升一个档次。

既然使用 cmake,那我们可以使用 cmake 自定义工具链的方式来处理交叉编译

首先是执行下面的命令

shell 复制代码
cd $GBDKDIR/share/
touch gb.toolchain.cmake

然后在 gb.toolchain.cmake 文件中写入以下内容

cmake 复制代码
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER lcc)
set(CMAKE_C_FLAGS "-Wa-l -Wl-m -Wl-j" CACHE STRING "" FORCE)

接着就可以写 CMakeLists.txt 的内容啦

cmake 复制代码
cmake_minimum_required(VERSION 3.10)

if (NOT DEFINED CMAKE_TOOLCHAIN_FILE)
    if (DEFINED ENV{GBDKDIR})
        set(CMAKE_TOOLCHAIN_FILE "$ENV{GBDKDIR}/share/gb.toolchain.cmake" CACHE PATH "toolchain file")
    else ()
        message(FATAL_ERROR "Please define GBDKDIR to point to your SDK path!")
    endif ()
endif ()

project(gb C)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(GBDK $ENV{GBDKDIR})

if (NOT GBDK)
    message(FATAL_ERROR "GBDK environment variable is not set")
endif ()

include_directories("${GBDK}/include" "include")

file(GLOB_RECURSE SOURCES "${PROJECT_SOURCE_DIR}/src/*.c")

add_executable(${PROJECT_NAME} ${SOURCES})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME} SUFFIX ".gb")

这个文件的内容我就不解释,因为相较 Makefile 而言太简单了,看两眼应该就知道啥意思,基本上都是固定写法。那么有了这个文件,在同级目录下建个 src 目录,然后把之前的 main.c 搬过来就行。因为上面 CMakeLists.txt 里写得是 project(gb C),所以实际构建出来的文件是 gb.gb

接着我们用 CLion 打开该项目,就可以愉快地进行开发,而且体验非常好。// 可惜 CLion 要钞票,虽然相比 Adobe 家的垃圾而言,价钱方面算是相当良心


如果上面的操作完成能得到相应的结果,基本上就属于环境搭建成功,后续就可以进行 GameBoy 程序的开发,当然我现在基本上是在 M1 芯片的 Mac 上进行。

相关推荐
charlie1145141912 天前
从0开始的STM32之旅8 串口通信(II)
stm32·单片机·嵌入式硬件·c·串口通信
孤寂大仙v2 天前
【C++】AVL树
开发语言·数据结构·c++·c
charlie1145141914 天前
嵌入式Linux入门具备:C语言基础与基本驱动学习(2):Linux GIibc IO基础
c语言·学习·c·io·嵌入式软件
Thomas_YXQ4 天前
Unity3D中管理Shader效果详解
开发语言·游戏·unity·unity3d·游戏开发
charlie1145141916 天前
从0开始的STM32之旅 7 串口通信(I)
stm32·单片机·嵌入式硬件·c
Java Fans6 天前
C++ 实现俄罗斯方块游戏
c
我要学脑机7 天前
电路知识的回顾
c·电路
Ljw...7 天前
C++游戏开发
c++·c·游戏开发
bin91539 天前
【热门主题】000013 C++游戏开发全攻略
c++·c
charlie11451419110 天前
STM32 从0开始系统学习2
stm32·嵌入式硬件·c·1024程序员节·arm架构·寄存器映射