Index  Comments

Here is the program itself and the program metadata.

Both of fizzbuzz.chip8 and fizzbuzz.mmc are available under the CC0 Public Domain Dedication.

This is documentation for the fizzbuzz program I've written for the fifth OctoJam event. Firstly, follows is a view of the program when it is first loaded into the tool; as this program was written in the tool, it will only be shown fully annotated with all metadata loaded as well:

200-201 0512-0513 ▀▄█   █  A262 41570                 I ← from
202-203 0514-0515 ▀██▀▀█▀█ FF65 65381                 Load V0→VF; I ← I + 16
204-205 0516-0517 ▀▀▀█ █ █ F515 62741           start delay ← V5
206-207 0518-0519   ▀▀▀  ▀ 3900 14592            fizz Skip next if V9 = 000
208-209 0520-0521    █ ▄▀  1214 04628                 Jump to buzz
20A-20B 0522-0523 ▀▄▀▄ ▄█  A256 41558                 I ← fi
20C-20D 0524-0525 █▀ █▀▄ █ D995 55701                 Draw 08×05 at V9,V9; VF ← XOR
20E-20F 0526-0527 ▀▄█   ▀  A260 41568                 I ← zz
210-211 0528-0529 █▀ █ ▄▀█ D395 54165                 Draw 08×05 at V3,V9; VF ← XOR
212-213 0530-0531  ▀▀ ▀██  6E06 28166                 VE ← 006
214-215 0532-0533   ▀▀▀ ▀  3A00 14848            buzz Skip next if VA = 000
216-217 0534-0535   ▄▀  █  1222 04642                 Jump to n
218-219 0536-0537 ▀▄▀▄▄ █▄ A25B 41563                 I ← bu
21A-21B 0538-0539 ██▄▀▀▄▀▄ DAE5 56037                 Draw 08×05 at VA,VE; VF ← XOR
21C-21D 0540-0541 ▀▄█   ▀  A260 41568                 I ← zz
21E-21F 0542-0543 ██▄▀ ▄▀█ D3E5 54245                 Draw 08×05 at V3,VE; VF ← XOR
220-221 0544-0545  ▀▀ ▀██  6E06 28166                 VE ← 006
222-223 0546-0547   ▀▀▀▀▀  3E00 15872               n Skip next if VE = 000
224-225 0548-0549   ▄█▄ ▀  1238 04664                 Jump to finish
226-227 0550-0551 █▄█▄██▀█ AFFD 45053                 I ← 4093
228-229 0552-0553 ▀▀██▀ ▄▄ F833 63539                 V8 as BCD stored from I
22A-22B 0554-0555 ▀██▀ ▄▀▄ F265 62053                 Load V0→V2; I ← I + 03
22C-22D 0556-0557 ▀▀█▀▄  ▄ F029 61481                 I ← digit sprite of V0
22E-22F 0558-0559 ██▄▀▀█▀▄ DEE5 57061                 Draw 08×05 at VE,VE; VF ← XOR
230-231 0560-0561 ▀▀█▀▄  █ F129 61737                 I ← digit sprite of V1
232-233 0562-0563 ██▄▀ ▄▀█ D3E5 54245                 Draw 08×05 at V3,VE; VF ← XOR
234-235 0564-0565 ▀▀█▀▄ ▀▄ F229 61993                 I ← digit sprite of V2
236-237 0566-0567 ██▄▀ █ ▄ D4E5 54501                 Draw 08×05 at V4,VE; VF ← XOR
238-239 0568-0569  ▀▀▀▀  ▄ 7801 30721          finish V8 ← V8 + 001
23A-23B 0570-0571  ▀▀▀▀  █ 7901 30977                 V9 ← V9 + 001
23C-23D 0572-0573  ▀▀▀▀ ▀▄ 7A01 31233                 VA ← VA + 001
23E-23F 0574-0575  ▀▀ ▀▀▀  6E00 28160                 VE ← 000
240-241 0576-0577  ▀  ▀    4800 18432                 Skip next if V8 <> 000
242-243 0578-0579  ▄ ▀  █  1242 04674             end Jump to end
244-245 0580-0581  ▀  ▀ ▄█ 4903 18691                 Skip next if V9 <> 003
246-247 0582-0583  ▀▀ ▀  ▀ 6900 26880                 V9 ← 000
248-249 0584-0585  ▀  ▀▄▀▄ 4A05 18949                 Skip next if VA <> 005
24A-24B 0586-0587  ▀▀ ▀ ▀  6A00 27136                 VA ← 000
24C-24D 0588-0589 ▀▀▀▀ ▄▄▄ F007 61447           delay V0 ← delay
24E-24F 0590-0591   ▀▀     3000 12288                 Skip next if V0 = 000
250-251 0592-0593  ▄ ▀▄▄▀  124C 04684                 Jump to delay
252-253 0594-0595 ▄▄▄      00E0 00224                 Clear the screen
254-255 0596-0597    ▀ ▄▀  1204 04612                 Jump to start
256     0598      ███ ███    EE   238              fi
257     0599      █    █     84   132
258     0600      ██   █     C4   196
259     0601      █    █     84   132
25A     0602      █   ███    8E   142
25B     0603      ███ █ █    EA   234              bu
25C     0604      █ █ █ █    AA   170
25D     0605      ██  █ █    CA   202
25E     0606      █ █ █ █    AA   170
25F     0607      ███ ███    EE   238
260     0608      ███ ███    EE   238              zz
261     0609        █   █    22   034
262     0610       █   █     44   068            from
263     0611      █   █      88   136
264     0612      ███ ███    EE   238
265     0613          █      08   008
266     0614         █       10   016
267     0615         ████    1E   030

