New Frontiers in High-Level 6502 Programming#
Programming directly in 6502 gets a little fiddly, so a higher-level language can make things easier. There have been many attempts to tame the 6502 to make programming more palatable. Interpreted languages like BASIC, FORTH, and Pascal were popular back in the day, and Infocom games had their own custom VM to run on many platforms. But programmers are a stubborn bunch, and want speed as well as usability.
One approach is to just write a really powerful macro assembler that almost looks like a high-level language. In the 1980s, Lucasfilm developed Macross as “an assembler for people who hate assembly language”. More recently, NESHLA is targeted at NES development, but hasn’t seen much new development since 2005.
The New Batch#
It’s been more than 40 years since Chuck Peddle sold the first 6502 samples out of a jar at a trade show. Intrepid developers are still making new languages for the CPU. Here’s a quick survey of some that have been active in the last few years:
cc65 is the most mature compiler for the 6502, but it’s not perfect. The C language is difficult to optimize for a machine with only three 8-bit registers, and so code quality is suboptimal. However, it has a complete set of libraries, and is a clear choice for building code for Atari, Apple, Commodore, Oric, NES, and many other systems.
cowgol is a strong-typed language based on
the Amsterdam Compiler Kit and inspired by Ada.
The compiler operates in several independent phases, so that it can build itself on small systems like the Z80 and
6502.
Because it forbids recursion, it doesn’t need stack frames, and thus can
arrange all variables in global memory.
The syntax should be familiar to fans of Pascal, and the language even supports
inheritance – no for
loops yet, though.
SixtyPical is sort of a high-level assembler with static analysis. It gives the programmer instruction-level control, but helps to catch common mistakes – use of uninitialized flags or registers, out-of-bounds array accesses, and subroutines unexpectedly trashing registers. As such, routines have to explicitly define their inputs, outputs, and side-effects, for example:
define vertical_blank routine
outputs VSYNC, WSYNC, TIM64T
trashes a, x, z, n
C02 is another recent contender that
looks like C, but really isn’t.
There are specific keywords for zero-page variables and page-aligned arrays.
Function calls are limited to three byte-sized arguments, and only the first
argument may be a complex expression.
Any more than that and you have to explicitly push
and pop
arguments
on and off the stack, or use “inline” arguments.
It looks promising, as there aren’t many high-level languages efficient
enough to target the Atari 2600. Speaking of which…
KickC is a C-compiler that creates optimized 6502 assembler. The language is classic C with some limitations and a few modifications to allow it to optimize better for 6502 assembler. It’s still in beta, but looks promising.
Millfork is a mid-level programming language targeting 6502-based, 8080-based and Z80-based microcomputers. Unlike in high-level languages, operators in Millfork have limited applicability. Not every well-formed expression is actually compilable. Most expressions involving single bytes compile, but for larger types usually you need to use in-place modification operators. Calling conventions pass in registers or in static locations on 6502/Z80 platforms. It has a “multi-pass whole-program optimizer”.
Wiz supports several 8-bit CPUs including the 6502.
It requires that the programmer manage their own registers.
For example, instead of saying hp -= 10
you’d write hp = a = hp - 10
.
vbcc is a highly optimizing portable and retargetable ISO C compiler. It supports 6502 and has NES and C64 libraries.
Single-platform systems#
Fred Quimby released batariBasic 1.0 in 2007, and recently others have been trying to resume development. This is a BASIC-inspired language wholly targeted at the Atari 2600 platform, and as such it has a lot of platform-specific quirks. For instance, to define a 8x8 player sprite you might do this:
10 player0:
%00000110
%00111110
%11110000
%11011011
%00011111
%11111000
%11001100
%00000100
The strong suit of this system is the availability of various “kernels” that can generate different combinations of playfield and sprite graphics without the pain of assembler. There is a strong community around the language, and many full games have been published. There’s even Visual bAtariBasic under developement which integrates various visual editors.
PLASMA is an interpreted language which is currently targeted to Apple I/II/III platforms. After trying to make a 6502 Java interpreter, the author took the lessons learned and designed his own language and bytecode scheme. PLASMA works with dynamically linked modules, so the runtime system is highly integrated with the host platform. There’s even support for JIT compilation on some platforms.
Action! is an ALGOL-like language and programming environment for Atari 8-bit computers, released in 1983. The author has recently released the source code and it’s enjoying a resurgence of popularity, as hobbyists are fixing bugs, writing documentation and extending the software.
@lkesteloot told me about his alternate Apple II ROM which runs Applesoft programs, but compiled instead of interpreted! This is supposed to speed things up 5-30x, but there’s no floating point support (an approach taken by vintage Applesoft compilers like TASC.)
Dustmop created the Lisp-y CO2 compiler to make the NES game “What Remains”. It supports bank-switched code, static local variable allocation, structured conditionals, and has a simple peephole optimizer. It’s built on top of Racket.
Mad-Pascal is a 32-bit Turbo Pascal-compatible compiler for Atari XE / XL.
XC=BASIC is a dialect of the BASIC programming language for the Commodore-64.
Fast Basic is a fast interpreter for the BASIC language on the Atari 8-bit computers that supports floating point and integer programming.
NESFab is a NES-specific language that automatically handles bank-switching and produces efficient 6502 code, and has lots of other features like NMI routines, inline assembler, character maps, asset loaders, and more.
cc2600 is a C-like compiler for the Atari VCS, written in Rust.
oscar64 is an optimizing C99 compiler that can emit a mixture of interpreted and native 6502 code.
What’s next?#
For homebrew game developers, using a non-standard language is just part of living on the edge of retro technology. These dev tools are still a little rough around the edges (with the possible exception of cc65) but ready for experimentation and improvement. Who knows, you might even see some of them one day on 8bitworkshop!