Action was the best 8-bit programming language

83 rbanffy 43 9/4/2025, 7:25:54 PM goto10retro.com ↗

Comments (43)

SeenNotHeard · 23h ago
One limitation not mentioned is that Action! didn't support recursion. This had to do with how local variables were stored.

Whether it was the best language for 8-bit programming, it certainly was a great fit for the 6502, as the language targeted the peculiarities of that chip. Accessing hardware-specific features of the 8-bit Atari's was a snap, which was necessary in order to do anything more interesting than sieves or print loops.

Action! probably could've been ported to the Apple line, but 8-bits were winding down by the time it was released. Porting to 16-bit machines like the IBM PC or Mac (or even the Atari ST) would have been a tougher sell, since Pascal and C were better established by that point, and worked well on those machines.

Two bad things about Action!: Charging a license fee to distribute the runtime, and that dumb bang in the name.

eschneider · 12h ago
The lack of recursion was not a practical limitation on the Atari. Base systems were 16K and you really didn't have space for recursion. And the license fee for the runtime didn't feel that painful compared to the other options.
NetMageSCW · 8h ago
I think a bigger problem for recursion support is the 6502 being limited to a 256 byte stack by its 8-bit stack pointer.
keyle · 16h ago
Wasn't recursion a problem for early C and Pascal in those days anyway? They didn't have tail call optimisations.

As in after X recursion, you'd get in trouble as the memory kept allocating new stack frames for every recurse...

stevefan1999 · 12h ago
You still don't have TCO anyway unless you use [[must_tail]] (or the upcoming become keyword in Rust)
pasc1878 · 15h ago
C and Pascal still don't have TCO.

But you still need some recursion and C and Pascal can do that.

keyle · 14h ago
When would you absolutely need recursion that couldn't be fulfilled with a while loop?
gavinray · 7h ago
Many algorithms are more simply expressed as recursive functions than stack-based iterators or "while" loops.
unnouinceput · 13h ago
Never, but I can counter with "when do you absolutely need switch that can't be fulfilled with if-else"?

It's a nice to have that makes your life easier

wduquette · 1d ago
The OP says that 8-bit CPUs couldn't handle Pascal well, and that Action! (release in 1983) was the first IDE for 8-bit machines.

But Apple Pascal was released for the Apple II in 1979. Based on UCSD Pascal, the Apple Pascal system was basically an OS that simply was an IDE; and it worked perfectly well on 8-bit hardware. I had quite a lot of fun with it back in the day.

eschneider · 12h ago
I remember Kyan Pascal on the Atari. It worked, but I'm not sure it worked _well_. Better than BASIC, but still quite a bit slower than ASM. Action! was much nicer if you were looking to deliver software on the Atari.
sema4hacker · 1d ago
Around 1979 or 1980 I was working for an 8080-based CRT terminal manufacturer and ported UCSD Pascal to our 8080 system, which worked flawlessly. I don't remember the details, but I believe all I had to do was implement a few BIOS-style routines. I got hung up for a few days because I had inited the heap pointer to a byte boundary instead of a word boundary, but after that everything booted and ran as advertised.
forinti · 1d ago
I learnt Pascal on a Beeb. It had a compiler, an editor, and a runtime in two 16KB ROMS.
brucehoult · 20h ago
As others have pointed out, Apple Pascal was a bytecode interpreter, not compiled to native 6502 code.

Even worse, the bytecode was standard UCSD Pascal, designed for mainframes, and not really how you'd design bytecode if you knew you were going to implement it on a 6502.

