A Documenting of a Tetris CHIP-8 Game This is my documenting of the Tetris game submitted to the fourth Octo Jam event. Given this game's large size, I will only show it fully documented and fragmented, with the explanations interspersed. This game is notable, and I chose it, because it was apparently written by-hand, and I can see this. The register usage is as follows, less detailed due to the game's large size: V0 Serve as a scratch register, an index, and miscellaneous purposes. V1 Serve as the horizontal sprite coordinate. V2 Serve as the vertical sprite coordinate. V3 Hold the piece rotation code, and later the height. V4 Hold the piece code. V5 Hold the next piece code. V6 Hold the low score. V7 Hold an initial key, and hold a shifting code. V8 unused V9 unused VA Hold the high score. VB Serve as a toggle. VC Hold a counter. VD Hold a counter. VE Hold a counter, and indexed codes. VF Hold key codes, manipulate the delay and sound registers, detect collision, hold constants, etc.. The game clears the screen, draws TETRIS, draws a symbol I don't understand, then waiting for a key: 200-201 0512-0513 ▄▄▄ 00E0 00224 Clear the screen 202-203 0514-0515 ▀▀▄ ▄ ▀ 6114 24852 V1 ← 020 204-205 0516-0517 ▀▀ ▄ █▄ 620B 25099 V2 ← 011 206-207 0518-0519 █▄▀ ▄▀▄ A4CA 42186 I ← te 208-209 0520-0521 ▀▀▄▀ ▄ █ D125 53541 Draw 08×05 at V1,V2; VF ← XOR 20A-20B 0522-0523 █▄▀ ▄█▄▄ A4CF 42191 I ← tr 20C-20D 0524-0525 ▀▀▀▄ ▀ 7108 28936 V1 ← V1 + 008 20E-20F 0526-0527 ▀▀▄▀ ▄ █ D125 53541 Draw 08×05 at V1,V2; VF ← XOR 210-211 0528-0529 █▄▀▄ █ A4D4 42196 I ← is 212-213 0530-0531 ▀▀▀▄ ▀ 7108 28936 V1 ← V1 + 008 214-215 0532-0533 ▀▀▄▀ ▄ █ D125 53541 Draw 08×05 at V1,V2; VF ← XOR 216-217 0534-0535 ▀▀▀▄ ▀ 7208 29192 V2 ← V2 + 008 218-219 0536-0537 ▄███ ▄█ 71F3 29171 V1 ← V1 + 243 21A-21B 0538-0539 █▄▀ ▀▄ A4C2 42178 I ← left symbol 21C-21D 0540-0541 ▀▀▄▀ ▄ ▀ D124 53540 Draw 08×04 at V1,V2; VF ← XOR 21E-21F 0542-0543 █▄▀ █▄ A4C6 42182 I ← right symbol 220-221 0544-0545 ▀▀▀▄ ▀ 7108 28936 V1 ← V1 + 008 222-223 0546-0547 ▀▀▄▀ ▄ ▀ D124 53540 Draw 08×04 at V1,V2; VF ← XOR 224-225 0548-0549 ▀▀▀▀▄▀█▀ F70A 63242 V7 ← key The screen is cleared, the key code is multiplied by four, and that U-shaped playing field is drawn: 226-227 0550-0551 ▄▄▄ 00E0 00224 Clear the screen 228-229 0552-0553 ▀▄▄▄▄██▀ 877E 34686 V7 ← V7 × 2; VF ← MSB 22A-22B 0554-0555 ▀▄▄▄▄██▀ 877E 34686 V7 ← V7 × 2; VF ← MSB 22C-22D 0556-0557 ▀▀▄▄ █ 621A 25114 V2 ← 026 22E-22F 0558-0559 ▄█▄ █ 2474 09332 Call draw bottom 230-231 0560-0561 ▀▄▀ ▀█ A341 41793 I ← border 232-233 0562-0563 ▀▀▄▄ ▄▀ 611A 24858 V1 ← 026 234-235 0564-0565 ▀▀ ▄▀▄ 6205 25093 V2 ← 005 236-237 0566-0567 ▀▀▄▀▄ ▄█ D12B 53547 Draw 08×11 at V1,V2; VF ← XOR 238-239 0568-0569 ▀▀▀▄ █▄ 720B 29195 V2 ← V2 + 011 23A-23B 0570-0571 ▀▀▄▀▄ ▄█ D12B 53547 Draw 08×11 at V1,V2; VF ← XOR 23C-23D 0572-0573 ▀▀▀▄ ▄█ 710B 28939 V1 ← V1 + 011 23E-23F 0574-0575 ▀▀▄▀▄ ▄█ D12B 53547 Draw 08×11 at V1,V2; VF ← XOR 240-241 0576-0577 ▄███ ▄▀▄ 72F5 29429 V2 ← V2 + 245 242-243 0578-0579 ▀▀▄▀▄ ▄█ D12B 53547 Draw 08×11 at V1,V2; VF ← XOR The score counters are initialized to zero, and the four digit score is displayed; the score is four digits, but the leftmost digit is a fiction. The positions are initialized and the piece is chosen: 244-245 0580-0581 ▀▀ ▀▀ 6600 26112 V6 ← 000 246-247 0582-0583 ▀▀ ▀ ▀ 6A00 27136 VA ← 000 248-249 0584-0585 █ ▄█ 242C 09260 Call show score 24A-24B 0586-0587 ▀▀▄▄ ▀ C430 50224 V4 ← ??? AND 048 24C-24D 0588-0589 ▀█▄▄ ▄█ 613B 24891 V1 ← 059 24E-24F 0590-0591 ▀▀ ▀▄ 6201 25089 V2 ← 001 250-251 0592-0593 ▀▀ ▀▀▀▀ 6F00 28416 VF ← 000 252-253 0594-0595 ▀▀█▀█▀▀█ FF29 65321 I ← digit sprite of VF 254-255 0596-0597 ▀▀▄▀ ▄ █ D125 53541 Draw 08×05 at V1,V2; VF ← XOR 256-257 0598-0599 ▄▄▄█▄ ▀ 12F8 04856 Jump to new piece The prime loop manages the delay in a queer, seemingly incorrect fashion, whilst maintaining several decreasing counters, and falls into the code conditionally selected anyway. I doubt it truly works: 258-259 0600-0601 ▀▀▀▀▀███ FF07 65287 prime VF ← delay 25A-25B 0602-0603 ▀▀▀▀▀▀ 3F00 16128 Skip next if VF = 000 25C-25D 0604-0605 ▄▄▀▄▄█ 126E 04718 Jump to left 25E-25F 0606-0607 ▀▀▀▀ 3C00 15360 Skip next if VC = 000 260-261 0608-0609 ▄█████▄▄ 7CFF 31999 VC ← VC + 255 262-263 0610-0611 ▀▀▀▀ ▀ 3D00 15616 Skip next if VD = 000 264-265 0612-0613 ▄█████▄█ 7DFF 32255 VD ← VD + 255 266-267 0614-0615 ▀▀▀▀▀ 3E00 15872 Skip next if VE = 000 268-269 0616-0617 ▄██████▄ 7EFF 32511 VE ← VE + 255 26A-26B 0618-0619 ▀▀ ▀▀▀█ 6F01 28417 VF ← 001 26C-26D 0620-0621 ▀▀▀█▀█▀█ FF15 65301 delay ← VF The code which controls moving the piece left probes for a key twice, to connect related conditions, which is something I avoid, as it's not guaranteed keys will be probed for it to work properly; this is endemic throughout the program. The game attempts to draw the piece, moving back upon collision: 26E-26F 0622-0623 ▀▀ ▀█▀▀ 6F04 28420 left VF ← 004 270-271 0624-0625 █▀▀▄███▀ EF9E 61342 Skip next if VF = key 272-273 0626-0627 ▀▀ ▀▀ 6C00 27648 VC ← 000 274-275 0628-0629 █▀▀▄███▀ EF9E 61342 Skip next if VF = key 276-277 0630-0631 ▄ ▀▄▄█ 128E 04750 Jump to right 278-279 0632-0633 ▀▀▀▀ 3C00 15360 Skip next if VC = 000 27A-27B 0634-0635 ▄ ▀▄▄█ 128E 04750 Jump to right 27C-27D 0636-0637 ▀▀ █▀ ▄ 6C09 27657 VC ← 009 27E-27F 0638-0639 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 280-281 0640-0641 ▄███▄▄▄█ 71FF 29183 V1 ← V1 + 255 282-283 0642-0643 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 284-285 0644-0645 ▀▀▀▀▀█ 3F01 16129 Skip next if VF = 001 286-287 0646-0647 ▄ ▀▄▄█ 128E 04750 Jump to right 288-289 0648-0649 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 28A-28B 0650-0651 ▀▀▀ █ 7101 28929 V1 ← V1 + 001 28C-28D 0652-0653 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra That code for moving right is very similar to that for moving left, and could've been parameterized: 28E-28F 0654-0655 ▀▀ ▀█▀█ 6F05 28421 right VF ← 005 290-291 0656-0657 █▀▀▄███▀ EF9E 61342 Skip next if VF = key 292-293 0658-0659 ▀▀ ▀▀ ▀ 6D00 27904 VD ← 000 294-295 0660-0661 █▀▀▄███▀ EF9E 61342 Skip next if VF = key 296-297 0662-0663 ▄ ▄▀▄▄█ 12AE 04782 Jump to rotate 298-299 0664-0665 ▀▀▀▀ ▀ 3D00 15616 Skip next if VD = 000 29A-29B 0666-0667 ▄ ▄▀▄▄█ 12AE 04782 Jump to rotate 29C-29D 0668-0669 ▀▀ █▀ █ 6D09 27913 VD ← 009 29E-29F 0670-0671 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2A0-2A1 0672-0673 ▀▀▀ █ 7101 28929 V1 ← V1 + 001 2A2-2A3 0674-0675 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2A4-2A5 0676-0677 ▀▀▀▀▀█ 3F01 16129 Skip next if VF = 001 2A6-2A7 0678-0679 ▄ ▄▀▄▄█ 12AE 04782 Jump to rotate 2A8-2A9 0680-0681 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2AA-2AB 0682-0683 ▄███▄▄▄█ 71FF 29183 V1 ← V1 + 255 2AC-2AD 0684-0685 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra The rotate code is, again, very similar, changing the rotation index instead of position: 2AE-2AF 0686-0687 ▀▀ ██▀█ 6F0D 28429 rotate VF ← 013 2B0-2B1 0688-0689 █▀▀▄███▀ EF9E 61342 Skip next if VF = key 2B2-2B3 0690-0691 ▀▀ ▀ ▀▀ 6B00 27392 VB ← 000 2B4-2B5 0692-0693 █▀▀▄███▀ EF9E 61342 Skip next if VF = key 2B6-2B7 0694-0695 ▄▄ ▀▄▄█ 12CE 04814 Jump to down 2B8-2B9 0696-0697 ▀▀▀ ▀▀ 3B00 15104 Skip next if VB = 000 2BA-2BB 0698-0699 ▄▄ ▀▄▄█ 12CE 04814 Jump to down 2BC-2BD 0700-0701 ▀▀ ▀ ▀█ 6B01 27393 VB ← 001 2BE-2BF 0702-0703 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2C0-2C1 0704-0705 ▀▀▀ ▄▀▀ 7304 29444 V3 ← V3 + 004 2C2-2C3 0706-0707 ▄ █▄▄▄▀▀ 23BC 09148 Call align and draw 2C4-2C5 0708-0709 ▀▀▀▀▀█ 3F01 16129 Skip next if VF = 001 2C6-2C7 0710-0711 ▄▄ ▀▄▄█ 12CE 04814 Jump to down 2C8-2C9 0712-0713 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2CA-2CB 0714-0715 ▄███▄▄▀▀ 73FC 29692 V3 ← V3 + 252 2CC-2CD 0716-0717 ▄ █▄▄▄▀▀ 23BC 09148 Call align and draw This routine appears to do naught but permit the piece to be dropped more quickly: 2CE-2CF 0718-0719 ▀ ▀▀▀ 4E00 19968 down Skip next if VE <> 000 2D0-2D1 0720-0721 ▄▄ █▄▄█ 12DE 04830 Jump to set 2D2-2D3 0722-0723 ▀▀ ▀███ 6F07 28423 VF ← 007 2D4-2D5 0724-0725 █▀▀▄███▀ EF9E 61342 Skip next if VF = key 2D6-2D7 0726-0727 ▄ █▄ ▀ 1258 04696 Jump to prime 2D8-2D9 0728-0729 ▀▀▀▀▀▄ 3E01 15873 Skip next if VE = 001 2DA-2DB 0730-0731 ▀▀ ▀▀█ 6E02 28162 VE ← 002 2DC-2DD 0732-0733 ▄ █▄ ▀ 1258 04696 Jump to prime The set routine is responsible for moving the piece down, and stopping it, when it contacts another. It sounds, calls clear line, and then calls the preview routine, to clear and prepare for that next: 2DE-2DF 0734-0735 ▀ ▀▀▀ 8E00 36352 set VE ← V0 2E0-2E1 0736-0737 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2E2-2E3 0738-0739 ▀▀▀ ▀▄ 7201 29185 V2 ← V2 + 001 2E4-2E5 0740-0741 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2E6-2E7 0742-0743 ▀▀▀▀▀█ 3F01 16129 Skip next if VF = 001 2E8-2E9 0744-0745 ▄ █▄ ▀ 1258 04696 Jump to prime 2EA-2EB 0746-0747 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2EC-2ED 0748-0749 ▄███▄▄█▄ 72FF 29439 V2 ← V2 + 255 2EE-2EF 0750-0751 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 2F0-2F1 0752-0753 ▀▀ ▀▀██ 6F03 28419 VF ← 003 2F2-2F3 0754-0755 ▀▀▀██▀▀▀ FF18 65304 sound ← VF 2F4-2F5 0756-0757 ▄▄█ ▄ ▀▀ 23E8 09192 Call clear line 2F6-2F7 0758-0759 █▄ ▄▀▀ 2334 09012 Call preview The new piece routine begins by transferring the next piece datum to the current piece register, and oddly uses the initial key code for determining some of this information. I find it a queer action: 2F8-2F9 0760-0761 █▄▀ ▄ █▀ A3CA 41930 new piece I ← table 2FA-2FB 0762-0763 ▀▄▄▄ 8070 32880 V0 ← V7 2FC-2FD 0764-0765 ▀ ▄▄ 8006 32774 V0 ← V0 ÷ 2; VF ← LSB 2FE-2FF 0766-0767 ▀ ▄▄ 8006 32774 V0 ← V0 ÷ 2; VF ← LSB 300-301 0768-0769 ▀▀▀█▄▄▄ F01E 61470 I ← I + V0 302-303 0770-0771 ▀██▀ ▄ ▄ F065 61541 Load V0→V0; I ← I + 01 304-305 0772-0773 ▀ ▀▀▀ 8E00 36352 VE ← V0 306-307 0774-0775 ▀▄ ▄ ▀ 8450 33872 V4 ← V5 The new next piece is determined with a loop which, in principle, could run forever. The next piece is previewed and lose is entered if drawing the now current piece at the top results in a collision: 308-309 0776-0777 ▀█▄▄ ▀ ▀ C570 50544 random V5 ← ??? AND 112 30A-30B 0778-0779 █▄▄ ▀ ▀ 4570 17776 Skip next if V5 <> 112 30C-30D 0780-0781 ▀▄ ▀▀ 1308 04872 Jump to random 30E-30F 0782-0783 █▄ ▄▀▀ 2334 09012 Call preview 310-311 0784-0785 ▀▀▄▄▄▄▀ 611E 24862 V1 ← 030 312-313 0786-0787 ▀▀ ▄▀▄ 6205 25093 V2 ← 005 314-315 0788-0789 ▀▀ ▀▀ 6300 25344 V3 ← 000 316-317 0790-0791 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 318-319 0792-0793 ▀ ▀▀▀▀ 4F00 20224 Skip next if VF <> 000 31A-31B 0794-0795 ▄ █▄ ▀ 1258 04696 Jump to prime The lose routine merely sounds, repeatedly draws the piece, doing this until key fifteen is pressed: 31C-31D 0796-0797 ▀▀▀█▄ ▀ F218 61976 lose sound ← V2 31E-31F 0798-0799 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 320-321 0800-0801 ▀▀ ▀ ▄ D001 53249 Draw 08×01 at V0,V0; VF ← XOR 322-323 0802-0803 ▄▄▀ ▀▀ 23C0 09152 Call draw tetra 324-325 0804-0805 ▀▀ ████ 6F0F 28431 VF ← 015 326-327 0806-0807 █▀▀▄███▀ EF9E 61342 Skip next if VF = key 328-329 0808-0809 █▄▄▀▀ 131C 04892 Jump to lose The previous routine oddly loops until that same key is released, then oddly drawing over that piece twice, to then restart. The preview routine merely draws that next piece in the specified location: 32A-32B 0810-0811 █▀█ ▀▀▀█ EFA1 61345 previous Skip next if VF <> key 32C-32D 0812-0813 ▄▀▄ █▀ 132A 04906 Jump to previous 32E-32F 0814-0815 ▀▀ ▀ ▄ D001 53249 Draw 08×01 at V0,V0; VF ← XOR 330-331 0816-0817 ▀▀ ▀ ▄ D001 53249 Draw 08×01 at V0,V0; VF ← XOR 332-333 0818-0819 ▀ ▀ 1200 04608 Jump to 0512 334-335 0820-0821 ▀█▄ ▀ 6130 24880 preview V1 ← 048 336-337 0822-0823 ▀▀▄ ▀ 6210 25104 V2 ← 016 338-339 0824-0825 ▀▄▀ ▄▄▀▀ A34C 41804 I ← tetraminoes 33A-33B 0826-0827 ▀▀▀█▄█▄▀ F51E 62750 I ← I + V5 33C-33D 0828-0829 ▄▄ ▀ ▄█▀ 13C6 05062 Jump to finish drawing The game is then followed by a long sea of constants, including all of the piece rotations: 33E 0830 █████ F8 248 bottom 33F 0831 ████████ FF 255 line check 340 0832 ██ C0 192 last check 341 0833 █ 80 128 border 342 0834 █ 80 128 343 0835 █ 80 128 344 0836 █ 80 128 345 0837 █ 80 128 346 0838 █ 80 128 347 0839 █ 80 128 348 0840 █ 80 128 349 0841 █ 80 128 34A 0842 █ 80 128 34B 0843 █ 80 128 34C 0844 00 000 tetraminoes 34D 0845 00 000 34E 0846 ███ E0 224 34F 0847 █ 80 128 350 0848 00 000 351 0849 ██ C0 192 352 0850 █ 40 064 353 0851 █ 40 064 354 0852 00 000 355 0853 █ 20 032 356 0854 ███ E0 224 357 0855 00 000 358 0856 00 000 359 0857 █ 40 064 35A 0858 █ 40 064 35B 0859 ██ 60 096 35C 0860 00 000 35D 0861 00 000 35E 0862 ███ E0 224 35F 0863 █ 20 032 360 0864 00 000 361 0865 █ 40 064 362 0866 █ 40 064 363 0867 ██ C0 192 364 0868 00 000 365 0869 █ 80 128 366 0870 ███ E0 224 367 0871 00 000 368 0872 00 000 369 0873 ██ 60 096 36A 0874 █ 40 064 36B 0875 █ 40 064 36C 0876 00 000 36D 0877 00 000 36E 0878 ████ F0 240 36F 0879 00 000 370 0880 █ 40 064 371 0881 █ 40 064 372 0882 █ 40 064 373 0883 █ 40 064 374 0884 00 000 375 0885 00 000 376 0886 ████ F0 240 377 0887 00 000 378 0888 █ 40 064 379 0889 █ 40 064 37A 0890 █ 40 064 37B 0891 █ 40 064 37C 0892 00 000 37D 0893 00 000 37E 0894 ██ 60 096 37F 0895 ██ 60 096 380 0896 00 000 381 0897 00 000 382 0898 ██ 60 096 383 0899 ██ 60 096 384 0900 00 000 385 0901 00 000 386 0902 ██ 60 096 387 0903 ██ 60 096 388 0904 00 000 389 0905 00 000 38A 0906 ██ 60 096 38B 0907 ██ 60 096 38C 0908 00 000 38D 0909 00 000 38E 0910 ██ C0 192 38F 0911 ██ 60 096 390 0912 00 000 391 0913 █ 40 064 392 0914 ██ C0 192 393 0915 █ 80 128 394 0916 00 000 395 0917 00 000 396 0918 ██ C0 192 397 0919 ██ 60 096 398 0920 00 000 399 0921 █ 40 064 39A 0922 ██ C0 192 39B 0923 █ 80 128 39C 0924 00 000 39D 0925 00 000 39E 0926 ██ 60 096 39F 0927 ██ C0 192 3A0 0928 00 000 3A1 0929 █ 80 128 3A2 0930 ██ C0 192 3A3 0931 █ 40 064 3A4 0932 00 000 3A5 0933 00 000 3A6 0934 ██ 60 096 3A7 0935 ██ C0 192 3A8 0936 00 000 3A9 0937 █ 80 128 3AA 0938 ██ C0 192 3AB 0939 █ 40 064 3AC 0940 00 000 3AD 0941 00 000 3AE 0942 ███ E0 224 3AF 0943 █ 40 064 3B0 0944 00 000 3B1 0945 █ 40 064 3B2 0946 ██ C0 192 3B3 0947 █ 40 064 3B4 0948 00 000 3B5 0949 █ 40 064 3B6 0950 ███ E0 224 3B7 0951 00 000 3B8 0952 00 000 3B9 0953 █ 40 064 3BA 0954 ██ 60 096 3BB 0955 █ 40 064 These two routines interrupt the sea, merely being fine convenience routines for drawing the pieces: 3BC-3BD 0956-0957 ▀▀ ██▀▀ 6F0C 28428 align and draw VF ← 012 3BE-3BF 0958-0959 █▄▄▄ █▀ 83F2 33778 V3 ← V3 AND VF 3C0-3C1 0960-0961 ▀▄▀ ▄▄▀▀ A34C 41804 draw tetra I ← tetraminoes 3C2-3C3 0962-0963 ▀▀▀█▄█▄ F41E 62494 I ← I + V4 3C4-3C5 0964-0965 ▀▀▀█▄▄█▀ F31E 62238 I ← I + V3 3C6-3C7 0966-0967 ▀▀▄▀ ▄ ▀ D124 53540 finish drawing Draw 08×04 at V1,V2; VF ← XOR 3C8-3C9 0968-0969 ▄▄▄ ▄▄▄ 00EE 00238 Return The sea continues with two more constant tables, one being used to hold score information: 3CA 0970 ██ █ █ 35 053 table 3CB 0971 ██ █ 31 049 3CC 0972 █ ██ █ 2D 045 3CD 0973 █ █ █ 29 041 3CE 0974 █ █ █ 25 037 3CF 0975 █ █ 21 033 3D0 0976 ███ 1C 028 3D1 0977 █ ██ 16 022 3D2 0978 █ █ 11 017 3D3 0979 █ ██ 0B 011 3D4 0980 █ █ 0A 010 3D5 0981 █ █ 09 009 3D6 0982 █ 08 008 3D7 0983 ███ 07 007 3D8 0984 ██ 06 006 3D9 0985 ██ 06 006 3DA 0986 █ █ 05 005 3DB 0987 █ █ 05 005 3DC 0988 █ 04 004 3DD 0989 █ 04 004 3DE 0990 ██ 03 003 3DF 0991 ██ 03 003 3E0 0992 █ 02 002 3E1 0993 00 000 3E2 0994 00 000 scores 3E3 0995 █ 01 001 3E4 0996 █ 02 002 3E5 0997 █ 08 008 3E6 0998 ████ 1E 030 3E7 0999 00 000 The clear line routine loads the piece index and then calls loader, which collects the piece height: 3E8-3E9 1000-1001 ▀▀ ▀▀▀ 6E00 28160 clear line VE ← 000 3EA-3EB 1002-1003 ▀▄▀ ▄▄▀▀ A34C 41804 I ← tetraminoes 3EC-3ED 1004-1005 ▀▀▀█▄█▄ F41E 62494 I ← I + V4 3EE-3EF 1006-1007 ▀▀▀█▄▄█▀ F31E 62238 I ← I + V3 3F0-3F1 1008-1009 ▀▀ ▀▀ 6300 25344 V3 ← 000 3F2-3F3 1010-1011 ▀▀▀ █▄ 7203 29187 V2 ← V2 + 003 3F4-3F5 1012-1013 ▄▀ ▄█▄ 244E 09294 Call loader 3F6-3F7 1014-1015 ▄▀ ▄█▄ 244E 09294 Call loader 3F8-3F9 1016-1017 ▄▀ ▄█▄ 244E 09294 Call loader 3FA-3FB 1018-1019 ▄▀ ▄█▄ 244E 09294 Call loader 3FC-3FD 1020-1021 ▀ 4000 16384 Skip next if V0 <> 000 3FE-3FF 1022-1023 ▄███▄▄█▄ 72FF 29439 V2 ← V2 + 255 This simple loop merely exhausts the height, checking each possible line for a clearing: 400-401 1024-1025 ▄▀▄ █▄ 2456 09302 loop Call line clear? 402-403 1026-1027 ▄███▄▄█▄ 72FF 29439 V2 ← V2 + 255 404-405 1028-1029 ▄███▄▄██ 73FF 29695 V3 ← V3 + 255 406-407 1030-1031 ▀▀ ▀▀ 3300 13056 Skip next if V3 = 000 408-409 1032-1033 ▀ ▀ 1400 05120 Jump to loop 40A-40B 1034-1035 ▀ ▀▀▀ 4E00 19968 Skip next if VE <> 000 40C-40D 1036-1037 ▄▄▄ ▄▄▄ 00EE 00238 Return The block shifter routine was puzzling at first, given how move and impress behave, but it's similar to the loop directly preceding it. The score is then adjusted. Note how the game subtracts a value of one hundred from the low score to add to the high score, to properly support a three digit score: 40E-40F 1038-1039 ▄ ▀ █ 2484 09348 block shifter Call move 410-411 1040-1041 ▄███▄▄█▄ 72FF 29439 V2 ← V2 + 255 412-413 1042-1043 ▀▀ ▀ 3400 13312 Skip next if V4 = 000 414-415 1044-1045 ▀▄█▄ 140E 05134 Jump to block shifter 416-417 1046-1047 █▄▄ █▀▀ 87E4 34788 V7 ← V7 + VE; VF ← overflow 418-419 1048-1049 █ ▄█ 242C 09260 Call show score 41A-41B 1050-1051 █▄█ █▀ A3E2 41954 I ← scores 41C-41D 1052-1053 ▀▀▀████ FE1E 65054 I ← I + VE 41E-41F 1054-1055 ▀██▀ ▄ ▄ F065 61541 Load V0→V0; I ← I + 01 420-421 1056-1057 ▀ █▀ 8604 34308 V6 ← V6 + V0; VF ← overflow 422-423 1058-1059 ██ ▀█▀▀ 6F64 28516 VF ← 100 424-425 1060-1061 █▄▄▄ █▀▄ 86F5 34549 V6 ← V6 − VF; VF ← borrow 426-427 1062-1063 ▀ ▀▀▀▀ 4F00 20224 Skip next if VF <> 000 428-429 1064-1065 ██▀ █▀ 7664 30308 V6 ← V6 + 100 42A-42B 1066-1067 █▄▄▄▀▄▀ 8AF4 35572 VA ← VA + VF; VF ← overflow The show score routine cleverly overwrites that first digit of the low score with that last digit of the high score, cleverly calling that draw digit implicitly on the third time, also using its return to return also. The loader simply increments register three based on the empty space of that piece: 42C-42D 1068-1069 █▄▀▄▄█ A4DC 42204 show score I ← 1244 42E-42F 1070-1071 ▀▀██ ▀█▄ F633 63027 V6 as BCD stored from I 430-431 1072-1073 █▄▀▄▄▀▄ A4DA 42202 I ← 1242 432-433 1074-1075 ▀▀██▀ █▄ FA33 64051 VA as BCD stored from I 434-435 1076-1077 ▀█ ▄▄ ▀ 612C 24876 V1 ← 044 436-437 1078-1079 ▀▀ ▀▄ 6201 25089 V2 ← 001 438-439 1080-1081 ▀▀ ▀▀ 6300 25344 V3 ← 000 43A-43B 1082-1083 █▄▄█▄ 243E 09278 Call draw digit 43C-43D 1084-1085 █▄▄█▄ 243E 09278 Call draw digit 43E-43F 1086-1087 █▄▀▄▄█ A4DC 42204 draw digit I ← 1244 440-441 1088-1089 ▀▀▀█▄▄█▀ F31E 62238 I ← I + V3 442-443 1090-1091 ▀▀▀ ▀█ 7301 29441 V3 ← V3 + 001 444-445 1092-1093 ▀██▀ ▄ ▄ F065 61541 Load V0→V0; I ← I + 01 446-447 1094-1095 ▀▀█▀▄ ▄ F029 61481 I ← digit sprite of V0 448-449 1096-1097 ▀▀▄▀ ▄ █ D125 53541 Draw 08×05 at V1,V2; VF ← XOR 44A-44B 1098-1099 ▀▀▀ ▄ █ 7105 28933 V1 ← V1 + 005 44C-44D 1100-1101 ▄▄▄ ▄▄▄ 00EE 00238 Return 44E-44F 1102-1103 ▀██▀ ▄ ▄ F065 61541 loader Load V0→V0; I ← I + 01 450-451 1104-1105 ▀▀ 3000 12288 Skip next if V0 = 000 452-453 1106-1107 ▀▀▀ ▀█ 7301 29441 V3 ← V3 + 001 454-455 1108-1109 ▄▄▄ ▄▄▄ 00EE 00238 Return The line clear? draws a filled line over the row twice, which will result in no collision, if a line be filled; if so, it does the same with another sprite for doing this with the two rightmost blocks: 456-457 1110-1111 ▀▀▄▄ ▄█ 611B 24859 line clear? V1 ← 027 458-459 1112-1113 ▀ █▄▄▄██ A33F 41791 I ← line check 45A-45B 1114-1115 ▀▀▄▀ █ D121 53537 Draw 08×01 at V1,V2; VF ← XOR 45C-45D 1116-1117 ▀▀▄▀ █ D121 53537 Draw 08×01 at V1,V2; VF ← XOR 45E-45F 1118-1119 ▀▀▀▀▀▀ 3F00 16128 Skip next if VF = 000 460-461 1120-1121 ▄ ▀ ▀ 1480 05248 Jump to not quite 462-463 1122-1123 ▀▀▀▄ ▀ 7108 28936 V1 ← V1 + 008 464-465 1124-1125 ▀▄▀ ▀▀ A340 41792 I ← last check 466-467 1126-1127 ▀▀▄▀ █ D121 53537 Draw 08×01 at V1,V2; VF ← XOR 468-469 1128-1129 ▀▀▄▀ █ D121 53537 Draw 08×01 at V1,V2; VF ← XOR 46A-46B 1130-1131 ▀▀▀▀▀▀ 3F00 16128 Skip next if VF = 000 46C-46D 1132-1133 ▄ ▀ ▀ 1480 05248 Jump to not quite 46E-46F 1134-1135 ▀▀▄▀▀▀▀ 6F10 28432 VF ← 016 470-471 1136-1137 ▀▀▀██▀▀▀ FF18 65304 sound ← VF 472-473 1138-1139 ▀▀▀▀▀▀▄ 7E01 32257 VE ← VE + 001 The draw bottom routine draws the bottom of the playing field and also totally clears a row thereof. The not quite routine bails if there be no more blocks to move, otherwise falling into that routine. This following juggle code is rather opaque, but works with impress to build a sprite mold to shift: 474-475 1140-1141 ▀ █▄▄▄█▀ A33E 41790 draw bottom I ← bottom 476-477 1142-1143 ▀▀▄▄ ▄█ 611B 24859 V1 ← 027 478-479 1144-1145 ▀▀▄▀ █ D121 53537 Draw 08×01 at V1,V2; VF ← XOR 47A-47B 1146-1147 ▀▀▀ ▄ █ 7105 28933 V1 ← V1 + 005 47C-47D 1148-1149 ▀▀▄▀ █ D121 53537 Draw 08×01 at V1,V2; VF ← XOR 47E-47F 1150-1151 ▄▄▄ ▄▄▄ 00EE 00238 Return 480-481 1152-1153 ▀ ▀▀▀ 4E00 19968 not quite Skip next if VE <> 000 482-483 1154-1155 ▄▄▄ ▄▄▄ 00EE 00238 Return 484-485 1156-1157 ▀▀▄▄ ▄█ 611B 24859 move V1 ← 027 486-487 1158-1159 ▀▀ ▀ 6400 25600 V4 ← 000 488-489 1160-1161 ▄ █▄▄█ 24BC 09404 Call last call 48A-48B 1162-1163 ▀▀▄▀ █ D121 53537 juggle Draw 08×01 at V1,V2; VF ← XOR 48C-48D 1164-1165 ▀ ▀▀▀█ 4F01 20225 Skip next if VF <> 001 48E-48F 1166-1167 ▀▀▀ ▄ 7004 28676 V0 ← V0 + 004 490-491 1168-1169 ▀ ▄▄▄ 800E 32782 V0 ← V0 × 2; VF ← MSB 492-493 1170-1171 ▀▀▀ █ 7101 28929 V1 ← V1 + 001 494-495 1172-1173 ▀▄ ▀ 4120 16672 Skip next if V1 <> 032 496-497 1174-1175 ▄ ▀▄▄█ 249C 09372 Call impress 498-499 1176-1177 █▀ ▄ █ 3125 12581 Skip next if V1 = 037 49A-49B 1178-1179 ▄ ▀▄▀▄ 148A 05258 Jump to juggle The impress code saves the mold to just past the end of the program, to draw it: 49C-49D 1180-1181 ▄███▄ ▄█ 71FB 29179 impress V1 ← V1 + 251 49E-49F 1182-1183 █▄▀▄▄▀▄ A4DA 42202 I ← 1242 4A0-4A1 1184-1185 ▀ 4000 16384 Skip next if V0 <> 000 4A2-4A3 1186-1187 ▄ ▄█ ▀ 14B0 05296 Jump to transplant 4A4-4A5 1188-1189 ▀▀ ▀ ▄ 6401 25601 V4 ← 001 4A6-4A7 1190-1191 █▄▄ ▄▀ 82E4 33508 V2 ← V2 + VE; VF ← overflow 4A8-4A9 1192-1193 ▀█▀█ ▄ ▄ F055 61525 Save V0→V0; I ← I + 01 4AA-4AB 1194-1195 █▄▀▄▄▀▄ A4DA 42202 I ← 1242 4AC-4AD 1196-1197 ▀▀▄▀ █ D121 53537 Draw 08×01 at V1,V2; VF ← XOR 4AE-4AF 1198-1199 █▄▄ ▄▀▄ 82E5 33509 V2 ← V2 − VE; VF ← borrow The transplant routine draws the adjusted mold; the last call routine is a miscellaneous routine, so called because it serves quite an odd mix of functionality. The game ends with the initial sprites: 4B0-4B1 1200-1201 ▄██▄█▀▀▀ 6FF8 28664 transplant VF ← 248 4B2-4B3 1202-1203 █▄▄▄ ▄▄ 80F3 33011 V0 ← V0 XOR VF 4B4-4B5 1204-1205 ▀█▀█ ▄ ▄ F055 61525 Save V0→V0; I ← I + 01 4B6-4B7 1206-1207 █▄▀▄▄▀▄ A4DA 42202 I ← 1242 4B8-4B9 1208-1209 ▀▀▄▀ █ D121 53537 Draw 08×01 at V1,V2; VF ← XOR 4BA-4BB 1210-1211 ▀▀▀ ▄ █ 7105 28933 V1 ← V1 + 005 4BC-4BD 1212-1213 ▀▀ 6000 24576 last call V0 ← 000 4BE-4BF 1214-1215 ▀▄▀ ▀█ A341 41793 I ← border 4C0-4C1 1216-1217 ▄▄▄ ▄▄▄ 00EE 00238 Return 4C2 1218 █ █ █ █ A5 165 left symbol 4C3 1219 █ █ ███ 97 151 4C4 1220 █ █ █ █ A5 165 4C5 1221 █ ██ █ █ B5 181 4C6 1222 ██ █ █ 69 105 right symbol 4C7 1223 ██ █ █ 65 101 4C8 1224 █ █ █ 49 073 4C9 1225 ██ ██ █ 6D 109 4CA 1226 ███ ███ EE 238 te 4CB 1227 █ █ 48 072 4CC 1228 █ ██ 4C 076 4CD 1229 █ █ 48 072 4CE 1230 █ ███ 4E 078 4CF 1231 ███ ██ EC 236 tr 4D0 1232 █ █ █ 4A 074 4D1 1233 █ ██ 4C 076 4D2 1234 █ █ █ 4A 074 4D3 1235 █ █ █ 4A 074 4D4 1236 ███ ██ E6 230 is 4D5 1237 █ █ 48 072 4D6 1238 █ █ 44 068 4D7 1239 █ █ 42 066 4D8 1240 ███ ██ EC 236 4D9 1241 ██ 0C 012 .