Add GPL3 notices and a copy of the GPL3.
[zx-fizzbuzz] / fizzbuzz.s
1 ;;; -*-asm-*-
2 ;;; (c) 2021 Mark Wooding
3 ;;;
4 ;;; Best not to ask why.
5
6 ;;;----- Licensing notice ---------------------------------------------------
7 ;;;
8 ;;; This file is part of ZX Fizzbuzz.
9 ;;;
10 ;;; ZX Fizzbuzz is free software: you can redistribute it and/or modify it
11 ;;; under the terms of the GNU Lesser General Public License as published
12 ;;; by the Free Software Foundation; either version 3 of the License, or
13 ;;; (at your option) any later version.
14 ;;;
15 ;;; ZX Fizzbuzz is distributed in the hope that it will be useful, but
16 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ;;; Lesser General Public License for more details.
19 ;;;
20 ;;; You should have received a copy of the GNU Lesser General Public
21 ;;; License along with ZX Fizzbuzz. If not, see
22 ;;; <https://www.gnu.org/licenses/>.
23
24 ;; Look at the buffer and decide what to do.
25 again: ld e, 0
26
27 ;; First, decide whether it's a multiple of three. This is a bit
28 ;; fiddly.
29 ld a, (len)
30 ld b, a
31 ld hl, buf
32 xor a
33
34 ;; Main `mod 3' loop. Load a byte and add it into the accumulator in
35 ;; decimal.
36 mod3: ld c, (hl)
37 inc hl
38 add a, c
39 daa
40 jr nc, mod3_1
41 call squish
42 add a, 1
43 daa
44 mod3_1: djnz mod3
45
46 call squish
47 call squish
48
49 and a
50 jr z, prfizz
51 cp 3
52 jr z, prfizz
53 cp 6
54 jr z, prfizz
55 cp 9
56 jr nz, nofizz
57
58 prfizz: ld hl, fizz
59 call print
60 inc e
61
62 ;; Next, decide whether it's a multiple of five. This is easier.
63 nofizz: ld a, (buf)
64 and 0x0f
65 jr z, prbuzz
66 cp 5
67 jr nz, nobuzz
68
69 prbuzz: ld hl, buzz
70 call print
71 jr prnl
72
73 ;; Not a multiple of five. Skip ahead if it was a multiple of three.
74 nobuzz: ld a, e
75 and a
76 jr nz, prnl
77
78 ;; OK, so just print the value.
79 ld hl, buf - 1
80 ld bc, (len)
81 add hl, bc
82 ld b, c
83
84 ld a, (hl)
85 ld d, a
86 srl a
87 srl a
88 srl a
89 srl a
90 jr z, skiplz
91 fixdig
92 print_a
93 skiplz: ld a, d
94 and 0x0f
95 fixdig
96 print_a
97 dec b
98 jr z, prnl
99
100 prdig: dec hl
101 ld a, (hl)
102 ld d, a
103 srl a
104 srl a
105 srl a
106 srl a
107 fixdig
108 print_a
109 ld a, d
110 and 0x0f
111 fixdig
112 print_a
113 djnz prdig
114
115 ;; Print the newline.
116 prnl: ld a, spc
117 print_a
118
119 ;; Increment the counter.
120 ld hl, buf
121 ld a, (len)
122 ld b, a
123 scf
124 incr: ld a, (hl)
125 adc a, 0
126 daa
127 ld (hl), a
128 jp nc, again
129 inc hl
130 djnz incr
131
132 ;; Carry out.
133 ld (hl), 1
134 ld hl, len
135 inc (hl)
136 jp again
137
138 squish:
139 ;; Add the two halves of a.
140 ld c, a
141 and 0x0f
142 srl c
143 srl c
144 srl c
145 srl c
146 add a, c
147 daa
148 ret
149
150 print:
151 ;; Print the string at hl.
152 ld a, (hl)
153 endstrp
154 ret z
155 print_a
156 inc hl
157 jr print
158
159 ;; Initial state. The buffer notionally continues for another 254
160 ;; bytes, but there's no point in including them in the image.
161 len: db 1, 0
162 buf: db 1