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: [32m200-201 [31m0512-0513 [34m▀▄█▄ █▄ A[4m2[m[34m[4m73[m[34m 41587 [39m I ← from [32m202-203 [31m0514-0515 [34m▀██▀▀█▀█ FF65 65381 [39m Load V0→VF; I ← I + 16 [32m204-205 [31m0516-0517 [34m▀▄█▄ ▄▀ A[4m2[m[34m[4m74[m[34m 41588 [39m I ← paddle [32m206-207 [31m0518-0519 [34m▀█ █ ▀ ▄ D451 54353 [39m Draw 08×01 at V4,V5; VF ← XOR [32m208-209 [31m0520-0521 [34m▀▄█▄ █ A[4m2[m[34m[4m72[m[34m 41586 [39m I ← blocks [32m20A-20B [31m0522-0523 [34m▀█▄▀▀█▀ DE64 56932[33m draw[39m Draw 08×04 at VE,V6; VF ← XOR [32m20C-20D [31m0524-0525 [34m ▀▀▀█▀▀ 7E08 32264 [39m VE ← VE + 008 [32m20E-20F [31m0526-0527 [34m ▄▀▀▀▀▀ 3E40 15936 [39m Skip next if VE = 064 [32m210-211 [31m0528-0529 [34m ▀▄ █ 1[4m2[m[34m[4m0A[m[34m 04618 [39m Jump to draw [32m212-213 [31m0530-0531 [34m▀▀▄▄███▄ CE3F 52799 [39m VE ← ??? AND 063 [32m214-215 [31m0532-0533 [34m▀▄█▄▄▄▀▄ A[4m2[m[34m[4m7D[m[34m 41597 [39m I ← ball [32m216-217 [31m0534-0535 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m218-219 [31m0536-0537 [34m▀▄█▄▄▄▀▄ A[4m2[m[34m[4m7D[m[34m 41597[33m prime[39m I ← ball [32m21A-21B [31m0538-0539 [34m▀▀▀█▀█ ▄ FC15 64533 [39m delay ← VC [32m21C-21D [31m0540-0541 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m21E-21F [31m0542-0543 [34m ▀ ▀ 4200 16896 [39m Skip next if V2 <> 000 [32m220-221 [31m0544-0545 [34m ▄▀▄ ▀ 1[4m2[m[34m[4m28[m[34m 04648 [39m Jump to continue [32m222-223 [31m0546-0547 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m224-225 [31m0548-0549 [34m▀ ▀ ▄█ 8903 35075 [39m V9 ← V9 XOR V0 [32m226-227 [31m0550-0551 [34m ▀▀▀▀ █ 7901 30977 [39m V9 ← V9 + 001 [32m228-229 [31m0552-0553 [34m ▀ ▀▀▀ 4E00 19968[33m continue[39m Skip next if VE <> 000 [32m22A-22B [31m0554-0555 [34m ▀▀ ▀ ▄ 6801 26625 [39m V8 ← 001 [32m22C-22D [31m0556-0557 [34m ▀▄▄███▄ 4E3F 20031 [39m Skip next if VE <> 063 [32m22E-22F [31m0558-0559 [34m▄██▄█▄▄▄ 68FF 26879 [39m V8 ← 255 [32m230-231 [31m0560-0561 [34m ▀ ▀▀ 4300 17152 [39m Skip next if V3 <> 000 [32m232-233 [31m0562-0563 [34m ▀▀ ▀ █ 6901 26881 [39m V9 ← 001 [32m234-235 [31m0564-0565 [34m ▀ ▄▄▄██ 431F 17183 [39m Skip next if V3 <> 031 [32m236-237 [31m0566-0567 [34m ▄█ ▄█ 1[4m2[m[34m[4m36[m[34m 04662[33m self[39m Jump to self [32m238-239 [31m0568-0569 [34m█ ▀█▀ 8E84 36484 [39m VE ← VE + V8; VF ← overflow [32m23A-23B [31m0570-0571 [34m█ ▄ ▄▀▀ 8394 33684 [39m V3 ← V3 + V9; VF ← overflow [32m23C-23D [31m0572-0573 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m23E-23F [31m0574-0575 [34m█▄▄▄ ▀ 82F0 33520 [39m V2 ← VF [32m240-241 [31m0576-0577 [34m ▀ ▄▄▄█▀ 431E 17182 [39m Skip next if V3 <> 030 [32m242-243 [31m0578-0579 [34m▀ ▄ ▀▄▀▄ 8A25 35365 [39m VA ← VA − V2; VF ← borrow [32m244-245 [31m0580-0581 [34m ▀ ▄▄▄█▀ 431E 17182 [39m Skip next if V3 <> 030 [32m246-247 [31m0582-0583 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m248-249 [31m0584-0585 [34m ▀ ▄▄▄█▀ 431E 17182 [39m Skip next if V3 <> 030 [32m24A-24B [31m0586-0587 [34m▀ ▄ ▀▀█▄ 8E23 36387 [39m VE ← VE XOR V2 [32m24C-24D [31m0588-0589 [34m▀ ▄ ▀▄▀ 8A24 35364 [39m VA ← VA + V2; VF ← overflow [32m24E-24F [31m0590-0591 [34m▀▄█▄ ▄▀ A[4m2[m[34m[4m74[m[34m 41588 [39m I ← paddle [32m250-251 [31m0592-0593 [34m▀█ █ ▀ ▄ D451 54353[33m delay[39m Draw 08×01 at V4,V5; VF ← XOR [32m252-253 [31m0594-0595 [34m█▀▀▄▄██ E69E 59038[33m left[39m Skip next if V6 = key [32m254-255 [31m0596-0597 [34m ▄ █▄ █ 1[4m2[m[34m[4m5A[m[34m 04698 [39m Jump to right [32m256-257 [31m0598-0599 [34m ▀▀ ▀ 3400 13312 [39m Skip next if V4 = 000 [32m258-259 [31m0600-0601 [34m▄███▄█▄ 74FE 29950 [39m V4 ← V4 + 254 [32m25A-25B [31m0602-0603 [34m█▀▀▄▄██▀ E79E 59294[33m right[39m Skip next if V7 = key [32m25C-25D [31m0604-0605 [34m ▄▄▀ █ 1[4m2[m[34m[4m62[m[34m 04706 [39m Jump to move [32m25E-25F [31m0606-0607 [34m ██▄▀ 3438 13368 [39m Skip next if V4 = 056 [32m260-261 [31m0608-0609 [34m ▀▀▀ ▀▄ 7402 29698 [39m V4 ← V4 + 002 [32m262-263 [31m0610-0611 [34m▀█ █ ▀ ▄ D451 54353[33m move[39m Draw 08×01 at V4,V5; VF ← XOR [32m264-265 [31m0612-0613 [34m▀▀▀▀▀███ FF07 65287 [39m VF ← delay [32m266-267 [31m0614-0615 [34m ▀▀▀▀▀▀ 3F00 16128 [39m Skip next if VF = 000 [32m268-269 [31m0616-0617 [34m ▄ █ ▀ 1[4m2[m[34m[4m50[m[34m 04688 [39m Jump to delay [32m26A-26B [31m0618-0619 [34m▄▀▄█▀ ▀ 5AB0 23216 [39m Skip next if VA = VB [32m26C-26D [31m0620-0621 [34m █▄ ▀ 1[4m2[m[34m[4m18[m[34m 04632 [39m Jump to prime [32m26E-26F [31m0622-0623 [34m▄▄▄ 00E0 00224 [39m Clear the screen [32m270-271 [31m0624-0625 [34m ▀ ▀ 1200 04608 [39m Jump to 0512 [32m272 [31m0626 [34m████████ FF 255[33m blocks [32m273 [31m0627 [34m████████ FF 255[33m from [32m274 [31m0628 [34m████████ FF 255[33m paddle [32m275 [31m0629 [34m 00 000 [32m276 [31m0630 [34m █ █ 0A 010 [32m277 [31m0631 [34m ███ 1C 028 [32m278 [31m0632 [34m ████ 1E 030 [32m279 [31m0633 [34m █ 04 004 [32m27A [31m0634 [34m ██ 06 006 [32m27B [31m0635 [34m █ 01 001 [32m27C [31m0636 [34m █ 01 001 [32m27D [31m0637 [34m█ 80 128[33m ball [32m27E [31m0638 [34m █ 40 064 [32m280 [31m0640 [34m █ █ 05 005 [32m281 [31m0641 [34m 00 000 [39m 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: [32m200-201 [31m0512-0513 [34m▀▄█▄ █▄ A[4m2[m[34m[4m73[m[34m 41587 [39m I ← from [32m202-203 [31m0514-0515 [34m▀██▀▀█▀█ FF65 65381 [39m Load V0→VF; I ← I + 16 [32m204-205 [31m0516-0517 [34m▀▄█▄ ▄▀ A[4m2[m[34m[4m74[m[34m 41588 [39m I ← paddle [32m206-207 [31m0518-0519 [34m▀█ █ ▀ ▄ D451 54353 [39m 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: [32m208-209 [31m0520-0521 [34m▀▄█▄ █ A[4m2[m[34m[4m72[m[34m 41586 [39m I ← blocks [32m20A-20B [31m0522-0523 [34m▀█▄▀▀█▀ DE64 56932[33m draw[39m Draw 08×04 at VE,V6; VF ← XOR [32m20C-20D [31m0524-0525 [34m ▀▀▀█▀▀ 7E08 32264 [39m VE ← VE + 008 [32m20E-20F [31m0526-0527 [34m ▄▀▀▀▀▀ 3E40 15936 [39m Skip next if VE = 064 [32m210-211 [31m0528-0529 [34m ▀▄ █ 1[4m2[m[34m[4m0A[m[34m 04618 [39m 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: [32m212-213 [31m0530-0531 [34m▀▀▄▄███▄ CE3F 52799 [39m VE ← ??? AND 063 [32m214-215 [31m0532-0533 [34m▀▄█▄▄▄▀▄ A[4m2[m[34m[4m7D[m[34m 41597 [39m I ← ball [32m216-217 [31m0534-0535 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m218-219 [31m0536-0537 [34m▀▄█▄▄▄▀▄ A[4m2[m[34m[4m7D[m[34m 41597[33m prime[39m I ← ball [32m21A-21B [31m0538-0539 [34m▀▀▀█▀█ ▄ FC15 64533 [39m delay ← VC [32m21C-21D [31m0540-0541 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m21E-21F [31m0542-0543 [34m ▀ ▀ 4200 16896 [39m Skip next if V2 <> 000 [32m220-221 [31m0544-0545 [34m ▄▀▄ ▀ 1[4m2[m[34m[4m28[m[34m 04648 [39m Jump to continue [32m222-223 [31m0546-0547 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m224-225 [31m0548-0549 [34m▀ ▀ ▄█ 8903 35075 [39m V9 ← V9 XOR V0 [32m226-227 [31m0550-0551 [34m ▀▀▀▀ █ 7901 30977 [39m V9 ← V9 + 001 This block manages the bounds of the game; if the ball hits the bottom of the screen, the game ends: [32m228-229 [31m0552-0553 [34m ▀ ▀▀▀ 4E00 19968[33m continue[39m Skip next if VE <> 000 [32m22A-22B [31m0554-0555 [34m ▀▀ ▀ ▄ 6801 26625 [39m V8 ← 001 [32m22C-22D [31m0556-0557 [34m ▀▄▄███▄ 4E3F 20031 [39m Skip next if VE <> 063 [32m22E-22F [31m0558-0559 [34m▄██▄█▄▄▄ 68FF 26879 [39m V8 ← 255 [32m230-231 [31m0560-0561 [34m ▀ ▀▀ 4300 17152 [39m Skip next if V3 <> 000 [32m232-233 [31m0562-0563 [34m ▀▀ ▀ █ 6901 26881 [39m V9 ← 001 [32m234-235 [31m0564-0565 [34m ▀ ▄▄▄██ 431F 17183 [39m Skip next if V3 <> 031 [32m236-237 [31m0566-0567 [34m ▄█ ▄█ 1[4m2[m[34m[4m36[m[34m 04662[33m self[39m 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: [32m238-239 [31m0568-0569 [34m█ ▀█▀ 8E84 36484 [39m VE ← VE + V8; VF ← overflow [32m23A-23B [31m0570-0571 [34m█ ▄ ▄▀▀ 8394 33684 [39m V3 ← V3 + V9; VF ← overflow [32m23C-23D [31m0572-0573 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m23E-23F [31m0574-0575 [34m█▄▄▄ ▀ 82F0 33520 [39m V2 ← VF [32m240-241 [31m0576-0577 [34m ▀ ▄▄▄█▀ 431E 17182 [39m Skip next if V3 <> 030 [32m242-243 [31m0578-0579 [34m▀ ▄ ▀▄▀▄ 8A25 35365 [39m VA ← VA − V2; VF ← borrow [32m244-245 [31m0580-0581 [34m ▀ ▄▄▄█▀ 431E 17182 [39m Skip next if V3 <> 030 [32m246-247 [31m0582-0583 [34m▀▀▄█▀▀▀▄ DE31 56881 [39m Draw 08×01 at VE,V3; VF ← XOR [32m248-249 [31m0584-0585 [34m ▀ ▄▄▄█▀ 431E 17182 [39m Skip next if V3 <> 030 [32m24A-24B [31m0586-0587 [34m▀ ▄ ▀▀█▄ 8E23 36387 [39m VE ← VE XOR V2 [32m24C-24D [31m0588-0589 [34m▀ ▄ ▀▄▀ 8A24 35364 [39m 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: [32m24E-24F [31m0590-0591 [34m▀▄█▄ ▄▀ A[4m2[m[34m[4m74[m[34m 41588 [39m I ← paddle [32m250-251 [31m0592-0593 [34m▀█ █ ▀ ▄ D451 54353[33m delay[39m Draw 08×01 at V4,V5; VF ← XOR [32m252-253 [31m0594-0595 [34m█▀▀▄▄██ E69E 59038[33m left[39m Skip next if V6 = key [32m254-255 [31m0596-0597 [34m ▄ █▄ █ 1[4m2[m[34m[4m5A[m[34m 04698 [39m Jump to right [32m256-257 [31m0598-0599 [34m ▀▀ ▀ 3400 13312 [39m Skip next if V4 = 000 [32m258-259 [31m0600-0601 [34m▄███▄█▄ 74FE 29950 [39m V4 ← V4 + 254 [32m25A-25B [31m0602-0603 [34m█▀▀▄▄██▀ E79E 59294[33m right[39m Skip next if V7 = key [32m25C-25D [31m0604-0605 [34m ▄▄▀ █ 1[4m2[m[34m[4m62[m[34m 04706 [39m Jump to move [32m25E-25F [31m0606-0607 [34m ██▄▀ 3438 13368 [39m Skip next if V4 = 056 [32m260-261 [31m0608-0609 [34m ▀▀▀ ▀▄ 7402 29698 [39m V4 ← V4 + 002 [32m262-263 [31m0610-0611 [34m▀█ █ ▀ ▄ D451 54353[33m move[39m Draw 08×01 at V4,V5; VF ← XOR [32m264-265 [31m0612-0613 [34m▀▀▀▀▀███ FF07 65287 [39m VF ← delay [32m266-267 [31m0614-0615 [34m ▀▀▀▀▀▀ 3F00 16128 [39m Skip next if VF = 000 [32m268-269 [31m0616-0617 [34m ▄ █ ▀ 1[4m2[m[34m[4m50[m[34m 04688 [39m 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: [32m26A-26B [31m0618-0619 [34m▄▀▄█▀ ▀ 5AB0 23216 [39m Skip next if VA = VB [32m26C-26D [31m0620-0621 [34m █▄ ▀ 1[4m2[m[34m[4m18[m[34m 04632 [39m Jump to prime [32m26E-26F [31m0622-0623 [34m▄▄▄ 00E0 00224 [39m Clear the screen [32m270-271 [31m0624-0625 [34m ▀ ▀ 1200 04608 [39m Jump to 0512 The game is terminated by the sprites for the blocks and paddle, interleaved with register initials: [32m272 [31m0626 [34m████████ FF 255[33m blocks [32m273 [31m0627 [34m████████ FF 255[33m from [32m274 [31m0628 [34m████████ FF 255[33m paddle [32m275 [31m0629 [34m 00 000 [32m276 [31m0630 [34m █ █ 0A 010 [32m277 [31m0631 [34m ███ 1C 028 [32m278 [31m0632 [34m ████ 1E 030 [32m279 [31m0633 [34m █ 04 004 [32m27A [31m0634 [34m ██ 06 006 [32m27B [31m0635 [34m █ 01 001 [32m27C [31m0636 [34m █ 01 001 [32m27D [31m0637 [34m█ 80 128[33m ball [32m27E [31m0638 [34m █ 40 064 [32m280 [31m0640 [34m █ █ 05 005 [32m281 [31m0641 [34m 00 000 [39m 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.