| 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 |