Fireworks!
A 256 byte intro for Amiga, made for ROMA.EXE 2026. A little fun production that even made it to the 3rd place of the compo! Well, why not, it’s pretty thrilling after all:
The name is a reference to a famous resp. funny scene from The Office US, the DVD logo opening.
So what I was thinking is: Maybe we should have some sort of graphic. Like, if we have a bad quarter, put in a storm cloud. And when we have a good quarter – fireworks!
By a weird coincidence, a production with a very similar name took part in the same competition. That one features actual fireworks, not some obscure reference, and it has sound!
The bytes
This isn’t the most optimized code ever, and I wasted a lot of bytes for pure text data (see below). The dekadence!
- OS overhead
Amiga executable hunk structure
- Code
68000 machine code
- Strings
Escape sequences, a BEL character, and the closing message.
- Data
Scroll variables and constants
00000000: 0000 03f3 0000 0000 0000 0001 0000 0000 ................ 00000010: 0000 0000 0000 0037 0000 03e9 0000 0037 .......7.......7 00000020: 6142 0c9b 3136 759b 3574 9b34 333b 316d aB..16u.5t.43;1m 00000030: 0c9b 3020 709b 3238 780a 7caf af5c 5c20 ..0 p.28x.|..\\ 00000040: 202f 7caf af5c 0a7c 5f5f 2f20 5c2f 207c /|..\.|__/ \/ | 00000050: 5f5f 2f0a 9b33 323b 336d 2056 2049 2044 __/..32;3m V I D 00000060: 2045 204f 7010 286a 00ac 221f 48e7 fffe E Op.(j..".H... 00000070: 7442 4e95 2a6a 0170 2458 2c50 2c6e 009c tBN.*j.p$X,P,n.. 00000080: 2a6d 0038 49fa 0066 34bc 153f 4c9c 00ff *m.8I..f4..?L... 00000090: 5347 6c06 3e02 4440 584b 5346 6c06 3c03 SGl.>.D@XKSFl.<. 000000a0: 4441 514b 48a4 ff00 43ed 0054 7403 760b DAQKH...C..Tt.v. 000000b0: 4eae fe74 41ed 002c 7003 3213 4eae fee0 N..tA..,p.2.N... 000000c0: 5f52 66c8 4cdf 7fff 6118 1b63 576f 7721 _Rf.L...a..cWow! 000000d0: 0720 4974 2068 6170 7065 6e65 6421 203a . It happened! : 000000e0: 290a 221f 7418 4e95 7000 4e75 0002 0001 ).".t.N.p.Nu.... 000000f0: 00ec 008d 027d 00c6 0001 0000 0000 03f2 .....}..........
The code
Short and sweet, nothing fancy. But I did find an ancient bug in the process!
; vasmm68k_mot -Fhunkexe -o fireworks.exe fireworks.asm
SCROLL_X1 = 3
SCROLL_Y1 = 11
SCROLL_X2 = 637
SCROLL_Y2 = 198
AMOUNT_X = (SCROLL_X2-SCROLL_X1-9*18)/2
AMOUNT_Y = (SCROLL_Y2-SCROLL_Y1-9*5-1)
bsr.b .tend
.txt dc.b 12 ; form feed = clear
dc.b $9b,'16u' ; 16 chars wide window
dc.b $9b,'5t' ; 5 rows high window
dc.b $9b,'43;1m' ; bg #3, bold
dc.b 12
dc.b $9b,'0 p' ; cursor off
dc.b $9b,'28x' ; left margin 28 px
dc.b 10
dc.b '|¯¯\\ /|¯¯\',10 ; '¯' = $af (macron)
dc.b '|__/ \/ |__/',10
dc.b $9b,'32;3m' ; fg #2, italics
dc.b ' V I D E O'
.tend moveq #16,d0 ; bcpl stack
move.l 172(a2),a4 ; writeoutput
move.l (a7)+,d1 ; text (APTR)
movem.l d0-a6,-(a7) ; save for end msg
moveq #.tend-.txt,d2 ; length
jsr (a5) ; a0 will be 0, a3 = next PC
move.l 368(a2),a5 ; intuition
move.l (a0)+,a2 ; a2 = 0, a0 = 4
move.l (a0),a6 ; exec
move.l 156(a6),a6 ; graphics
move.l 56(a5),a5 ; intuition.ib_ActiveScreen
lea .data(pc),a4
move.w #777*7,(a2) ; global countdown
.loop movem.w (a4)+,d0-d7 ; fetch variables
subq.w #1,d7 ; x countdown
bge.b .norx ; flip?
move.w d2,d7 ; AMOUNT_X
neg.w d0
addq.w #4,a3 ; change color
.norx subq.w #1,d6 ; y countdown
bge.b .nory ; flip?
move.w d3,d6 ; AMOUNT_Y
neg.w d1
subq.w #8,a3 ; change color
.nory movem.w d0-d7,-(a4) ; write variables back
lea 84(a5),a1 ; screen.sc_RastPort
moveq #SCROLL_X1,d2
moveq #SCROLL_Y1,d3
jsr -396(a6) ; ScrollRaster
lea 44(a5),a0 ; screen.sc_ViewPort
moveq #3,d0 ; color #3
move.w (a3),d1 ; d1 = red
jsr -288(a6) ; SetRGB4
subq.w #7,(a2)
bne.b .loop
movem.l (a7)+,d0-a6 ; restore BCPL env
bsr.b .t2end
.txt2 dc.b $1b,'c' ; terminal reset
dc.b 'Wow!',7,' It happened! :)',10
.t2end move.l (a7)+,d1
moveq #.t2end-.txt2,d2
jsr (a5) ; writeoutput
moveq #0,d0 ; clean exit
rts
.data dc.w 2 ; dx
dc.w 1 ; dy
dc.w AMOUNT_X
dc.w AMOUNT_Y
dc.w SCROLL_X2 ; xmax
dc.w SCROLL_Y2 ; ymax
dc.w 1 ; y to go
dc.w 0 ; x to go
I’m using a new byte-saving trick I learned from STI’s VCCC 2024 code. Props and thanks to Saturnus the Invincible/SCA!
To load a PC-relative address into a non-address register, usually you do this:
lea .text(pc),a0 ; 41fa 000e
move.l a0,d1 ; 2208
.text dc.b 'Text...',0
If your data has an even number of bytes you can use
bsr to push its location onto the stack.
Cram your data into the code and transfer the “return address” into the target data register –
two bytes saved!
bsr.b .cont ; 6108 .text dc.b 'Text...',0 .cont move.l (a7)+,d1 ; 221f


