使用 CodeLite IDE、Retro68 和 pce-macplus 模拟器开发复古 68K Macintosh 应用






4.50/5 (2投票s)
使用 CodeLite IDE、Retro68 和 pce-macplus 模拟器开发复古 68K Macintosh 应用
在我之前的文章中,我介绍了如何使用 Retro68 从现代 Linux 发行版编译 68K Macintosh 应用,并探讨了 Retro68 与 CodeLite 和 pce/macplus 模拟器如何构成一个非常好的 68k 开发环境。在这篇文章中,我将提供如何在常见的 Linux 发行版 Ubuntu 上创建这样的开发环境的详细信息。对于那些没有时间从头开始设置一切的人来说,在文章的最后,我将提供下载 VirtualBox 镜像的链接,该镜像在一个 Ubuntu 安装中包含了 Retro68、CodeLite、pce/macplus 以及其他必要的组件。
必备组件
在我们开始之前,你应该已经在你喜欢的 Linux 发行版上安装了Retro68、pce/macplus,并且可选地安装了Basilisk II,例如,通过使用 sudo apt-get install basilisk2
和 sudo apt-get install codelite
。虽然任何版本的 CodeLite 都可以满足我们的需求,但如果你有时间,请尝试从最新源代码安装 CodeLite,因为一些旧版本的 CodeLite 可能存在自动补全问题,这在使用 Retro68 SDK 时会显现出来。
准备构建环境
我们的目标是在 CodeLite 中编译和运行 Retro68 应用,最好还能提供一些调试支持,因此我们的第一个任务是编写 bash 脚本来自动化各种任务。对于我们的目的,我们只需要以下脚本(有关完整源代码,请参阅文章末尾的下载链接)
- build.sh:构建指定项目
- build_and_run.sh:构建指定项目并在指定模拟器中运行。此脚本将调用 build.sh,完成后启动选定的 Mac OS 模拟器。
- clean.sh:删除选定项目的所有构建输出。
从命令行构建 Retro68 应用以及启动 pce/macplus 模拟器非常简单。然而,将编译后的可执行文件复制到选定的模拟器,以便用户在模拟器启动完成后进行启动,这是一个挑战。幸运的是,Retro68 会生成 BinHex (.BIN) 或 800k 磁盘镜像 (.DSK) 的构建输出。你可以简单地将 .DSK 输出重命名为 .image,然后将其作为 800k 软盘驱动器挂载到 pce/macplus 中。或者,你可以使用 hformat
、hmount
和 hcopy
(它们是 hfsutils 包的一部分)来创建一个 HFS 磁盘镜像,其中包含 .BIN 文件以及应用程序中的任何其他输入文件,并将其挂载到 pce/macplus 中。HFS 镜像将显示为一个 Hard Disk 20 硬盘驱动器,可以在装有标准 ROM 的 Macintosh Plus 及更新机型上读取,或者在装有 Macintosh Plus ROM 的 Macintosh 128K/512K 上读取。
我们的第一个 CodeLite 68k 项目现在准备创建了。我们将使用 CodeLite 的 C++ 模板,并为不同类型的 Mac OS 模拟器添加不同的项目配置。
对于每个项目配置,我们将在 **Workspace** > **Open Active Project Settings** 中配置我们的 bash 脚本。在 **General** 设置中,配置脚本以使用我们选定的模拟器构建和运行项目。
我们的 build_and_run.sh 脚本的参数指示要构建的项目和要运行它的模拟器,这需要在程序参数中正确指定。工作目录也需要正确设置。请记住勾选 _“This program is a GUI application”_,否则模拟器将无法启动。在 **Customize** > **Custom Build** 中,指定构建和运行项目的命令。
在 **Code Completion** 中,指定 Macintosh Programmer’s Workshop C 头文件的路径,特别是 CIncludes 和 RIncludes 文件夹,以便自动补全正常工作。
这些文件夹也需要在 **Global Settings** > **Additional Include Paths** 中指定。
还将这些文件夹添加到 **Settings** > **Code Completion** > **CTags** > **Search Paths**。
由于 MPW 使用 `.r` 文件,这些文件是用一种类似于 C 的语言编写的,用于对话框资源,因此我们也应该在 C++ 文件扩展名列表中添加 `*.r`。你可以在 **Settings** > **Colours and Fonts** > **Customize** > **C++** 中进行设置。
当然,你可能还想根据自己的需要调整自动补全和其他编辑器设置。对每个项目配置重复上述步骤,并记住更改命令行参数以指示要运行项目的 Mac OS 模拟器。完成后,选择 **Workspace** > **Parse Workspace** 并重新启动 CodeLite。你会注意到方法签名现在可以被检测到,自动补全也可以正常工作。
通过这种设置,常见的 CodeLite 任务,如构建、运行和清理,现在应该可以正常工作了。下面的屏幕截图显示 CodeLite 在 pce/macplus 下的 System 6.0.8 上运行 MenuSample
示例。
MenuSample
应用可以从模拟的 Test Apps 磁盘启动。
为了让 pce/macplus 从现有的带有 System 软件的硬盘启动,而不是从我们刚刚编译代码创建的 HFS 磁盘启动,设置 pce 配置中的 insert_delay
参数的值约为 3-5 秒非常重要。否则,模拟器将尝试从该 HFS 磁盘启动并失败,因为我们的 HFS 磁盘显然不是可引导的。
添加调试支持
pce/macplus 提供了一些调试支持,但其集成调试器只能在汇编语言级别工作,不适合我们的目的。而且,虽然 Retro68 生成 GDB 调试符号,但由于涉及模拟层,通过 pce/macplus 利用这些符号来调试我们的 68K 应用并非易事。我想到的唯一简单方法是将调试消息写入 Macintosh 串行端口,并配置将串行输出重定向到磁盘上的文本文件。这可以通过以下配置项完成。
serial {
port = 1
drive = "stdio:file=serial.out"
}
上面的配置会将所有串行输出重定向到磁盘上名为 serial.out 的文件。然后可以使用以下代码从 pce 写入串行端口。
#include <Serial.h>
#include <Devices.h>
OSErr writeSerialPort(short refNum, const char* str)
{
#define MODEM_PORT_OUT "\p.AOut"
#define MODEM_PORT_IN "\p.AIn"
#define PRINTER_PORT_OUT "\p.BOut"
#define PRINTER_PORT_IN "\p.BIn"
const char* nameStr = "";
switch (refNum)
{
case aoutRefNum:
nameStr = MODEM_PORT_OUT;
break;
case boutRefNum:
nameStr = PRINTER_PORT_OUT;
break;
// input device not valid for writing data
/*
case ainRefNum:
nameStr = MODEM_PORT_IN;
break;
case binRefNum:
nameStr = MODEM_PORT_IN;
break;
*/
default:
return -1;
}
short serialPort = 0;
OSErr err = MacOpenDriver(nameStr, &serialPort);
if (err < 0) return err;
CntrlParam cb;
cb.ioCRefNum = serialPort;
cb.csCode = 8;
cb.csParam[0] = stop10 | noParity | data8 | baud9600;
err = PBControl ((ParmBlkPtr) & cb, 0);
if (err < 0) return err;
IOParam pb2;
pb2.ioRefNum = serialPort;
char str2[255];
sprintf(str2, "%s\n", str);
pb2.ioBuffer = (Ptr) str2;
pb2.ioReqCount = strlen(str2);
err = PBWrite((ParmBlkPtr)& pb2, 0);
if (err < 0) return err;
err = MacCloseDriver(serialPort);
return err;
}
writeSerialPort(aoutRefNum, "Hello World"); // write to Modem Port
writeSerialPort(boutRefNum, "Hello World"); // write to Printer Port
复古 Macintosh 计算机通常有两个串行端口:调制解调器端口和打印机端口。在我们的 pce/macplus 模拟器上,最好将调制解调器端口用于网络,并将打印机端口用于输出调试消息。CodeLite 也可以设置为“tail”串行输出文件以监控调试消息。
CodeLite、Retro68 和 pce/macplus 作为 VirtualBox 镜像
你可以在这里下载一个 VirtualBox 镜像,该镜像在一个 Ubuntu 安装中包含了 Retro68、CodeLite、pce/macplus 和其他必要的组件。这个 10GB 的 ZIP 文件已被分割成 10 个部分,可以使用类似 FFSJ 的工具进行合并。用户名是 macdev,密码是 macdev。Retro68 安装在 Documents 文件夹中,与为 CodeLite 使用而改编的 HelloWorld
、MenuSample
和 Dialog
示例一起。Basilisk 2 模拟器也已安装,并附带 System 7.6 磁盘镜像。我还包含了原始的 MPW 3.1 和 MPW 3.5 头文件,以及一本《Inside Macintosh》的副本,对于任何认真进行 68k Macintosh 编程的人来说,这都是必读的。
Mac OS Emulators 文件夹中安装的所有 pce/macplus 实例都已准备好与 CodeLite 一起使用。System 6.0.8 实例还包含 MacTCP 和其他有用的网络实用程序。通过使用包含的 Fetch,你还可以传输 System 6.0.8 实例和已安装 vsftpd
的 Ubuntu 主机之间的文件。为了允许从 TUN 接口访问 Internet,我还通过以下命令启用了 LAN 接口上 TUN 流量的 IP 伪装。
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o enp0s3 -j MASQUERADE
文章中提到的脚本可以在 Retro68kApps 文件夹中找到。还有一个 create_tun.sh 脚本,用于创建可以与 pce 一起使用的隧道(在更新接口名称和 IP 地址以反映你的网络配置之后)。如果 TUN 对你不起作用,你也可以使用 start_ppd.sh 和 start_tty0tty.sh 来模拟一个 PPPD 服务器。
在 VirtualBox 上运行时,有时你无法打开 **Settings** > **Displays** 来更改分辨率。如果发生这种情况,你可以使用类似 **xrandr -s 1366×768** 的命令来设置首选分辨率。VirtualBox 鼠标集成应在 **Input** > **Mouse Integration** 菜单下禁用,否则鼠标在 Mac OS 模拟器中会 erratic 地移动。
以下 YouTube 视频(使用 VirtualBox
录制)演示了我们设置的所有内容如何协同工作,形成一个自定义的 68k 开发环境。
对于那些不想下载整个 VirtualBox 镜像的人来说,一个只包含 CodeLite 项目、bash 脚本和《Inside Macintosh》软拷贝的 ZIP 文件可以在这里下载。