+;;; -*-asm-*-
+;;;
+;;; Best not to ask why.
+
+ org 0xf000
+
+print_a: equ 0x10
+tvflag: equ 0x5c3c
+
+entry:
+ ;; Initialize the buffer.
+ ld a, 1
+ ld (buf), a
+ ld (len), a
+
+ ;; Use the main screen.
+ xor a
+ ld (tvflag), a
+
+ ;; Look at the buffer and decide what to do.
+again: ld e, 0
+
+ ;; First, decide whether it's a multiple of three. This is a bit
+ ;; fiddly.
+ ld a, (len)
+ ld b, a
+ ld hl, buf
+ xor a
+
+ ;; Main `mod 3' loop. Load a byte and add it into the accumulator in
+ ;; decimal.
+mod3: ld c, (hl)
+ inc hl
+ add a, c
+ daa
+ jr nc, mod3_1
+ call squish
+ add a, 1
+ daa
+mod3_1: djnz mod3
+
+ call squish
+ call squish
+
+ cp 0
+ jr z, prfizz
+ cp 3
+ jr z, prfizz
+ cp 6
+ jr z, prfizz
+ cp 9
+ jr nz, nofizz
+
+prfizz: ld hl, fizz
+ call print
+ inc e
+
+ ;; Next, decide whether it's a multiple of five. This is easier.
+nofizz: ld a, (buf)
+ and 0x0f
+ jr z, prbuzz
+ cp 5
+ jr nz, nobuzz
+
+prbuzz: ld hl, buzz
+ call print
+ jr prnl
+
+ ;; Not a multiple of five. Skip ahead if it was a multiple of three.
+nobuzz: ld a, e
+ cp 0
+ jr nz, prnl
+
+ ;; OK, so just print the value.
+ ld a, (len)
+ ld b, 0
+ ld c, a
+ ld hl, buf - 1
+ add hl, bc
+ ld b, c
+
+ ld a, (hl)
+ ld d, a
+ srl a
+ srl a
+ srl a
+ srl a
+ jr z, skiplz
+ or 0x30
+ rst print_a
+skiplz: ld a, d
+ and 0x0f
+ or 0x30
+ rst print_a
+ dec b
+ jr z, prnl
+
+prdig: dec hl
+ ld a, (hl)
+ ld d, a
+ srl a
+ srl a
+ srl a
+ srl a
+ or 0x30
+ rst print_a
+ ld a, d
+ and 0x0f
+ or 0x30
+ rst print_a
+ djnz prdig
+
+ ;; Print the newline.
+prnl: ld a, ' '
+ rst print_a
+
+ ;; Increment the counter.
+ ld hl, buf
+ ld a, (len)
+ ld b, a
+ scf
+incr: ld a, (hl)
+ adc a, 0
+ daa
+ ld (hl), a
+ jp nc, again
+ inc hl
+ djnz incr
+
+ ;; Carry out.
+ ld a, (len)
+ ld b, 0
+ ld c, a
+ ld hl, buf
+ add hl, bc
+ ld (hl), 1
+ inc a
+ ld (len), a
+ jp again
+
+squish:
+ ;; Add the two halves of a.
+ ld c, a
+ and 0x0f
+ srl c
+ srl c
+ srl c
+ srl c
+ add a, c
+ daa
+ ret
+
+print:
+ ;; Print the string at hl.
+ ld a, (hl)
+ cp 0
+ ret z
+ rst print_a
+ inc hl
+ jr print
+
+fizz: defb "fizz", 0
+buzz: defb "buzz", 0
+
+len: defb 0
+buf: defs 256