The register usage is as follows:

  1. V0 Load from I and then BCD display; manipulating the delay register.
  2. V1 Load from I and then BCD display.
  3. V2 Load from I and then BCD display.
  4. V3 Horizontal positioning of second sprite for display.
  5. V4 Horizontal positioning of third sprite for display.
  6. V5 Hold the delay register delay value.
  7. V6 Unused.
  8. V7 Unused.
  9. V8 Hold the current number for numerical display.
  10. V9 Hold the current number modulo three for fizz display. Horizontal or vertical positioning of fizz sprites.
  11. VA Hold the current number modulo five for buzz display. Horizontal positioning of bu sprite.
  12. VB Unused.
  13. VC Unused.
  14. VD Unused.
  15. VE Horizontal or vertical positioning of several sprites. Flag to indicate number modularity.
  16. VF Unused.

As this program was written by me, it will contain some history of the tool, rather than simply being a more bare exploration. This is the only fizzbuzz program written in CHIP-8 that I'm aware of. A goal with this was assuming little about peculiars of the environment and being small.

The registers were chosen for the following reasons:

  1. V0 Ease of access and unimportance.
  2. V1 Ease of access.
  3. V2 Ease of access.
  4. V3 Ease of access.
  5. V4 Ease of access.
  6. V5 Ease of access.
  7. V6 Unused.
  8. V7 Unused.
  9. V8 The V9 and VA were being used and this is contiguous with them.
  10. V9 The V3 was already used and nine is a multiple of three.
  11. VA The V9 was being used and ten is a multiple of five.
  12. VB Unused.
  13. VC Unused.
  14. VD Unused.
  15. VE The VF was to be used, but this was chosen on a whim and away from other values.
  16. VF Unused.

The program begins by loading the first registers to unimportant values; loading registers three, four, and five to their only values; and loading all remaining registers to zero:

200-201 0512-0513 ▀▄█   █  A262 41570                 I ← from
202-203 0514-0515 ▀██▀▀█▀█ FF65 65381                 Load V0→VF; I ← I + 16

The program was originally written to load the delay register and wait at the end of the work, but adding this single instruction before the work required no effort, sans shifting code by two, and improves the timing as much as is possible; the delay is half a second:

204-205 0516-0517 ▀▀▀█ █ █ F515 62741           start delay ← V5

The fizz case is handled first. If register nine is zero, this case is skipped; if not, the fi and zz sprites are drawn, using register nine as a zero register, and register fourteen is set to indicate this and also adjust the drawing of any buzz:

206-207 0518-0519   ▀▀▀  ▀ 3900 14592            fizz Skip next if V9 = 000
208-209 0520-0521    █ ▄▀  1214 04628                 Jump to buzz
20A-20B 0522-0523 ▀▄▀▄ ▄█  A256 41558                 I ← fi
20C-20D 0524-0525 █▀ █▀▄ █ D995 55701                 Draw 08×05 at V9,V9; VF ← XOR
20E-20F 0526-0527 ▀▄█   ▀  A260 41568                 I ← zz
210-211 0528-0529 █▀ █ ▄▀█ D395 54165                 Draw 08×05 at V3,V9; VF ← XOR
212-213 0530-0531  ▀▀ ▀██  6E06 28166                 VE ← 006

The buzz case is handled next. If register ten is zero, this case is skipped; if not, the bu and zz sprites are drawn, using register ten as a zero register, and using register fourteen for vertical positioning below any potential fizz sprites. Register fourteen is then set, regardless:

214-215 0532-0533   ▀▀▀ ▀  3A00 14848            buzz Skip next if VA = 000
216-217 0534-0535   ▄▀  █  1222 04642                 Jump to n
218-219 0536-0537 ▀▄▀▄▄ █▄ A25B 41563                 I ← bu
21A-21B 0538-0539 ██▄▀▀▄▀▄ DAE5 56037                 Draw 08×05 at VA,VE; VF ← XOR
21C-21D 0540-0541 ▀▄█   ▀  A260 41568                 I ← zz
21E-21F 0542-0543 ██▄▀ ▄▀█ D3E5 54245                 Draw 08×05 at V3,VE; VF ← XOR
220-221 0544-0545  ▀▀ ▀██  6E06 28166                 VE ← 006

