Hellmood's Starpath Intro, but on Apple II in 256B
Details
Hellmood released an amazing
64-byte DOS intro "Starpath" at the
Lovebyte 2025
size-coding demoparty. It makes an animated ray-marched path against
a gradient sky with stars. All in 64 bytes.
I've always wanted to get some ray-matching going on Apple II, the problem
is a 1MHz 6502 isn't really up to it. I thought maybe this intro was simple
enougn to be doable, but in the end I get about 1/2 frame per second.
After 70s of precalc (32 frames) it can run at full speed.
Recording captured on an actual Apple IIe platinum:
Implementation
This runs on a 1MHz Apple II with 48k of RAM, in the lo-res
40x48x15-color mode.
To speed things up a bunch of the multiply/divides from the DOS version
are turned into table lookups, taking 6k of RAM. Some of this is stored
in the $2000 hi-res graphics area so we turn on hi-res graphics at the
start so you can watch the pre-calc happening.
We draw 32 frames, each one 1k, so that takes up another 32k of RAM, not
leaving much room left on a 48k Apple II.
A huge amount of size-optimization happened here, see the source code
for details, I won't list it all here and it's mostly lots of small stuff.
Due to rounding compared to the DOS version the actual code had some
instability that made it feel a bit glitchy. Oddly the C version I had
written to test things didn't show this... and I found out it's because
I had an off-by-one error in the C code. I actually intentionally
added this off-by-one error back to the 6502 code (even though it
wasted 3 bytes) because it made the output much smoother.
Some space is wasted to approximate the VGA color ordering. I originally
had the sky a bit different but got some feedback and now the ordering
is Hellmood-approved(TM).
Another big time and space saver was using random ROM contents to
"randomly" generate a stable star pattern. Helmood's trick of using
free leftovers from the multiply on x86 wasn't really free on 6502.
It does mean the star pattern repeats if you look closely enough.
I did manage to free up enough room for some sound, not sure if it
is worth it in the end. All you can really do on 6502 is click at the
right times, here we're doing it in the memcpy() based on the colors so it
does sort of give a whooshing sound as the path scrolls by.
I could have saved another 3 bytes or so by drawing the frames bottom-to-top
during the pre-render but it just felt wrong for some reason so I left
it top-down.
To save space I also load the executable to the latter half of the zero page /
overlapping into the stack area. This horrifies people sometimes, but
it's really easy to do on Apple II and saves a decent amount of space
with variable init and self-modifying code.