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