The last case is that of drawing the number, which only occurs if register fourteen is zero; if not, I is set to write the three decimal digits to the very end of the memory space using register eight, the first three registers are loaded with this, and that is then used for display, using register fourteen as a zero register. Note that the program reuses the offsets for the other sprites; this is done to save space and still looks nice:

222-223 0546-0547   ▀▀▀▀▀  3E00 15872               n Skip next if VE = 000
224-225 0548-0549   ▄█▄ ▀  1238 04664                 Jump to finish
226-227 0550-0551 █▄█▄██▀█ AFFD 45053                 I ← 4093
228-229 0552-0553 ▀▀██▀ ▄▄ F833 63539                 V8 as BCD stored from I
22A-22B 0554-0555 ▀██▀ ▄▀▄ F265 62053                 Load V0→V2; I ← I + 03
22C-22D 0556-0557 ▀▀█▀▄  ▄ F029 61481                 I ← digit sprite of V0
22E-22F 0558-0559 ██▄▀▀█▀▄ DEE5 57061                 Draw 08×05 at VE,VE; VF ← XOR
230-231 0560-0561 ▀▀█▀▄  █ F129 61737                 I ← digit sprite of V1
232-233 0562-0563 ██▄▀ ▄▀█ D3E5 54245                 Draw 08×05 at V3,VE; VF ← XOR
234-235 0564-0565 ▀▀█▀▄ ▀▄ F229 61993                 I ← digit sprite of V2
236-237 0566-0567 ██▄▀ █ ▄ D4E5 54501                 Draw 08×05 at V4,VE; VF ← XOR

Registers eight, nine, ten, and fourteen are then set to their new values:

238-239 0568-0569  ▀▀▀▀  ▄ 7801 30721          finish V8 ← V8 + 001
23A-23B 0570-0571  ▀▀▀▀  █ 7901 30977                 V9 ← V9 + 001
23C-23D 0572-0573  ▀▀▀▀ ▀▄ 7A01 31233                 VA ← VA + 001
23E-23F 0574-0575  ▀▀ ▀▀▀  6E00 28160                 VE ← 000

If a full looping of the count has occured, the program ends; note that it would be possible to have the program instead loop indefinitely by simply changing the byte at location 243 to zero. As the program doesn't assume register values or anything of such a sort, it can restart in this way.

240-241 0576-0577  ▀  ▀    4800 18432                 Skip next if V8 <> 000
242-243 0578-0579  ▄ ▀  █  1242 04674             end Jump to end

The remainder of the count for moduli three and five is then computed and assigned:

244-245 0580-0581  ▀  ▀ ▄█ 4903 18691                 Skip next if V9 <> 003
246-247 0582-0583  ▀▀ ▀  ▀ 6900 26880                 V9 ← 000
248-249 0584-0585  ▀  ▀▄▀▄ 4A05 18949                 Skip next if VA <> 005
24A-24B 0586-0587  ▀▀ ▀ ▀  6A00 27136                 VA ← 000

Lastly the remaining delay, if any, is exhausted before the screen is cleared and the next iteration is performed:

24C-24D 0588-0589 ▀▀▀▀ ▄▄▄ F007 61447           delay V0 ← delay
24E-24F 0590-0591   ▀▀     3000 12288                 Skip next if V0 = 000
250-251 0592-0593  ▄ ▀▄▄▀  124C 04684                 Jump to delay
252-253 0594-0595 ▄▄▄      00E0 00224                 Clear the screen
254-255 0596-0597    ▀ ▄▀  1204 04612                 Jump to start

The program ends with the sprites for fi, bu, and zz, followed by the three important values assigned to registers three, four, and five. As the first three registers are assigned no important values from here, they are filled with part of the zz sprite:

256     0598      ███ ███    EE   238              fi
257     0599      █    █     84   132
258     0600      ██   █     C4   196
259     0601      █    █     84   132
25A     0602      █   ███    8E   142
25B     0603      ███ █ █    EA   234              bu
25C     0604      █ █ █ █    AA   170
25D     0605      ██  █ █    CA   202
25E     0606      █ █ █ █    AA   170
25F     0607      ███ ███    EE   238
260     0608      ███ ███    EE   238              zz
261     0609        █   █    22   034
262     0610       █   █     44   068            from
263     0611      █   █      88   136
264     0612      ███ ███    EE   238
265     0613          █      08   008
266     0614         █       10   016
267     0615         ████    1E   030

It was originally figured that an adjustable delay would be implemented, for interactivity, but this wasn't done once size become a greater issue. Also note that the middle of the screen was to be used for display, but using location 0,0 was not only easier and looked nice but also permitted greater reuse of coordinates among sprites, as did displaying fizzbuzz vertically rather than horizontally. The program was originally to reuse a coordinate for the delay, but this delay was 16/60 of a second and the program was 103 bytes; to improve the delay and pad to an even number, an explicit delay was used.