@@@ DUO OS 2 @@@ Designed for the DUO Compact @@@ by Jack Eisenmann @@@ Works like the default increment function, @@@ but occupies less space when called. N incrementLight /N num_ [ incrementLight |<< increment /num_ ] @@@ Works like the default decrement function, @@@ but occupies less space when called. N decrementLight /N num_ [ decrementLight |<< decrement /num_ ] @@@ Works like the default read function, @@@ but occupies less space when called. N readLight /P source_ [ readLight |<< read /source_ ] @@@ Works like the default write function, @@@ but occupies less space when called. V writeLight /P destination, N data_ [ write /destination, data_ ] @@@ XOR together the corresponding bits of two bytes. N xor /N data1, N data2_ [ N temp1 N temp2 temp1 |<< or /data1, data2_ temp2 |<< and /data1, data2_ temp2 |<< not /temp2_ xor |<< and /temp1, temp2_ ] @@@ Add two bytes. N add /N num1, N num2_ [ N temp1 N temp2 while /num2_ [ temp1 |<< xor /num1, num2_ temp2 |<< and /num1, num2_ num1 |<< temp1 num2 |<< shiftRight /temp2_ ] add |<< num1 ] @@@ Subtract two bytes. N subtract /N num1, N num2_ [ num2 |<< decrementLight /num2_ num2 |<< not /num2_ subtract |<< add /num1, num2_ ] @@@ Returns 1 if value is 0; returns 0 otherwise. N booleanNot /N value_ [ booleanNot |<< 1 if /value_ [ booleanNot |<< 0 ] ] @@@ Test equality of two bytes. N equal /N num1, N num2_ [ equal |<< xor /num1, num2_ equal |<< booleanNot /equal_ ] @@@ If num1 is greater than num2, returns 1; @@@ returns 0 otherwise. N greater /N num1, N num2_ [ N bit1 N bit2 N bool while /num2_ [ bit1 |<< and /num1, 128_ bit2 |<< and /num2, 128_ bool |<< xor /bit1, bit2_ if /bool_ [ greater |<< bit1 jump /end_ ] num1 |<< shiftRight /num1_ num2 |<< shiftRight /num2_ ] greater |<< num1 *end* ] @@@ Pause for a short time. V sleep /N count_ [ while /count_ [ count |<< decrementLight /count_ ] ] @@@ Move pointer forward by 1. P incrementPointer /P pointer_ [ N upperByte upperByte |<< second /pointer_ N lowerByte lowerByte |<< first /pointer_ lowerByte |<< incrementLight /lowerByte_ ifNot /lowerByte_ [ upperByte |<< incrementLight /upperByte_ ] incrementPointer |<< pair /lowerByte, upperByte_ ] @@@ Move pointer backward by 1. P decrementPointer /P pointer_ [ N upperByte upperByte |<< second /pointer_ N lowerByte lowerByte |<< first /pointer_ lowerByte |<< decrementLight /lowerByte_ N temp temp |<< not /lowerByte_ ifNot /temp_ [ upperByte |<< decrementLight /upperByte_ ] decrementPointer |<< pair /lowerByte, upperByte_ ] @@@ Move pointer forward by a given offset. P addPointer /P pointer, N offset_ [ N lowerByte lowerByte |<< first /pointer_ N upperByte upperByte |<< second /pointer_ N lastByte lastByte |<< lowerByte lowerByte |<< add /lowerByte, offset_ N temp temp |<< greater /lastByte, lowerByte_ if /temp_ [ upperByte |<< incrementLight /upperByte_ ] addPointer |<< pair /lowerByte, upperByte_ ] @@@ Move pointer backward by a given offset. P subtractPointer /P pointer, N offset_ [ N lowerByte lowerByte |<< first /pointer_ N upperByte upperByte |<< second /pointer_ N lastByte lastByte |<< lowerByte lowerByte |<< subtract /lowerByte, offset_ N temp temp |<< greater /lowerByte, lastByte_ if /temp_ [ upperByte |<< decrementLight /upperByte_ ] subtractPointer |<< pair /lowerByte, upperByte_ ] @@@ Determine whether the first pointer is @@@ greater than the second. N greaterPointer /P pointer1, P pointer2_ [ N upperByte1 N upperByte2 upperByte1 |<< second /pointer1_ upperByte2 |<< second /pointer2_ N bool bool |<< greater /upperByte1, upperByte2_ if /bool_ [ greaterPointer |<< 1 jump /end_ ] bool |<< equal /upperByte1, upperByte2_ ifNot /bool_ [ greaterPointer |<< 0 jump /end_ ] N lowerByte1 N lowerByte2 lowerByte1 |<< first /pointer1_ lowerByte2 |<< first /pointer2_ greaterPointer |<< greater /lowerByte1, lowerByte2_ *end* ] @@@ I/O address for the alphanumeric screen. P screenDataAddress P screenSignalAddress screenDataAddress |<< pair /0, 192_ screenSignalAddress |<< pair /1, 192_ @@@ Send data and signals to the screen. V outputScreen /N data, N signal1, N signal2_ [ output /screenDataAddress, data_ output /screenSignalAddress, signal1_ output /screenSignalAddress, signal2_ ] @@@ Erase all contents of the screen. V clearScreen /_ [ outputScreen /screen#1, 2, 0_ outputScreen /screen#1, 1, 0_ ] @@@ The bytes to send to the display in @@@ order to wake it up. C B}7 wakeDataSet wakeDataSet |<< /screen#48, screen#48, screen#48, screen#56, screen#8, screen#6, screen#12_ @@@ Wake up half of the screen. V wakeScreenHalf /N signal_ [ P source source |<< reference /wakeDataSet_ N count count |<< ?wakeDataSet? while /count_ [ N data data |<< readLight /source_ outputScreen /data, signal, 0_ source |<< incrementPointer /source_ count |<< decrementLight /count_ ] ] @@@ Wake up the entire screen. V wakeScreen /_ [ wakeScreenHalf /2_ wakeScreenHalf /1_ ] @@@ Actually wake and clear the screen for @@@ the first time. wakeScreen /_ clearScreen /_ @@@ Copy a number of bytes from one location @@@ to another. V copyBar /P source, P destination, N count_ [ while /count_ [ N data data |<< readLight /source_ writeLight /destination, data_ source |<< incrementPointer /source_ destination |<< incrementPointer /destination_ count |<< decrementLight /count_ ] ] @@@ Determine whether two bars have equal bytes @@@ in corresponding addresses. N equalBar /P source1, P source2, N count_ [ while /count_ [ N data1 N data2 data1 |<< readLight /source1_ data2 |<< readLight /source2_ N bool bool |<< xor /data1, data2_ if /bool_ [ equalBar |<< 0 jump /end_ ] source1 |<< incrementPointer /source1_ source2 |<< incrementPointer /source2_ count |<< decrementLight /count_ ] equalBar |<< 1 *end* ] @@@ Set all bytes in a bar to a given value. V fillBar /P destination, N data, N count_ [ while /count_ [ writeLight /destination, data_ destination |<< incrementPointer /destination_ count |<< decrementLight /count_ ] ] @@@ Determine the length of some text. N measureText /P source_ [ measureText |<< 0 while /1_ [ N data data |<< readLight /source_ N bool bool |<< equal /data, screen#3_ if /bool_ [ jump /end_ ] measureText |<< incrementLight /measureText_ source |<< incrementPointer /source_ ifNot /measureText_ [ jump /end_ ] ] *end* ] @@@ Display text on the screen. The signal @@@ should be 6 for the top half of the @@@ screen or 5 for the bottom half. V displayText /P source, N signal_ [ while /1_ [ N data data |<< readLight /source_ N bool bool |<< equal /data, screen#3_ if /bool_ [ jump /end_ ] outputScreen /data, signal, 4_ source |<< incrementPointer /source_ ] *end* ] @@@ This is where text is written before it @@@ is dumped to the screen. B}160 screenBuffer P screenBufferHalf1 P screenBufferHalf2 screenBufferHalf1 |<< reference /screenBuffer_ screenBufferHalf2 |<< addPointer /screenBufferHalf1, 80_ fillBar /screenBufferHalf1, screen#32, 160_ @@@ Display half of a screen buffer. V dumpScreenBufferHalf /P source, N signal_ [ N count count |<< 80 while /count_ [ N data data |<< readLight /source_ outputScreen /data, signal, 4_ source |<< incrementPointer /source_ count |<< decrementLight /count_ ] ] @@@ Display the whole screen buffer. V dumpScreenBuffer /_ [ outputScreen /screen#128, 2, 0_ dumpScreenBufferHalf /screenBufferHalf1, 6_ outputScreen /screen#128, 1, 0_ dumpScreenBufferHalf /screenBufferHalf2, 5_ ] @@@ Various locations related to @@@ scrolling buffer text. P scrollScreenBufferStart scrollScreenBufferStart |<< addPointer /screenBufferHalf1, 40_ P displayTextLineStart displayTextLineStart |<< addPointer /screenBufferHalf2, 40_ @@@ Scroll all of the screen buffer lines @@@ up by one, leaving a blank line on @@@ the bottom. V scrollScreenBuffer /_ [ copyBar /scrollScreenBufferStart, screenBufferHalf1, 120_ fillBar /displayTextLineStart, screen#32, 40_ ] @@@ Scroll text lines, write given text @@@ to the bottom of the screen buffer, @@@ and display the screen buffer. V displayTextLine /P source_ [ scrollScreenBuffer /_ N textLength textLength |<< measureText /source_ copyBar /source, displayTextLineStart, textLength_ dumpScreenBuffer /_ ] @@@ Variables pertaining to text entry. N inputCursor C B}40 inputCursorDataSet inputCursorDataSet |<< /screen#192, screen#193, screen#194, screen#195, screen#196, screen#197, screen#198, screen#199, screen#200, screen#201, screen#202, screen#203, screen#204, screen#205, screen#206, screen#207, screen#208, screen#209, screen#210, screen#211, screen#212, screen#213, screen#214, screen#215, screen#216, screen#217, screen#218, screen#219, screen#220, screen#221, screen#222, screen#223, screen#224, screen#225, screen#226, screen#227, screen#228, screen#229, screen#230, screen#231_ P inputCursorDataSetStart inputCursorDataSetStart |<< reference /inputCursorDataSet_ B}40 inputBuffer P inputBufferStart inputBufferStart |<< reference /inputBuffer_ @@@ Change the selected character in the @@@ input buffer. V writeUnderInputCursor /N char_ [ P pointer pointer |<< addPointer /inputBufferStart, inputCursor_ writeLight /pointer, char_ pointer |<< addPointer /inputCursorDataSetStart, inputCursor_ N data data |<< readLight /pointer_ outputScreen /data, 1, 0_ outputScreen /char, 5, 4_ ] @@@ The characters available for text entry. C B}38 promptCharSet promptCharSet |<< "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 " P promptCharSetStart promptCharSetStart |<< reference /promptCharSet_ N selectedPromptCharPos @@@ Returns the character value under @@@ the cursor. N getSelectedPromptChar /_ [ P pointer pointer |<< addPointer /promptCharSetStart, selectedPromptCharPos_ getSelectedPromptChar |<< readLight /pointer_ ] @@@ The I/O address of the keypad. P keyDataAddress keyDataAddress |<< pair /9, 192_ @@@ Scrolls the screen and prompts the user @@@ to enter text. V promptTextLine /_ [ scrollScreenBuffer /_ dumpScreenBuffer /_ inputCursor |<< 0 selectedPromptCharPos |<< 0 N screenData screenData |<< getSelectedPromptChar /_ writeUnderInputCursor /screenData_ outputScreen /screen#95, 5, 4_ while /1_ [ N keyData N bool bool |<< 1 while /bool_ [ keyData |<< readLight /keyDataAddress_ bool |<< booleanNot /keyData_ ] bool |<< and /keyData, 32_ if /bool_ [ selectedPromptCharPos |<< incrementLight /selectedPromptCharPos_ ] bool |<< and /keyData, 4_ if /bool_ [ selectedPromptCharPos |<< decrementLight /selectedPromptCharPos_ ] bool |<< and /keyData, 64_ if /bool_ [ selectedPromptCharPos |<< add /selectedPromptCharPos, 5_ ] bool |<< and /keyData, 2_ if /bool_ [ selectedPromptCharPos |<< subtract /selectedPromptCharPos, 5_ ] bool |<< and /keyData, 8_ if /bool_ [ inputCursor |<< incrementLight /inputCursor_ ] bool |<< and /keyData, 1_ if /bool_ [ writeUnderInputCursor /screen#32_ outputScreen /screen#32, 5, 4_ inputCursor |<< decrementLight /inputCursor_ ] bool |<< and /keyData, 16_ if /bool_ [ jump /break_ ] bool |<< and /keyData, 128_ if /bool_ [ P quitPointer quitPointer |<< pair /0, 0_ jump /quitPointer_ ] bool |<< greater /selectedPromptCharPos, 200_ if /bool_ [ selectedPromptCharPos |<< 36 ] bool |<< greater /selectedPromptCharPos, 36_ if /bool_ [ selectedPromptCharPos |<< 0 ] screenData |<< getSelectedPromptChar /_ writeUnderInputCursor /screenData_ outputScreen /screen#95, 5, 4_ while /keyData_ keyData |<< readLight /keyDataAddress_ ] ] *break* inputCursor |<< incrementLight /inputCursor_ writeUnderInputCursor /screen#3_ copyBar /inputBufferStart, displayTextLineStart, inputCursor_ ] @@@ I/O address for flash chip. P flashOutputAddress P flashInputAddress P bottomFlashAddressAddress P middleFlashAddressAddress P flashSignalAddress flashOutputAddress |<< pair /8, 192_ flashInputAddress |<< pair /2, 192_ bottomFlashAddressAddress |<< pair /3, 192_ middleFlashAddressAddress |<< pair /4, 192_ flashSignalAddress |<< pair /5, 192_ @@@ Store flash address and signal between @@@ function calls. N currentFlashSignal N currentTopFlashAddress currentFlashSignal |<< 224 currentTopFlashAddress |<< 0 @@@ Set the selected flash address @@@ without changing the signal. V selectFlashAddress /P address, N topAddress_ [ N data data |<< first /address_ output /bottomFlashAddressAddress, data_ data |<< second /address_ output /middleFlashAddressAddress, data_ currentTopFlashAddress |<< topAddress data |<< or /currentFlashSignal, currentTopFlashAddress_ output /flashSignalAddress, data_ ] @@@ Send a signal to flash while @@@ keeping the address constant. V signalFlash /N signal_ [ currentFlashSignal |<< signal N data data |<< or /currentFlashSignal, currentTopFlashAddress_ output /flashSignalAddress, data_ ] @@@ Set all flash operations to @@@ inactive. signalFlash /224_ @@@ Output a value to flash. This @@@ does not actually write a value @@@ unless you follow the chip @@@ security protocol. V outputFlash /P address, N topAddress, N value_ [ signalFlash /96_ output /flashInputAddress, value_ selectFlashAddress /address, topAddress_ signalFlash /64_ signalFlash /96_ ] @@@ Erases a sector in flash. A sector @@@ is 4096 bytes long. V eraseFlash /P address, N topAddress_ [ P tempAddress tempAddress |<< pair /58, 26_ outputFlash /tempAddress, 2, 170_ tempAddress |<< pair /197, 5_ outputFlash /tempAddress, 1, 85_ tempAddress |<< pair /58, 26_ outputFlash /tempAddress, 2, 128_ tempAddress |<< pair /58, 26_ outputFlash /tempAddress, 2, 170_ tempAddress |<< pair /197, 5_ outputFlash /tempAddress, 1, 85_ outputFlash /address, topAddress, 48_ sleep /255_ sleep /255_ ] @@@ Writes a value into flash. The @@@ sector must be erased first. V writeFlash /P address, N topAddress, N value_ [ P tempAddress tempAddress |<< pair /58, 26_ outputFlash /tempAddress, 2, 170_ tempAddress |<< pair /197, 5_ outputFlash /tempAddress, 1, 85_ tempAddress |<< pair /58, 26_ outputFlash /tempAddress, 2, 160_ outputFlash /address, topAddress, value_ ] @@@ Reads a value from flash. N readFlash /P address, N topAddress_ [ signalFlash /160_ selectFlashAddress /address, topAddress_ readFlash |<< readLight /flashOutputAddress_ ] @@@ Erases a given number of flash sectors. V eraseFlashSectors /P address, N topAddress, N count_ [ while /count_ [ eraseFlash /address, topAddress_ N bottomAddress N middleAddress bottomAddress |<< first /address_ middleAddress |<< second /address_ middleAddress |<< add /middleAddress, 16_ address |<< pair /bottomAddress, middleAddress_ ifNot /middleAddress_ [ topAddress |<< incrementLight /topAddress_ ] count |<< decrementLight /count_ ] ] @@@ Writes many values to flash @@@ as specified by the source. @@@ Note that the sectors must @@@ first be erased. V writeFlashBar /P address, N topAddress, P source, N upperCount_ [ N count count |<< 0 while /1_ [ ifNot /count_ [ ifNot /upperCount_ [ jump /break_ ] upperCount |<< decrementLight /upperCount_ ] count |<< decrementLight /count_ N data data |<< readLight /source_ writeFlash /address, topAddress, data_ address |<< incrementPointer /address_ N bottomAddress N middleAddress bottomAddress |<< first /address_ middleAddress |<< second /address_ N bool bool |<< or /bottomAddress, middleAddress_ ifNot /bool_ [ topAddress |<< incrementLight /topAddress_ ] source |<< incrementPointer /source_ ] *break* ] @@@ Reads many values from flash @@@ and stores them in destination. V readFlashBar /P address, N topAddress, P destination, N count, N upperCount_ [ while /1_ [ ifNot /count_ [ ifNot /upperCount_ [ jump /break_ ] upperCount |<< decrementLight /upperCount_ ] count |<< decrementLight /count_ N data data |<< readFlash /address, topAddress_ writeLight /destination, data_ address |<< incrementPointer /address_ N bottomAddress N middleAddress bottomAddress |<< first /address_ middleAddress |<< second /address_ N bool bool |<< or /bottomAddress, middleAddress_ ifNot /bool_ [ topAddress |<< incrementLight /topAddress_ ] destination |<< incrementPointer /destination_ ] *break* ] @@@ DUO OS 2 uses a file lookup table @@@ to locate files in flash memory. @@@ The table begins at address 0. @@@ Each entry in the file lookup table @@@ is 16 bytes long. @@@ File lookup entries have this format: @@@ (address) (size) (name) @@@ The address is 3 bytes, size is 1 byte, @@@ and the name is up to 12 bytes. @@@ The size is measured in sectors. @@@ A size of 0 indicates a blank entry. @@@ A size of 255 marks the end of @@@ the lookup table. @@@ The name must end in the string @@@ terminating byte, so the name @@@ may contain up to 11 characters. @@@ Accepts a pointer to text. @@@ Returns a pointer to an entry @@@ in the file lookup table. @@@ If the given file name is not @@@ found, returns 255 255. P findFile /P name_ [ N nameLength nameLength |<< measureText /name_ nameLength |<< incrementLight /nameLength_ findFile |<< pair /3, 0_ while /1_ [ N size size |<< readFlash /findFile, 0_ findFile |<< incrementPointer /findFile_ N bool ifNot /size_ [ jump /ignoreEntry_ ] N bool bool |<< not /size_ ifNot /bool_ [ findFile |<< pair /255, 255_ jump /break_ ] B}12 entryName P entryNameStart entryNameStart |<< reference /entryName_ readFlashBar /findFile, 0, entryNameStart, 12, 0_ bool |<< equalBar /entryNameStart, name, nameLength_ if /bool_ [ findFile |<< subtractPointer /findFile, 4_ jump /break_ ] *ignoreEntry* findFile |<< addPointer /findFile, 15_ ] *break* ] @@@ Returns a pointer to an entry @@@ in the file lookup table. P findBlankEntry /_ [ findBlankEntry |<< pair /3, 0_ while /1_ [ N size size |<< readFlash /findBlankEntry, 0_ ifNot /size_ [ jump /break_ ] N bool bool |<< not /size_ ifNot /bool_ [ jump /break_ ] findBlankEntry |<< addPointer /findBlankEntry, 16_ ] *break* findBlankEntry |<< subtractPointer /findBlankEntry, 3_ ] @@@ Accepts a pointer to an entry @@@ in the file lookup table. @@@ Returns the entry's lower address. P getEntryAddress /P entry_ [ N bottomAddress N middleAddress bottomAddress |<< readFlash /entry, 0_ entry |<< incrementPointer /entry_ middleAddress |<< readFlash /entry, 0_ getEntryAddress |<< pair /bottomAddress, middleAddress_ ] @@@ Accepts a pointer to an entry @@@ in the file lookup table. @@@ Returns the entry's top address. N getEntryTopAddress /P entry_ [ entry |<< addPointer /entry, 2_ getEntryTopAddress |<< readFlash /entry, 0_ ] @@@ Accepts a pointer to an entry @@@ in the file lookup table. @@@ Returns the entry's file size. N getEntrySize /P entry_ [ entry |<< addPointer /entry, 3_ getEntrySize |<< readFlash /entry, 0_ ] @@@ Accepts an entry file size. @@@ Returns the upper byte count which @@@ may be used for bar manipulation. N convertEntrySizeToUpperCount /N size_ [ N count count |<< 4 while /count_ [ size |<< shiftRight /size_ count |<< decrementLight /count_ ] convertEntrySizeToUpperCount |<< size ] @@@ Accepts a pointer to an entry @@@ in the file lookup table. @@@ Writes data from the source. V writeFile /P entry, P source_ [ P address N topAddress N size N upperCount address |<< getEntryAddress /entry_ topAddress |<< getEntryTopAddress /entry_ size |<< getEntrySize /entry_ upperCount |<< convertEntrySizeToUpperCount /size_ eraseFlashSectors /address, topAddress, size_ writeFlashBar /address, topAddress, source, upperCount_ ] @@@ Accepts a pointer to an entry @@@ in the file lookup table. @@@ Reads data into the destination. V readFile /P entry, P destination_ [ P address N topAddress N size N upperCount address |<< getEntryAddress /entry_ topAddress |<< getEntryTopAddress /entry_ size |<< getEntrySize /entry_ upperCount |<< convertEntrySizeToUpperCount /size_ readFlashBar /address, topAddress, destination, 0, upperCount_ ] @@@ Accepts a pointer to text. @@@ Returns a pointer to an entry @@@ in the file lookup table. P createFile /P name, N size_ [ N upperCount upperCount |<< convertEntrySizeToUpperCount /size_ N bool N num1 N num2 P pointer P tableAddress P tablePointer tableAddress |<< pair /0, 0_ tablePointer |<< pair /0, 180_ readFlashBar /tableAddress, 0, tablePointer, 0, 4_ createFile |<< findBlankEntry /_ P creationTablePointer num1 |<< first /createFile_ num2 |<< second /createFile_ num2 |<< add /num2, 180_ creationTablePointer |<< pair /num1, num2_ N lastSize lastSize |<< getEntrySize /createFile_ pointer |<< addPointer /creationTablePointer, 3_ writeLight /pointer, 0_ bool |<< not /lastSize_ ifNot /bool_ [ pointer |<< addPointer /creationTablePointer, 19_ writeLight /pointer, 255_ ] P higherAddress higherAddress |<< pair /16, 0_ N shouldLoop shouldLoop |<< 1 while /shouldLoop_ [ shouldLoop |<< 0 P tempEntry tempEntry |<< pair /0, 0_ while /1_ [ N tempSize tempSize |<< getEntrySize /tempEntry_ ifNot /tempSize_ [ jump /avoid_ ] bool |<< not /tempSize_ ifNot /bool_ [ jump /break_ ] N tempUpperCount tempUpperCount |<< convertEntrySizeToUpperCount /tempSize_ N tempMiddleAddress N tempTopAddress pointer |<< incrementPointer /tempEntry_ tempMiddleAddress |<< readFlash /pointer, 0_ tempTopAddress |<< getEntryTopAddress /tempEntry_ P tempHigherAddress tempHigherAddress |<< pair /tempMiddleAddress, tempTopAddress_ P higherEndAddress P tempHigherEndAddress higherEndAddress |<< addPointer /higherAddress, upperCount_ tempHigherEndAddress |<< addPointer /tempHigherAddress, tempUpperCount_ num1 |<< greaterPointer /higherEndAddress, tempHigherAddress_ num2 |<< greaterPointer /tempHigherEndAddress, higherAddress_ bool |<< and /num1, num2_ ifNot /bool_ [ jump /avoid_ ] higherAddress |<< tempHigherEndAddress shouldLoop |<< 1 *avoid* tempEntry |<< addPointer /tempEntry, 16_ ] *break* ] pointer |<< creationTablePointer writeLight /pointer, 0_ pointer |<< incrementPointer /pointer_ num1 |<< first /higherAddress_ num2 |<< second /higherAddress_ writeLight /pointer, num1_ pointer |<< incrementPointer /pointer_ writeLight /pointer, num2_ pointer |<< incrementPointer /pointer_ writeLight /pointer, size_ pointer |<< incrementPointer /pointer_ copyBar /name, pointer, 12_ eraseFlashSectors /tableAddress, 0, 1_ writeFlashBar /tableAddress, 0, tablePointer, 4_ ] @@@ Accepts a pointer to an entry @@@ in the file lookup table. @@@ Removes the entry. V deleteFile /P entry_ [ N num1 N num2 P pointer P tableAddress P tablePointer tableAddress |<< pair /0, 0_ tablePointer |<< pair /0, 180_ readFlashBar /tableAddress, 0, tablePointer, 0, 4_ P deletionTablePointer num1 |<< first /entry_ num2 |<< second /entry_ num2 |<< add /num2, 180_ deletionTablePointer |<< pair /num1, num2_ pointer |<< addPointer /deletionTablePointer, 3_ writeLight /pointer, 0_ eraseFlashSectors /tableAddress, 0, 1_ writeFlashBar /tableAddress, 0, tablePointer, 4_ ] @@@ Text to display while waiting @@@ for a program to run. C B}20 loadingText loadingText |<< "Loading program..." P loadingTextStart loadingTextStart |<< reference /loadingText_ @@@ Accepts a pointer to an entry @@@ in the file lookup table. @@@ Loads and runs the contents @@@ of the entry's file. V runFile /P entry_ [ P pointer pointer |<< pair /0, 128_ displayTextLine /loadingTextStart_ readFile /entry, pointer_ jump /pointer_ ] @@@ End of function definitions. C B}10 tempFileName tempFileName |<< "START" P tempFileNameStart tempFileNameStart |<< reference /tempFileName_ P tempEntry tempEntry |<< findFile /tempFileNameStart_ runFile /tempEntry_ @@@ The file lookup table. FLASH SEQUENCE 0 16 0 1 "DEMO" 0 0 0 0 0 0 0 SEQUENCE 0 32 0 1 "TEXT" 0 0 0 0 0 0 0 SEQUENCE 0 48 0 2 "START" 0 0 0 0 0 0 SEQUENCE 0 80 0 2 "MANAGE" 0 0 0 0 0 SEQUENCE 0 112 0 2 "EDIT" 0 0 0 0 0 0 0 SEQUENCE 0 144 0 3 "PLATFORM" 0 0 0 SEQUENCE 0 192 0 1 "LEVEL" 0 0 0 0 0 0 SEQUENCE 0 208 0 3 "HEX" 0 0 0 0 0 0 0 0 SEQUENCE 0 0 1 3 "ROOT" 0 0 0 0 0 0 0 SEQUENCE 0 48 1 3 "EXPLORE" 0 0 0 0 SEQUENCE 0 96 1 1 "WORLD" 0 0 0 0 0 0 SEQUENCE 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@@ Program to read and write a file. BUFFER 4096 METASCOPE demo *loopStart* P messageStart messageStart |<< message1 displayTextLine /messageStart_ P textFileNameStart textFileNameStart |<< textFileName P textFileEntry textFileEntry |<< findFile /textFileNameStart_ P textFileAddress textFileAddress |<< getEntryAddress /textFileEntry_ N textFileTopAddress textFileTopAddress |<< getEntryTopAddress /textFileEntry_ B}40 textFileContents P textFileContentsStart textFileContentsStart |<< reference /textFileContents_ readFlashBar /textFileAddress, textFileTopAddress, textFileContentsStart, 40, 0_ displayTextLine /textFileContentsStart_ messageStart |<< message2 displayTextLine /messageStart_ promptTextLine /_ messageStart |<< message3 displayTextLine /messageStart_ eraseFlashSectors /textFileAddress, textFileTopAddress, 1_ writeFlashBar /textFileAddress, textFileTopAddress, inputBufferStart, 1_ messageStart |<< message4 displayTextLine /messageStart_ jump /loopStart_ *message1* SEQUENCE "Contents of file:" *message2* SEQUENCE "Enter some new text:" *message3* SEQUENCE "Writing text to file..." *message4* SEQUENCE "Finished writing." *textFileName* SEQUENCE "TEXT" @@@ A sample text file. BUFFER 8192 METASCOPE text SEQUENCE "HAPPY WEDNESDAY " "FLUTTERSHY IS BEST TREE " screen#25 @@@ The OS command prompt BUFFER 12288 METASCOPE start @@@ Reads text from file entry to @@@ destination. Does not include stop @@@ marker. Source pointer should be @@@ at the entry text, not start of @@@ entry. Returns length of name. N readEntryText /P source, P destination_ [ readEntryText |<< 0 while /1_ [ N data data |<< readFlash /source, 0_ N bool bool |<< equal /data, screen#3_ if /bool_ [ jump /end_ ] writeLight /destination, data_ source |<< incrementPointer /source_ destination |<< incrementPointer /destination_ readEntryText |<< incrementLight /readEntryText_ ] *end* ] @@@ The main program loop. P messageStart messageStart |<< message1 displayTextLine /messageStart_ while /1_ [ N hasRecognizedCommand hasRecognizedCommand |<< 0 promptTextLine /_ messageStart |<< command1 N bool bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ messageStart |<< message3 displayTextLine /messageStart_ messageStart |<< message4 displayTextLine /messageStart_ hasRecognizedCommand |<< 1 ] messageStart |<< command2 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ B}41 textLine P textLineStart textLineStart |<< reference /textLine_ fillBar /textLineStart, screen#32, 39_ P textLinePointer textLinePointer |<< addPointer /textLineStart, 39_ writeLight /textLinePointer, screen#3_ textLinePointer |<< textLineStart P entryPointer entryPointer |<< pair /3, 0_ N textLineIndex textLineIndex |<< 0 while /1_ [ *viewContinue* N fileSize fileSize |<< readFlash /entryPointer, 0_ ifNot /fileSize_ [ entryPointer |<< addPointer /entryPointer, 16_ jump /viewContinue_ ] bool |<< not /fileSize_ ifNot /bool_ [ jump /viewBreak_ ] entryPointer |<< incrementPointer /entryPointer_ N textLength textLength |<< readEntryText /entryPointer, textLinePointer_ textLength |<< incrementLight /textLength_ textLinePointer |<< addPointer /textLinePointer, textLength_ textLineIndex |<< add /textLineIndex, textLength_ bool |<< greater /textLineIndex, 27_ if /bool_ [ displayTextLine /textLineStart_ fillBar /textLineStart, screen#32, 39_ textLinePointer |<< textLineStart textLineIndex |<< 0 ] entryPointer |<< addPointer /entryPointer, 15_ ] *viewBreak* if /textLineIndex_ [ displayTextLine /textLineStart_ ] hasRecognizedCommand |<< 1 ] messageStart |<< command3 bool |<< equalBar /inputBufferStart, messageStart, 3_ if /bool_ [ P fileNameStart fileNameStart |<< addPointer /inputBufferStart, 4_ P tempEntry tempEntry |<< findFile /fileNameStart_ N data data |<< second /tempEntry_ bool |<< not /data_ ifNot /bool_ [ messageStart |<< message5 displayTextLine /messageStart_ jump /runSkip_ ] runFile /tempEntry_ *runSkip* hasRecognizedCommand |<< 1 ] ifNot /hasRecognizedCommand_ [ messageStart |<< message2 displayTextLine /messageStart_ ] ] *message1* SEQUENCE "Welcome to DUO OS 2.0!" *message2* SEQUENCE "You seem confused. Type HELP." *message3* SEQUENCE "List of commands:" *message4* SEQUENCE "HELP; VIEW; RUN [name]" *message5* SEQUENCE "Sorry, no such file." *command1* SEQUENCE "HELP" *command2* SEQUENCE "VIEW" *command3* SEQUENCE "RUN" @@@ The OS file manager. BUFFER 20480 METASCOPE manage @@@ Accept a pointer to some text and @@@ a start index. Returns the next @@@ index of a space or end of text. N findNextSpace /P pointer, N index_ [ while /1_ [ N data data |<< read /pointer_ N bool bool |<< equal /data, screen#32_ if /bool_ [ jump /break_ ] bool |<< equal /data, screen#3_ if /bool_ [ jump /break_ ] pointer |<< incrementPointer /pointer_ index |<< incrementLight /index_ ] *break* findNextSpace |<< index ] @@@ Refer to the start of the digit set. P digitSetStart digitSetStart |<< digitSet @@@ Accepts a screen character. @@@ Returns the digit number value. N convertDigitToNumber /N digit_ [ convertDigitToNumber |<< 0 P pointer pointer |<< digitSetStart N count count |<< 9 while /count_ [ N tempDigit tempDigit |<< readLight /pointer_ N bool bool |<< equal /digit, tempDigit_ if /bool_ [ jump /break_ ] convertDigitToNumber |<< incrementLight /convertDigitToNumber_ pointer |<< incrementPointer /pointer_ count |<< decrementLight /count_ ] *break* ] @@@ The main program loop. P messageStart messageStart |<< message1 displayTextLine /messageStart_ while /1_ [ N hasRecognizedCommand hasRecognizedCommand |<< 0 promptTextLine /_ messageStart |<< command1 N bool bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ messageStart |<< message3 displayTextLine /messageStart_ messageStart |<< message4 displayTextLine /messageStart_ messageStart |<< message5 displayTextLine /messageStart_ hasRecognizedCommand |<< 1 ] messageStart |<< command2 bool |<< equalBar /inputBufferStart, messageStart, 6_ if /bool_ [ messageStart |<< message6 displayTextLine /messageStart_ P inputPointer inputPointer |<< addPointer /inputBufferStart, 7_ N tempIndex tempIndex |<< findNextSpace /inputPointer, 0_ B}12 tempName P tempNameStart tempNameStart |<< reference /tempName_ copyBar /inputPointer, tempNameStart, tempIndex_ P tempNamePointer tempNamePointer |<< addPointer /tempNameStart, tempIndex_ writeLight /tempNamePointer, screen#3_ tempIndex |<< incrementLight /tempIndex_ inputPointer |<< addPointer /inputPointer, tempIndex_ N digit digit |<< readLight /inputPointer_ N tempSize tempSize |<< convertDigitToNumber /digit_ tempNamePointer |<< createFile /tempNameStart, tempSize_ messageStart |<< message7 displayTextLine /messageStart_ hasRecognizedCommand |<< 1 ] messageStart |<< command3 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ P tempNameStart tempNameStart |<< addPointer /inputBufferStart, 5_ P tempEntry tempEntry |<< findFile /tempNameStart_ N tempSize tempSize |<< getEntrySize /tempEntry_ messageStart |<< message8 P messagePointer messagePointer |<< addPointer /messageStart, 19_ P digitSetStart digitSetStart |<< digitSet P tempDigitPointer tempDigitPointer |<< addPointer /digitSetStart, tempSize_ N tempDigit tempDigit |<< readLight /tempDigitPointer_ writeLight /messagePointer, tempDigit_ displayTextLine /messageStart_ hasRecognizedCommand |<< 1 ] messageStart |<< command4 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ P tempNameStart tempNameStart |<< addPointer /inputBufferStart, 7_ P tempEntry tempEntry |<< findFile /tempNameStart_ messageStart |<< message9 displayTextLine /messageStart_ deleteFile /tempEntry_ messageStart |<< message7 displayTextLine /messageStart_ hasRecognizedCommand |<< 1 ] ifNot /hasRecognizedCommand_ [ messageStart |<< message2 displayTextLine /messageStart_ ] ] *message1* SEQUENCE "DUO OS File Manager" *message2* SEQUENCE "You seem confused. Type HELP." *message3* SEQUENCE "List of commands:" *message4* SEQUENCE "HELP; CREATE [name] [size];" *message5* SEQUENCE "DELETE [name]; INFO [name]" *message6* SEQUENCE "Creating file..." *message7* SEQUENCE "Finished." *message8* SEQUENCE "Number of sectors: 0" *message9* SEQUENCE "Deleting file..." *command1* SEQUENCE "HELP" *command2* SEQUENCE "CREATE" *command3* SEQUENCE "INFO" *command4* SEQUENCE "DELETE" *digitSet* SEQUENCE "0123456789" @@@ The text editor. BUFFER 28672 METASCOPE edit @@@ Determines whether the cursor is at @@@ the end of the text file. N isAtEndOfTextFile /_ [ N tempData tempData |<< readLight /textFileCursor_ isAtEndOfTextFile |<< equal /tempData, screen#25_ ] @@@ The main program loop. P messageStart messageStart |<< message1 displayTextLine /messageStart_ P textFileStart textFileStart |<< pair /0, 160_ P textFileCursor textFileCursor |<< textFileStart while /1_ [ N hasRecognizedCommand hasRecognizedCommand |<< 0 promptTextLine /_ messageStart |<< command1 N bool bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ messageStart |<< message3 displayTextLine /messageStart_ messageStart |<< message4 displayTextLine /messageStart_ messageStart |<< message5 displayTextLine /messageStart_ hasRecognizedCommand |<< 1 ] messageStart |<< command2 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ P fileNameStart fileNameStart |<< addPointer /inputBufferStart, 5_ P tempEntry tempEntry |<< findFile /fileNameStart_ messageStart |<< message6 displayTextLine /messageStart_ readFile /tempEntry, textFileStart_ textFileCursor |<< textFileStart hasRecognizedCommand |<< 1 ] messageStart |<< command3 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ bool |<< isAtEndOfTextFile /_ ifNot /bool_ [ textFileCursor |<< addPointer /textFileCursor, 40_ ] hasRecognizedCommand |<< 1 ] messageStart |<< command4 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ bool |<< greaterPointer /textFileCursor, textFileStart_ if /bool_ [ textFileCursor |<< subtractPointer /textFileCursor, 40_ ] hasRecognizedCommand |<< 1 ] messageStart |<< command5 bool |<< equalBar /inputBufferStart, messageStart, 5_ if /bool_ [ textFileCursor |<< textFileStart hasRecognizedCommand |<< 1 ] messageStart |<< command6 bool |<< equalBar /inputBufferStart, messageStart, 3_ if /bool_ [ bool |<< isAtEndOfTextFile /_ whileNot /bool_ [ textFileCursor |<< addPointer /textFileCursor, 40_ bool |<< isAtEndOfTextFile /_ ] hasRecognizedCommand |<< 1 ] messageStart |<< command8 bool |<< equalBar /inputBufferStart, messageStart, 6_ if /bool_ [ bool |<< isAtEndOfTextFile /_ ifNot /bool_ [ P oldCursor oldCursor |<< textFileCursor bool |<< 0 whileNot /bool_ [ P tempPointer tempPointer |<< addPointer /textFileCursor, 40_ copyBar /tempPointer, textFileCursor, 40_ bool |<< isAtEndOfTextFile /_ textFileCursor |<< tempPointer ] textFileCursor |<< oldCursor ] hasRecognizedCommand |<< 1 ] messageStart |<< command9 bool |<< equalBar /inputBufferStart, messageStart, 5_ if /bool_ [ textFileCursor |<< textFileStart writeLight /textFileCursor, screen#25_ hasRecognizedCommand |<< 1 ] messageStart |<< command10 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ P fileNameStart fileNameStart |<< addPointer /inputBufferStart, 5_ P tempEntry tempEntry |<< findFile /fileNameStart_ messageStart |<< message8 displayTextLine /messageStart_ writeFile /tempEntry, textFileStart_ hasRecognizedCommand |<< 1 ] messageStart |<< command7 bool |<< equalBar /inputBufferStart, messageStart, 6_ if /bool_ [ promptTextLine /_ P oldCursor oldCursor |<< textFileCursor bool |<< 0 whileNot /bool_ [ bool |<< isAtEndOfTextFile /_ textFileCursor |<< addPointer /textFileCursor, 40_ ] bool |<< 1 while /bool_ [ P tempPointer tempPointer |<< subtractPointer /textFileCursor, 40_ copyBar /tempPointer, textFileCursor, 40_ textFileCursor |<< tempPointer bool |<< greaterPointer /textFileCursor, oldCursor_ ] copyBar /inputBufferStart, oldCursor, 40_ textFileCursor |<< addPointer /oldCursor, 40_ hasRecognizedCommand |<< 1 ] ifNot /hasRecognizedCommand_ [ messageStart |<< message2 displayTextLine /messageStart_ ] bool |<< isAtEndOfTextFile /_ if /bool_ [ messageStart |<< message7 displayTextLine /messageStart_ ] ifNot /bool_ [ displayTextLine /textFileCursor_ ] ] *message1* SEQUENCE "DUO Text Editor" *message2* SEQUENCE "You seem confused. Type HELP." *message3* SEQUENCE "List of commands:" *message4* SEQUENCE "HELP; OPEN [name]; NEXT; BACK; START;" *message5* SEQUENCE "END; INSERT; DELETE; EMPTY; SAVE [name]" *message6* SEQUENCE "Reading file..." *message7* SEQUENCE "(End of file)" *message8* SEQUENCE "Writing file..." *command1* SEQUENCE "HELP" *command2* SEQUENCE "OPEN" *command3* SEQUENCE "NEXT" *command4* SEQUENCE "BACK" *command5* SEQUENCE "START" *command6* SEQUENCE "END" *command7* SEQUENCE "INSERT" *command8* SEQUENCE "DELETE" *command9* SEQUENCE "EMPTY" *command10* SEQUENCE "SAVE" @@@ The platform game. BUFFER 36864 METASCOPE platform @@@ Define where to read level data. P fileNameStart fileNameStart |<< fileName P tempEntry tempEntry |<< findFile /fileNameStart_ P currentSegmentPointer N fileTopAddress currentSegmentPointer |<< getEntryAddress /tempEntry_ fileTopAddress |<< getEntryTopAddress /tempEntry_ @@@ The start of the screen position set. P screenPositionSetStart screenPositionSetStart |<< screenPositionSet @@@ Displays a single character in the @@@ given location on the screen. V displayCharacter /N character, N posX, N posY_ [ N tempIndex tempIndex |<< posX N bool bool |<< and /posY, 1_ if /bool_ [ tempIndex |<< add /tempIndex, 40_ ] P screenPositionSetPointer screenPositionSetPointer |<< addPointer /screenPositionSetStart, tempIndex_ N screenPosition screenPosition |<< readLight /screenPositionSetPointer_ N screenPositionSignal N screenCharacterSignal screenPositionSignal |<< 2 screenCharacterSignal |<< 6 N bool bool |<< and /posY, 2_ if /bool_ [ screenPositionSignal |<< 1 screenCharacterSignal |<< 5 ] outputScreen /screenPosition, screenPositionSignal, 0_ outputScreen /character, screenCharacterSignal, 4_ ] @@@ The position of the player. N playerPosX N playerPosY @@@ The number of coins remaining @@@ on the screen. N coinsRemaining @@@ List of enemies. Format: @@@ (direction) (posX) (posY) @@@ If direction is 0, the enemy @@@ does not exist. B}9 enemyList P enemyListStart enemyListStart |<< reference /enemyList_ @@@ Writes a set of data to an enemy @@@ entry. V writeEnemyEntry /P enemyEntry, N direction, N posX, N posY_ [ writeLight /enemyEntry, direction_ enemyEntry |<< incrementPointer /enemyEntry_ writeLight /enemyEntry, posX_ enemyEntry |<< incrementPointer /enemyEntry_ writeLight /enemyEntry, posY_ ] @@@ Loads a segment of the level. V loadSegment /P filePointer_ [ P screenBufferPointer screenBufferPointer |<< screenBufferHalf1 count |<< 4 while /count_ [ readFlashBar /filePointer, fileTopAddress, screenBufferPointer, 39, 0_ filePointer |<< addPointer /filePointer, 40_ screenBufferPointer |<< addPointer /screenBufferPointer, 40_ count |<< decrementLight /count_ ] coinsRemaining |<< 0 screenBufferPointer |<< screenBufferHalf1 N posX N posY posX |<< 0 posY |<< 0 P enemyEntry enemyEntry |<< enemyListStart N enemiesRemaining enemiesRemaining |<< 3 count |<< 160 while /count_ [ N tempCharacter tempCharacter |<< readLight /screenBufferPointer_ N bool bool |<< equal /tempCharacter, screen#111_ if /bool_ [ coinsRemaining |<< incrementLight /coinsRemaining_ ] bool |<< equal /tempCharacter, screen#88_ if /bool_ [ writeEnemyEntry /enemyEntry, 1, posX, posY_ enemyEntry |<< addPointer /enemyEntry, 3_ setScreenBufferCharacter /posX, posY, screen#32_ enemiesRemaining |<< decrementLight /enemiesRemaining_ ] screenBufferPointer |<< incrementPointer /screenBufferPointer_ posX |<< incrementLight /posX_ bool |<< equal /posX, 40_ if /bool_ [ posX |<< 0 posY |<< incrementLight /posY_ ] count |<< decrementLight /count_ ] while /enemiesRemaining_ [ writeLight /enemyEntry, 0_ enemyEntry |<< addPointer /enemyEntry, 3_ enemiesRemaining |<< decrementLight /enemiesRemaining_ ] dumpScreenBuffer /_ playerPosX |<< 0 playerPosY |<< 3 displayCharacter /screen#109, playerPosX, playerPosY_ ] @@@ Retrieves the character at the given position @@@ in the screen buffer. Returns an equal sign @@@ if the positions are out of bounds. N getScreenBufferCharacter /N posX, N posY_ [ N bool bool |<< greater /posX, 38_ if /bool_ [ getScreenBufferCharacter |<< screen#61 jump /end_ ] bool |<< greater /posY, 3_ if /bool_ [ getScreenBufferCharacter |<< screen#61 jump /end_ ] P screenBufferPointer screenBufferPointer |<< addPointer /screenBufferHalf1, posX_ while /posY_ [ screenBufferPointer |<< addPointer /screenBufferPointer, 40_ posY |<< decrementLight /posY_ ] getScreenBufferCharacter |<< readLight /screenBufferPointer_ *end* ] @@@ Determines whether a screen buffer @@@ character is equal to another @@@ character. N equalScreenBufferCharacter /N posX, N posY, N character_ [ N tempCharacter tempCharacter |<< getScreenBufferCharacter /posX, posY_ equalScreenBufferCharacter |<< equal /tempCharacter, character_ ] @@@ Sets the character at the given position @@@ in the screen buffer. Does not check for @@@ boundary conditions. V setScreenBufferCharacter /N posX, N posY, N character_ [ P screenBufferPointer screenBufferPointer |<< addPointer /screenBufferHalf1, posX_ while /posY_ [ screenBufferPointer |<< addPointer /screenBufferPointer, 40_ posY |<< decrementLight /posY_ ] writeLight /screenBufferPointer, character_ ] @@@ Displays a character in the screen @@@ buffer at the given position. V displayScreenBufferCharacter /N posX, N posY_ [ N tempCharacter tempCharacter |<< getScreenBufferCharacter /posX, posY_ displayCharacter /tempCharacter, posX, posY_ ] @@@ Determines if an entity may pass @@@ through a given position. N isPhantomCell /N posX, N posY_ [ N tempCharacter isPhantomCell |<< equalScreenBufferCharacter /posX, posY screen#61_ isPhantomCell |<< booleanNot /isPhantomCell_ ] @@@ Determines if an entity should @@@ fall down through a cell. N shouldFallThroughCell /N posX, N posY_ [ shouldFallThroughCell |<< 0 N bool bool |<< equalScreenBufferCharacter /posX, posY, screen#72_ ifNot /bool_ [ shouldFallThroughCell |<< isPhantomCell /posX, posY_ ] ] @@@ For when the player dies. P deathMessageStart deathMessageStart |<< message1 N playerIsDead playerIsDead |<< 0 @@@ Kills the player if they @@@ occupy the given position. V killAtPos /N posX, N posY_ [ N bool bool |<< equal /playerPosX, posX_ if /bool_ [ bool |<< equal /playerPosY, posY_ if /bool_ [ displayTextLine /deathMessageStart_ playerIsDead |<< 1 ] ] ] @@@ The main program loop. loadSegment /currentSegmentPointer_ while /1_ [ *continue* N shouldMove shouldMove |<< 0 N nextPosX N nextPosY nextPosX |<< playerPosX nextPosY |<< playerPosY shouldMove |<< 0 bool |<< shouldFallThroughCell /nextPosX, nextPosY_ if /bool_ [ N tempPosY tempPosY |<< incrementLight /nextPosY_ bool |<< shouldFallThroughCell /nextPosX, tempPosY_ if /bool_ [ nextPosY |<< tempPosY shouldMove |<< 1 ] ] N keyData keyData |<< readLight /keyDataAddress_ N bool bool |<< and /keyData, 128_ if /bool_ [ P tempPointer tempPointer |<< pair /0, 0_ jump /tempPointer_ ] if /playerIsDead_ [ jump /continue_ ] N verticalOffset verticalOffset |<< 0 bool |<< and /keyData, 32_ if /bool_ [ verticalOffset |<< 255 ] bool |<< and /keyData, 4_ if /bool_ [ verticalOffset |<< 1 ] if /verticalOffset_ [ N tempPosY tempPosY |<< add /nextPosY, verticalOffset_ bool |<< isPhantomCell /nextPosX, tempPosY_ if /bool_ [ nextPosY |<< tempPosY shouldMove |<< 1 ] ] N horizontalOffset horizontalOffset |<< 0 bool |<< and /keyData, 2_ if /bool_ [ horizontalOffset |<< 255 ] bool |<< and /keyData, 8_ if /bool_ [ horizontalOffset |<< 1 ] if /horizontalOffset_ [ N tempPosX tempPosX |<< add /nextPosX, horizontalOffset_ bool |<< isPhantomCell /tempPosX, nextPosY_ if /bool_ [ nextPosX |<< tempPosX shouldMove |<< 1 ] ifNot /bool_ [ N tempPosY tempPosY |<< decrementLight /nextPosY_ bool |<< isPhantomCell /tempPosX, tempPosY_ if /bool_ [ nextPosX |<< tempPosX nextPosY |<< tempPosY shouldMove |<< 1 ] ] ] if /shouldMove_ [ displayScreenBufferCharacter /playerPosX, playerPosY_ playerPosX |<< nextPosX playerPosY |<< nextPosY displayCharacter /screen#109, playerPosX, playerPosY_ bool |<< equalScreenBufferCharacter /playerPosX, playerPosY, screen#111_ if /bool_ [ setScreenBufferCharacter /playerPosX, playerPosY, screen#32_ coinsRemaining |<< decrementLight /coinsRemaining_ ifNot /coinsRemaining_ [ displayCharacter /screen#62, 39, 2_ ] ] ifNot /coinsRemaining_ [ bool |<< equal /playerPosX, 38_ if /bool_ [ currentSegmentPointer |<< addPointer /currentSegmentPointer, 160_ loadSegment /currentSegmentPointer_ ] ] ] P enemyEntry enemyEntry |<< enemyListStart N count count |<< 3 while /count_ [ N direction direction |<< readLight /enemyEntry_ if /direction_ [ P enemyPointer enemyPointer |<< incrementPointer /enemyEntry_ N posX posX |<< readLight /enemyPointer_ enemyPointer |<< incrementPointer /enemyPointer_ N posY posY |<< readLight /enemyPointer_ killAtPos /posX, posY_ displayScreenBufferCharacter /posX, posY_ N tempPosX tempPosX |<< add /posX, direction_ N bool bool |<< isPhantomCell /tempPosX, posY_ ifNot /bool_ [ direction |<< subtract /0, direction_ ] posX |<< add /posX, direction_ displayCharacter /screen#88, posX, posY_ killAtPos /posX, posY_ writeEnemyEntry /enemyEntry, direction, posX, posY_ ] enemyEntry |<< addPointer /enemyEntry, 3_ count |<< decrementLight /count_ ] ] *fileName* SEQUENCE "LEVEL" *message1* SEQUENCE "You have died!" *screenPositionSet* SEQUENCE screen#128, screen#129, screen#130, screen#131, screen#132, screen#133, screen#134, screen#135, screen#136, screen#137, screen#138, screen#139, screen#140, screen#141, screen#142, screen#143, screen#144, screen#145, screen#146, screen#147, screen#148, screen#149, screen#150, screen#151, screen#152, screen#153, screen#154, screen#155, screen#156, screen#157, screen#158, screen#159, screen#160, screen#161, screen#162, screen#163, screen#164, screen#165, screen#166, screen#167 SEQUENCE screen#192, screen#193, screen#194, screen#195, screen#196, screen#197, screen#198, screen#199, screen#200, screen#201, screen#202, screen#203, screen#204, screen#205, screen#206, screen#207, screen#208, screen#209, screen#210, screen#211, screen#212, screen#213, screen#214, screen#215, screen#216, screen#217, screen#218, screen#219, screen#220, screen#221, screen#222, screen#223, screen#224, screen#225, screen#226, screen#227, screen#228, screen#229, screen#230, screen#231 @@@ The platform game level data. BUFFER 49152 METASCOPE level SEQUENCE " o = = = = = " SEQUENCE " == H======== o o H " SEQUENCE " === H = ========H " SEQUENCE " ==== H = H " SEQUENCE " " SEQUENCE " H======H = o X o = " SEQUENCE " H H H======H======H " SEQUENCE " = X = H o H o H " SEQUENCE " =======HHHHHHHHHHHHHH o " SEQUENCE " HHHHHHHHH H " SEQUENCE " H=X = o === o " SEQUENCE " H= X= ======= " SEQUENCE " = o X = o " SEQUENCE " H======H X o H======H " SEQUENCE " H H======H======H H " SEQUENCE " H o =H H o H o X H= " SEQUENCE " = o X = " SEQUENCE " = = o H X = " SEQUENCE " == = H H X o = " SEQUENCE " ==o H H H " SEQUENCE " =HHHHHoHHHHHHH=HHHHHHoHHHHHHHH= " SEQUENCE " =XHHHHHHHHHHHH=XHHHHHHHHHHHHHH= " SEQUENCE " HHHHHH=HHHHHHHHHHHHHX=HHHHHHHHH " SEQUENCE " HHHHHH=HHHHHHHoHHHHHH=HHHHHHHHH " SEQUENCE " H H =" SEQUENCE " H H ===================== H H =" SEQUENCE " H === Congratulations! === H =" SEQUENCE " === You are a super winner! === =" @@@ The hex editor. BUFFER 53248 METASCOPE hex @@@ The list of hexadecimal digits. P hexDigitSetStart hexDigitSetStart |<< hexDigitSet @@@ Returns the index of the digit @@@ in the hex digit set. N findHexDigit /N digit_ [ P hexDigitSetPointer hexDigitSetPointer |<< hexDigitSetStart findHexDigit |<< 0 while /1_ [ N tempDigit tempDigit |<< readLight /hexDigitSetPointer_ N bool bool |<< equal /tempDigit, digit_ if /bool_ [ jump /break_ ] hexDigitSetPointer |<< incrementPointer /hexDigitSetPointer_ findHexDigit |<< incrementLight /findHexDigit_ ] *break* ] @@@ Accepts a pointer to two hexadecimal @@@ digits. Returns the number value. N convertHexToNumber /P text_ [ N tempDigit tempDigit |<< readLight /text_ convertHexToNumber |<< findHexDigit /tempDigit_ text |<< incrementPointer /text_ tempDigit |<< readLight /text_ N tempNumber tempNumber |<< findHexDigit /tempDigit_ N count count |<< 4 while /count_ [ tempNumber |<< shiftRight /tempNumber_ count |<< decrementLight /count_ ] convertHexToNumber |<< add /convertHexToNumber, tempNumber_ ] @@@ Global variables to be modified @@@ by certain functions. P sectorAddress N sectorTopAddress @@@ Accepts a pointer to six hexadecimal @@@ digits. Writes the number value to @@@ the global sector address variables. V convertHexToSectorAddress /P text_ [ N tempNumber1 tempNumber1 |<< convertHexToNumber /text_ text |<< addPointer /text, 2_ N tempNumber2 tempNumber2 |<< convertHexToNumber /text_ text |<< addPointer /text, 2_ sectorAddress |<< pair /tempNumber1, tempNumber2_ sectorTopAddress |<< convertHexToNumber /text_ ] @@@ Accepts a number and a pointer. @@@ Writes the hexadecimal representation @@@ of the number to the destination. V convertNumberToHex /N num, P destination_ [ N tempNumber tempNumber |<< and /num, 15_ P hexDigitSetPointer hexDigitSetPointer |<< addPointer /hexDigitSetStart, tempNumber_ N tempDigit tempDigit |<< readLight /hexDigitSetPointer_ writeLight /destination, tempDigit_ destination |<< incrementPointer /destination_ tempNumber |<< num N count count |<< 4 while /count_ [ tempNumber |<< shiftLeft /tempNumber_ count |<< decrementLight /count_ ] hexDigitSetPointer |<< addPointer /hexDigitSetStart, tempNumber_ tempDigit |<< readLight /hexDigitSetPointer_ writeLight /destination, tempDigit_ ] @@@ The location for the sector buffer @@@ and its cursor. P sectorBufferStart sectorBufferStart |<< pair /0, 168_ P sectorBufferCursor sectorBufferCursor |<< sectorBufferStart @@@ The main program loop. P messageStart messageStart |<< message1 displayTextLine /messageStart_ while /1_ [ N hasRecognizedCommand hasRecognizedCommand |<< 0 promptTextLine /_ messageStart |<< command1 N bool bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ messageStart |<< message3 displayTextLine /messageStart_ messageStart |<< message4 displayTextLine /messageStart_ messageStart |<< message5 displayTextLine /messageStart_ hasRecognizedCommand |<< 1 ] messageStart |<< command2 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ P hexValueStart hexValueStart |<< addPointer /inputBufferStart, 5_ convertHexToSectorAddress /hexValueStart_ messageStart |<< message6 displayTextLine /messageStart_ readFlashBar /sectorAddress, sectorTopAddress, sectorBufferStart, 0, 16_ hasRecognizedCommand |<< 1 ] messageStart |<< command3 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ P hexValueStart hexValueStart |<< addPointer /inputBufferStart, 5_ N tempNumber1 tempNumber1 |<< convertHexToNumber /hexValueStart_ hexValueStart |<< addPointer /hexValueStart, 2_ N tempNumber2 tempNumber2 |<< convertHexToNumber /hexValueStart_ N tempOffset tempOffset |<< second /sectorBufferStart_ tempNumber2 |<< add /tempNumber2, tempOffset_ sectorBufferCursor |<< pair /tempNumber1, tempNumber2_ hasRecognizedCommand |<< 1 ] messageStart |<< command4 bool |<< equalBar /inputBufferStart, messageStart, 5_ if /bool_ [ P hexValueStart hexValueStart |<< addPointer /inputBufferStart, 6_ convertHexToSectorAddress /hexValueStart_ messageStart |<< message7 displayTextLine /messageStart_ eraseFlashSectors /sectorAddress, sectorTopAddress, 1_ writeFlashBar /sectorAddress, sectorTopAddress, sectorBufferStart, 16_ hasRecognizedCommand |<< 1 ] ifNot /hasRecognizedCommand_ [ N tempLength tempLength |<< measureText /inputBufferStart_ bool |<< equal /tempLength, 11_ if /bool_ [ P hexValueStart hexValueStart |<< inputBufferStart P sectorBufferPointer sectorBufferPointer |<< sectorBufferCursor N count count |<< 4 while /count_ [ N tempNumber tempNumber |<< convertHexToNumber /hexValueStart_ writeLight /sectorBufferPointer, tempNumber_ hexValueStart |<< addPointer /hexValueStart, 3_ sectorBufferPointer |<< incrementPointer /sectorBufferPointer_ count |<< decrementLight /count_ ] hasRecognizedCommand |<< 1 ] ] messageStart |<< message8 P messagePointer messagePointer |<< messageStart P sectorBufferPointer sectorBufferPointer |<< sectorBufferCursor N count count |<< 4 while /count_ [ N data data |<< readLight /sectorBufferPointer_ convertNumberToHex /data, messagePointer_ messagePointer |<< addPointer /messagePointer, 3_ sectorBufferPointer |<< incrementPointer /sectorBufferPointer_ count |<< decrementLight /count_ ] displayTextLine /messageStart_ ifNot /hasRecognizedCommand_ [ messageStart |<< message2 displayTextLine /messageStart_ ] ] *message1* SEQUENCE "DUO Hex Editor" *message2* SEQUENCE "You seem confused. Type HELP." *message3* SEQUENCE "List of commands:" *message4* SEQUENCE "HELP; READ [addr]; SKIP [addr];" *message5* SEQUENCE "[val] [val] [val] [val]; WRITE [addr]" *message6* SEQUENCE "Reading sector..." *message7* SEQUENCE "Writing sector..." *message8* SEQUENCE "00 00 00 00" *command1* SEQUENCE "HELP" *command2* SEQUENCE "READ" *command3* SEQUENCE "SKIP" *command4* SEQUENCE "WRITE" *hexDigitSet* SEQUENCE "0123456789ABCDEF" @@@ The square root calculator. BUFFER 65536 METASCOPE root @@@ The list of decimal digits. P digitSetStart digitSetStart |<< digitSet @@@ Accepts a decimal digit. @@@ Returns the number value. N convertDigitToNumber /N digit_ [ P digitSetPointer digitSetPointer |<< digitSetStart convertDigitToNumber |<< 0 while /1_ [ N tempDigit tempDigit |<< readLight /digitSetPointer_ N bool bool |<< equal /tempDigit, digit_ if /bool_ [ jump /break_ ] digitSetPointer |<< incrementPointer /digitSetPointer_ convertDigitToNumber |<< incrementLight /convertDigitToNumber_ ] *break* ] @@@ BCD bar representation: @@@ XX.XXXXXXYYYYYY @@@ The Decimal point is always after @@@ the second place value. @@@ For display purposes, the last 6 @@@ digits are truncated. @@@ The start of division and @@@ modulus tables. P divideByTenStart P modulusByTenStart divideByTenStart |<< divideByTen modulusByTenStart |<< modulusByTen @@@ Accepts pointers to coded bars. @@@ Determines whether the first @@@ coded bar is greater than the @@@ second. N greaterCodedBar /P source1, P source2_ [ N count count |<< 11 while /count_ [ N tempNumber1 N tempNumber2 tempNumber1 |<< readLight /source1_ tempNumber2 |<< readLight /source2_ N bool bool |<< greater /tempNumber1, tempNumber2_ if /bool_ [ greaterCodedBar |<< 1 jump /break_ ] bool |<< greater /tempNumber2, tempNumber1_ if /bool_ [ greaterCodedBar |<< 0 jump /break_ ] source1 |<< incrementPointer /source1_ source2 |<< incrementPointer /source2_ count |<< decrementLight /count_ ] *break* ] @@@ The desired square value. B}14 targetCodedBar P targetCodedBarStart targetCodedBarStart |<< reference /targetCodedBar_ @@@ The candidate guess for @@@ a square root. B}14 guessCodedBar P guessCodedBarStart guessCodedBarStart |<< reference /guessCodedBar_ P guessCodedBarCursor N guessNumber N guessNumberOffset N placesRemaining @@@ The result of squaring the guess @@@ coded bar. B}14 productCodedBar P productCodedBarStart productCodedBarStart |<< reference /productCodedBar_ @@@ The square when the selected digit @@@ is removed. B}14 lastProductCodedBar P lastProductCodedBarStart lastProductCodedBarStart |<< reference /lastProductCodedBar_ @@@ The square of the last iteration. B}14 smallerProductCodedBar P smallerProductCodedBarStart smallerProductCodedBarStart |<< reference /smallerProductCodedBar_ @@@ Converts text into a coded bar. V convertInputBufferToTargetCodedBar /_ [ N tempDigit N tempNumber tempDigit |<< readLight /inputBufferStart_ tempNumber |<< convertDigitToNumber /tempDigit_ writeLight /targetCodedBarStart, tempNumber_ P tempSource P tempDestination tempSource |<< incrementPointer /inputBufferStart_ tempDestination |<< incrementPointer /targetCodedBarStart_ tempDigit |<< readLight /tempSource_ tempNumber |<< convertDigitToNumber /tempDigit_ writeLight /tempDestination, tempNumber_ tempDestination |<< incrementPointer /tempDestination_ fillBar /tempDestination, 0, 12_ ] @@@ Converts a coded bar into text. V displayCodedBar /P codedBarPointer_ [ B}11 tempText P tempTextStart tempTextStart |<< reference /tempText_ P tempTextPointer tempTextPointer |<< reference /tempText_ N count count |<< 8 while /count_ [ N tempNumber tempNumber |<< readLight /codedBarPointer_ P digitSetPointer digitSetPointer |<< addPointer /digitSetStart, tempNumber_ N tempDigit tempDigit |<< readLight /digitSetPointer_ writeLight /tempTextPointer, tempDigit_ codedBarPointer |<< incrementPointer /codedBarPointer_ tempTextPointer |<< incrementPointer /tempTextPointer_ count |<< decrementLight /count_ N bool bool |<< equal /count, 6_ if /bool_ [ writeLight /tempTextPointer, screen#46_ tempTextPointer |<< incrementPointer /tempTextPointer_ ] ] writeLight /tempTextPointer, screen#3_ displayTextLine /tempTextStart_ ] @@@ Returns the product of two numbers. N multiply /N num1, N num2_ [ multiply |<< 0 while /num1_ [ multiply |<< add /multiply, num2_ num1 |<< decrementLight /num1_ ] ] @@@ Carries any number greater than @@@ nine in the product coded bar. V carryProductCodedBar /_ [ P productCodedBarPointer productCodedBarPointer |<< addPointer /productCodedBarStart, 13_ N carryNumber carryNumber |<< 0 N count count |<< 14 while /count_ [ N tempNumber tempNumber |<< readLight /productCodedBarPointer_ tempNumber |<< add /tempNumber, carryNumber_ P tempPointer N tempRemainder tempPointer |<< addPointer /divideByTenStart, tempNumber_ carryNumber |<< readLight /tempPointer_ tempPointer |<< addPointer /modulusByTenStart, tempNumber_ tempRemainder |<< readLight /tempPointer_ writeLight /productCodedBarPointer, tempRemainder_ productCodedBarPointer |<< decrementPointer /productCodedBarPointer_ count |<< decrementLight /count_ ] ] @@@ Squares the guess coded bar. @@@ Writes to productCodedBar. V squareGuessCodedBar /_ [ copyBar /lastProductCodedBarStart, productCodedBarStart, 14_ N tempNumber tempNumber |<< multiply /guessNumber, guessNumber_ N tempOffset tempOffset |<< add /guessNumberOffset, guessNumberOffset_ tempOffset |<< incrementLight /tempOffset_ P productCodedBarPointer productCodedBarPointer |<< addPointer /productCodedBarStart, tempOffset_ writeLight /productCodedBarPointer, tempNumber_ carryProductCodedBar /_ P guessCodedBarPointer guessCodedBarPointer |<< guessCodedBarCursor tempOffset |<< guessNumberOffset while /tempOffset_ [ productCodedBarPointer |<< decrementPointer /productCodedBarPointer_ guessCodedBarPointer |<< decrementPointer /guessCodedBarPointer_ tempOffset |<< decrementLight /tempOffset_ tempNumber |<< readLight /guessCodedBarPointer_ tempNumber |<< multiply /tempNumber, guessNumber_ tempNumber |<< add /tempNumber, tempNumber_ N lastNumber lastNumber |<< readLight /productCodedBarPointer_ tempNumber |<< add /tempNumber, lastNumber_ writeLight /productCodedBarPointer, tempNumber_ carryProductCodedBar /_ ] ] @@@ The main program loop. P messageStart messageStart |<< message1 displayTextLine /messageStart_ while /1_ [ promptTextLine /_ convertInputBufferToTargetCodedBar /_ fillBar /guessCodedBarStart, 0, 14_ guessCodedBarCursor |<< incrementPointer /guessCodedBarStart_ guessNumber |<< 0 guessNumberOffset |<< 0 placesRemaining |<< 7 fillBar /lastProductCodedBarStart, 0, 14_ fillBar /smallerProductCodedBarStart, 0, 14_ while /placesRemaining_ [ squareGuessCodedBar /_ N bool bool |<< greaterCodedBar /productCodedBarStart, targetCodedBarStart_ if /bool_ [ if /guessNumber_ [ guessNumber |<< decrementLight /guessNumber_ ] writeLight /guessCodedBarCursor, guessNumber_ displayCodedBar /guessCodedBarStart_ guessCodedBarCursor |<< incrementPointer /guessCodedBarCursor_ guessNumber |<< 0 guessNumberOffset |<< incrementLight /guessNumberOffset_ placesRemaining |<< decrementLight /placesRemaining_ copyBar /smallerProductCodedBarStart, lastProductCodedBarStart, 14_ ] ifNot /bool_ [ guessNumber |<< incrementLight /guessNumber_ copyBar /productCodedBarStart, smallerProductCodedBarStart, 14_ ] ] ] *message1* SEQUENCE "Square Root Calculator" *digitSet* SEQUENCE "0123456789" *divideByTen* SEQUENCE 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 11 11 12 12 12 12 12 12 12 12 12 12 13 13 13 13 13 13 13 13 13 13 14 14 14 14 14 14 14 14 14 14 15 15 15 15 15 15 15 15 15 15 16 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 17 17 17 17 *modulusByTen* SEQUENCE 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 @@@ The text adventure. BUFFER 77824 METASCOPE explore @@@ The world and room to interpret. P fileNameStart fileNameStart |<< fileName P tempEntry tempEntry |<< findFile /fileNameStart_ P fileAddress N fileTopAddress fileAddress |<< getEntryAddress /tempEntry_ fileTopAddress |<< getEntryTopAddress /tempEntry_ P instructionPointer P loadRoomDestination loadRoomDestination |<< pair /0, 176_ @@@ Loads a room into memory. V loadRoom /P address_ [ N tempNumber1 N tempNumber2 tempNumber1 |<< second /address_ tempNumber1 |<< subtract /tempNumber1, 128_ tempNumber2 |<< second /fileAddress_ tempNumber2 |<< add /tempNumber1, tempNumber2_ tempNumber1 |<< first /address_ P tempAddress tempAddress |<< pair /tempNumber1, tempNumber2_ readFlashBar /tempAddress, fileTopAddress, loadRoomDestination, 0, 3_ instructionPointer |<< loadRoomDestination ] @@@ Retrieves an argument from the @@@ current instruction. N getArg /N which_ [ P tempPointer tempPointer |<< addPointer /instructionPointer, which_ getArg |<< readLight /tempPointer_ ] @@@ The set of registers for use @@@ by the world instructions. @@@ All registers have an initial @@@ value of 1. B}32 worldRegisters P worldRegistersStart worldRegistersStart |<< reference /worldRegisters_ fillBar /worldRegistersStart, 1, ?worldRegisters?_ @@@ Retrieves a register value. N getReg /N which_ [ P tempPointer tempPointer |<< addPointer /worldRegistersStart, which_ getReg |<< readLight /tempPointer_ ] @@@ Changes a register value. V setReg /N which, N value_ [ P tempPointer tempPointer |<< addPointer /worldRegistersStart, which_ writeLight /tempPointer, value_ ] @@@ Checks to see if the input @@@ option is the same as the @@@ text argument. N lastInputOptionMatchesArg /_ [ N tempLength tempLength |<< measureText /lastInputOptionStart_ P tempPointer tempPointer |<< addPointer /instructionPointer, 2_ lastInputOptionMatchesArg |<< equalBar /lastInputOptionStart, tempPointer, tempLength_ ] @@@ The list of inventory items. @@@ The start of each name is @@@ separated by 12 bytes. B}96 inventoryItems P inventoryItemsStart inventoryItemsStart |<< reference /inventoryItems_ fillBar /inventoryItemsStart, screen#3, ?inventoryItems?_ @@@ Accepts the name of an item. @@@ Returns a pointer to the item @@@ in inventory. If the item cannot @@@ be found, the function returns @@@ the pointer 255 255. P findInventoryItem /P name_ [ findInventoryItem |<< inventoryItemsStart N tempLength tempLength |<< measureText /name_ tempLength |<< incrementLight /tempLength_ N count count |<< 8 while /count_ [ N bool bool |<< equalBar /name, findInventoryItem, tempLength_ if /bool_ [ jump /end_ ] findInventoryItem |<< addPointer /findInventoryItem, 12_ count |<< decrementLight /count_ ] findInventoryItem |<< pair /255, 255_ *end* ] @@@ The main program loop. P tempAddress tempAddress |<< pair /0, 128_ loadRoom /tempAddress_ P messageStart while /1_ [ N shouldLoop shouldLoop |<< 1 while /shouldLoop_ [ N currentOperation currentOperation |<< readLight /instructionPointer_ N tempArg1 N tempArg2 tempArg1 |<< getArg /1_ tempArg2 |<< getArg /2_ N instructionLength instructionLength |<< 3 N shouldMeasureInstruction shouldMeasureInstruction |<< 0 P argumentTextStart argumentTextStart |<< incrementPointer /instructionPointer_ N bool bool |<< equal /currentOperation, 1_ if /bool_ [ displayTextLine /argumentTextStart_ shouldMeasureInstruction |<< 1 ] bool |<< equal /currentOperation, 2_ if /bool_ [ shouldLoop |<< 0 instructionLength |<< 1 ] bool |<< equal /currentOperation, 3_ if /bool_ [ setReg /tempArg1, tempArg2_ ] bool |<< equal /currentOperation, 4_ if /bool_ [ N tempValue tempValue |<< getReg /tempArg2_ setReg /tempArg1, tempValue_ ] bool |<< equal /currentOperation, 5_ if /bool_ [ N tempValue tempValue |<< getReg /tempArg1_ tempValue |<< booleanNot /tempValue_ setReg /tempArg1, tempValue_ instructionLength |<< 2 ] bool |<< equal /currentOperation, 6_ if /bool_ [ N tempValue1 N tempValue2 tempValue1 |<< getReg /tempArg1_ tempValue2 |<< getReg /tempArg2_ N tempValue tempValue |<< and /tempValue1, tempValue2_ setReg /tempArg1, tempValue_ ] N tempOperation N tempAction tempOperation |<< 7 tempAction |<< 1 N count count |<< 3 while /count_ [ bool |<< equal /currentOperation, tempOperation_ if /bool_ [ N tempValue tempValue |<< 0 bool |<< equal /lastInputAction, tempAction_ if /bool_ [ tempValue |<< lastInputOptionMatchesArg /_ ] setReg /tempArg1, tempValue_ shouldMeasureInstruction |<< 1 ] tempOperation |<< add /tempOperation, 2_ tempAction |<< incrementLight /tempAction_ count |<< decrementLight /count_ ] bool |<< equal /currentOperation, 8_ if /bool_ [ N tempAddress tempAddress |<< pair /tempArg1, tempArg2_ loadRoom /tempAddress_ instructionLength |<< 0 ] bool |<< equal /currentOperation, 10_ if /bool_ [ P emptyItemStart emptyItemStart |<< emptyItem P inventoryItemsPointer inventoryItemsPointer |<< findInventoryItem /emptyItemStart_ copyBar /argumentTextStart, inventoryItemsPointer, 12_ shouldMeasureInstruction |<< 1 ] bool |<< equal /currentOperation, 12_ if /bool_ [ P inventoryItemsPointer inventoryItemsPointer |<< findInventoryItem /argumentTextStart_ writeLight /inventoryItemsPointer, screen#3_ shouldMeasureInstruction |<< 1 ] bool |<< equal /currentOperation, 13_ if /bool_ [ instructionLength |<< 2 N tempValue tempValue |<< getReg /tempArg1_ ifNot /tempValue_ [ N hasReachedEndOfBlock hasReachedEndOfBlock |<< 0 whileNot /hasReachedEndOfBlock_ [ N tempData tempData |<< readLight /instructionPointer_ bool |<< equal /tempData, 14_ if /bool_ [ instructionPointer |<< incrementPointer /instructionPointer_ tempData |<< readLight /instructionPointer_ hasReachedEndOfBlock |<< equal /tempData, 15_ ] instructionPointer |<< incrementPointer /instructionPointer_ ] instructionLength |<< 0 ] ] bool |<< equal /currentOperation, 14_ if /bool_ [ instructionLength |<< 2 ] if /shouldMeasureInstruction_ [ P tempPointer tempPointer |<< addPointer /instructionPointer, 2_ instructionLength |<< measureText /tempPointer_ instructionLength |<< add /instructionLength, 3_ ] instructionPointer |<< addPointer /instructionPointer, instructionLength_ ] N lastInputAction P lastInputOptionStart shouldLoop |<< 1 while /shouldLoop_ [ N hasRecognizedCommand hasRecognizedCommand |<< 0 promptTextLine /_ messageStart |<< command1 N bool bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ messageStart |<< message2 displayTextLine /messageStart_ messageStart |<< message3 displayTextLine /messageStart_ messageStart |<< message4 displayTextLine /messageStart_ hasRecognizedCommand |<< 1 ] messageStart |<< command2 bool |<< equalBar /inputBufferStart, messageStart, 4_ if /bool_ [ instructionPointer |<< loadRoomDestination shouldLoop |<< 0 hasRecognizedCommand |<< 1 ] messageStart |<< command3 bool |<< equalBar /inputBufferStart, messageStart, 5_ if /bool_ [ P inventoryItemsPointer inventoryItemsPointer |<< reference /inventoryItems_ N count count |<< 8 while /count_ [ N tempData tempData |<< readLight /inventoryItemsPointer_ bool |<< equal /tempData, screen#3_ ifNot /bool_ [ displayTextLine /inventoryItemsPointer_ ] inventoryItemsPointer |<< addPointer /inventoryItemsPointer, 12_ count |<< decrementLight /count_ ] hasRecognizedCommand |<< 1 ] lastInputAction |<< 0 N tempOffset tempOffset |<< 4 messageStart |<< command4 bool |<< equalBar /inputBufferStart, messageStart, 2_ if /bool_ [ lastInputAction |<< 1 tempOffset |<< 3 ] messageStart |<< command5 bool |<< equalBar /inputBufferStart, messageStart, 3_ if /bool_ [ lastInputAction |<< 2 ] lastInputOptionStart |<< addPointer /inputBufferStart, tempOffset_ messageStart |<< command6 bool |<< equalBar /inputBufferStart, messageStart, 3_ if /bool_ [ P inventoryItemPointer inventoryItemPointer |<< findInventoryItem /lastInputOptionStart_ N bool bool |<< second /inventoryItemPointer_ bool |<< not /bool_ if /bool_ [ lastInputAction |<< 3 ] ] if /lastInputAction_ [ hasRecognizedCommand |<< 1 shouldLoop |<< 0 ] ifNot /hasRecognizedCommand_ [ messageStart |<< message1 displayTextLine /messageStart_ ] ] ] *message1* SEQUENCE "You seem confused. Type HELP." *message2* SEQUENCE "List of commands:" *message3* SEQUENCE "HELP; LOOK; STOCK; GO [path];" *message4* SEQUENCE "GET [item]; USE [item]" *command1* SEQUENCE "HELP" *command2* SEQUENCE "LOOK" *command3* SEQUENCE "STOCK" *command4* SEQUENCE "GO" *command5* SEQUENCE "GET" *command6* SEQUENCE "USE" *fileName* SEQUENCE "WORLD" *emptyItem* SEQUENCE screen#3 @@@ The text adventure world data. BUFFER 90112 METASCOPE world @@@ List of room directives: @@@ 1 (text) = display text. @@@ 2 = prompt input. @@@ 3 (reg) (val) = set boolean register. @@@ 4 (reg) (reg) = copy register. @@@ 5 (reg) = invert register. @@@ 6 (reg) (reg) = and registers. @@@ 7 (reg) (path) = has entered path. @@@ 8 (val) (val) = go to room. @@@ 9 (reg) (item) = has picked up item. @@@ 10 (item) = add item. @@@ 11 (reg) (item) = has used item. @@@ 12 (item) = remove item. @@@ 13 (reg) = conditional block. @@@ 14 15 = end block. @@@ Reg 0: rock is on ground. @@@ Reg 1: rusty bars are blocking. @@@ Reg 2: bacon is on ground. @@@ Reg 3: keys are on hook. @@@ Reg 4: cell is locked. @@@ Reg 5: ladder is on ground. @@@ Reg 6: dogs are alert. @@@ Reg 7: ladder is on wall. @@@ Reg 10 + 11: temporary data. *startCode* SEQUENCE 3 7 0 8 cell1 *cell1* SEQUENCE 1 "You are in a dark, smelly prison cell." 1 "The exit is EAST." 13 1 1 "Rusty bars block the exit." 14 15 13 0 1 "There is a big ROCK in the corner." 14 15 2 9 10 "ROCK" 13 10 1 "You pick up the heavy rock." 3 0 0 10 "ROCK" 14 15 11 10 "ROCK" 13 10 1 "The rock smashes the bars open!" 3 1 0 14 15 7 10 "EAST" 4 11 1 5 11 6 10 11 13 10 8 hall 14 15 8 cell1 *hall* SEQUENCE 1 "You are in a hall with several rooms:" 1 "CELL1, CELL2, CELL3, and CELL4." 13 4 1 "Cell 3 seems to be locked." 14 15 1 "The exit is NORTH." 2 11 10 "KEY" 13 10 1 "The bars swing open." 3 4 0 14 15 7 10 "CELL1" 13 10 8 cell1 14 15 7 10 "CELL2" 13 10 8 cell2 14 15 7 10 "CELL4" 13 10 8 cell4 14 15 7 10 "NORTH" 13 10 8 lobby 14 15 7 10 "CELL3" 4 11 4 5 11 6 10 11 13 10 8 cell3 14 15 8 hall *cell2* SEQUENCE 1 "Nothing seems to be here except for" 1 "writing on the wall:" 1 "'My next project will be spectacular.'" 1 "The exit is EAST." 2 7 10 "EAST" 13 10 8 hall 14 15 8 cell2 *cell3* SEQUENCE 1 "You are in a *very* smelly cell." 13 2 1 "There is some BACON near the window." 14 15 1 "The exit is WEST." 2 9 10 "BACON" 13 10 1 "You now have greasy bacon." 3 2 0 10 "BACON" 14 15 7 10 "WEST" 13 10 8 hall 14 15 8 cell3 *cell4* SEQUENCE 1 "This cell is littered with saw dust." 13 5 1 "There is a long LADDER on the ground." 14 15 1 "The exit is WEST." 2 9 10 "LADDER" 13 10 1 "You hold the ladder under your arm." 3 5 0 10 "LADDER" 14 15 7 10 "WEST" 13 10 8 hall 14 15 8 cell4 *lobby* SEQUENCE 1 "You are in a lobby with a counter." 13 3 1 "There is a KEY on a hook." 14 15 1 "Some dogs are growling NORTH." 1 "The hall is SOUTH." 2 9 10 "KEY" 13 10 1 "You put the key into your pocket." 3 3 0 10 "KEY" 14 15 7 10 "SOUTH" 13 10 8 hall 14 15 7 10 "NORTH" 13 10 8 yard 14 15 8 lobby *yard* SEQUENCE 1 "You are in a yard with high walls." 1 "You see some ferocious dogs." 4 10 6 5 10 13 10 1 "The dogs are distracted by bacon." 14 15 13 7 1 "The ladder on the wall leads NORTH." 14 15 1 "The building entrance is SOUTH." 2 11 10 "BACON" 13 10 1 "You toss the bacon to the dogs." 12 "BACON" 3 6 0 14 15 13 6 8 death 14 15 11 10 "LADDER" 13 10 1 "You put the ladder against the wall." 12 "LADDER" 3 7 1 14 15 7 10 "SOUTH" 13 10 8 lobby 14 15 7 10 "NORTH" 6 10 7 13 10 8 victory 14 15 8 yard *death* SEQUENCE 1 "The dogs ate you." 1 "You are dead." 2 8 death *victory* SEQUENCE 1 "You escaped the prison yard." 1 "You win!" 2 8 victory