A Documenting of my Rule 30 CHIP-8 Program This is documentation for the Rule 30 program I've written. Wanting to use my MMC more and waiting no longer for the sixth OctoJam event, I decided it was past time to write another program and I'll simply improve this program for the event. As with my other programs, only the fully annotated view will be shown here, and so follows is a view of the program when it is first loaded into the tool: 200-201 0512-0513 ÜÜÜÜÜÜÜÜ 00FF 00255 Enable extended mode 202-203 0514-0515 Û ß ÜÛÜ A287 41607 begin I  from 204-205 0516-0517 ßÛÛßßÛßÜ FE65 65125 bar Load V0VE; I  I + 15 206-207 0518-0519 ß ß Üß A204 41476 I  bar 208-209 0520-0521 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 20A-20B 0522-0523 ßßßßÛßÜß FD0A 64778 input VD  key 20C-20D 0524-0525 ß ß Üß A204 41476 I  bar 20E-20F 0526-0527 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 210-211 0528-0529 ß ßßÜß 4D02 19714 Skip next if VD <> 002 212-213 0530-0531 ÜÛÛÛÛÛÛÜ 7EFF 32511 VE  VE + 255 214-215 0532-0533 ß Ûß ß 4D08 19720 Skip next if VD <> 008 216-217 0534-0535 ßßßßßßÜ 7E01 32257 VE  VE + 001 218-219 0536-0537 ß ÜßßÛ 8E12 36370 VE  VE AND V1 21A-21B 0538-0539 ß ÛÛÜÛ 4D0F 19727 Skip next if VD <> 015 21C-21D 0540-0541 ÜÛÜÜß 123C 04668 Jump to automata 21E-21F 0542-0543 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 220-221 0544-0545 ßßßÛ Û 3D05 15621 Skip next if VD = 005 222-223 0546-0547 ßÜ Û 120A 04618 Jump to input 224-225 0548-0549 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 226-227 0550-0551 ßßßÛÛÛÛ FE1E 65054 I  I + VE 228-229 0552-0553 ßÛÛß Ü Ü F065 61541 Load V0V0; I  I + 01 22A-22B 0554-0555 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 22C-22D 0556-0557 ßßßÛÛÛÛ FE1E 65054 I  I + VE 22E-22F 0558-0559 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 230-231 0560-0561 ßÜ ÜÜ 8043 32835 V0  V0 XOR V4 232-233 0562-0563 ßÛßÛ Ü Ü F055 61525 Save V0V0; I  I + 01 234-235 0564-0565 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 236-237 0566-0567 ßßßÛÛÛÛ FE1E 65054 I  I + VE 238-239 0568-0569 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 23A-23B 0570-0571 ßÜ Û 120A 04618 Jump to input 23C-23D 0572-0573 ßßßÛ ÜßÛ F315 62229 automata delay  V3 23E-23F 0574-0575 ÜÛÛÜÛÛÛÜ 6EFF 28415 VE  255 240-241 0576-0577 ßß ßß 6C00 27648 VC  000 242-243 0578-0579 ßßß ßÜ 7201 29185 V2  V2 + 001 244-245 0580-0581 ÛÜÜÜ ß 4278 17016 Skip next if V2 <> 120 246-247 0582-0583 ÜÛÛÛÜÜß 72FC 29436 V2  V2 + 252 248-249 0584-0585 ßßßßßßÜ 7E01 32257 prime VE  VE + 001 24A-24B 0586-0587 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 24C-24D 0588-0589 ßßßÛÛÛÛ FE1E 65054 I  I + VE 24E-24F 0590-0591 ßÛÛß Ü Û F165 61797 Load V0V1; I  I + 02 250-251 0592-0593 ß ßßßß 8F00 36608 rule 30 begins VF  V0 252-253 0594-0595 ß Ü Ü 8011 32785 V0  V0 OR V1 254-255 0596-0597 ÛÜ ÜÜ 80C3 32963 V0  V0 XOR VC 256-257 0598-0599 ÛÜÜÜßß 8CF0 36080 rule 30 ends VC  VF 258-259 0600-0601 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 25A-25B 0602-0603 ßßßÛÛÛÛ FE1E 65054 I  I + VE 25C-25D 0604-0605 ßÛßÛ Ü Ü F055 61525 Save V0V0; I  I + 01 25E-25F 0606-0607 Üßßßßß 3E40 15936 Skip next if VE = 064 260-261 0608-0609 Ü ßÜ ß 1248 04680 Jump to prime 262-263 0610-0611 ßß ßßß 6E00 28160 VE  000 264-265 0612-0613 Û ÛÜÛÛÛÛ AFBF 44991 draw I  4031 266-267 0614-0615 ßßßÛÛÛÛ FE1E 65054 I  I + VE 268-269 0616-0617 ÛÛÜßÜÜÛÜ D2EF 53999 Draw 08x15 at V2,VE; VF  XOR 26A-26B 0618-0619 ßßßÛÛÛÜ 7E0F 32271 VE  VE + 015 26C-26D 0620-0621 ÛÛÛÛß 3E3C 15932 Skip next if VE = 060 26E-26F 0622-0623 ÜÜß Üß 1264 04708 Jump to draw 270-271 0624-0625 ÛÜÛÜÛßÛÛ AFFB 45051 I  4091 272-273 0626-0627 ÛÛÜß Üß D2E4 53988 Draw 08x04 at V2,VE; VF  XOR 274-275 0628-0629 ßßßßßÛÛÛ FF07 65287 delay VF  delay 276-277 0630-0631 ÛßÛ ß Ü E4A1 58529 Skip next if V4 <> key 278-279 0632-0633 ÜÜÜÜÜÜ Ü 00FD 00253 Exit program 27A-27B 0634-0635 ßßßßßß 3F00 16128 Skip next if VF = 000 27C-27D 0636-0637 ÜÜÛ Üß 1274 04724 Jump to delay 27E-27F 0638-0639 ÛÜÜ ÜÛÜ 4277 17015 Skip next if V2 <> 119 280-281 0640-0641 ÜÜÜÜÜÜ 00FC 00252 Scroll  by 04 282-283 0642-0643 ÜÛÜÜß 123C 04668 Jump to automata 284-285 0644-0645 ÜÜÜ 00E0 00224 restart Clear the screen 286-287 0646-0647 ß Û 1202 04610! from Jump to begin 288 0648 ÛÛÛÛÛÛ 3F 063 289 0649 ÛÛÛ Û 74 116 28A 0650 Û Û 0A 010 28B 0651 Û 01 001 The register usage is as follows: V0 Cell manipulation. V1 Cell manipulation; hold a boundary. V2 Horizontal positioning of all drawing. V3 Hold the delay register delay value. V4 Hold a constant for cell manipulation and a key code. V5 Unused. V6 Unused. V7 Unused. V8 Unused. V9 Unused. VA Unused. VB Unused. VC Store a previous cell. VD Store a key. VE Vertical positioning of all drawing. VF Store a temporary result. As this program was written by me, I will discuss the history of the program to a point, as opposed to being a more bare examination. This is the only Rule 30 program written in CHIP-8 I'm aware of. One goal of this program was being small and making novel use of some CHIP-8 particulars. The registers were chosen for the following reasons: V0 Ease of access. V1 Ease of access. V2 Ease of access. V3 Ease of access. V4 Ease of access. V5 Unused. V6 Unused. V7 Unused. V8 Unused. V9 Unused. VA Unused. VB Unused. VC Distance from lower registers. VD Distance from lower registers. VE Distance from lower registers. VF Unimportance and distance from lower registers. The program begins by instating Super CHIP-8 mode and initializing all registers to their decided values or zero. Note that register fifteen isn't initialized purely because the constant FE was to be used as part of the interface and it was recognized early that modifying this instruction would result in the desired constant; by using FE for the interface, the drawing code is simplified: 200-201 0512-0513 ÜÜÜÜÜÜÜÜ 00FF 00255 Enable extended mode 202-203 0514-0515 Û ß ÜÛÜ A287 41607 begin I  from 204-205 0516-0517 ßÛÛßßÛßÜ FE65 65125 bar Load V0VE; I  I + 15 Following that, the bar is drawn at the top of the screen and in the same position that will be used for all drawing in the pattern entry routine: 206-207 0518-0519 ß ß Üß A204 41476 I  bar 208-209 0520-0521 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR Pattern entry involves accepting a key, moving up for two, moving down for eight, and changing the value of a cell for five; the initial value of register one is used for wrapping bounds protection; observe that the bar is erased even when nothing else takes place: 20A-20B 0522-0523 ßßßßÛßÜß FD0A 64778 input VD  key 20C-20D 0524-0525 ß ß Üß A204 41476 I  bar 20E-20F 0526-0527 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 210-211 0528-0529 ß ßßÜß 4D02 19714 Skip next if VD <> 002 212-213 0530-0531 ÜÛÛÛÛÛÛÜ 7EFF 32511 VE  VE + 255 214-215 0532-0533 ß Ûß ß 4D08 19720 Skip next if VD <> 008 216-217 0534-0535 ßßßßßßÜ 7E01 32257 VE  VE + 001 218-219 0536-0537 ß ÜßßÛ 8E12 36370 VE  VE AND V1 Key fifteen is used to end pattern entry and I believe this is a nice key for it: 21A-21B 0538-0539 ß ÛÛÜÛ 4D0F 19727 Skip next if VD <> 015 21C-21D 0540-0541 ÜÛÜÜß 123C 04668 Jump to automata The bar is then redrawn in its new position, which may be the same position, and what remains of the input routine is dedicated to key five, cell modification: 21E-21F 0542-0543 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 220-221 0544-0545 ßßßÛ Û 3D05 15621 Skip next if VD = 005 222-223 0546-0547 ßÜ Û 120A 04618 Jump to input The proper cell is loaded into register zero by initializing I to the base and then adding what is the current vertical coordinate; due to the implicit movement of I by loading, it must be set again. The location of 4031 was chosen in the same way I choose the last three locations for the decimal representation storage; it is chosen because I can't run out of space by using this location and it requires no adjustment based on other program changes: 224-225 0548-0549 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 226-227 0550-0551 ßßßÛÛÛÛ FE1E 65054 I  I + VE 228-229 0552-0553 ßÛÛß Ü Ü F065 61541 Load V0V0; I  I + 01 22A-22B 0554-0555 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 22C-22D 0556-0557 ßßßÛÛÛÛ FE1E 65054 I  I + VE The current value of the cell is then drawn, in order to erase any live cells; it has no effect on cells already dead. The current value is then flipped by the one stored in register four and it is stored back: 22E-22F 0558-0559 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 230-231 0560-0561 ßÜ ÜÜ 8043 32835 V0  V0 XOR V4 232-233 0562-0563 ßÛßÛ Ü Ü F055 61525 Save V0V0; I  I + 01 The I is then set again, as before, and used to draw the new value properly, again only having an effect if the cell is living. The input routine then loops to the beginning: 234-235 0564-0565 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 236-237 0566-0567 ßßßÛÛÛÛ FE1E 65054 I  I + VE 238-239 0568-0569 ÛÛÜß ßÜ D2E1 53985 Draw 08x01 at V2,VE; VF  XOR 23A-23B 0570-0571 ßÜ Û 120A 04618 Jump to input The automata routine is the next and final stage of the program. It begins by setting a delay and initializing the higher registers to appropriate values; note that register two was previously used for the horizontal position of the initial pattern and so can simply be incremented; this is part of the simplification that comes about from using the FE bar pattern for the pattern entry interface: 23C-23D 0572-0573 ßßßÛ ÜßÛ F315 62229 automata delay  V3 23E-23F 0574-0575 ÜÛÛÜÛÛÛÜ 6EFF 28415 VE  255 240-241 0576-0577 ßß ßß 6C00 27648 VC  000 242-243 0578-0579 ßßß ßÜ 7201 29185 V2  V2 + 001 If the horizontal position has reached its end, it is decremented by four: 244-245 0580-0581 ÛÜÜÜ ß 4278 17016 Skip next if V2 <> 120 246-247 0582-0583 ÜÛÛÛÜÜß 72FC 29436 V2  V2 + 252 The prime routine implements the core of the cellular automata, with the automata routine merely being the initialization and looping around it. The vertical position is incremented and again used to collect the appropriate cells. Note that location 4031 is used instead of location 4032 so that the last memory address accessed is 4095, the end of memory: 248-249 0584-0585 ßßßßßßÜ 7E01 32257 prime VE  VE + 001 24A-24B 0586-0587 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 24C-24D 0588-0589 ßßßÛÛÛÛ FE1E 65054 I  I + VE 24E-24F 0590-0591 ßÛÛß Ü Û F165 61797 Load V0V1; I  I + 02 These four instructions form the core of the program and can be modified to change the particular cellular automata implemented. The current cell value is stored in register fifteen as a temporary place; the current cell is compared with the right cell and register twelve stores the left cell; after this, the old current cell is stored as the new left cell, for the next iteration. In doing this, the pattern can be manipulated in-place, yet as if it was modified all at once: 250-251 0592-0593 ß ßßßß 8F00 36608 rule 30 begins VF  V0 252-253 0594-0595 ß Ü Ü 8011 32785 V0  V0 OR V1 254-255 0596-0597 ÛÜ ÜÜ 80C3 32963 V0  V0 XOR VC 256-257 0598-0599 ÛÜÜÜßß 8CF0 36080 rule 30 ends VC  VF The new current cell value is then stored and the prime routine is entered again if not all cells have been updated: 258-259 0600-0601 Û ÛÜÛÛÛÛ AFBF 44991 I  4031 25A-25B 0602-0603 ßßßÛÛÛÛ FE1E 65054 I  I + VE 25C-25D 0604-0605 ßÛßÛ Ü Ü F055 61525 Save V0V0; I  I + 01 25E-25F 0606-0607 Üßßßßß 3E40 15936 Skip next if VE = 064 260-261 0608-0609 Ü ßÜ ß 1248 04680 Jump to prime When all cells have been updated, drawing is performed. Register fourteen is set to zero and loops quatrice, displaying the tallest sprite, fifteen high, in order to display the first sixty cells of the new pattern. Note that eight loopings of eight high would've resulted in shorter code, however this is maximally efficient and it is so rare to be able to draw an entire column of the screen in the most efficient five drawings that I opted to do so: 262-263 0610-0611 ßß ßßß 6E00 28160 VE  000 264-265 0612-0613 Û ÛÜÛÛÛÛ AFBF 44991 draw I  4031 266-267 0614-0615 ßßßÛÛÛÛ FE1E 65054 I  I + VE 268-269 0616-0617 ÛÛÜßÜÜÛÜ D2EF 53999 Draw 08x15 at V2,VE; VF  XOR 26A-26B 0618-0619 ßßßÛÛÛÜ 7E0F 32271 VE  VE + 015 26C-26D 0620-0621 ÛÛÛÛß 3E3C 15932 Skip next if VE = 060 26E-26F 0622-0623 ÜÜß Üß 1264 04708 Jump to draw As it's a constant which cells are those last four, I is set explicitly rather than indirectly by register fourteen and those last four are drawn: 270-271 0624-0625 ÛÜÛÜÛßÛÛ AFFB 45051 I  4091 272-273 0626-0627 ÛÛÜß Üß D2E4 53988 Draw 08x04 at V2,VE; VF  XOR The remaining delay is then exhausted in turn with checking for key one, as that's a good value that was readily available in register four; pressing that key ends the program: 274-275 0628-0629 ßßßßßÛÛÛ FF07 65287 delay VF  delay 276-277 0630-0631 ÛßÛ ß Ü E4A1 58529 Skip next if V4 <> key 278-279 0632-0633 ÜÜÜÜÜÜ Ü 00FD 00253 Exit program 27A-27B 0634-0635 ßßßßßß 3F00 16128 Skip next if VF = 000 27C-27D 0636-0637 ÜÜÛ Üß 1274 04724 Jump to delay The screen is scrolled if the horizontal position is at its end and the automata routine loops; it's noteworthy that this scrolling behavior is what influenced the idea of implementing such a cellular automata program initially: 27E-27F 0638-0639 ÛÜÜ ÜÛÜ 4277 17015 Skip next if V2 <> 119 280-281 0640-0641 ÜÜÜÜÜÜ 00FC 00252 Scroll  by 04 282-283 0642-0643 ÜÛÜÜß 123C 04668 Jump to automata These instructions are not currently used, but will be later; the remainder of the program are those initial values for the lower registers. Note here that the from is overlapped with this ending jump and this case warrants a special display mechanism, indicating that from is not of location 0646 but 0647; orange is the chosen color to contrast nicely with yellow and I noticed a pleasant orange form of decreasing powers of two with one subtracted, RGB 255 127 63: 284-285 0644-0645 ÜÜÜ 00E0 00224 restart Clear the screen 286-287 0646-0647 ß Û 1202 04610! from Jump to begin 288 0648 ÛÛÛÛÛÛ 3F 063 289 0649 ÛÛÛ Û 74 116 28A 0650 Û Û 0A 010 28B 0651 Û 01 001 Those reading this with color terminal codes note that the code for orange is subtly incorrect, to appease those terminal emulators, all I know of, which implement these extended colors incorrectly. This appeasement is disgusting to me, but expected from incompetent programmers who don't read the standards they claim to implement and then insist on incorrect behavior to be compatible. I was initially wanting to wait to write this, to write it for the sixth OctoJam, but decided I'd already waited too long to write another program with my MMC, so long that I'd needed to relearn my own key tables. Instead, this is an initial implementation and I will improve it for that event. It will be noticed that the I adjustment could be made a routine, that the speed could be made able to be changed interactively, that the interface could have a notice, that the cellular automata does not draw on the rightmost column, and that a discovered peculiarity results in an unpleasant pattern eventually overtaking the screen and that I intend to correct this by experimenting with behavior in having the edges of the pattern both be living or only one of which would be living. These changes and perhaps others will be made during that event. It was refreshing to write this program over the time that I did, making a few changes or advancements over many days instead of writing it all in a lone sitting. It was nice to finally implement the hidden address name display in my MMC for this, also. .