Files
akbasic/examples/megademo/megademo.bas
Tachikoma 16aa052119 Decompress a full-screen picture and six frames of video from strings
The megademo gains a scene: an 800x600 vaporwave sunset carried inside
the listing, then six looping delta frames of full motion video -- the
floor grid rolling forward and the sun's slices crawling, about 220
bytes a frame. DATA cannot carry an image (512 items, ~350 owned by the
stroke font), so the picture rides in RLE-encoded string literals
decoded with INSTR: 2 KB of base frame, 1.3 KB of video. Row records
jump the decoder between changed rows, an unreachable colour is the
skip, black draws so a delta can erase, and the rays are struck live
over every frame rather than encoded. The 63-byte bird gliding over it
is the one image DATA does have room for, via SPRSAV's type-in form.

examples/megademo/vaporwave.py composes the image in palette space,
dithers by row so the gradients band instead of shattering the RLE,
proves base-plus-deltas reproduces every frame against a simulation of
the decoder, and owns the generated block between the PICTURE markers.
TODO.md section 4 records the DATA ceiling and the wanted verb.

Co-Authored-By: Claude Code (Fable 5) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwxGB6TdoVvZ11KQQME9cL
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-02 16:26:56 -04:00

1574 lines
41 KiB
QBasic

REM =====================================================================
REM
REM A K L A B S M E G A D E M O ' 8 5
REM
REM CODE AND FX ............. TACHIKOMA
REM DEDICATED TO ............ GAMECUBE
REM MEGAGREETZ .............. STARFORT
REM
REM A demoscene production for the akbasic interpreter, written as if
REM it were 1985 and this dialect were the machine under the tree.
REM It leans on every corner of the interpreter on purpose:
REM
REM - there is no RND, so it carries chapter 17's LCG and seeds it
REM from the jiffy clock
REM - the palette cannot be rewritten, so every "colour cycle" is an
REM honest redraw of the same strokes in the next colour
REM - there are eight sprites, so the lettering IS the sprite bank:
REM each letter of GAMECUBE is drawn with the stroke font, captured
REM with SSHAPE and installed with SPRSAV
REM - SOLID walls and COLLISION 2 bounce that lettering around the
REM screen with RCOLLISION(n, 7) saying which axis to reverse
REM - the PLAY queue is one queue -- monophonic, one instrument per
REM batch (TODO.md 4) -- so the soundtrack is beeper-style: one
REM interleaved line that is its own kick, bass and arpeggio,
REM with a noise drum break every third batch. Voice 1 is music,
REM voice 2 the collision blips, voice 3 the scene sweeps
REM - 3D wireframes with no matrices: two composed rotations and a
REM perspective divide per vertex, floats kept on the left the
REM whole way because the left operand decides the arithmetic
REM
REM It probes for its hardware like a proper boot loader. No audio
REM device mutes it. No text grid drops the status row. A host with no
REM clock -- tools/screenshot.c -- gets each scene as a still and the
REM finale as the picture, because every animation loop is gated on
REM TI# actually moving.
REM
REM Q or ESC quits. TODO.md section 4 records what this program wanted
REM and could not have.
REM
REM =====================================================================
REM ---- every pool up front: the DIM pool never frees (chapter 13) ----
DIM FNC#(41)
DIM FNI#(41)
DIM FNS#(280)
DIM RBW#(7)
DIM STC#(4)
DIM BARC#(20)
DIM SBG#(9)
DIM BYO%(4)
DIM WVX%(14)
DIM WVY%(14)
DIM WVZ%(14)
DIM WPX#(14)
DIM WPY#(14)
DIM WQX#(14)
DIM WQY#(14)
DIM WE1#(24)
DIM WE2#(24)
DIM PBRD#(63)
ALPHA$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :-.!"
GC$ = "GAMECUBE"
REM The picture decoder's alphabets: a run is two characters, colour
REM then length, and INSTR turns each back into a number.
CPAL$ = "ABCDEFGHIJKLMNOP"
LTAB$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
SEED# = 314159
QF# = 0
RB# = 0
PH% = 0
MT# = 0
W# = 320
H# = 200
REM A scalar FIRST assigned inside a GOSUB lives in that call's scope
REM and dies at RETURN, so a subroutine's OUTPUT must be assigned here
REM first to make it a global -- that is why chapter 18 predeclares.
REM But only the outputs: there are 128 variable slots in the whole
REM machine and a predeclared scratch variable occupies one forever,
REM where a scoped one gives its slot back. The first cut of this
REM program predeclared everything and ran the pool dry.
RMAX# = 0
RND# = 0
TX% = 0
TB# = 0
REM =====================================================================
REM Probe the machine. Graphics is mandatory; everything else degrades.
REM =====================================================================
GFX# = 1
TRAP NOGFX
W# = RGR(1)
H# = RGR(2)
TRAP
IF GFX# = 1 THEN GOTO HAVEGFX
PRINT "THIS DEMO NEEDS THE SDL BUILD (-DAKBASIC_WITH_AKGL=ON)."
END
LABEL HAVEGFX
SND# = 1
TRAP NOSID
SOUND 1, 17175, 4
VOL 12
TRAP
TXT# = 1
TRAP NOGRID
WINDOW 0, 0, 39, 0
TRAP
KEYS# = 1
K# = 0
TRAP NOKEYS
GET K#
TRAP
REM A host that never sets the clock is the screenshot tool. TI# stays
REM zero there, so every wait would spin forever: render stills instead.
HL# = 0
SLEEP 0.3
IF TI# = 0 THEN HL# = 1
SEED# = SEED# + TI#
GOSUB LOADTABLES
GOSUB LOADWIRE
GOSUB LOADFONT
GOSUB LOADBIRD
IF SND# = 1 THEN GOSUB SIDINIT
GOSUB TUNE
IF TXT# = 1 THEN CHAR 1, 0, 0, "AKLABS MEGADEMO 85 - PRESS Q TO EXIT"
REM =====================================================================
REM SCENE 1 : TITLE. Starfield from the LCG, the logo in rainbow,
REM and the "palette cycle" that is really a redraw.
REM =====================================================================
GRAPHIC 1, 1
WIDTH 1
NS# = 120
GOSUB STARS
WIDTH 2
T$ = "AKLABS"
SZ% = 0.025 * W#
GOSUB CENTERX
TY% = 0.12 * H#
CM# = 1
GOSUB DRAWTEXT
CM# = 0
COLOR 1, 2
T$ = "PRESENTS"
SZ% = 0.008 * W#
GOSUB CENTERX
TY% = 0.45 * H#
GOSUB DRAWTEXT
COLOR 1, 4
T$ = "A 1985 DEMO FOR GAMECUBE"
SZ% = 0.006 * W#
GOSUB CENTERX
TY% = 0.58 * H#
GOSUB DRAWTEXT
GOSUB SWEEP
IF HL# = 1 THEN GOTO S1DONE
T$ = "AKLABS"
SZ% = 0.025 * W#
GOSUB CENTERX
TY% = 0.12 * H#
DL# = TI# + 420
DO WHILE TI# < DL#
RB# = RB# + 1
CM# = 1
GOSUB DRAWTEXT
CM# = 0
GOSUB POLLKEY
IF QF# = 1 THEN EXIT
SLEEP 0.12
LOOP
LABEL S1DONE
IF QF# = 1 THEN GOTO BYE
REM =====================================================================
REM SCENE 2 : LISSAJOUS BRAID. Twelve phase-shifted 3:2 curves, drawn
REM once each -- the drawing layer persists, so the braid accumulates.
REM =====================================================================
GRAPHIC 1, 1
WIDTH 1
CX% = 0.5 * W#
CY% = 0.5 * H#
R1% = 0.3 * W#
R2% = 0.38 * H#
PN# = 0
DO WHILE PN# < 12
COLOR 1, RBW#(MOD(PN#, 7))
GOSUB SPIRO1
IF HL# = 0 THEN SLEEP 0.25
GOSUB POLLKEY
IF QF# = 1 THEN EXIT
PN# = PN# + 1
LOOP
WIDTH 2
COLOR 1, 2
T$ = "TACHIKOMA FX"
SZ% = 0.007 * W#
GOSUB CENTERX
TY% = 0.88 * H#
GOSUB DRAWTEXT
IF HL# = 0 THEN SLEEP 1.5
IF QF# = 1 THEN GOTO BYE
REM =====================================================================
REM SCENE 3 : WIREFRAMES. A cube and an octahedron out of one pooled
REM vertex and edge table -- two composed rotations and a perspective
REM divide per vertex, no matrices anywhere. Each frame erases the
REM previous edges in black and draws the new ones, the raster bars'
REM trick applied to twenty-four lines. A clockless host gets five
REM exposures without the erase: a tumble, as a still.
REM
REM The way out is the way in: the solids drift together, the point
REM they share ignites -- pulsing through the bar ramp table, because
REM it is the origin of the next scene -- the camera dives through
REM the frames as the perspective scale outgrows the window, and the
REM origin splits in two, rides the Y axis to the bars' band, and
REM stretches into the first two raster bars itself.
REM =====================================================================
GRAPHIC 1, 1
WIDTH 1
NS# = 90
GOSUB STARS
WIDTH 2
COLOR 1, 2
T$ = "TWO SOLIDS - NO MATRICES - PURE SIN"
SZ% = 0.0045 * W#
GOSUB CENTERX
TY% = 0.06 * H#
GOSUB DRAWTEXT
SF% = 0.24 * H#
CY% = 0.55 * H#
A1% = 0.4
B1% = 0.9
A2% = 1.1
B2% = 0.3
FC# = 0
IF HL# = 0 THEN GOTO WIRELIVE
PN# = 0
DO WHILE PN# < 5
RA% = A1%
RB% = B1%
CX% = 0.3 * W#
VS# = 0
VE# = 8
ES# = 0
EE# = 12
GOSUB WIRESPIN
COLOR 1, RBW#(PN#)
GOSUB WIREDRAW
RA% = A2%
RB% = B2%
CX% = 0.7 * W#
VS# = 8
VE# = 14
ES# = 12
EE# = 24
GOSUB WIRESPIN
GOSUB WIREDRAW
A1% = A1% + 0.3
B1% = B1% + 0.19
A2% = A2% - 0.26
B2% = B2% + 0.17
PN# = PN# + 1
LOOP
GOTO WIREDONE
LABEL WIRELIVE
C1X% = 0.3 * W#
C2X% = 0.7 * W#
DL# = TI# + 360
DO WHILE TI# < DL#
GOSUB SPINSTEP
IF TI# > MT# THEN GOSUB TUNE
GOSUB POLLKEY
IF QF# = 1 THEN EXIT
GOSUB VSYNC
LOOP
IF QF# = 1 THEN GOTO WIREDONE
REM Converge: the two solids drift to the shared centre, spinning
REM the whole way in.
XS1% = (0.2 * W#) / 36
GF# = 0
DO WHILE GF# < 36
C1X% = C1X% + XS1%
C2X% = C2X% - XS1%
GOSUB SPINSTEP
IF TI# > MT# THEN GOSUB TUNE
GOSUB POLLKEY
GOSUB VSYNC
GF# = GF# + 1
LOOP