| 1 | ;;; -*-asm-*- |
| 2 | ;;; |
| 3 | ;;; Best not to ask why. |
| 4 | |
| 5 | org 0xf000 |
| 6 | |
| 7 | print_a: equ 0x10 |
| 8 | tvflag: equ 0x5c3c |
| 9 | |
| 10 | entry: |
| 11 | ;; Initialize the buffer. |
| 12 | ld a, 1 |
| 13 | ld (buf), a |
| 14 | ld (len), a |
| 15 | |
| 16 | ;; Use the main screen. |
| 17 | xor a |
| 18 | ld (tvflag), a |
| 19 | |
| 20 | ;; Look at the buffer and decide what to do. |
| 21 | again: ld e, 0 |
| 22 | |
| 23 | ;; First, decide whether it's a multiple of three. This is a bit |
| 24 | ;; fiddly. |
| 25 | ld a, (len) |
| 26 | ld b, a |
| 27 | ld hl, buf |
| 28 | xor a |
| 29 | |
| 30 | ;; Main `mod 3' loop. Load a byte and add it into the accumulator in |
| 31 | ;; decimal. |
| 32 | mod3: ld c, (hl) |
| 33 | inc hl |
| 34 | add a, c |
| 35 | daa |
| 36 | jr nc, mod3_1 |
| 37 | call squish |
| 38 | add a, 1 |
| 39 | daa |
| 40 | mod3_1: djnz mod3 |
| 41 | |
| 42 | call squish |
| 43 | call squish |
| 44 | |
| 45 | cp 0 |
| 46 | jr z, prfizz |
| 47 | cp 3 |
| 48 | jr z, prfizz |
| 49 | cp 6 |
| 50 | jr z, prfizz |
| 51 | cp 9 |
| 52 | jr nz, nofizz |
| 53 | |
| 54 | prfizz: ld hl, fizz |
| 55 | call print |
| 56 | inc e |
| 57 | |
| 58 | ;; Next, decide whether it's a multiple of five. This is easier. |
| 59 | nofizz: ld a, (buf) |
| 60 | and 0x0f |
| 61 | jr z, prbuzz |
| 62 | cp 5 |
| 63 | jr nz, nobuzz |
| 64 | |
| 65 | prbuzz: ld hl, buzz |
| 66 | call print |
| 67 | jr prnl |
| 68 | |
| 69 | ;; Not a multiple of five. Skip ahead if it was a multiple of three. |
| 70 | nobuzz: ld a, e |
| 71 | cp 0 |
| 72 | jr nz, prnl |
| 73 | |
| 74 | ;; OK, so just print the value. |
| 75 | ld a, (len) |
| 76 | ld b, 0 |
| 77 | ld c, a |
| 78 | ld hl, buf - 1 |
| 79 | add hl, bc |
| 80 | ld b, c |
| 81 | |
| 82 | ld a, (hl) |
| 83 | ld d, a |
| 84 | srl a |
| 85 | srl a |
| 86 | srl a |
| 87 | srl a |
| 88 | jr z, skiplz |
| 89 | or 0x30 |
| 90 | rst print_a |
| 91 | skiplz: ld a, d |
| 92 | and 0x0f |
| 93 | or 0x30 |
| 94 | rst print_a |
| 95 | dec b |
| 96 | jr z, prnl |
| 97 | |
| 98 | prdig: dec hl |
| 99 | ld a, (hl) |
| 100 | ld d, a |
| 101 | srl a |
| 102 | srl a |
| 103 | srl a |
| 104 | srl a |
| 105 | or 0x30 |
| 106 | rst print_a |
| 107 | ld a, d |
| 108 | and 0x0f |
| 109 | or 0x30 |
| 110 | rst print_a |
| 111 | djnz prdig |
| 112 | |
| 113 | ;; Print the newline. |
| 114 | prnl: ld a, ' ' |
| 115 | rst print_a |
| 116 | |
| 117 | ;; Increment the counter. |
| 118 | ld hl, buf |
| 119 | ld a, (len) |
| 120 | ld b, a |
| 121 | scf |
| 122 | incr: ld a, (hl) |
| 123 | adc a, 0 |
| 124 | daa |
| 125 | ld (hl), a |
| 126 | jp nc, again |
| 127 | inc hl |
| 128 | djnz incr |
| 129 | |
| 130 | ;; Carry out. |
| 131 | ld a, (len) |
| 132 | ld b, 0 |
| 133 | ld c, a |
| 134 | ld hl, buf |
| 135 | add hl, bc |
| 136 | ld (hl), 1 |
| 137 | inc a |
| 138 | ld (len), a |
| 139 | jp again |
| 140 | |
| 141 | squish: |
| 142 | ;; Add the two halves of a. |
| 143 | ld c, a |
| 144 | and 0x0f |
| 145 | srl c |
| 146 | srl c |
| 147 | srl c |
| 148 | srl c |
| 149 | add a, c |
| 150 | daa |
| 151 | ret |
| 152 | |
| 153 | print: |
| 154 | ;; Print the string at hl. |
| 155 | ld a, (hl) |
| 156 | cp 0 |
| 157 | ret z |
| 158 | rst print_a |
| 159 | inc hl |
| 160 | jr print |
| 161 | |
| 162 | fizz: defb "fizz", 0 |
| 163 | buzz: defb "buzz", 0 |
| 164 | |
| 165 | len: defb 0 |
| 166 | buf: defs 256 |