A Documenting of my Ball Breaker CHIP-8 Game This is documentation for the Ball Breaker game of mine own writing. This was created in pursuit of a rather simple mechanism which could be used to demonstrate a compelling game, using a small space. This game has been written to later be improved for the Octo Jam VII event, as with those preceding. Follows is the program upon being loaded into the MMC: 200-201 0512-0513 ▀▄█▄ █▄ A273 41587 I ← from 202-203 0514-0515 ▀██▀▀█▀█ FF65 65381 Load V0→VF; I ← I + 16 204-205 0516-0517 ▀▄█▄ ▄▀ A274 41588 I ← paddle 206-207 0518-0519 ▀█ █ ▀ ▄ D451 54353 Draw 08×01 at V4,V5; VF ← XOR 208-209 0520-0521 ▀▄█▄ █ A272 41586 I ← blocks 20A-20B 0522-0523 ▀█▄▀▀█▀ DE64 56932 draw Draw 08×04 at VE,V6; VF ← XOR 20C-20D 0524-0525 ▀▀▀█▀▀ 7E08 32264 VE ← VE + 008 20E-20F 0526-0527 ▄▀▀▀▀▀ 3E40 15936 Skip next if VE = 064 210-211 0528-0529 ▀▄ █ 120A 04618 Jump to draw 212-213 0530-0531 ▀▀▄▄███▄ CE3F 52799 VE ← ??? AND 063 214-215 0532-0533 ▀▄█▄▄▄▀▄ A27D 41597 I ← ball 216-217 0534-0535 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 218-219 0536-0537 ▀▄█▄▄▄▀▄ A27D 41597 prime I ← ball 21A-21B 0538-0539 ▀▀▀█▀█ ▄ FC15 64533 delay ← VC 21C-21D 0540-0541 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 21E-21F 0542-0543 ▀ ▀ 4200 16896 Skip next if V2 <> 000 220-221 0544-0545 ▄▀▄ ▀ 1228 04648 Jump to continue 222-223 0546-0547 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 224-225 0548-0549 ▀ ▀ ▄█ 8903 35075 V9 ← V9 XOR V0 226-227 0550-0551 ▀▀▀▀ █ 7901 30977 V9 ← V9 + 001 228-229 0552-0553 ▀ ▀▀▀ 4E00 19968 continue Skip next if VE <> 000 22A-22B 0554-0555 ▀▀ ▀ ▄ 6801 26625 V8 ← 001 22C-22D 0556-0557 ▀▄▄███▄ 4E3F 20031 Skip next if VE <> 063 22E-22F 0558-0559 ▄██▄█▄▄▄ 68FF 26879 V8 ← 255 230-231 0560-0561 ▀ ▀▀ 4300 17152 Skip next if V3 <> 000 232-233 0562-0563 ▀▀ ▀ █ 6901 26881 V9 ← 001 234-235 0564-0565 ▀ ▄▄▄██ 431F 17183 Skip next if V3 <> 031 236-237 0566-0567 ▄█ ▄█ 1236 04662 self Jump to self 238-239 0568-0569 █ ▀█▀ 8E84 36484 VE ← VE + V8; VF ← overflow 23A-23B 0570-0571 █ ▄ ▄▀▀ 8394 33684 V3 ← V3 + V9; VF ← overflow 23C-23D 0572-0573 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 23E-23F 0574-0575 █▄▄▄ ▀ 82F0 33520 V2 ← VF 240-241 0576-0577 ▀ ▄▄▄█▀ 431E 17182 Skip next if V3 <> 030 242-243 0578-0579 ▀ ▄ ▀▄▀▄ 8A25 35365 VA ← VA − V2; VF ← borrow 244-245 0580-0581 ▀ ▄▄▄█▀ 431E 17182 Skip next if V3 <> 030 246-247 0582-0583 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 248-249 0584-0585 ▀ ▄▄▄█▀ 431E 17182 Skip next if V3 <> 030 24A-24B 0586-0587 ▀ ▄ ▀▀█▄ 8E23 36387 VE ← VE XOR V2 24C-24D 0588-0589 ▀ ▄ ▀▄▀ 8A24 35364 VA ← VA + V2; VF ← overflow 24E-24F 0590-0591 ▀▄█▄ ▄▀ A274 41588 I ← paddle 250-251 0592-0593 ▀█ █ ▀ ▄ D451 54353 delay Draw 08×01 at V4,V5; VF ← XOR 252-253 0594-0595 █▀▀▄▄██ E69E 59038 left Skip next if V6 = key 254-255 0596-0597 ▄ █▄ █ 125A 04698 Jump to right 256-257 0598-0599 ▀▀ ▀ 3400 13312 Skip next if V4 = 000 258-259 0600-0601 ▄███▄█▄ 74FE 29950 V4 ← V4 + 254 25A-25B 0602-0603 █▀▀▄▄██▀ E79E 59294 right Skip next if V7 = key 25C-25D 0604-0605 ▄▄▀ █ 1262 04706 Jump to move 25E-25F 0606-0607 ██▄▀ 3438 13368 Skip next if V4 = 056 260-261 0608-0609 ▀▀▀ ▀▄ 7402 29698 V4 ← V4 + 002 262-263 0610-0611 ▀█ █ ▀ ▄ D451 54353 move Draw 08×01 at V4,V5; VF ← XOR 264-265 0612-0613 ▀▀▀▀▀███ FF07 65287 VF ← delay 266-267 0614-0615 ▀▀▀▀▀▀ 3F00 16128 Skip next if VF = 000 268-269 0616-0617 ▄ █ ▀ 1250 04688 Jump to delay 26A-26B 0618-0619 ▄▀▄█▀ ▀ 5AB0 23216 Skip next if VA = VB 26C-26D 0620-0621 █▄ ▀ 1218 04632 Jump to prime 26E-26F 0622-0623 ▄▄▄ 00E0 00224 Clear the screen 270-271 0624-0625 ▀ ▀ 1200 04608 Jump to 0512 272 0626 ████████ FF 255 blocks 273 0627 ████████ FF 255 from 274 0628 ████████ FF 255 paddle 275 0629 00 000 276 0630 █ █ 0A 010 277 0631 ███ 1C 028 278 0632 ████ 1E 030 279 0633 █ 04 004 27A 0634 ██ 06 006 27B 0635 █ 01 001 27C 0636 █ 01 001 27D 0637 █ 80 128 ball 27E 0638 █ 40 064 280 0640 █ █ 05 005 281 0641 00 000 The register usage is as follows: V0 Hold a constant. V1 Unused. V2 Store the collision datum, which is also used as a mask. V3 Store the vertical ball coordinate. V4 Store the horizontal paddle coordinate. V5 Store the vertical paddle coordinate. V6 Store the left key constant and the field vertical coordinate. V7 Store the right key constant. V8 Store the ball horizontal delta. V9 Store the ball vertical delta. VA Store the relative collision count and ball sprite. VB Store the relative collision maximum. VC Store the delay. VD Unused. VE Store the horizontal ball and field coordinate. VF Hold the collision datum; manipulate the delay register. It's appropriate to explain the history of these games I've authored. This game was created from my desire to create very small and simple games from very basic instruction sequences. I realized mere conditional redrawing was sufficient to implement block erasure for a ball breaker game. While that code surrounding this is more complex, the core of the game is still very simple. Later, I realized the simplest method available for checking if the field is clear, knowing that total and counting in sync with its destruction. This implementation makes the counting unconditional, but requires a one be used for collision indication; this also has the caveat that the ball must destroy one-at-a-time. The registers were chosen for the following reasons: V0 Ease of access and happenstance. V1 Unused. V2 Ease of access. V3 Ease of access. V4 Ease of access. V5 Ease of access. V6 Ease of access. V7 Ease of access. V8 Ease of access. V9 Ease of access. VA Ease of access. VB Ease of access. VC Ease of access. VD Unused. VE Distance from other registers. VF Unimportance and by its necessity. The game begins by initializing all registers to their initial states, and then drawing that paddle: 200-201 0512-0513 ▀▄█▄ █▄ A273 41587 I ← from 202-203 0514-0515 ▀██▀▀█▀█ FF65 65381 Load V0→VF; I ← I + 16 204-205 0516-0517 ▀▄█▄ ▄▀ A274 41588 I ← paddle 206-207 0518-0519 ▀█ █ ▀ ▄ D451 54353 Draw 08×01 at V4,V5; VF ← XOR The game then draws that field of blocks using a simple loop. Originally, this was intended to be a four-by-sixty-four field, but this introduced a one-off problem with the game finishing calculation, and I ultimately found it simpler to reduce size than to organize the game to begin with a breaking: 208-209 0520-0521 ▀▄█▄ █ A272 41586 I ← blocks 20A-20B 0522-0523 ▀█▄▀▀█▀ DE64 56932 draw Draw 08×04 at VE,V6; VF ← XOR 20C-20D 0524-0525 ▀▀▀█▀▀ 7E08 32264 VE ← VE + 008 20E-20F 0526-0527 ▄▀▀▀▀▀ 3E40 15936 Skip next if VE = 064 210-211 0528-0529 ▀▄ █ 120A 04618 Jump to draw The ball is initialized to a random horizontal coordinate and wastefully drawn before the prime loop is entered. The prime loop sets the delay, wastefully draws the ball, and wastefully undraws it, if register two indicates a collision occurred. The latter two instructions take advantage of the bits in register zero to flip register nine between positive and negative one upon a collision. The idea of the game came about from the realization leading to this block, although not as nice as I prefer: 212-213 0530-0531 ▀▀▄▄███▄ CE3F 52799 VE ← ??? AND 063 214-215 0532-0533 ▀▄█▄▄▄▀▄ A27D 41597 I ← ball 216-217 0534-0535 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 218-219 0536-0537 ▀▄█▄▄▄▀▄ A27D 41597 prime I ← ball 21A-21B 0538-0539 ▀▀▀█▀█ ▄ FC15 64533 delay ← VC 21C-21D 0540-0541 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 21E-21F 0542-0543 ▀ ▀ 4200 16896 Skip next if V2 <> 000 220-221 0544-0545 ▄▀▄ ▀ 1228 04648 Jump to continue 222-223 0546-0547 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 224-225 0548-0549 ▀ ▀ ▄█ 8903 35075 V9 ← V9 XOR V0 226-227 0550-0551 ▀▀▀▀ █ 7901 30977 V9 ← V9 + 001 This block manages the bounds of the game; if the ball hits the bottom of the screen, the game ends: 228-229 0552-0553 ▀ ▀▀▀ 4E00 19968 continue Skip next if VE <> 000 22A-22B 0554-0555 ▀▀ ▀ ▄ 6801 26625 V8 ← 001 22C-22D 0556-0557 ▀▄▄███▄ 4E3F 20031 Skip next if VE <> 063 22E-22F 0558-0559 ▄██▄█▄▄▄ 68FF 26879 V8 ← 255 230-231 0560-0561 ▀ ▀▀ 4300 17152 Skip next if V3 <> 000 232-233 0562-0563 ▀▀ ▀ █ 6901 26881 V9 ← 001 234-235 0564-0565 ▀ ▄▄▄██ 431F 17183 Skip next if V3 <> 031 236-237 0566-0567 ▄█ ▄█ 1236 04662 self Jump to self The game then adds the deltas, and redraws the ball. The collision information is saved in register two, to be unconditionally added to the hit count, with a compensating subtraction for the case when the paddle is hit, using this to determine when the field is clear. Collisions must be zero or one. As a late change, collision with the paddle is wastefully determined thrice to also redraw the ball, and so avoid display errors, and also potentially shifts it by one, to prevent ball journey looping: 238-239 0568-0569 █ ▀█▀ 8E84 36484 VE ← VE + V8; VF ← overflow 23A-23B 0570-0571 █ ▄ ▄▀▀ 8394 33684 V3 ← V3 + V9; VF ← overflow 23C-23D 0572-0573 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 23E-23F 0574-0575 █▄▄▄ ▀ 82F0 33520 V2 ← VF 240-241 0576-0577 ▀ ▄▄▄█▀ 431E 17182 Skip next if V3 <> 030 242-243 0578-0579 ▀ ▄ ▀▄▀▄ 8A25 35365 VA ← VA − V2; VF ← borrow 244-245 0580-0581 ▀ ▄▄▄█▀ 431E 17182 Skip next if V3 <> 030 246-247 0582-0583 ▀▀▄█▀▀▀▄ DE31 56881 Draw 08×01 at VE,V3; VF ← XOR 248-249 0584-0585 ▀ ▄▄▄█▀ 431E 17182 Skip next if V3 <> 030 24A-24B 0586-0587 ▀ ▄ ▀▀█▄ 8E23 36387 VE ← VE XOR V2 24C-24D 0588-0589 ▀ ▄ ▀▄▀ 8A24 35364 VA ← VA + V2; VF ← overflow The paddle is erased, and a delta is collected whilst the remaining delay is exhausted; importantly, the paddle is bounds checked before that delta is changed. A faster paddle makes for a better game: 24E-24F 0590-0591 ▀▄█▄ ▄▀ A274 41588 I ← paddle 250-251 0592-0593 ▀█ █ ▀ ▄ D451 54353 delay Draw 08×01 at V4,V5; VF ← XOR 252-253 0594-0595 █▀▀▄▄██ E69E 59038 left Skip next if V6 = key 254-255 0596-0597 ▄ █▄ █ 125A 04698 Jump to right 256-257 0598-0599 ▀▀ ▀ 3400 13312 Skip next if V4 = 000 258-259 0600-0601 ▄███▄█▄ 74FE 29950 V4 ← V4 + 254 25A-25B 0602-0603 █▀▀▄▄██▀ E79E 59294 right Skip next if V7 = key 25C-25D 0604-0605 ▄▄▀ █ 1262 04706 Jump to move 25E-25F 0606-0607 ██▄▀ 3438 13368 Skip next if V4 = 056 260-261 0608-0609 ▀▀▀ ▀▄ 7402 29698 V4 ← V4 + 002 262-263 0610-0611 ▀█ █ ▀ ▄ D451 54353 move Draw 08×01 at V4,V5; VF ← XOR 264-265 0612-0613 ▀▀▀▀▀███ FF07 65287 VF ← delay 266-267 0614-0615 ▀▀▀▀▀▀ 3F00 16128 Skip next if VF = 000 268-269 0616-0617 ▄ █ ▀ 1250 04688 Jump to delay The program compares the aligned count of struck blocks to a counter relatively aligned to the total amount, and when they're equal the condition is equivalent to determining whether the field be empty or not. If so, the screen is cleared and the game returns to the beginning, to repeat indefinitely. There were originally four rows, but this aligned perfectly with the value for register rollover; it was far too difficult to avoid this, by adjusting the ball to strick a block before that comparison: 26A-26B 0618-0619 ▄▀▄█▀ ▀ 5AB0 23216 Skip next if VA = VB 26C-26D 0620-0621 █▄ ▀ 1218 04632 Jump to prime 26E-26F 0622-0623 ▄▄▄ 00E0 00224 Clear the screen 270-271 0624-0625 ▀ ▀ 1200 04608 Jump to 0512 The game is terminated by the sprites for the blocks and paddle, interleaved with register initials: 272 0626 ████████ FF 255 blocks 273 0627 ████████ FF 255 from 274 0628 ████████ FF 255 paddle 275 0629 00 000 276 0630 █ █ 0A 010 277 0631 ███ 1C 028 278 0632 ████ 1E 030 279 0633 █ 04 004 27A 0634 ██ 06 006 27B 0635 █ 01 001 27C 0636 █ 01 001 27D 0637 █ 80 128 ball 27E 0638 █ 40 064 280 0640 █ █ 05 005 281 0641 00 000 I've successfully crafted another small game to elaborate in that Octo Jam VII with this. This game contains minor inefficiencies I'll correct, and could be made more elaborate. Currently, the paddle merely prevents the ball from falling, but has no true control, which can be easily fixed; it's much easier to test two simple predicates than one slightly more complex, which is why the paddle lies on that penultimate row, but better ball control will combine with better paddle detection, eliminating code and also allowing it to lie on that final row. In sum, it's nice for this simple game to work. .