We can actually compile Pascal / C style languages to the 6502 pretty well these days. The way to do it is treat it the same as a RISC machine with a lot of registers (let's say 32 2-byte pairs in zero page, leaving 75% of ZP for globals and a handful of important runtime functions that benefit from self-modifying code). Split the 32 pseudo-registers up into A, S, T registers the same as you do for any RISC (or x86_64 for that matter).

It's problem to handle recursion. Just the same as any function call, put anything you still want after the function call into S registers, and in the called function if it needs to use S registers then it needs to save them on a stack (NOT the 256 byte hardware stack) first and restore them after. For more than one or two saved registers it's better to use a runtime function for this -- 12 cycles overhead, but lots of bytes of code saved. RISC-V's -msave-restore provides a good model for this.

You can make a nice set of 2-address arithmetic routines between 16 or 32 bit Zero-Page registers by using the X and Y registers to pass which locations to work on.

    add16:
        clc
        lda 0,x
        adc 0,y
        sta 0,x
        lda 1,x
        adc 1,y
        sta 1,x
        ret
    
        ...
        ldx #dst
        ldy #src
        jsr add16
This reduces the call site from 13 bytes to 7 bytes (and you can often reuse an X or Y), while increasing the execution time for an inline add from 20 cycles to 42 (1 cycle extra per instruction for the indexed addressing = 6, 4 cycles for loading X and Y, 12 cycles for the jsr/ret)

For 32 bit arithmetic the time overhead is much reduced. For floating point it would be negligable!

There is no convenient way to make 3-address routines, but `mov16` is only 5 instructions and 28 cycles. Or just 4 instructions (8 bytes) and 12 cycles if inlined, which might be a better tradeoff i.e.

        lda src1
        sta dst
        lda src1+1
        sta dst+1
        ldx #dst
        ldx #src2
        jsr add16
vs

        ldx #dst
        ldy #src1
        jsr mov16
        ldy #src2
        jsr add16

Stack-based 6502 code is both bigger and slower than (pseudo) register-based code -- a zero-argument `jsr add16` itself is smaller, but it's significantly slower, and loading and storing values between stack and somewhere else will be much more code and much slower.

Stack-based bytecode has a whole lot more overhead again to fetch the next instruction and dispatch to the correct code for it. Register-based bytecode would be a much better idea, as it uses several times fewer bytecode instructions, and is more compact to boot (see Dalvik vs JVM ... sad that webasm didn't pay attention).

ajross · 1d ago
Apple Pascal was a UCSD Pascal descendant, which means it was a P-Code interpreter.

The article is broadly correct. The 6502 had what amounts to a mixed-performance address space. All indirect addressing had to be done via pairs of registers in the zero page at addresses 0-255. Essentially all the "pointers" in your application wanted naturally to live as one of these 128 "pointer registers". But that's not the way natural code generation wants to work, where the pointers get stored in the data memory along with everything else.

So compiled languages need to have some kind of trampoline for every pointer to copy it into the memory where it needed to live, which was a really tall order for the optimizers of 1983.

Or they could just cheat and compile to a virtualized instruction set and feed that to an interpreter. Apple chose this, twice: once with Woz's sweet16 in which Integer BASIC was written, and again with the port of the P-Code interpreter for Pascal.

kjs3 · 1d ago
The OP says that 8-bit CPUs couldn't handle Pascal well

The 6502 might not have been able to handle Pascal well, but Borland Turbo Pascal for CP/M (z80, 8080, etc) worked very, very well. It was also released in 1983 or so, but dunno whether it or Factor was 'first'.

guenthert · 8h ago
Yes, Turbo Pascal was awesome and quite possibly the best programming environment for the Z80. The register-starved 6502 however relies on zero-page addressing for efficient code, that's difficult to exploit in compilers for high level languages (and hence why you don't see that in general purpose CPUs anymore). One way around that is to compile to a byte code which is then interpreted (e.g. BCPL, UCSD Pascal).
cmrdporcupine · 1d ago
If I'm not mistaken Apple Pascal ran a virtual machine which executed "p-Code" and the compiler emitted that.

Because, yeah, the 6502 is a difficult target for high level languages.

greggman65 · 19h ago
My best friend in high school, John Alvarado, and I, loved the game BoulderDash. John reproduced the algorithm for it in Action!

https://github.com/greggman/rockfall/blob/main/ROCK4.ACT

I've since ported that code multiple times. Once to Gameboy (unshipped, it was just for learning when I was hired to make a gameboy game). Once to C. Once to Java for a feature phone software interview. A couple of years ago to JavaScript

https://greggman.github.io/rockfall/

Zeetah · 1d ago
An excellent interview with the creator of Action! - Clinton Parker.

https://ataripodcast.libsyn.com/antic-interview-111-clinton-...

rtpg · 22h ago
I have this theory that Go tickles people because like Basic or something like Action it has all of these sort of abstraction ceilings that lead to "straight down the middle" procedural code.

Definitely leads to a feeling of velocity. I don't like the language that much but I do get the fun from that feeling!

jdndnfbdn · 16h ago
I personally do not get the feeling of velocity since I need to struggle with language and tooling to get the most basic things done

However I love the ease of cross compiling and distributing cross compiled binaries that much that Go is still the best tool for some jobs

smackeyacky · 16h ago
You could argue that the “best” programming environment available for DOS machines was dBase. dBase III in particular. For storing rows of data and building text interfaces it was very impressive. Not for games, but for information systems that ran a lot of small business back then.
Zardoz84 · 5h ago
Clipper
NetMageSCW · 8h ago
When I started college my computer was an Atari 400 I had purchased with money from my after-school job programming commercial software. I had replaced the membrane keyboard with a third party “real” keyboard and had the Action! cartridge. I used the editor primarily to write papers for class printed on my dot-matrix electric arc printer (it produced the dots by scorching the paper with a tiny carbon electrode thus needing no ink, though the print was brown and lower contrast). Sadly I sold the 400 to someone I knew for their child and loaned the Action! cartridge to a co-worker who moved across the country and we lost touch. I’ve been searching eBay for years for a copy of the manual as well - at one time I had an ambition to create a version for iPad or Windows.
jhallenworld · 18h ago
I never had Action!, but I did try Deep Blue C for the Atari 800. One issue was lack of brackets in the character set.. I think it used $( and $) instead.

https://www.atariarchives.org/APX/showdocs.php?cat=20166

There were some other weird 8-bit programming languages: PLM and MPL. These are PL/I clones for 8080 and 6800. I used MPL long ago and wrote an article about it:

https://github.com/jhallen/exorsim/tree/master/mpl

PLM was much more popular and better:

https://en.wikipedia.org/wiki/PL/M

jasperry · 23h ago
Another 8-bit "better than BASIC" language was COMAL. Similar to the language in the article, it also had structured programming constructs, and the C64 version had built-in turtle graphics, sprite, and sound commands. I remember picking a version up at a mall kiosk that sold PD disks and it expanded my horizons!
jjwiseman · 11m ago
Same here. I knew BASIC very well and had done some 6502 assembly, but the COMAL disk I picked up somewhere for the C64 was my first exposure to structured programming, and it definitely expanded my young mind.
pikeangler · 12h ago
There was the fantastic COMAL 80 cardtrige for the Commodore 64 with high level commands for sound and graphics, and a full screen editor. It bank-switched so you could use the full 64K RAM on the C64.
cmrdporcupine · 1d ago
"I found it endearing that to end an IF block you used FI (IF spelled backwards) and to end a DO block you used OD. That is some interesting symmetry although I’m not really sure it helps readability."

This comes straight from Algol if I'm not mistaken. It seems weird to us now (tho bourne shell / bash kinda has this in spots) but it was in the air in the 60s/70s.

When I've looked at it in the past I definitely got the sense that Action was very much inspired by Algol-68, but with some accomodations for the niche of 6502.

6502 is a terrible target for C (and even Pascal) compilation, I have often wondered if it made sense for someone to try and revive Action for the 21st century as a general purpose 6502 high level PL.

rootbear · 22h ago
That was from Algol 68. Algol 60 used BEGIN/END blocks when the body of a do loop (or a then or else block, etc.) had more than one statement. Bash was influenced by Algol 68.
hmmokidk · 22h ago
I like it because I definitely spend brain cycles trying to figure out what is being closed!

It’s like HTML hah.

jnaina · 14h ago
Blast from the past. Still have my Action cartridge.
charcircuit · 1d ago
This article doesn't really prove why it's the best. I feel like if it's the best it would have been ported to more systems.
wk_end · 1d ago
I think it hinges on:

  The Action! language may not have been as advanced as C or Pascal, but because it was designed with the 6502 CPU in mind, compiling the language was astonishingly fast.

  The original Atari Pascal system from APX needed multiple disk drives and could take several minutes to compile a small program. The only C package available in 1983 (Deep Blue C) was at least as limited as Action!, but also not an integrated package and compiled slowly. Draper Pascal only compiled to pseudo-code.

  Action! compiled your program to machine code in memory and in seconds. Typing C (to compile) and then R (to run) was hardly slower than just typing RUN in BASIC.
So less about the language itself (unless it had some particular properties that facilitated compiling it quickly) and more about the tooling.
buescher · 1d ago
Micro-SPL was cut down from the HP SPL systems programming language to run on the Xerox Alto, in microcode, and was ported pretty directly to the 6502 as Action! The Action! folks were pretty coy about this back in the eighties.
charcircuit · 20h ago
I missed the "was" in the title. In the last 40 years a lot has progressed, so I don't think Action would be the best anymore.
veltas · 1d ago
Any relation to ActionScript?
hn_acc1 · 1d ago
ActionScript came ~10-15 years later. I would be very surprised if there was any relation.
veltas · 9h ago
That's why I asked, fishing for surprising but interesting information.
cosmotic · 1d ago
ActionScript is based on ECMA/JavaScript
fourthark · 1d ago
Originally it was based on HyperTalk, then it switched to ECMA later on.
jjtheblunt · 23h ago
not historically, but merged back into implementing ECMA/Javascript later. it predates javascript by years in earlier revisions.