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