8 个版本
0.4.4 | 2024年2月21日 |
---|---|
0.4.1 | 2023年12月22日 |
0.4.0 | 2023年8月14日 |
0.3.1 | 2023年5月1日 |
0.2.0 |
|
#161 在 游戏开发
每月 201 次下载
135KB
1K SLoC
cc2600
cc2600 实现了 Atari 2600 的 C 编译器子集。cc2600 的主要目标是使开发者能够使用 C 语言为 Atari 2600 开发游戏,包括编写内核,而不是提供对 6502 的完整 C 支持(如果您需要这个功能,请查看 cc65)。任何为 cc2600 编写的代码都可以用 gcc 编译,但反之则不行... 6502 处理器因其堆栈支持差、著名的索引模式以及缺少寄存器而闻名,因此它不是 C 编译器的理想目标。除了 Atari 2600 的限制(128 字节 RAM、强烈依赖 bankswitching、总体速度慢)外,在此平台上使用纯 C 的限制也很大。cc2600 通过不严格实现所有 C 功能,而是将 C 语法映射到 6502 的具体特性,特别是索引模式,来应对这些限制。
请注意,此编译器用于编写“复古”风格的 ATARI 2600 代码。它不适用于 CDFJ(Melody/Harmony 卡上的自定义 ARM 代码)开发,其中 6507 代码已缩减到最小。相反,它被设计用于以经典 Atari 方式编写代码,可能使用 DPC 或 DPC+ 加速器或 Superchip 以获得更多 RAM。
cc2600 不应作为编写您的第一个 Atari 2600 游戏的起点。您首先必须学习汇编语言的编程(我强烈推荐阅读 Steven Hugg 的《Making Games For The Atari 2600》,见 https://8bitworkshop.com/docs/books)。另一方面,如果您是经验丰富的汇编语言程序员,您可能会在编写下一个游戏时利用 cc2600 节省大量时间,因为 cc2600 可以使您利用结构化代码编写。
cc2600 使用 Rust 编程语言实现,为 45 年的旧式游戏机增添了一丝现代感... C 语言的语法是从头开始手写的 PEG 语法,因此不要期望它符合 ANSI 或 ISO C 标准。
主要功能
- 生成与 DASM 兼容的代码(需要 DASM 作为第二阶段编译器)
- 支持本地Atari F4、F6和F8、3E(大量RAM!)DPC和DPC+银行切换方案
- 支持Superchip(128字节额外RAM!)
- 仅使用1个字节的RAM
- 加载/存储/时钟中断内建函数允许编写高效的内核。
- X和Y寄存器直接映射到X和Y变量,就像它们被声明为无符号字符全局变量一样。
- 实现了所有C结构(for、if、while、goto等)。
- 自动生成干净的引导/银行切换代码
- 支持PlusROM,与PlusCART进行WiFi通信
已知限制
- 支持的数据类型只有char(8位)、short(16位)和char指针(16位),以及这些类型的单维数组。
- 数组下标限制为常量、X和Y变量/寄存器。
- 实现了16位算术,但仅限于简单操作。
- 没有32位操作,没有浮点数。
- 与一个C文件一起工作。不提供链接。使用
#include "other_file.c"
来处理这个问题。
安装方法
当您的平台上可用Rust Cargo时,从源代码安装相当简单。如果这种情况不存在,请使用rustup来安装它,然后在根目录中使用cargo install --path .
来本地编译和安装cc2600。使用cargo test
启动cc2600的单元测试。
您可以使用Cargo直接通过键入cargo install cc2600
来安装二进制文件。
如果您确实不想安装Rust(相当可惜),可以使用提供的Windows安装程序。
使用cc2600的代码示例
cc2600可以实现的可能性的一个相当完整的例子是HappyBird游戏,可以免费下载。这个例子演示了很多不同的功能:内联汇编器的使用(用于savekey i2c通信)、48像素宽度的图形显示、ROMplus访问、银行切换、通过指针进行间接寻址等。
在examples
目录中也有几个示例。文件夹中有一个Makefile,但它应该只在Linux上工作。如果您想构建包含Garfield的出色的DPC(David Patrick Crane协处理器)示例,请输入:
cc2600 -Iheaders examples/test_dpc.c
这将生成out.a
,这是一个DASM兼容的源代码。
输入dasm out.a -f3 -v4 -oout.bin -lout.lst -sout.sym
来制作卡带。
然后您可以使用stella模拟器运行二进制文件out.bin
,或者将其复制到Harmony或PlusCart卡带。
技术细节
银行切换
Bankswitching 被cc2600隐藏在幕后。在实际定义之前,只需指定bank1
到bank*n*
,就可以将数据或代码定位到指定的bank中。cc2600将在编译时计算bank的数量,并据此生成卡带。不指定任何内容将数据放入bank0,这是默认的起始bank。只有从bank0到bankn和从bankn到bankn才能进行bank之间的函数调用。如果需要,会自动插入Bankswitching代码。
3E Bankswitching
对于高级用户,cc2600可以支持3E Bankswitching。只需包含"3e.h"头文件,它就会被选中。使用bank1到bankn声明变量,并将它们放入RAM banks(每个1kB。最大数量受卡带实现限制,因此未知)。ROM banks的大小为2KB,而不是Atari传统bankswitching方法的4KB。由于3E Bankswitching方法中,最后一个bank总是在可访问内存的最后2KB中始终处于活动状态,因此bank0被放在ROM的最后。啊,是的!别忘了使用select(x)
宏来手动选择内存第一部分的第x个RAM bank。从select()
开始,而对于变量分配,从bank1
开始。如果你想要从一个可以运行的例子开始,看看test_3e.c
。
DPC Bankswitching
实现了DPC协处理器的支持。使用"dpc.h"头文件来激活它。使用关键字display
填充2kB显示ROM,代码的ROM大小固定为8kB。是时候实现你自己的陷阱3了。
DPC+ Bankswitching
也支持DPC+协处理器,并打开4KB的显示RAM,2B的音乐/频率ROM(使用dpcplus_frequencies.h
预先填充),以及24KB的游戏数据。大胆想想。DPC+生成的代码在Stella上直接运行,但你必须在ARM代码"驱动程序"(DPC+.arm)前添加它才能在Harmony卡或CartPlus上运行(尽管后者不使用它)。如果你对这个问题一无所知,请在AtariAge论坛上寻求帮助。
Superchip
如果你在变量声明之前使用关键字superchip
,Superchip支持会自动激活。这将提供128字节额外的RAM。请注意,这与其他3E、DPC和DPC+ Bankswitching方案不兼容(但3E和DPC+通过其他方式提供了一些RAM)。
内联函数
cc2600支持一些内联函数,以帮助制作类似ASM的调优代码
-
load(expr)
使用expr
将6502累加器加载。它实现了LDA
指令。 -
store(expr)
将expr
存储到累加器中。它实现了STA
指令。 -
strobe(pointer)
也实现了STA
指令。它和store一样,但只接受指针。通常用于内核中的大量strobe(WSYNC)
指令... -
asm(string)
将给定的汇编指令内联到 C 代码中。特别适用于调用 ASM 函数(使用asm("jsr asm_function")
)。 -
csleep(int)
代表周期睡眠。有助于在代码中插入 nops。实现了 2 到 10 个周期。
汇编代码插入
您可以使用 #include
插入汇编代码。如果提供的文件名以 ".a" 或 ".inc" 结尾,它将被视为汇编器并插入到 DASM 生成的代码中。您还可以使用以下特殊标记内联代码:=== ASSEMBLER BEGIN ===
。例如,要激活 "i2c.inc"(savekey 代码)并告诉宏使用 i
临时变量,只需键入
=== ASSEMBLER BEGIN ===
I2C_SUBS i
==== ASSEMBLER END ====
16 位算术支持
支持 16 位算术,但请注意,只能使用简单的表达式(如简单的加法或 +=
,而不是同一行代码上的多个加法),因为进位传播没有保证(可能将来会有)。特别是 16 位操作不支持在比较中。使用 short
声明 16 位变量。char *
也是 16 位变量,因为 6502 的地址空间是 16 位宽的。
为了将 16 位转换为 8 位,请使用 >> 8
特殊操作来获取 short
的较高字节,而使用 nothing 获取较低字节。
优化
X 和 Y 是 unsigned char
类型,但为了优化循环,当与 0 进行比较时,它们被认为是 signed char
。因此,代码 do { something; Y-- { } while (Y >= 0);
将使用 BPL
(分支如果正)指令实现,就像在汇编器中做的那样。注意,如果 Y > 128,由于补码到 2 的二进制表示,它将被视为负数,循环将立即退出(即不要用这个做你的 192 行内核循环。使用 Y > 0
比较使用进位标志)。
TODO
- 提供更多示例
- 修复 16 位算术,使其更易于使用...
- 实现符号扩展(从 8 位到 16 位变量分配)
- DWARF 数据输出,用于与 Gopher2600 进行调试
- 添加 3E+ 银行切换方案支持
悼念
Chuck Peddle 1937 - 2019
依赖关系
~8.5MB
~152K SLoC