/GAME OF LIFE /KYLE OWEN - 24 MARCH 2019 /UPDATED - 14 APRIL 2019 /14 APRIL 2019 - ADDED OS/8 SUPPORT /9 APRIL 2019 - ADDED BUGGY FAST RASTER SCAN, STATISTICS, AND NEW RLE PARSER /8 APRIL 2019 - ADDED VC8E SUPPORT FOR BOTH STORAGE AND NON-STORAGE 'SCOPES /FOCAL: 11 BY 11 /BASIC: 32 BY 32 /ASSEMBLY: 192 BY 256 (OR BEYOND?) /THAT WAS THE MAIN REASON FOR WRITING THIS... /PROBABLY WOULD'VE BEEN EASIER TO WRITE IN FORTRAN, THOUGH. /I THINK THERE WAS A DECUS VERSION, BUT I CAN'T FIND IT. /DFIELD SELECTS THE FIELD FOR STORING THE BITMAP /BITMAP IS ORGANIZED AS 192 WIDE BY 256 TALL /WORD 0 BIT 0 IS TOP LEFT, WORD 7777 BIT 11 IS BOTTOM RIGHT /INTERNALLY, BIT NUMBER IS STORED AS A NEGATIVE NUMBER, -14 TO -1 (OCTAL!) /HENCE, BIT IN WORD: /... -3 -2 -1 | -14 -13 -12 -11 ... -3 -2 -1 | -14 -13 -12 ... / WORD - 1 | CURRENT WORD | WORD + 1 /AND, LOOKING JUST AT THE WORDS IN THE BITMAP: /... WORD - WRDCOL - 1 | WORD - WRDCOL | WORD - WRDCOL + 1 ... /... WORD - 1 | CURRENT WORD | WORD + 1 ... /... WORD + WRDCOL - 1 | WORD + WRDCOL | WORD + WRDCOL + 1 ... /IN THIS WORLD, THE SCREEN WRAPS FROM LEFT TO RIGHT, TOP TO BOTTOM /IT WOULDN'T BE HARD TO TERMINATE LIFE AT SCREEN BOUNDARIES, THOUGH /A LITTLE SUMMARY OF OPERATION: /FIRST, BITMAP IS CLEARED, THEN INITIAL CONDITIONS ARE LOADED. /THEN, THREE ROWS ARE COPIED INTO THREE CACHE ROWS. /FOR EACH ROW COPIED, A BIT IN LIFDET IS SET OR CLEARED TO INDICATE WHETHER /OR NOT THE CACHE ACTUALLY HAS ANY LIFE. IF THERE'S NO LIFE, WE CAN TAKE A /SHORTCUT. /SINCE WE START WITH PIXEL (0,0), AKA THE LEFT PIXEL OF THE FIRST ROW, /THE THREE ROWS TO CACHE ARE THE ROW ABOVE US, OUR CURRENT ROW, AND THE /ROW BELOW US. THE ROW ABOVE US IS ACTUALLY THE LAST ROW IN THE BITMAP /BECAUSE OF WRAPPING. /NOW, ASSUMING WE HAVE LIFE IN THE CACHE... /IF YOU ARE INSIDE A WORD SUCH THAT YOU WON'T WRAP TO SURROUNDING WORDS AND THE /WORD IS ZERO, YOU CAN SKIP RIGHT ON TO THE END OF THAT WORD...JUST ANOTHER /OPTIMIZATION FOR SPEED. /OTHERWISE, WE ITERATE THROUGH THE CACHE ROWS, COUNTING EVERY NEIGHBORHOOD OF /9 PIXELS. WHEN WE ARE AT THE EDGE OF A WORD, EITHER BIT 0 (-14) OR /BIT 11 (-1), WE NEED TO COUNT PIXELS IN THE ADJACENT WORDS. OTHERWISE, WE /ONLY CONSIDER OUR CURRENT WORD, PLUS THE WORD ABOVE US AND THE WORD BELOW US, /OF COURSE. /ONCE WE HAVE COUNTED THE NEIGHBORHOOD, WE COMPARE THE TOTAL LIVE CELLS TO 3 /AND 4. IF THE NUMBER OF LIVE CELLS IS 3, THE MIDDLE CELL WILL BE ALIVE. IF /THE NUMBER IS 4, THE MIDDLE CELL WILL REMAIN UNCHANGED. EVERY OTHER SUM /RESULTS IN...DEATH! /ONCE WE ARE TO THE END OF THE CURRENT ROW, THE CACHE MUST BE UPDATED. /FORTUNATELY, THIS IS PRETTY EASY. THE CURRENT (MIDDLE) CACHE ROW BECOMES /THE TOP ROW, THE BOTTOM ROW BECOMES THE CURRENT ROW, AND THE TOP ROW BECOMES /THE BOTTOM ROW. THE BOTTOM ROW OF THE CACHE (FORMERLY THE TOP ROW OF THE /CACHE) IS COPIED OVER WITH THE ROW BELOW THE CURRENT ROW OF THE BITMAP. /INSTEAD OF DOING A BUNCH OF COPYING, WE JUST CHANGE THE POINTERS TO THE CACHE /ROWS, AND ONLY COPY THE ONE NEW ROW. NOT TOO BAD, RIGHT? OH, BE SURE TO UPDATE /LIFDET TO GIVE US A POSSIBLE SHORTCUT IF THERE'S NO MORE LIFE IN THE CACHE FOR /NEXT TIME. /IF THERE'S NO LIFE IN THE CACHE, UPDATE THE CACHE AND TRY AGAIN. /THE PROGRAM USES WORDS 0 TO 7 AS A BIT COUNT LOOKUP TABLE FOR EXTRA SPEED. /MAYBE THERE'S A FASTER WAY TO COUNT BITS? IF SO, PLEASE FORWARD THIS ON TO ME! /THE PROGRAM ALSO USES WORDS 7764 TO 7777 (-14 TO -1, RIGHT?) FOR THE BITMASK. /THERE'S ALSO A ROTATE SUBROUTINE WHICH TRIES TO GO FOR SPEED. MAYBE IT CAN BE /OPTIMIZED AS WELL? /PARTING THOUGHTS: YOU COULD CRAM THIS INTO ONE FIELD IF YOU WANTED TO REDUCE /THE BITMAP SIZE BY A BIT (HEH); WRAPPING VERTICALLY IS NO LONGER QUITE AS /TRIVIAL, THOUGH...FOR AN 8K MACHINE WITH AN OS, I BELIEVE REDUCING THE BITMAP /SIZE WILL BE REQUIRED. /IT TURNS OUT THAT PRINTING TO THE TERMINAL TAKES A...SURPRISINGLY LARGE AMOUNT /OF TIME. /WRDCOL, AKA THE NUMBER OF WORD COLUMNS (AKA THE NUMBER OF WORDS IN A ROW) /SHOULD DEFINITELY BE A POWER OF TWO, AS THE PROGRAM ASSUMES IT WILL BE. /SMALLER WOULD PROBABLY BE FINE, BUT WILL INCREASE THE NUMBER OF ROWS. /BIGGER WOULD BE FINE TOO, GIVEN PAGE ZERO IS DECLUTTERED. /ANOTHER BIG IMPROVEMENT WOULD BE THE ABILITY TO STORE INITIAL CONDITIONS IN /AN EASY TO USE FILE FORMAT, PERHAPS LOADING FROM OS/8 (OR P?S/8). /ADDING THE ABILITY TO NOT PRINT (OR DRAW) TO INCREASE SPEED MAY BE A GOOD /ADDITION. /THE CURLY BRACES IN THE SOURCE COMMENTS ARE SOLELY FOR BRACKET MATCHING, SINCE /GT AND LT SIGNS ARE NOT USED AS MODERN BRACKETS. HELPFUL IF YOU'RE USING VIM /OR EMACS. NOT HELPFUL IF YOU'RE USING EDIT, EDLIN, ETC. /THE FAST RASTER ROUTINE USES MEMORY FROM 8K UP, AND HAS THE POTENTIAL TO WRAP /BACK TO THE ZERO FIELD. NO CHECK IS MADE THAT YOU ARE ABOUT TO OVERFLOW THE /POINT BUFFER; THIS WAS DONE FOR SPEED, RIGHT? THAT SAID, THE MAXIMUM NUMBER /OF POINTS FOR A FINITE ARRAY IS ABOUT 50 PERCENT, SO... / 256*192/2 = 24,576 = 24K. /WORST CASE, I THINK YOU'D NEED JUST A HAIR OVER 24K TO STORE 24K POINTS, /SOMETHING LIKE 256*97+1, I BELIEVE, ASSUMING EVERY ROW HAS 96 POINTS, WHICH /MEANS WE'D BE REALLY CLOSE. FORTUNATELY, THE WORLD WRAPS, SO THE MAX FILLER /AND SUCH DIE BEFORE YOU GET ANYWHERE CLOSE TO 50 PERCENT. THIS STILL HAS SOME /BUGS TO BE WORKED OUT; IT SEEMS LIKE THE ROUTINE IS SKIPPING TOO MANY LINES /SOMETIMES. IT DOES SEEM TO BE MUCH FASTER, THOUGH! /STATISTICS INCLUDE THE GENERATION NUMBER AND THE NUMBER OF LIVE CELLS. BOTH /ARE STORED AS DOUBLE WORDS. IF YOU OVERFLOW EITHER, ALL BETS ARE OFF. I'M NOT /REALLY SURE HOW YOU WOULD GET UP THAT HIGH FOR EITHER, THOUGH. /PRINTING THE NUMBERS WAS FUN. THIS USES A 24-BIT IMPLEMENTATION OF THE /DOUBLE-DABBLE ALGORITHM, ALONG WITH A SIMPLE MEANS OF LEADING ZERO /SUPPRESSION. THIS CODE COULD BE USEFUL ALL BY ITSELF FOR OTHER APPLICATIONS. /THE NEW RLE PARSER USES INPUT FROM THE TTY AT THE MOMENT. IT DOES VERY LITTLE /ERROR CHECKING, EXCEPT TO CHECK TO SEE IF A NUMBER IS LARGER THAN 255 DECIMAL. /THIS IS A RECOVERABLE ERROR; EITHER GIVE A NEW NUMBER, OR TYPE CTRL-U TO START /THE WHOLE RLE SEQUENCE OVER. MIND YOU, IF YOU TRY TO USE A NUMBER LARGER THAN /192 FOR SOMETHING OTHER THAN THE END OF LINE MARKER ($), RESULTS MAY NOT BE /WHAT YOU EXPECT. /A TYPICAL RLE STRING FOR THE NEW TTY PARSER WOULD LOOK SOMETHING LIKE THIS: /70X192Y2BO4BO2B$2B6O2B$2BO4BO2B4$2B6O2B$BO6BOB$O8BO$BO6BOB$2B6O! /(KAREL'S P15, FOR THE CURIOUS.) /WHERE ALL NUMBERS ARE IN DECIMAL. B IS DEATH, O IS LIFE. /END OF LINE IS $, END OF RLE SEQUENCE IS ! /CARRIAGE RETURNS ARE ECHOED AS CRLF; LINEFEEDS ARE IGNORED. /CTRL-U TO START THE SEQUENCE OVER, CTRL-D TO IMMEDIATELY EXIT (USEFUL FOR /REPLAYING THE LAST SEQUENCE) /ALL OTHER CHARACTERS ARE IGNORED AND NOT ECHOED. /OS/8 SUPPORT WORKS SOMETHING LIKE THIS...WHEN THE PROGRAM IS FIRST CALLED, THE /LAST PAGES OF THE FIRST TWO FIELDS (FIRST THREE FIELDS IF FAST RASTER MODE IS /ENABLED) ARE COPIED INTO SAFE SPOTS IN THE FIRST FIELD STARTING AT 7000. /HENCE, 7000-7577 WILL CONTAIN THE OS INFORMATION. THE BIT MASK TABLE THAT /NEEDS TO RESIDE AT 7764 IS POPULATED AFTER THE COPIES ARE COMPLETE. WHEN A /CTRL-C IS DETECTED AT THE END OF A GENERATION, THE PAGES ARE RESTORED AND /CONTROL IS RETURNED TO OS/8 AT 7600. YOU COULD MODIFY THE PROGRAM TO RETURN /SOONER IF DESIRED, BUT THIS WILL ADD A FEW CYCLES MULTIPLIED BY THOUSANDS OF /CALCULATIONS, POTENTIALLY, AND WILL SLOW THINGS DOWN. /THE PROGRAM ALSO CHECKS FOR A CTRL-U AT THE END OF A GENERATION. IF IT FINDS /ONE, THE PROGRAM WILL RESTART FROM THE TOP. /BASIC CONFIGURATION OS8=1 /IF 0, ASSUMES NO OPERATING SYSTEM; IF 1, SHOULD RUN UNDER OS/8 MEMORY=7 /TOTAL MEMORY FIELDS MINUS 1; WILL NOT ASSEMBLE IF TOO LITTLE MEMORY PARSER=0 /IF 0, RUNS THE NORMAL INIT ROUTINE; IF 1, TAKES RLE VIA TTY VC8E=1 /IF 0, ASSUMES A (VERY LARGE!) TERMINAL; IF 1, USE A VC8E STORE=0 /IF 0, ASSUMES A NON-STORAGE OSCILLOSCOPE; IF 1, A STORAGE 'SCOPE FASTR=0 /IF 0, SLOW RASTER; IF 1, FAST RASTER (NEEDS 32K); ONLY FOR STORE=0 VT100=0 /IF 0, ASSUMES A DUMB TERMINAL; IF 1, A VT100-LIKE TERMINAL STATS=1 /IF 0, NO STATISTICS; IF 1, PRINTS GENERATION AND TOTAL LIFE PRTDOT=0 /IF 0, PRINTS SPACES FOR DEATH; IF 1, DOTS SIMHVC=0 /IF 0, ASSUMES A REAL VC8E; IF 1, ASSUMES VC8 DEVICE IN SIMH /FUN INITIAL CONDITIONS; USE COMBINATIONS AS YOU LIKE /DEFINITIONS ARE AT THE END OF THE FILE GLDERS=0 GOSPER=0 RPENTO=1 MWSS=0 HWSS=0 DIEHARD=0 ACORN=0 BREED=0 FILLER=0 MAXFIL=0 BAKRAK=0 SPCRAK=0 KAREL=0 IFNZRO RLYNPR < /{ TSF=SKP TLS=NOP STATS=0 > /} /STUFF THAT PROBABLY SHOULDN'T BE MESSED WITH WRDCOL=20 /16 WORDS TIMES 12 BITS IS 192 ACROSS DFIELD=10 /BITMAP FIELD NOPRT=0 /NO PRINT FOR DEBUGGING (EXCEPT STATS, IF NEEDED) RLYNPR=0 /REALLY DON'T PRINT ANYTHING FOR DEBUGGING RSTRSC=0 /RASTER SHORTCUT FOR DEBUGGING /DEFINING CONSTANTS FOR CONDITIONAL ASSEMBLY NOSTOR=1-STORE SLOWR=1-FASTR USETTY=1-VC8E /FOR DUMB TERMINALS, OR IF WE PRINT DOTS, DEATH IS SLOW SLODTH=0 IFZERO VC8E < /{ IFZERO VT100 < /{ SLODTH=1 > /} IFNZRO PRTDOT < /{ SLODTH=1 > /} > /} /4K WON'T WORK (YET) IFZERO MEMORY < /{ ERROR: TOO LITTLE MEMORY; UPGRADE TO 8K AND TRY AGAIN > /} /FAST RASTER ONLY WORKS WITH 32K IFNZRO MEMORY-7 < /{ IFNZRO VC8E&NOSTOR&FASTR < /{ ERROR: TOO LITTLE MEMORY; TRY FASTR=0 > /} > /} /VC8E DEFINITIONS IFNZRO VC8E< /{ IFZERO SIMHVC < /{ DISD= 6052 > /} IFNZRO SIMHVC < /{ DISD= SKP > /} DILX= 6053 DILY= 6054 DIXY= 6055 DILE= 6056 DIRE= 6057 > /} /BIT COUNT TABLE *0 0 1 1 2 1 2 2 3 *10 PRIDX, 0 CPTR1, 0 CPTR2, 0 RLEPTR, 0 IFNZRO VC8E&NOSTOR&FASTR < /{ FSTPTR, 0 > /} *20 /CURRENT WORD IN BITMAP ADDR, 0 /CURRENT BIT IN WORD CURBIT, 0 /NEIGHBORHOOD TOTAL TOTAL, 0 /LIFE DETECTED IN CACHE LIFDET, 0 /CACHE POINTERS TOPPTR, 0 MIDPTR, 0 BOTPTR, 0 /STATISTICS IFNZRO STATS < /{ LIFCNT, 0 0 > /} /MISC STUFF CNT, 0 TEMP, 0 TMPPTR, 0 /STUFF FOR VC8E IFNZRO VC8E < /{ STARTX, -600 STARTY, 1000 X, 0 Y, 0 > /} /CACHE *40 CACHE1, ZBLOCK WRDCOL CACHE2, ZBLOCK WRDCOL CACHE3, ZBLOCK WRDCOL /ROTATE AC RIGHT BY (2 - BIT) TIMES, WHERE BIT IS -2 TO -11 DECIMAL /THE SUBROUTINE DOES NOT LIKE WHEN YOU CALL IT WITH -1 OR -12, THOUGH... /THEN, AND RESULT WITH 7 AND RETURN DOROT, 0 DCA ROT TAD (ROTTBL+1 TAD CURBIT DCA JMPLOC TAD ROT JMP I JMPLOC /ROTATE TABLE JMP ERR JMP FOURL JMP FIVEL JMP SIXL JMP SIXR JMP FIVER JMP FOURR JMP THREER JMP TWOR JMP ONER JMP DOAND ROTTBL, JMP ERR ERR, HLT JMP I DOROT SIXL, RTL FOURL, RTL TWOL, RTL AND (7 JMP I DOROT FIVEL, RTL THREEL, RTL ONEL, RAL AND (7 JMP I DOROT SIXR, RTR FOURR, RTR TWOR, RTR AND (7 JMP I DOROT FIVER, RTR THREER, RTR ONER, RAR DOAND, AND (7 JMP I DOROT ROT, 0 JMPLOC, 0 /GENERATION COUNTER IFNZRO STATS < /{ GENCNT, 0 0 > /} /BIT MASK TABLE /IF RUNNING UNDER OS/8, WE'LL HAVE TO COPY THIS HERE IFZERO OS8 < /{ *7764 4000 2000 1000 400 200 100 40 20 10 4 2 1 > /} /PROGRAM STARTS HERE *200 IFNZRO OS8 < /{ JMS SAVOS8 /SAVE OS/8 > /} 6040 /CLEAR TTY FLAG START, IFNZRO STATS < /{ JMS RSTLIF /RESET LIFE COUNTER JMS RSTGEN /RESET CYCLE COUNTER > /} JMS INIT /INITIALIZE THE BITMAP IFNZRO STATS < /{ JMS PRNTST /PRINT INITIAL STATISTICS JMS RSTLIF /RESET LIFE COUNTER > /} IFNZRO VC8E&STORE < /{ CLA /SET VC8E FOR STORAGE MODE TAD (20 DILE > /} IFNZRO VC8E&NOSTOR&FASTR < /{ CLA CMA /INITIALIZE PREVIOUS Y VALUE FOR FAST RASTER DCA PREVY CLA CMA DCA FSTPTR JMS RSTDF /RESET CDF FOR FAST RASTER > /} CLA /INITIALIZE CURRENT BIT AND ADDRESS TAD (-14 DCA CURBIT /CURBIT = -14 (AKA BIT 0) DCA ADDR /ADDR = 0 DCA LIFDET DCA TEMP TAD (CACHE1 /SET UP THE CACHE DCA TOPPTR TAD (CACHE2 DCA MIDPTR TAD (CACHE3 DCA BOTPTR TAD (-WRDCOL-1 /COPY INITIAL CACHE DCA CPTR1 TAD (CACHE1-1 DCA CPTR2 TAD (-WRDCOL /COPYING ONE ROW DCA CNT CDF DFIELD TAD I CPTR1 CDF 0 SZA ISZ TEMP /INCREMENT IF LIFE DETECTED DCA I CPTR2 ISZ CNT JMP .-7 TAD TEMP /ANY LIFE? SZA CLA IAC /YES TAD LIFDET CLL RAL DCA LIFDET DCA TEMP TAD (-WRDCOL /COPYING ONE ROW TO WHERE WE LEFT OFF DCA CNT CDF DFIELD TAD I CPTR1 CDF 0 SZA ISZ TEMP /INCREMENT IF LIFE DETECTED DCA I CPTR2 ISZ CNT JMP .-7 TAD TEMP /ANY LIFE? SZA CLA IAC /YES TAD LIFDET CLL RAL DCA LIFDET DCA TEMP TAD (-WRDCOL /COPYING ONE ROW TO WHERE WE LEFT OFF DCA CNT CDF DFIELD TAD I CPTR1 CDF 0 SZA ISZ TEMP /INCREMENT IF LIFE DETECTED DCA I CPTR2 ISZ CNT JMP .-7 TAD TEMP /ANY LIFE? SZA CLA ISZ LIFDET /YES JMP CHKLIF /JUMP TO THE MAIN LOOP IFNZRO STATS < /{ /INCREMENT LIFE COUNTER FOR STATISTICS INCLIF, 0 ISZ LIFCNT /INCREMENT BOTTOM 12 JMP I INCLIF /NO OVERFLOW ISZ LIFCNT+1 /OVERFLOW JMP I INCLIF /OVERFLOW ON TOP 12 WOULD BE A SERIOUS PROBLEM! /RESET LIFE COUNTER FOR STATISTICS RSTLIF, 0 CLA DCA LIFCNT DCA LIFCNT+1 JMP I RSTLIF /INCREMENT CYCLE COUNTER FOR STATISTICS INCGEN, 0 ISZ GENCNT /INCREMENT BOTTOM 12 JMP I INCGEN /NO OVERFLOW ISZ GENCNT+1 /OVERFLOW JMP I INCGEN /OVERFLOW ON TOP 12 WOULD BE A SERIOUS PROBLEM! /RESET CYCLE COUNTER FOR STATISTICS RSTGEN, 0 CLA DCA GENCNT DCA GENCNT+1 JMP I RSTGEN > /} PAGE CHKLIF, TAD LIFDET /ANY LIFE IN THE CACHE? SNA CLA JMP NOLIFE /NOPE, SHORTCUT! DOLIFE, TAD CURBIT /ARE WE AT A WORD EDGE? TAD (14 /CHECK LEFT WORD EDGE SZA JMP NLBIT /NO, NOT THE LEFT WORD EDGE TAD I TOPPTR /YES, GET TOP WORD SNA JMP .+6 /NOTHING TO DO IF WORD IS ZERO RTL /GET TOP TWO BITS DOWN LOW RAL AND (3 /JUST KEEP THE TWO DCA TEMP TAD I TEMP /AND COUNT THEM DCA TOTAL TAD I MIDPTR /DO THE SAME FOR MIDDLE SNA JMP .+10 /NOTHING TO DO IF WORD IS ZERO RTL RAL AND (3 DCA TEMP TAD I TEMP TAD TOTAL DCA TOTAL TAD I BOTPTR /DO THE SAME FOR BOTTOM SNA JMP .+10 /NOTHING TO DO IF WORD IS ZERO RTL RAL AND (3 DCA TEMP TAD I TEMP TAD TOTAL DCA TOTAL CMA /STILL MISSING THE LEFT COLUMN TAD ADDR /GET WORD TO OUR LEFT, WRAP AS NECESSARY AND (WRDCOL-1 TAD (CACHE1 /DON'T CARE ABOUT ORDER OF BITS ANYWAYS! DCA TMPPTR IAC AND I TMPPTR SZA CLA ISZ TOTAL TAD (WRDCOL /DO NEXT CACHED ROW TAD TMPPTR DCA TMPPTR IAC AND I TMPPTR SZA CLA ISZ TOTAL TAD (WRDCOL /AND THE LAST CACHED ROW TAD TMPPTR DCA TMPPTR IAC AND I TMPPTR SZA CLA ISZ TOTAL JMP DOCALC /ALL DONE FOR NOW NLBIT, TAD (-13 /HOW ABOUT RIGHT WORD EDGE? SZA CLA JMP NOTEDG /NO, NOT AT EITHER WORD EDGE TAD I TOPPTR /YES, GET TOP WORD SNA JMP .+4 /NOTHING TO DO IF WORD IS ZERO AND (3 /JUST KEEP THE TWO BOTTOM BITS DCA TEMP TAD I TEMP /AND COUNT THEM DCA TOTAL TAD I MIDPTR /DO THE SAME FOR MIDDLE SNA JMP .+6 /NOTHING TO DO IF WORD IS ZERO AND (3 DCA TEMP TAD I TEMP TAD TOTAL DCA TOTAL TAD I BOTPTR /DO THE SAME FOR BOTTOM SNA JMP .+6 /NOTHING TO DO IF WORD IS ZERO AND (3 DCA TEMP TAD I TEMP TAD TOTAL DCA TOTAL IAC /STILL MISSING THE RIGHT COLUMN TAD ADDR /GET WORD TO OUR RIGHT, WRAP AS NECESSARY AND (WRDCOL-1 TAD (CACHE1 /DON'T CARE ABOUT ORDER OF BITS ANYWAYS! DCA TMPPTR TAD I TMPPTR SPA CLA ISZ TOTAL TAD (WRDCOL /DO NEXT CACHED ROW TAD TMPPTR DCA TMPPTR TAD I TMPPTR SPA CLA ISZ TOTAL TAD (WRDCOL /AND THE LAST CACHED ROW TAD TMPPTR DCA TMPPTR TAD I TMPPTR SPA CLA ISZ TOTAL JMP DOCALC /ALL DONE FOR NOW PAGE NOTEDG, TAD I TOPPTR /GET TOP WORD SNA TAD I MIDPTR /GET MIDDLE WORD SNA TAD I BOTPTR /GET BOTTOM WORD SNA CLA /ANY LIFE? JMP NWRDLF /NO, NO LIFE IN CURRENT WORD AREA TAD I TOPPTR /GET TOP WORD JMS DOROT /ROTATE AS NECESSARY DCA TEMP /SAVE IT TAD I TEMP /AND COUNT THE BITS DCA TOTAL /SAVE THAT AS TOTAL SO FAR TAD I MIDPTR /GET MIDDLE WORD JMS DOROT DCA TEMP TAD I TEMP TAD TOTAL /ADD TO TOTAL DCA TOTAL TAD I BOTPTR /GET BOTTOM WORD JMS DOROT DCA TEMP TAD I TEMP TAD TOTAL /ADD TO TOTAL DCA TOTAL JMP DOCALC NWRDLF, CMA /SKIP TO LAST BIT OF WORD DCA CURBIT IFZERO VC8E+NOPRT+RLYNPR < /{ TAD (-12 /SKIPPING 10 DEAD PIXELS DCA CNT IFNZRO PRTDOT < /{ TAD (56 > /} IFZERO PRTDOT < /{ TAD (40 > /} TSF JMP .-1 TLS ISZ CNT JMP .-4 CLA > /} JMP DOLIFE DOCALC, TAD TOTAL TAD (-3 SNA JMP BIRTH /EXACTLY 3 TAD (-1 SNA CLA JMP SAME /EXACTLY 4 JMP DEATH /OTHERWISE... :( SAME, TAD I CURBIT /GET MASK AND I MIDPTR /AND WITH CURRENT WORD SZA CLA /IS IT ALIVE OR DEAD? JMP BIRTH DEATH, IFZERO VC8E+NOPRT+RLYNPR < /{ JMS PRTDTH /PRINT DEATH (AWW...) > /} TAD I CURBIT /CLEAR THE BIT IN THE BITMAP CMA CDF DFIELD AND I ADDR DCA I ADDR CDF 0 JMP BITLP BIRTH, IFNZRO STATS < /{ JMS INCLIF /INCREMENT LIFE COUNTER > /} IFNZRO VC8E&NOSTOR&FASTR < /{ JMS STORPT > /} IFNZRO VC8E&STORE < /{ JMS DISPT /VC8E STORAGE, DISPLAY A POINT > /} IFZERO VC8E+NOPRT+RLYNPR < /{ JMS PRTLIF /PRINT LIFE (YAY) > /} TAD I CURBIT /GET MASK CMA CDF DFIELD AND I ADDR /COMPLEMENT MASK AND 'AND' IT WITH CURRENT WORD CDF 0 TAD I CURBIT /ADD IN LIVE CELL CDF DFIELD DCA I ADDR /SAVE IT CDF 0 BITLP, ISZ CURBIT /NEXT BIT JMP DOLIFE /NOTHING ELSE TO DO HERE! CLA /NEED TO GO TO NEXT WORD AND RESET CURRENT BIT TO -14 TAD (-14 DCA CURBIT ISZ ADDR /FINAL BITMAP ADDRESS? JMP CHKROW /NO JMP FINAL /YES CHKROW, TAD ADDR /END OF ROW? AND (WRDCOL-1 SZA CLA JMP NOTDUN /NO IFZERO VC8E+NOPRT+RLYNPR < /{ JMS DOCRLF /YES > /} JMS UCACHE /UPDATE CACHE JMP CHKLIF NOTDUN, ISZ TOPPTR /NEXT WORDS ISZ MIDPTR ISZ BOTPTR JMP DOLIFE NOLIFE, IFZERO VC8E+NOPRT+RLYNPR < /{ JMS DTHROW /PRINT A ROW OF DEATH... > /} TAD ADDR /END OF BITMAP? TAD (WRDCOL SZA JMP NOTFIN /NO FINAL, KSF /ANY CHARACTER? SKP /NOPE JMS CHKCTL /YES, CHECK FOR A CONTROL CHARACTER IFNZRO STATS < /{ JMS INCGEN /YES, INCREMENT CYCLE COUNT IFZERO VC8E+NOPRT+RLYNPR < /{ JMS DOCRLF /GO TO NEXT LINE IF NEEDED > /} JMS PRNTST /PRINT STATISTICS JMS RSTLIF /AND RESET LIFE COUNTER > /} IFZERO VC8E+NOPRT+RLYNPR < /{ JMS PRTHOM /GO BACK HOME > /} IFNZRO VC8E < /{ JMS RASERA /EITHER DISPLAY A RASTER OR ERASE THE SCREEN > /} NOTFIN, DCA ADDR JMS UCACHE /UPDATE CACHE JMP CHKLIF /AND TRY AGAIN PAGE /UPDATE CACHE UCACHE, 0 CLA /MID TO TOP, BOT TO MID, TOP TO BOT TAD TOPPTR AND (-WRDCOL DCA TEMP TAD MIDPTR AND (-WRDCOL DCA TOPPTR TAD BOTPTR AND (-WRDCOL DCA MIDPTR TAD TEMP DCA BOTPTR DCA TEMP TAD LIFDET /UPDATE THE LIFE DETECTION CLL RAL AND (6 DCA LIFDET /NOW, ONLY REFRESH BOTTOM CACHED ROW CMA TAD ADDR /ADDR IS POINTING TO THE NEXT ROW IN THE BITMAP TAD (WRDCOL /WE NEED THE NEXT ROW DOWN DCA CPTR1 CMA TAD BOTPTR DCA CPTR2 TAD (-WRDCOL /COPYING ONE ROW DCA CNT CDF DFIELD TAD I CPTR1 CDF 0 SZA /ANY LIFE DETECTED? ISZ TEMP /YES DCA I CPTR2 ISZ CNT JMP .-7 TAD TEMP /ANY LIFE? SZA CLA ISZ LIFDET /YES JMP I UCACHE IFZERO VC8E+NOPRT+RLYNPR < /{ /VT100 HOME SEQUENCE, ESC[H PRTHOM, 0 CLA TAD (HOMSEQ-1 JMS PUTS JMP I PRTHOM IFNZRO VT100 < /{ HOMSEQ, 33 133 110 > /} IFZERO VT100 < /{ HOMSEQ, 14 > /} 0 IFNZRO VT100 < /{ /VT100 ERASE LINE, ESC[2K, PLUS CRLF ERALIN, 0 CLA TAD (ERASEQ-1 JMS PUTS JMP I ERALIN ERASEQ, 33 133 62 113 15 12 0 > /} /PRINT NULL-TERMINATED STRING PUTS, 0 DCA PRIDX TAD I PRIDX SNA JMP I PUTS TSF JMP .-1 TLS CLA JMP .-7 /PRINT DEATH PRTDTH, 0 CLA IFNZRO PRTDOT < /{ TAD (56 > /} IFZERO PRTDOT < /{ TAD (40 > /} TSF JMP .-1 TLS CLA JMP I PRTDTH /PRINT A ROW OF DEATH DTHROW, 0 IFZERO SLODTH < /{ JMS ERALIN > /} /PRTDOT=1 OR VT100=0 IFNZRO SLODTH < /{ CLA TAD (-WRDCOL^14 /12 PIXELS PER WORD DCA CNT IFNZRO PRTDOT < /{ TAD (56 > /} IFZERO PRTDOT < /{ TAD (40 > /} TSF JMP .-1 TLS ISZ CNT JMP .-4 JMS DOCRLF > /} JMP I DTHROW /PRINT A # FOR LIFE PRTLIF, 0 CLA TAD (43 TSF JMP .-1 TLS CLA JMP I PRTLIF > /} IFNZRO VC8E < /{ IFNZRO NOSTOR&FASTR < /{ RSTDF, 0 CLA TAD CDFCDF DCA FSTDF1 TAD CDFCDF DCA FSTDF2 TAD CDFCDF DCA FSTDF4 JMP I RSTDF CDFCDF, CDF 10 INCDF, 0 CLA TAD FSTDF1 TAD (10 /NEXT FIELD DCA FSTDF1 TAD FSTDF1 DCA FSTDF2 TAD FSTDF1 DCA FSTDF4 JMP I INCDF STORPT, 0 CLA TAD FSTPTR CMA SNA JMS INCDF /AT THE LAST POINTER IN THE FIELD; INCREMENT DF CLA CLL TAD ADDR /X = (12 * (ADDR & (WRDCOL-1))) + CURBIT + 12 + STARTX AND (WRDCOL-1 DCA X TAD X TAD X TAD X RTL TAD CURBIT TAD (12 CLL RTL DCA X TAD ADDR /Y = (((ADDR SHR 4) & 0377) + STARTY) RTR RTR AND (377 CLL RTL DCA Y TAD Y CMA IAC TAD PREVY SNA CLA JMP NOSTRY /DON'T STORE Y CLA IAC RAL TAD FSTPTR /NEED TO STORE TWO VALUES; ARE WE AT 7776? SNA CLA JMS INCDF /YES TAD Y /SAVE THE NEW Y FOR NEXT TIME DCA PREVY CLA CML RAR /SET SIGN BIT TAD Y FSTDF1, HLT /ACTUALLY A CDF DCA I FSTPTR /SAVE THE Y WITH TAG BIT CDF 0 NOSTRY, TAD X FSTDF2, HLT /ACTUALLY A CDF DCA I FSTPTR /SAVE THE X WITH NO TAG BIT CDF 0 JMP I STORPT PREVY, 0 > /} IFNZRO STORE < /{ DISPT, 0 CLA CLL TAD ADDR /X = (12 * (ADDR & (WRDCOL-1))) + CURBIT + 12 + STARTX AND (WRDCOL-1 DCA X TAD X TAD X TAD X RTL TAD CURBIT TAD (12 CLL RTL TAD STARTX DILX DCA X TAD ADDR /Y = (((ADDR SHR 4) & 0377) + STARTY) RTR RTR AND (377 CLL RTL CMA IAC TAD STARTY DILY DCA Y DISD JMP .-1 DIXY /X,Y JMP I DISPT > /} PAGE IFZERO FASTR+STORE < /{ /DO A RASTER SCAN OF THE BITMAP AND DISPLAY IT /IF THE PREVIOUS WORD HAD ACTIVITY AND WE HAVE NOT YET FINISHED A LINE, THE /Y DAC IS ALREADY SET UP FOR US. NO NEED TO RECALCULATE IT. THE X DAC IS /ACTUALLY SET UP AS WELL, SO THAT'S HANDY. RASTER, 0 CLA DCA ADDR TAD (-14 DCA CURBIT IFNZRO RSTRSC < /{ TAD STARTX DILX CLA TAD STARTY DILY CLA CMA DCA SHRTCT /SET UP FOR TAKING SHORTCUT > /} RASLP, CDF DFIELD TAD I ADDR CDF 0 SZA JMP DODRAW IFNZRO RSTRSC < /{ DCA SHRTCT /CAN'T DO SHORTCUT > /} RSCONT, ISZ ADDR JMP RASLP JMP I RASTER /YES, ALL DONE DODRAW, DCA DRWWRD /STORE WORD TO PLOT IFNZRO RSTRSC < /{ ISZ SHRTCT /CAN WE DO THE SHORTCUT? JMP CALCXY /NO, WE CAN'T SKPCAL, TAD ADDR /MAYBE...ARE WE AT A NEW LINE? AND (WRDCOL-1 SZA CLA JMP SCTCON /NO, DON'T CALCULATE Y IF WE DON'T HAVE TO TAD STARTX /YES, BEGINNING OF LINE DILX /RESET X DCA X JMP CALCY /AND JUST CALCULATE Y > /} CALCXY, TAD ADDR /X = (4 * 12 * (ADDR & (WRDCOL-1))) + STARTX AND (WRDCOL-1 DCA X TAD X TAD X TAD X CLL RTL CLL RTL TAD STARTX DILX DCA X CALCY, TAD ADDR /Y = STARTY - (4 * ((ADDR SHR 4) & 0377)) RTR AND (1774 CMA IAC TAD STARTY DILY DCA Y IFNZRO RSTRSC < /{ SCTCON, CMA /WE CAN TAKE A SHORTCUT NEXT TIME, MAYBE... DCA SHRTCT > /} IFNZRO RSTRSC < /{ WRDLP, TAD DRWWRD AND I CURBIT SNA CLA /ARE WE PLOTTING A BIT OR NOT? JMP NEXTX /NOPE, SKIP AHEAD DISD /YES, WAIT FOR DACS TO SETTLE JMP .-1 DIXY NEXTX, TAD X /INCREMENT X BY 4 BECAUSE OF OUR SCALE TAD (4 DILX DCA X ISZ CURBIT JMP WRDLP TAD (-14 DCA CURBIT JMP RSCONT SHRTCT, 0 > /} IFZERO RSTRSC < /{ WRDLP, TAD DRWWRD AND I CURBIT SNA CLA /ARE WE PLOTTING A BIT OR NOT? JMP NXTBIT /NOPE, SKIP AHEAD DISD /YES, WAIT FOR DACS TO SETTLE JMP .-1 DIXY NXTBIT, ISZ CURBIT JMP NEXTX TAD (-14 DCA CURBIT JMP RSCONT NEXTX, TAD X /INCREMENT X BY 4 BECAUSE OF OUR SCALE TAD (4 DILX DCA X JMP WRDLP SHRTCT, 0 > /} DRWWRD, 0 > /} IFZERO SLOWR+STORE < /{ RSTDF2, 0 CLA TAD CDFCDF DCA FSTDF3 JMP I RSTDF2 INCDF2, 0 CLA TAD FSTDF3 TAD (10 DCA FSTDF3 JMP I INCDF2 /FAST RASTER IMPLEMENTATION /USES TAGGED Y VALUES AND NON-TAGGED X VALUES IN A WHOLE SEPARATE ARRAY RASTER, 0 JMS RSTDF2 /RESET CDF INSTRUCTIONS CLA CMA DCA FSTPTR /INITIALIZE POINTER TAD STARTY /INITIALIZE Y DAC DILY RSTLP, CLA TAD FSTPTR CMA SNA CLA JMS INCDF2 /AT THE LAST POINTER IN THE FIELD; INCREMENT DF FSTDF3, HLT /ACTUALLY A CDF TAD I FSTPTR /GET DATA CDF 0 SPA /WAS SIGN SET? JMP SETY /YES, IT'S A Y VALUE OR THE END TAD STARTX /NO, ADD THE START X POSITION DILX DISD JMP .-1 DIXY /AND DISPLAY THE POINT JMP RSTLP SETY, CLL CMA RAL SNA /WAS IT END OF LIST? JMP I RASTER /YES, WE'RE DONE CLL CML RAR /CLEAR TAG BIT IAC /FINISH TWO'S COMPLEMENT TAD STARTY /APPLY THE OFFSET DILY /UPDATE Y DAC JMP RSTLP /SETY, RAL / SPA /WAS NEXT BIT SET? / JMP I RASTER /YES, WE'RE DONE / CLL /NOPE, CLEAR THE TAG BIT / RAR /ROTATE BACK / CMA IAC / TAD STARTY /APPLY THE OFFSET / DILY /UPDATE Y DAC / JMP RSTLP > /} /DEPENDING ON IF WE HAVE A STORAGE 'SCOPE OR NOT, EITHER /RASTER THE BITMAP HERE FOR SEVERAL LOOPS, OR ERASE THE /SCREEN. YOU COULD ADD A DELAY BEFORE THE ERASE TO ADMIRE /THE COMPLETED CYCLE LONGER. RASERA, 0 IFNZRO STORE < /{ CLA TAD (30 /ERASE VC8E DILE DISD /WAIT FOR ERASE TO COMPLETE JMP .-1 CLA > /} IFZERO STORE < /{ IFNZRO FASTR < /{ CLA TAD FSTPTR CMA SNA JMS INCDF /AT THE LAST POINTER IN THE FIELD; INCREMENT DF CLA CMA FSTDF4, HLT /ACTUALLY A CDF DCA I FSTPTR /MARK THE FINISH CDF 0 /TAD (-20 /16 LOOPS CMA DCA CNT JMS RASTER /DO THE RASTER ISZ CNT JMP .-2 JMS RSTDF /RESET CDF INSTRUCTIONS CLA CMA /INITIALIZE POINTER FOR WRITING DCA FSTPTR CLA CMA /INITIALIZE PREVIOUS Y VALUE FOR FAST RASTER DCA PREVY > /} IFZERO FASTR < /{ CLA TAD (-20 /16 LOOPS DCA CNT JMS RASTER /DO THE RASTER ISZ CNT JMP .-2 > /} > /} JMP I RASERA > /} PAGE /RUN-LENGTH ENCODING INITIALIZER /TAKES MULTIPLES OF THREE ARGUMENTS /1. POINTER TO RLE DATA /2. X ADDRESS IN BITMAP, 0 TO 191 DECIMAL /3. Y ADDRESS IN BITMAP, 0 TO 255 DECIMAL /AND REPEAT /RLE IS SUPPLIED AS: /TAG!COUNT; TAG!COUNT; TAG!COUNT; ...ETC. /WHERE COUNT IS 1 TO 192, AND TAG IS: /6000 OCTAL - DEAD /4000 OCTAL - ALIVE /1000 OCTAL - END OF LINE /0 TERMINATES THE SEQUENCE /IF COUNT IS ZERO, IT IS ASSUMED TO BE 1 /KEEPS GOING UNTIL THE POINTER TO RLE DATA IS ZERO RLE, 0 NXTRLE, CLA CMA TAD I RLE /GET POINTER TO RLE DCA RLEPTR TAD RLEPTR /WAS IT ZERO? CMA SNA CLA JMP RLEDUN ISZ RLE TAD I RLE /GET X VALUE DCA SBIT DCA SADDR TAD SBIT TAD (-14 /DIVIDE BY 12 SPA JMP DIVDUN /NO MORE TO DIVIDE ISZ SADDR JMP .-4 DIVDUN, DCA SBIT TAD SBIT DCA CURBIT ISZ RLE TAD I RLE /GET Y VALUE CLL RTL /MULTIPLY BY 16 RTL TAD SADDR /ADD TO X OFFSET DCA SADDR TAD SADDR DCA ADDR ISZ RLE /POINT TO RETURN RMAIN, DCA CURSTA /RESET CURRENT STATE TAD I RLEPTR /GET DATA SNA /END OF SEQUENCE? JMP NXTRLE /GET NEXT RLE CLL RAL SNL /NOPE, WHAT WAS IT? ISZ CURSTA SMA ISZ CURSTA /CURSTA = 0 FOR DEAD, 1 FOR LIFE, 2 FOR EOL RAR /GO BACK THE OTHER WAY AND (377 /KEEP JUST THE COUNT CMA IAC /NEGATE IT SNA /IF IT IS ZERO CMA /MAKE IT ONE DCA RLECNT /STORE IT RLOOP, TAD CURSTA /LIFE OR DEATH OR EOL? SNA JMP RCONT /0 FOR DEATH RAR SZL CLA JMP RLIVE /1 FOR LIFE JMP NEXTLN /2 FOR NEXT LINE RLIVE, IFNZRO STATS < /{ JMS INCLIF /INCREMENT LIFE COUNTER > /} TAD I CURBIT /GET MASK CMA CDF DFIELD AND I ADDR /COMPLEMENT MASK AND 'AND' IT WITH CURRENT WORD CDF 0 TAD I CURBIT /ADD IN LIVE CELL CDF DFIELD DCA I ADDR /SAVE IT CDF 0 RCONT, ISZ CURBIT /NEXT BIT JMP RCHECK CLA /NEED TO GO TO NEXT WORD AND RESET CURRENT BIT TO -14 TAD (-14 DCA CURBIT TAD ADDR IAC AND (WRDCOL-1 DCA TEMP TAD ADDR AND (-WRDCOL TAD TEMP DCA ADDR RCHECK, ISZ RLECNT /ANY MORE TO DO? JMP RLOOP /YES JMP RMAIN /NOPE, GET MORE DATA NEXTLN, TAD SBIT DCA CURBIT TAD SADDR TAD (WRDCOL DCA SADDR TAD SADDR DCA ADDR JMP RCHECK RLEDUN, ISZ RLE JMP I RLE CURSTA, 0 CURDAT, 0 SADDR, 0 SBIT, 0 RLECNT, 0 PAGE IFNZRO STATS < /{ /DOUBLE DABBLE IMPLEMENTATION FOR 24-BIT UNSIGNED INPUT /BINARY TO BCD CONVERSION /TAKES POINTER TO DOUBLE WORD IN AC /RETURNS ASCII STRING POINTER IN AC OF CONVERSION DUBDAB, 0 DCA DUBPTR /STORE POINTER TAD I DUBPTR /GET DOUBLE LSW DCA SCRATC /STORE IT IN SCRATCH ISZ DUBPTR TAD I DUBPTR /GET DOUBLE MSW DCA SCRATC+1 /STORE IT NEXT DCA SCRATC+2 /CLEAR REST OF SCRATCH DCA SCRATC+3 DCA SCRATC+4 TAD (-30 /LOOP 24 TIMES DCA CNT DABLP, TAD SCRATC+2 /CHECK FOR NECESSARY ADDITIONS JMS DABADD DCA SCRATC+2 TAD SCRATC+3 JMS DABADD DCA SCRATC+3 TAD SCRATC+4 JMS DABADD DCA SCRATC+4 TAD SCRATC /ROTATE EVERYTHING LEFT RAL DCA SCRATC TAD SCRATC+1 RAL DCA SCRATC+1 TAD SCRATC+2 RAL DCA SCRATC+2 TAD SCRATC+3 RAL DCA SCRATC+3 TAD SCRATC+4 RAL DCA SCRATC+4 ISZ CNT /KEEP GOING? JMP DABLP /YES /TIME TO DISH UP SOME ASCII TAD (ASCOUT /PUT OUTPUT POINTER DCA DUBPTR /IN OUR POINTER TAD SCRATC+4 /ADD DIGITS TO OUTPUT JMS DABASC TAD SCRATC+3 JMS DABASC TAD SCRATC+2 JMS DABASC DCA I DUBPTR /NULL TERMINATOR TAD (ASCOUT /DO ZERO SUPPRESSION DCA DUBPTR TAD I DUBPTR /IS IT ASCII ZERO? TAD (-60 SZA JMP DABDUN /NOT ASCII ZERO ISZ DUBPTR /YES, TRY AGAIN JMP .-5 DABDUN, TAD (60 /WAS IT OUR TERMINATION? SNA CLA CMA /YES, SUBTRACT ONE FROM POINTER TAD DUBPTR /RETURN POINTER JMP I DUBDAB /DECOMPOSES EACH NIBBLE OF WORD INTO THREE ASCII BYTES /IF LINK IS SET AND ASCII POINTER HASN'T CHANGED, PUT A ZERO /OTHERWISE, DO LEADING ZERO SUPPRESSION DABASC, 0 DCA TEMP /STORE THE DIGITS TAD TEMP /GET TOP BCD DIGIT RTL RTL RAL AND (17 TAD (60 /ADD ASCII ZERO DCA I DUBPTR ISZ DUBPTR TAD TEMP /GET MIDDLE BCD DIGIT RTR RTR AND (17 TAD (60 /ADD ASCII ZERO DCA I DUBPTR ISZ DUBPTR TAD TEMP /GET BOTTOM BCD DIGIT AND (17 TAD (60 /ADD ASCII ZERO DCA I DUBPTR ISZ DUBPTR JMP I DABASC DUBPTR, 0 SCRATC, ZBLOCK 5 ASCOUT, ZBLOCK 12 /9 BCD DIGITS IN 3 WORDS, PLUS NULL TERMINATION PAGE /ADDS 3 TO EACH NIBBLE OF WORD IF NIBBLE IS GREATER THAN 4 DABADD, 0 DCA TEMP TAD TEMP /IS BOTTOM BCD DIGIT GREATER THAN 4? AND (17 TAD (-5 SMA CLA TAD (3 /YES, ADD 3 TAD TEMP /TO THE BOTTOM BCD DIGIT DCA TEMP /AND SAVE IT TAD TEMP /IS MIDDLE BCD DIGIT GREATER THAN 4? RTR RTR AND (17 TAD (-5 SMA CLA TAD (60 /YES, ADD 3 TAD TEMP /TO THE MIDDLE BCD DIGIT DCA TEMP /AND SAVE IT TAD TEMP /IS TOP BCD DIGIT GREATER THAN 4? RTL RTL RAL AND (17 TAD (-5 SMA CLA TAD (1400 /YES, ADD 3 TAD TEMP /TO THE TOP BCD DIGIT JMP I DABADD /AND RETURN /PRINT STATISTICS PRNTST, 0 CLA TAD (GENTXT JMS PUTSIX TAD (GENCNT JMS DUBDAB JMS PUTS2 TAD TAB JMS PUTC TAD (LIFTXT JMS PUTSIX TAD (LIFCNT JMS DUBDAB JMS PUTS2 JMS DOCRLF JMP I PRNTST GENTXT, TEXT"GENERATION: " LIFTXT, TEXT"LIVE CELLS: " TAB, 11 > /} IFNZRO STATS+PARSER < /{ /LIKE PUTS, BUT TAKES POINTER, NOT POINTER-1 PUTS2, 0 TAD (-1 DCA PRIDX TAD I PRIDX SNA JMP I PUTS2 JMS PUTC JMP .-4 /PRINT A SIXBIT STRING PUTSIX, 0 DCA TMPPTR TAD I TMPPTR /GET WORD RTR /GET TOP SIX IN BOTTOM RTR RTR AND (77 SNA /WAS IT ZERO? JMP I PUTSIX /YES, RETURN JMS PUTCSX /CONVERT AND PRINT TAD I TMPPTR /GET WORD AND (77 /KEEP BOTTOM SIX SNA /WAS IT ZERO? JMP I PUTSIX /YES, RETURN JMS PUTCSX /CONVERT AND PRINT ISZ TMPPTR /LOOP JMP PUTSIX+2 /SIXBIT CONVERSION AND PRINT PUTCSX, 0 TAD (-40 /WAS IT GTE 40? SMA TAD (-100 /YES TAD (140 /MAKE IT ASCII JMS PUTC /PRINT IT JMP I PUTCSX /PRINT A CHARACTER PUTC, 0 TSF JMP .-1 TLS CLA JMP I PUTC PAGE > /} IFNZRO STATS+USETTY < /{ DOCRLF, 0 CLA TAD (CRLF-1 DCA PRIDX TAD I PRIDX SNA JMP I DOCRLF TSF JMP .-1 TLS CLA JMP .-7 CRLF, 15 12 0 > /} /INITIALIZATION ROUTINE INIT, 0 CLA /ZERO PLAYING FIELD DCA ADDR CDF DFIELD DCA I ADDR CDF 0 ISZ ADDR JMP .-4 IFNZRO PARSER < /{ JMS PARSE > /} JMS RLE IFZERO PARSER < /{ IFNZRO GLDERS < /{ RGLIDR; 0; 0 /RGLIDR; 0; 7 > /} IFNZRO GOSPER < /{ RGSPER; 10; 10 /RGSPER; 40; 0 /RGSPER; 100; 0 > /} IFNZRO RPENTO < /{ RRPENT; 137; 176 > /} IFNZRO MWSS < /{ RMWSS; 200; 200 > /} IFNZRO HWSS < /{ RHWSS; 200; 220 > /} IFNZRO DIEHARD < /{ RDIHRD; 137; 176 > /} IFNZRO ACORN < /{ RACORN; 137; 176 > /} IFNZRO BREED < /{ RBREED; 0; 0 > /} IFNZRO FILLER < /{ RFILL; 110; 163 > /} IFNZRO MAXFIL < /{ RMAX; 110; 163 > /} IFNZRO BAKRAK < /{ RBAKRK; 137; 176 > /} IFNZRO SPCRAK < /{ RSPCRK; 137; 176 > /} IFNZRO KAREL < /{ RKAREL; 137; 176 > /} > /} IFNZRO PARSER < /{ RPARSE XPARSE, 0 YPARSE, 0 > /} 0 /END OF INITIALIZATION JMP I INIT /RLE INFORMATION B=6000 /DEAD O=4000 /ALIVE L=1000 /END OF LINE E=0 /END OF RLE /PARSES TYPICAL RLE STRINGS /CTRL-U TO START OVER /CTRL-D TO END IMMEDIATELY /B FOR DEATH /O FOR LIFE /$ FOR END OF LINE /! FOR END OF FILE /X FOR INITIAL X POSITION /Y FOR INITIAL Y POSITION IFNZRO PARSER < /{ PARSE, 0 JMS DOCRLF /PRINT A FRIENDLY PROMPT TAD (PROMPT JMS PUTSIX JMS DOCRLF TAD (RPARSE-1 /SET UP OUR POINTER DCA RLEPTR PARSLP, DCA NUMBUF /CLEAR THE NUMBER BUFFER GETCH, KSF /AWAIT A CHARACTER JMP .-1 KRB /READ IT AND (177 /KEEP BOTTOM 7 BITS DCA TEMP /STORE IT TAD TEMP IFNZRO OS8 < /{ TAD (-3 /IS IT A CTRL-C? SNA JMP EXIT /YES, EXIT TO OS/8 TAD (-4+3 /IS IT A CTRL-D? > /} IFZERO OS8 < /{ TAD (-4 /IS IT A CTRL-D? > /} SNA JMP CTRLD /YES TAD (-15+4 /IS IT A CR? SNA JMP CR /YES TAD (-25+15 /IS IT A CTRL-U? SNA JMP CTRLU /YES TAD (-41+25 /IS IT AN EXCLAMATION MARK? SNA JMP EXCLAM /YES TAD (-44+41 /IS IT A DOLLAR SIGN? SNA JMP DOLLAR /YES TAD (-100+44 /IS IT GEQ TO THE AT SIGN? SPA JMP CHKNUM /NO, MAYBE IT'S A NUMBER AND (37 /YES, MAYBE A LETTER, MAKE IT UPPERCASE TAD (-2 /WAS IT A B? SNA JMP PARSEB /YES TAD (-17+2 /HOW ABOUT AN O? SNA JMP PARSEO /YES TAD (-30+17 /HOW ABOUT AN X? SNA JMP PARSEX /YES TAD (-31+30 /HOW ABOUT A Y? SNA CLA JMP PARSEY /YES JMP GETCH /NOPE, IGNORE IT CR, JMS DOCRLF /DO FULL CRLF JMP GETCH /AND CONTINUE EXCLAM, JMS DOECHO /ECHO CHAR JMS DOCRLF DCA I RLEPTR /MARK END OF FILE JMP I PARSE /AND RETURN CTRLD, CLA TAD (CTRLDP JMS PUTSIX JMS DOCRLF JMP I PARSE /GET OUTTA HERE NOW! CTRLDP, TEXT"^D" CTRLU, CLA TAD (CTRLUP JMS PUTSIX JMS DOCRLF JMP PARSE+1 /GO BACK TO THE START CTRLUP, TEXT"^U" PAGE DOLLAR, JMS DOECHO /ECHO CHAR JMS NUMCHK /CHECK NUMBER TAD (L /GET END OF LINE DCA I RLEPTR /STORE IT JMP PARSLP /AND LOOP AGAIN CHKNUM, CLA TAD TEMP /IS IT POSSIBLY A NUMBER? TAD (-60 SPA CLA JMP GETCH /NOPE, IGNORE IT TAD TEMP /WELL, MAYBE... TAD (-72 SMA CLA JMP GETCH /NOPE, IGNORE IT JMS DOECHO /YES IT IS, ECHO IT TAD TEMP AND (17 /KEEP BOTTOM NIBBLE DCA TEMP TAD NUMBUF /MULTIPLY EXISTING NUMBER BUFFER BY 10 DECIMAL CLL RTL TAD NUMBUF CLL RAL TAD TEMP /ADD OUR NIBBLE TO IT DCA NUMBUF /AND STORE IT JMP GETCH /GO GET SOME MORE PARSEB, JMS DOECHO /ECHO CHAR JMS NUMCHK /CHECK NUMBER TAD (B /GET DEATH DCA I RLEPTR /STORE IT JMP PARSLP /AND LOOP AGAIN PARSEO, JMS DOECHO /ECHO CHAR JMS NUMCHK /CHECK NUMBER TAD (O /GET LIFE DCA I RLEPTR /STORE IT JMP PARSLP /AND LOOP AGAIN PARSEX, JMS DOECHO /ECHO CHAR JMS NUMCHK /CHECK NUMBER DCA XPARSE /STORE IT JMP PARSLP /AND LOOP AGAIN PARSEY, JMS DOECHO /ECHO CHAR JMS NUMCHK /CHECK NUMBER DCA YPARSE /STORE IT JMP PARSLP /AND LOOP AGAIN NUMBUF, 0 /PRINT CHARACTER IN BUFFER DOECHO, 0 CLA TAD TEMP TSF JMP .-1 TLS CLA JMP I DOECHO /CHECK NUMBER FOR LESS THAN 256 DECIMAL NUMCHK, 0 CLA CLL TAD NUMBUF /GET THE NUMBER FROM THE BUFFER TAD (7400 /OUT OF BOUNDS? SZL CLA JMP NUMERR /YES, WE HAVE AN ERROR TAD NUMBUF /NOPE, RETURN IT JMP I NUMCHK NUMERR, JMS DOCRLF TAD (NUMMSG /PRINT THE ERROR MESSAGE JMS PUTSIX JMS DOCRLF JMP PARSLP /AND TRY TO CONTINUE NUMMSG, TEXT"NUMBER TOO BIG" PROMPT, TEXT"ENTER RLE:" > /} PAGE IFZERO PARSER < /{ IFNZRO GLDERS < /{ RGLIDR, DECIMAL 1!B;1!O;L 2!B;1!O;L 3!O;E OCTAL > /} IFNZRO GOSPER < /{ RGSPER, DECIMAL 24!B;O;L 22!B;O;B;O;L 12!B;2!O;6!B;2!O;12!B;2!O;L 11!B;O;3!B;O;4!B;2!O;12!B;2!O;L 2!O;8!B;O;5!B;O;3!B;2!O;L 2!O;8!B;O;3!B;O;B;2!O;4!B;O;B;O;L 10!B;O;5!B;O;7!B;O;L 11!B;O;3!B;O;L 12!B;2!O;E OCTAL > /} IFNZRO RPENTO < /{ RRPENT, DECIMAL B;2!O;L;2!O;B;L;B;O;E OCTAL > /} IFNZRO MWSS < /{ RMWSS, DECIMAL 3!B;O;2!B;L;B;O;3!B;O;L;O;5!B;L;O;4!B;O;L;5!O;E OCTAL > /} IFNZRO HWSS < /{ RHWSS, DECIMAL 3!B;2!O;2!B;L;B;O;4!B;O;L;O;6!B;L;O;5!B;O;L;6!O;E OCTAL > /} IFNZRO DIEHARD < /{ RDIHRD, DECIMAL 6!B;O;B;L;2!O;6!B;L;B;O;3!B;3!O;E OCTAL > /} IFNZRO ACORN < /{ RACORN, DECIMAL B;O;5!B;L;3!B;O;3!B;L;2!O;2!B;3!O;E OCTAL > /} IFNZRO BREED < /{ RBREED, DECIMAL 133!B;O;L;134!B;O;L;130!B;O;3!B;O;L;131!B;4!O;3!L;130!B;O;L;131!B;O;L 132!B;O;L;132!B;O;L;131!B;2!O;4!L;133!B;O;L;134!B;O;L;130!B;O;3!B;O;L 131!B;4!O;9!L;96!B;O;L;97!B;O;L;93!B;O;3!B;O;L;94!B;4!O;8!L;3!B;O;L 4!B;O;L;O;3!B;O;L;B;4!O;E OCTAL > /} IFNZRO FILLER < /{ RFILL, DECIMAL 20!B;3!O;3!B;3!O;L;19!B;O;B;B;O;3!B;O;B;B;O;L;4!O;18!B;O;3!B;O;18!B 4!O;L;O;3!B;O;17!B;O;3!B;O;17!B;O;3!B;O;L;O;8!B;O;12!B;O;3!B;O;12!B;O 8!B;O;L;B;O;B;B;O;B;B;O;O;B;B;O;25!B;O;B;B;O;O;B;B;O;B;B;O;L;6!B;O;5!B O;7!B;3!O;3!B;3!O;7!B;O;5!B;O;L;6!B;O;5!B;O;8!B;O;5!B;O;8!B;O;5!B;O;L 6!B;O;5!B;O;8!B;7!O;8!B;O;5!B;O;L;B;O;B;B;O;B;B;O;O;B;B;O;B;B;O;O;4!B O;7!B;O;4!B;O;O;B;B;O;B;B;O;O;B;B;O;B;B;O;L;O;8!B;O;3!B;O;O;4!B;11!O 4!B;O;O;3!B;O;8!B;O;L;O;3!B;O;9!B;O;O;17!B;O;O;9!B;O;3!B;O;L;4!O;11!B 19!O;11!B;4!O;L;16!B;O;B;O;11!B;O;B;O;L;19!B;11!O;L;19!B;O;9!B;O;L 20!B;9!O;L;24!B;O;L;20!B;3!O;3!B;3!O;L;22!B;O;3!B;O;L;L;21!B;3!O;B;3!O L;21!B;3!O;B;3!O;L;20!B;O;B;O;O;B;O;O;B;O;L;20!B;3!O;3!B;3!O;L;21!B;O 5!B;O;E OCTAL > /} IFNZRO MAXFIL < /{ RMAX, DECIMAL 18!B;O;8!B;L;17!B;3!O;7!B;L;12!B;3!O;4!B;2!O;6!B;L;11!B;O;2!B;3!O;2!B O;B;2!O;4!B;L;10!B;O;3!B;O;B;O;2!B;O;B;O;5!B;L;10!B;O;4!B;O;B;O;B;O;B O;B;2!O;2!B;L;12!B;O;4!B;O;B;O;3!B;2!O;2!B;L;4!O;5!B;O;B;O;4!B;O;3!B;O B;3!O;2!B;L;O;3!B;2!O;B;O;B;3!O;B;2!O;9!B;2!O;B;L;O;5!B;2!O;5!B;O;13!B L;B;O;2!B;2!O;B;O;2!B;O;2!B;O;B;2!O;10!B;L;7!B;O;B;O;B;O;B;O;B;O;B;O 5!B;4!O;L;B;O;2!B;2!O;B;O;2!B;O;2!B;O;2!B;2!O;B;O;B;2!O;3!B;O;L;O;5!B 2!O;3!B;O;B;O;B;O;3!B;2!O;5!B;O;L;O;3!B;2!O;B;O;B;2!O;2!B;O;2!B;O;2!B O;B;2!O;2!B;O;B;L;4!O;5!B;O;B;O;B;O;B;O;B;O;B;O;7!B;L;10!B;2!O;B;O;2!B O;2!B;O;B;2!O;2!B;O;B;L;13!B;O;5!B;2!O;5!B;O;L;B;2!O;9!B;2!O;B;3!O;B;O B;2!O;3!B;O;L;2!B;3!O;B;O;3!B;O;4!B;O;B;O;5!B;4!O;L;2!B;2!O;3!B;O;B;O 4!B;O;12!B;L;2!B;2!O;B;O;B;O;B;O;B;O;4!B;O;10!B;L;5!B;O;B;O;2!B;O;B;O 3!B;O;10!B;L;4!B;2!O;B;O;2!B;3!O;2!B;O;11!B;L;6!B;2!O;4!B;3!O;12!B;L 7!B;3!O;17!B;L;8!B;O;E OCTAL > /} IFNZRO SPCRAK < /{ RSPCRK, DECIMAL 11!B;2!O;5!B;4!O;L;9!B;2!O;B;2!O;3!B;O;3!B;O;L;9!B;4!O;8!B;O;L;10!B 2!O;5!B;O;2!B;O;B;2!L;8!B;O;13!B;L;7!B;2!O;8!B;2!O;3!B;L;6!B;O;9!B;O 2!B;O;2!B;L;7!B;5!O;4!B;O;2!B;O;2!B;L;8!B;4!O;3!B;2!O;B;2!O;2!B;L;11!B O;4!B;2!O;4!B;4!L;18!B;4!O;L;O;2!B;O;13!B;O;3!B;O;L;4!B;O;16!B;O;L;O 3!B;O;12!B;O;2!B;O;B;L;B;4!O;E OCTAL > /} IFNZRO BAKRAK < /{ RBAKRK, DECIMAL 3!B;O;15!B;L;2!B;3!O;14!B;L;B;2!O;B;O;5!B;O;8!B;L;B;3!O;5!B;3!O;7!B;L 2!B;2!O;4!B;O;2!B;2!O;3!B;3!O;L;8!B;3!O;4!B;O;2!B;O;L;18!B;O;L;18!B;O L;18!B;O;L;2!B;3!O;12!B;O;B;L;2!B;O;2!B;O;13!B;L;2!B;O;16!B;L;2!B;O 16!B;L;3!B;O;15!B;7!L;3!O;16!B;L;O;2!B;O;11!B;O;3!B;L;O;13!B;3!O;2!B;L O;12!B;2!O;B;O;2!B;L;O;12!B;3!O;3!B;L;B;O;12!B;2!O;E OCTAL > /} IFNZRO KAREL < /{ RKAREL, DECIMAL 53!B;O;113!B;L;53!B;O;B;O;111!B;L;53!B;2!O;112!B;2!L;17!B;O;B;O;147!B L;18!B;2!O;147!B;L;18!B;O;45!B;O;102!B;L;62!B;2!O;103!B;L;63!B;2!O 102!B;8!L;38!B;O;128!B;L;38!B;O;B;O;42!B;O;51!B;2!O;6!B;2!O;22!B;L 38!B;2!O;41!B;2!O;47!B;2!O;2!B;O;2!B;O;4!B;O;2!B;O;2!B;2!O;17!B;L;82!B 2!O;45!B;O;2!B;2!O;B;2!O;6!B;2!O;B;2!O;2!B;O;16!B;L;127!B;2!O;B;3!O 14!B;3!O;B;2!O;14!B;L;126!B;O;4!B;O;16!B;O;4!B;O;13!B;L;129!B;O;20!B;O 16!B;L;6!B;O;B;O;158!B;L;7!B;2!O;33!B;O;82!B;O;3!B;O;20!B;O;3!B;O;12!B L;7!B;O;32!B;2!O;84!B;3!O;22!B;3!O;13!B;L;41!B;2!O;124!B;3!L;120!B;O 38!B;O;7!B;L;117!B;O;3!B;O;36!B;O;3!B;O;4!B;L;42!B;O;73!B;O;4!B;O;36!B O;4!B;O;3!B;L;B;O;40!B;O;B;O;71!B;O;4!B;O;36!B;O;4!B;O;3!B;L;2!B;O 39!B;2!O;71!B;O;2!B;O;B;O;38!B;O;B;O;2!B;O;2!B;L;3!O;111!B;O;B;O;46!B O;B;O;B;L;114!B;O;B;2!O;44!B;2!O;B;O;B;L;115!B;2!O;46!B;2!O;2!B;L 115!B;O;48!B;O;2!B;L;69!B;3!O;42!B;O;50!B;O;B;L;69!B;O;43!B;O;B;O;48!B O;B;O;L;62!B;O;7!B;O;42!B;O;B;O;48!B;O;B;O;L;61!B;2!O;51!B;O;50!B;O;B L;54!B;3!O;4!B;O;B;O;103!B;L;32!B;O;21!B;O;112!B;L;33!B;O;21!B;O;111!B L;24!B;O;B;O;4!B;3!O;133!B;L;25!B;2!O;87!B;O;50!B;O;B;L;17!B;O;7!B;O 87!B;O;B;O;48!B;O;B;O;L;18!B;O;94!B;O;B;O;48!B;O;B;O;L;16!B;3!O;95!B;O 50!B;O;B;L;115!B;O;48!B;O;2!B;L;115!B;2!O;46!B;2!O;2!B;L;114!B;O;B;2!O 44!B;2!O;B;O;B;L;85!B;3!O;26!B;O;B;O;46!B;O;B;O;B;L;44!B;2!O;39!B;O 29!B;O;2!B;O;B;O;38!B;O;B;O;2!B;O;2!B;L;43!B;O;B;O;40!B;O;29!B;O;4!B;O 36!B;O;4!B;O;3!B;L;45!B;O;70!B;O;4!B;O;36!B;O;4!B;O;3!B;L;117!B;O;3!B O;36!B;O;3!B;O;4!B;L;120!B;O;38!B;O;7!B;3!L;45!B;2!O;120!B;L;46!B;2!O 32!B;O;45!B;3!O;22!B;3!O;13!B;L;45!B;O;33!B;2!O;44!B;O;3!B;O;20!B;O 3!B;O;12!B;L;79!B;O;B;O;85!B;L;129!B;O;20!B;O;16!B;L;126!B;O;4!B;O 16!B;O;4!B;O;13!B;L;127!B;2!O;B;3!O;14!B;3!O;B;2!O;14!B;L;4!B;2!O 123!B;O;2!B;2!O;B;2!O;6!B;2!O;B;2!O;2!B;O;16!B;L;5!B;2!O;41!B;2!O;80!B 2!O;2!B;O;2!B;O;4!B;O;2!B;O;2!B;2!O;17!B;L;4!B;O;42!B;O;B;O;85!B;2!O 6!B;2!O;22!B;L;49!B;O;117!B;8!L;23!B;2!O;142!B;L;24!B;2!O;141!B;L;23!B O;45!B;O;97!B;L;68!B;2!O;97!B;L;68!B;O;B;O;96!B;2!L;33!B;2!O;132!B;L 32!B;O;B;O;132!B;L;34!B;O;E OCTAL > /} > /} IFNZRO PARSER < /{ RPARSE, 0 > /} *6600 /CHECK FOR CONTROL CHARACTERS CHKCTL, 0 KRB /READ IT AND (177 /KEEP BOTTOM 7 BITS IFNZRO OS8 < /{ DCA TEMP /STORE IT TAD TEMP TAD (-3 /IS IT A CTRL-C? SNA JMP EXIT /YES, EXIT TO OS/8 TAD (-25+3 /IS IT A CTRL-U? > /} IFZERO OS8 < /{ TAD (-25 /IS IT A CTRL-U? > /} SNA CLA JMP START /YES, RESTART THE PROGRAM JMP I CHKCTL /NOT A CTRL-C OR CTRL-U IFNZRO OS8 < /{ EXIT, JMS RSTOS8 /PUT THINGS BACK THE WAY WE FOUND IT JMP I (7600 /AND RETURN TO OS/8 SAVOS8, 0 CLA /HAS THE SYSTEM ALREADY BEEN SAVED? TAD OS8SAV SZA JMP I SAVOS8 /YES, RETURN JMS COPY /NO, DO THE COPIES 0 /COPY FROM 07600 7600-1 0 /TO 07400 7400-1 JMS COPY 10 /COPY FROM 17600 7600-1 0 /TO 07200 7200-1 /MORE THAN 8K AND USING FAST RASTER? IFNZRO MEMORY-1 < /{ IFNZRO VC8E&NOSTOR&FASTR < /{ JMS COPY 20 /COPY FROM 27600 7600-1 0 /TO 07000 7000-1 > /} > /} ISZ OS8SAV /THE SYSTEM HAS BEEN SAVED TAD (7764 /PUT THE MASK TABLE AT 7764 DCA ADDR CLA CLL CML RAR /AC=4000 DCA I ADDR /SAVE IT TAD I ADDR /GET IT CLL RAR /ROTATE IT ISZ ADDR /ANY MORE TO DO? JMP .-4 /NOPE JMP I SAVOS8 RSTOS8, 0 CLA /HAS THE SYSTEM ACTUALLY BEEN SAVED? TAD OS8SAV SNA JMP I RSTOS8 /NOPE, RETURN JMS COPY /YES, COPY BACK 0 /COPY FROM 07400 7400-1 0 /TO 07600 7600-1 JMS COPY 0 /COPY FROM 07200 7200-1 10 /TO 17600 7600-1 /MORE THAN 8K AND USING FAST RASTER? IFNZRO MEMORY-1 < /{ IFNZRO VC8E&NOSTOR&FASTR < /{ JMS COPY 0 /COPY FROM 07000 7000-1 20 /TO 27600 7600-1 > /} > /} DCA OS8SAV /THE SYSTEM HAS BEEN RESTORED JMP I RSTOS8 /BLOCK PAGE COPY BETWEEN FIELDS /ARGUMENTS FOLLOW JMS: /FROM FIELD /FROM ADDR MINUS 1 /TO FIELD /TO ADDR MINUS 1 COPY, 0 CLA TAD (-200 DCA CNT /JUST COPY ONE PAGE TAD I COPY /GET FROM FIELD TAD CDFI DCA FRMCDF /SELF MODIFY FOR FIELD CHANGES ISZ COPY TAD I COPY /GET FROM ADDR MINUS 1 DCA CPTR1 ISZ COPY TAD I COPY /GET TO FIELD TAD CDFI DCA TOCDF /SELF MODIFY FOR FIELD CHANGES ISZ COPY TAD I COPY /GET TO ADDR MINUS 1 DCA CPTR2 ISZ COPY /POINT TO RETURN FRMCDF, HLT /BETTER BE A CDF! TAD I CPTR1 /GET DATA TOCDF, HLT /BETTER BE A CDF! DCA I CPTR2 /SAVE DATA CDFI, CDF 0 ISZ CNT JMP .-6 /DO THE LOOP JMP I COPY /ALL DONE OS8SAV, 0 > /} $