19个版本
0.2.25 | 2024年5月10日 |
---|---|
0.2.21 | 2024年1月30日 |
0.2.19 | 2023年12月22日 |
0.2.17 | 2023年11月18日 |
0.2.10 | 2023年7月17日 |
#27 in 游戏开发
275KB
3K SLoC
cc7800
cc7800实现了Atari 7800的C编译器子集。cc7800的主要目标是使用C语言为Atari 7800制作游戏,包括快速填充Maria显示列表,但不是为6502提供完整的C支持(如果需要,请查看cc65)。为cc7800编写的任何代码都可以用gcc编译,但反之则不行... 6502处理器因其糟糕的堆栈支持、臭名昭著的索引模式以及缺乏寄存器而闻名,是C编译器的不高效目标。cc7800通过不严格实现所有C功能,而是将C语法映射到6502的特定之处(特别是6502 X/Y索引模式),来应对这些限制。
cc7800是用Rust编程语言实现的,为这个近40年的游戏机带来了一丝现代气息... C语言语法是从头开始手写的PEG语法,因此不要期望有任何ANSI或ISO C的兼容性。
主要功能
- 生成DASM兼容代码(需要DASM作为第二阶段编译器)
- 仅使用1个字节的RAM
- 支持通过scatter关键字散列ROM数据,这大大简化了Holey DMA和精灵数据布局的使用。
- X和Y寄存器直接映射到X和Y变量,就像它们被声明为无符号char全局变量一样。
- 实现了所有C结构(for、if、while、goto等)。
- 支持SuperGame切换和卡带上的额外RAM
- 自动生成干净的引导代码
已知限制
- 支持的数据类型只有char(8位)、short(16位)和char指针(16位),以及这些类型的单维数组。
- 数组下标最好是常量,X和Y变量/寄存器(复杂下标会导致性能损失或错误)
- 16位算术受到严格限制。生成的代码如果过于复杂可能会产生错误(进位传播检查)。
- 不支持32位操作,不支持浮点数。
- 仅支持一个C文件。不提供链接。使用
#include "other_file.c" 来解决这个问题。
如何安装
当您的平台上安装了Rust Cargo时,从源代码安装就非常简单。如果情况不是这样,请使用rustup来安装它,然后在根目录下使用cargo install --path .
来本地编译和安装cc7800。
您可以直接使用Cargo通过输入cargo install cc7800
来安装二进制文件。
如果您绝对不想安装Rust(实在有点遗憾),在未来几年内将提供一个Windows安装程序。
使用cc7800的代码示例
一些示例可以在examples
目录中找到。要编译HelloWorld,请在根目录中输入
cc7800 -Iheaders examples/test_helloworld.c
这将生成a.out
,它是一个具有.a78头文件的atari 7800卡带。请注意,运行cc7800需要在当前目录中安装DASM或可以在系统路径中找到。
可以使用a7800
模拟器通过输入a7800 a7800 -cart a.out
执行a.out
文件,或者直接复制到Concerto卡上。
技术细节
Atari 7800特定关键字
为了处理非常特殊的Atari 7800内存映射,标准C语言中增加了一些特定关键字。这些关键字是scattered
、holeydma
、reversed
、ramchip
和bankX
。请查看示例以了解如何/在哪里使用这些关键字。
内联函数
cc7800支持一些内联函数来帮助编写类似ASM的调优代码
-
load(expr)
使用expr
加载6502累加器。它实现了LDA
指令。 -
store(expr)
将expr
存储到累加器中。它实现了STA
指令。 -
strobe(pointer)
也实现了STA
指令。它与存储相同,但只接受指针。通常用于内核中的许多strobe(WSYNC)
指令... -
asm(string)
将给定的汇编指令内联到C代码中。特别有用,用于调用ASM函数(使用asm("jsr asm_function")
)。
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的补码表示法,它将被视为负数,并且循环将立即退出。
待办事项
- 修复Atari 7800内存映射问题
- 提供更多示例
- 添加银行切换支持
- 添加银行集支持
- 创建一个处理文本、图形、瓦片、多精灵等的高级库
- 修复16位算术,使其更易于使用...
依赖关系
~7.5MB
~141K SLoC