#编译器 #游戏开发 #列表 #cli #atari7800

应用 cc7800

Atari 7800的C编译器子集

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 游戏开发

GPL-3.0-or-later

275KB
3K SLoC

Rust 2K SLoC // 0.1% comments Assembly 1.5K SLoC // 0.1% comments C 74 SLoC // 0.1% comments AsciiDoc 26 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语言中增加了一些特定关键字。这些关键字是scatteredholeydmareversedramchipbankX。请查看示例以了解如何/在哪里使用这些关键字。

内联函数

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