Undocumented 8.1 commands: Difference between revisions

From Color 64 BBS Wiki
No edit summary
No edit summary
 
(18 intermediate revisions by the same user not shown)
Line 1: Line 1:
At the time of this revision for Color 64 v8.1a, there are notably several ML related commands and variables that are not documented as well as some basic shortcuts and appear to have been introduced from the 8.1 upgrade. I find that comparing 8.0 code with 8.1 helps you along in figuring out what these undocumented items perform. Below are some of my notes and observations of what the code was in 8.0 and the observed shortcuts implemented in 8.1 Please note it is a work-in-progress and I don’t have all the answers (yet), so some of this is just “observation” without any conclusion!
At the time of this revision for Color 64 v8.1a, several ML-related commands and variables are notably absent from the original 8.0 manuscript. In addition, some BASIC shortcuts appear to have been introduced or expanded as part of the 8.1 upgrade. Much of the information below comes from reverse-engineering performed by comparing 8.1 code to predecessor versions.


Getting to understand some of the modified BASIC can be easy. If you have the ML loaded into your system, you can write your own program to test out the modified BASIC by having your first line call the ML routine: SYS49923
Below are notes and observations comparing what the code did in 8.0 or 7.37 with the shortcuts and behaviors observed in 8.1.
 
Please note that this section is a work in progress and is updated frequently. Some observations may still be incomplete or under active investigation. Even so, understanding some of the modified BASIC can be relatively straightforward.
 
If the ML is loaded into your system, for example by loading and running <strong>+SHELL</strong>, you can write your own program to test the modified BASIC by calling the ML routine in the first line:


  10 SYS49923
  10 SYS49923
  20 #"Test of program"
  20 #"Test of program"
  30 etc....
  30 ETC....


Below are some of my observations.
Topics:
* General Programming (below)
* [[#mlcommands|ML Commands]]
* [[#mlvariables|ML Variables]]
* [[#mlfunctions|ML Functions]]


----
----
''' General Programming '''
'''General Programming'''


{| class="wikitable
{| class="wikitable"
|-
|-
! Topic
! Topic
Line 18: Line 26:
|-
|-
| <strong>Simple Addition</strong>
| <strong>Simple Addition</strong>
| All overlays
| <strong>All overlays</strong><br><br>
Color 64 allows simple numeric addition without always using the full:
: <code>A=A+12</code>
In some cases, this can instead be written as:
: <code>A+12</code>
This appears to work only with numeric variables, not strings, and success has not been completely consistent. Use with caution.
|}


Color 64 allows simple addition without using < var >=< same var >+< value >
{| class="wikitable"
 
So <code>a=a+12</code> can alternately just be: <code>a+12</code>. This only works with numbers (not strings) and success with this has not been consistent. Use with caution.
|}
{| class="wikitable
|-
|-
! Topic  
! Topic
! Notes  
! Notes
|-
|-
|style="vertical-align: top;" | <strong>Branch Shortcuts </strong>
| style="vertical-align: top;" | <strong>Branch Shortcuts</strong>
| <strong>√bbs.init</strong>
| <strong>All Main Overlays</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 54: Line 65:
|}
|}


<u>Conclusion</u>: [and @are used for loops with [“ being the starting position and @” being the condition that will cause the function to return to the starting point of the loop. Also note in line 8220 how the “RETURN” statement moved from line 8230 up into the 8220 loop in version 8.1 (example 2), indicating that it will execute the return if a$ <> “” and a$ <> home key.  
<u>Conclusion</u>: <code>[</code> and <code>@</code> are used for looping, with <code>[</code> marking the loop anchor and <code>@</code> providing the condition that causes execution to return to that anchor.
: <strong>[</strong> starts loop (the anchor)
 
: <strong>@</strong> loop condition – goes back to the last anchor
Also note, in line 8220, how the <code>RETURN</code> statement moved from line 8230 into the 8220 loop in version 8.1 (Example 2), indicating that it will execute the return if <code>A$&lt;&gt;""</code> and <code>A$</code> is not the HOME key.
: <strong>@[x]</strong> jump back if <code>x</code> is non-zero
 
: <strong>]</strong>is the Color 64 BASIC conditional action delimiter: it separates an IF test from the statement list executed when the test is true.
: <strong>[</strong> starts the loop (the anchor)
: <strong>@</strong> is the loop condition and jumps back to the last anchor
: <strong>@[x]</strong> jumps back if <code>x</code> is non-zero
: <strong>]</strong> is the Color 64 BASIC conditional-action delimiter; it separates an IF test from the statement list executed when the test is true


This is heavily used with status:
This is used heavily with status values:
* @[SR] means: if SR<>0 then jump back to the last [ anchor.
* <code>@[SR]</code> means: if <code>SR&lt;&gt;0</code>, jump back to the last <code>[</code> anchor.
* If SR is 0, it falls through and the loop ends naturally.
* If <code>SR=0</code>, execution falls through and the loop ends naturally.


So you will see in numerous places:
So you will see patterns such as:
# do read / set SR=ST
# perform read / set <code>SR=ST</code>
# @[SR] to continue while status says “keep going”
# use <code>@[SR]</code> to continue while status says “keep going”
|}
|}


{| class="wikitable
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" | <strong>"THEN" with IF </strong>
| style="vertical-align: top;" | <strong>"THEN" with IF</strong>
| <strong>All Main Overlays</strong>
| <strong>All Main Overlays</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! 8.0
! 8.0
Line 84: Line 99:
| [[File:ifthen_ex1_81.png|center|300px]]
| [[File:ifthen_ex1_81.png|center|300px]]
|}
|}
<u>Conclusion</u>: “then” statements are not required for “if/then” – <strong>if <condition> <action></strong> is legal in most cases.
 
<u>Conclusion</u>: <code>THEN</code> is not required in many cases. A form like:
 
: <strong>IF &lt;condition&gt; &lt;action&gt;</strong>
 
is legal in most observed uses.
|}
|}


{| class="wikitable
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>if...£</strong>
| style="vertical-align: top;" | <strong>if...£</strong>
| <strong>√bbs.msgs</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 104: Line 125:
| [[File:britishpoundif_ex1_81.png|center|300px]]
| [[File:britishpoundif_ex1_81.png|center|300px]]
|}
|}
<u>Observation</u>: Observe the 8.1 authors reversed the checks in variable comparisons as the conditions, with end-result being the same.


<u>Conclusion</u>: Serves as an “not” function  
<u>Observation</u>: The 8.1 authors often reversed the comparison order in variable checks while preserving the same end result.
“(lv is not less than cm%(2,2) and lv not less than cm%(29,2) and fr does not equal 1, then print (P)rivate)”  
 
<u>Conclusion</u>: This appears to serve as a <strong>not</strong> function.
 
Example meaning:
: “LV is not less than <code>CM%(2,2)</code>, and LV is not less than <code>CM%(29,2)</code>, and <code>FR</code> does not equal 1, then print (P)rivate.


Another example:
Another example:
[[File:If_not_observation.png|center|300px]]
[[File:If_not_observation.png|center|300px]]
|}
|}


{| class="wikitable
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>@ </strong>
| style="vertical-align: top;" | <strong>@</strong>
| <strong>√bbs.msgs</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 132: Line 156:
| [[File:at_ex1_81.png|center|300px]]
| [[File:at_ex1_81.png|center|300px]]
|}
|}
<u>Conclusion</u>: Seems to serve as an “if” keyword - but testing this theory in a traditional sense resulted in a syntax error.
 
<u>Conclusion</u>: This seems to act somewhat like an <code>IF</code> keyword in certain contexts, although testing this idea in a traditional standalone sense resulted in a syntax error.
|}
|}


{| class="wikitable
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>[var$] </strong>
| style="vertical-align: top;" | <strong>[var$]</strong>
| <strong>√bbs.msgs</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 152: Line 178:
| [[File:var_ex1_81.png|center|300px]]
| [[File:var_ex1_81.png|center|300px]]
|}
|}
<u>Conclusion</u>: Can serve as an empty variable check (null)
 
<u>Conclusion</u>: This can serve as an empty-variable or null-string check.
|}
|}


<span id="mlcommands"></span>
----
----
''' ML Commands '''
'''ML Commands'''


<span id="dot8"></span>
<span id="dot8"></span>
{| class="wikitable  
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>.8</strong>
| style="vertical-align: top;" | <strong>.8</strong>
| <strong>All Main Overlays</strong>
| <strong>All Main Overlays</strong><br><br>


''' .8 - Session/Input Poll) '''
''' .8 - Session/Input Poll '''


Previously documented in 8.0 documentation as "Equivalent of the "%" command…", this appears to be rewritten in version 8.1 - and is particularly noticeable in bbs.msgs where comparing the two show that <code>.8</code> has replaced the <code>gosub110</code> routine (which in 7.37 called <code>sysc(4)</code> or in 8.0, <code>.00</code>.  
Previously documented in 8.0 as the “equivalent of the <code>%</code> command,this appears to have been rewritten in version 8.1. It is especially noticeable in <code>bbs.msgs</code>, where comparison shows that <code>.8</code> has replaced the <code>GOSUB110</code> routine, which in 7.37 called <code>SYSC(4)</code> or, in 8.0, <code>.00</code>.


{| class="wikitable  
{| class="wikitable"
|-
|-
! 7.37
! 7.37
! 8.1
! 8.1
|-
|-
|[[File:737_msgs_9010.png|center|350px]]
| [[File:737_msgs_9010.png|center|350px]]<br><br>
 
and routine at 110....<br>
and routine at 110....
[[File:737_msgs_110.png|center|350px]]
[[File:737_msgs_110.png|center|350px]]
|No use of routine at 110...
| No use of routine at 110....<br>
[[File:81_msgs_9010.png|center|350px]]
[[File:81_msgs_9010.png|center|350px]]
|}
|}


Polls for typed input (non-blocking, local or remote), normalizes transient input-status states, and refreshes session status. Typically used inside scrolling output/file display loops and before slow operations. Side effects include updating P (0 OK, 1 user abort, 255 carrier lost/timeout) and possibly the same underlying status/character registers used by .00.
Polls for typed input in a non-blocking manner, whether local or remote, normalizes transient input-status states, and refreshes session status. It is typically used inside scrolling output or file-display loops and before slow operations.
 
Observed side effects include updating <code>P</code>:
* <code>0</code> = OK
* <code>1</code> = user abort
* <code>255</code> = carrier lost / timeout
 
It may also update the same underlying status and character registers used by <code>.00</code>.


While further testing is required, theoretically this should fully replace use of <code>gosub110</code>
While further testing is still required, this appears to be the practical replacement for <code>GOSUB110</code>.
|}
|}


<span id="dot9"></span>
<span id="dot9"></span>
{| class="wikitable  
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>.9</strong>
| style="vertical-align: top;" | <strong>.9</strong>
| <strong>All Main Overlays</strong>
| <strong>All Main Overlays</strong><br><br>
Previously documented in 8.0 documentation as a "do not use" command that replaces "&" function, this appears to be repurposed for single key command input replacing the traditional "gosub110" routine.
 
Previously documented in 8.0 as a “do not use” command that replaced the <code>&amp;</code> function, this appears to have been repurposed in 8.1 for single-key command input, replacing the traditional <code>GOSUB110</code> routine.


''' .9 – Single-Key Command Input Poll '''
''' .9 – Single-Key Command Input Poll '''
Line 204: Line 239:
'''Overview'''
'''Overview'''


The <code>.9</code> command polls for a single keypress and stores the result into the BASIC string variable <code>A$</code>. It is used at the command prompt to capture one-character command input from either the local keyboard or remote modem connection.
The <code>.9</code> command polls for a single keypress and stores the result in the BASIC string variable <code>A$</code>. It is used at the command prompt to capture one-character command input from either the local keyboard or the remote modem connection.
 
Previous versions of Color 64 used <code>GOSUB110</code> in the same areas.


Previous iterations of Color 64 used <code>gosub110</code> in the same areas.
----
----


When a key is pressed:
When a key is pressed:


* <code>A$</code> is set to the key pressed
* <code>A$</code> is set to the key pressed
* The character is stored in high-bit PETSCII format
* The character is stored in high-bit PETSCII format
* Example:
* Example:
** Pressing "X" <code>ASC(A$)=216</code>
** Pressing "X" gives <code>ASC(A$)=216</code>
** Pressing "O" <code>ASC(A$)=207</code>
** Pressing "O" gives <code>ASC(A$)=207</code>
::(Standard ASCII value + 128)
:: (standard ASCII value + 128)


When no key is pressed:
When no key is pressed:


* <code>A$=""</code> (empty string) 
* <code>A$=""</code>
* The command does not block execution
* The command does not block execution
----
----
Examples (bbs.msgs):
 
{| class="wikitable  
Examples (<code>bbs.msgs</code>):
 
{| class="wikitable"
|-
! Usage
! Example
|-
|-
| Bare Poll
| Bare Poll
|  
|
  110 .9:RETURN
  110 .9:RETURN
  995 .9:IF A$<>NU$ OR P=1 THEN 995:RETURN (loop until a key appears or abort)
  995 .9:IF A$<>NU$ OR P=1 THEN 995:RETURN
:(loop until a key appears or abort)
|-
|-
| Filtered Keys
| Filtered Keys
|
|
  1020 .9,"YN":RETURN (only accept Y/N)
  1020 .9,"YN":RETURN
  3715 .9,"12345"+CR$:IF P ... (menu choices plus Enter)
  3715 .9,"12345"+CR$:IF P ...
:(menu choices plus Enter)
|-
|-
| Space-as-abort convention
| Space-as-abort convention
|
|
  9132 .9:IF A$=" " THEN P=1
  9132 .9:IF A$=" " THEN P=1
:(and several more spots do the same)
:(and several more spots do the same)
|}
|}
So .9 is essentially the modern ML command that replaced the old sysc(4) “get typed character” behavior, with a nice extra: it can be told “only accept these characters”.
 
So <code>.9</code> is essentially the modern ML command that replaced the old <code>SYSC(4)</code> “get typed character” behavior, with an added feature: it can be instructed to accept only a defined set of characters.
|}
|}


<span id="dot31"></span>
<span id="dot31"></span>
{| class="wikitable  
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>.31 and !55</strong>
| style="vertical-align: top;" | <strong>.31 and !55</strong>
| <strong>√bbs.msgs</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 262: Line 308:
| [[File:31and55_ex1_81.png|center|300px]]
| [[File:31and55_ex1_81.png|center|300px]]
|}
|}
<u>Conclusion</u>: .31 – Message-Aware Disk Input (Version 8.1)
<u>Conclusion</u>: .31 – Message-Aware Disk Input (Version 8.1)


Earlier documentation listed the ML command '''.31''' as "not used.Analysis of Version 8.1 confirms this is incorrect. In Color 64 v8.1, the <code>.31</code> command is actively used within message-handling overlays (notably <code>BBS.MSGS</code>) and functions as a specialized form of disk input. It replaces the earlier <strong>.01</strong> disk input command used in Version 8.0 when scanning and reading private messages.
Earlier documentation listed ML command <strong>.31</strong> as “not used.Analysis of version 8.1 confirms this is incorrect. In Color 64 v8.1, the <code>.31</code> command is actively used within message-handling overlays, especially <code>BBS.MSGS</code>, and functions as a specialized disk-input routine. It replaces the earlier <strong>.01</strong> disk-input command used in version 8.0 when scanning and reading private messages.


<strong>Comparison: Version 8.0 vs Version 8.1</strong>
<strong>Comparison: Version 8.0 vs Version 8.1</strong>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! 8.0
! 8.0
! 8.1
! 8.1
|-
|-
| style="vertical-align: top;" | Message scanning used: <code>.01</code>
| style="vertical-align: top;" |
After each read, BASIC code manually checked for a message delimiter: <code>IF @0 = CHR$(14) THEN ...</code>. The byte <code>{0E}</code> ('''CHR$(14)''') acted as the message record separator. When this character was encountered, the system incremented or decremented message counters, control flow moved to the next message record, and the loop continued scanning until completion. The delimiter (end of message) detection was handled explicitly in BASIC.  
Message scanning used: <code>.01</code>.<br><br>
| style="vertical-align: top;" | In Version 8.1, <code>.01</code> is replaced in message routines by: <code>.31</code>.  
After each read, BASIC manually checked for a message delimiter:
: <code>IF @0 = CHR$(14) THEN ...</code>
The byte <code>{0E}</code> (<code>CHR$(14)</code>) acted as the message record separator. When this character was encountered, the system incremented or decremented message counters, control flow moved to the next message record, and the loop continued scanning. Delimiter detection was handled explicitly in BASIC.
| style="vertical-align: top;" |
In version 8.1, <code>.01</code> is replaced in message routines by <code>.31</code>.<br><br>
The <code>.31</code> command performs the disk input operation and internally detects the message delimiter. Instead of BASIC checking <code>@0 = CHR$(14)</code>, version 8.1 uses the ML variable <code>IF !55 THEN ...</code>. When <code>!55</code> becomes non-zero, the system has reached the end of the current message record, message counters are updated, and control moves to the next message or exits the loop. Delimiter detection is now handled inside the ML routine rather than in BASIC.<br><br>


The <code>.31</code> command performs the disk input operation and internally detects the message delimiter. Instead of BASIC checking <code>@0 = CHR$(14)</code>, Version 8.1 uses the ML variable <code>IF !55 THEN ...</code>. When <code>!55</code> becomes non-zero, the system has reached the end of the current message record, message counters are updated, and control moves to the next message or exits the loop. Delimiter detection is now handled inside the ML routine rather than in BASIC.
<strong>!55 – Message Record Delimiter Flag</strong><br>
 
<code>!55</code> is an ML variable introduced in version 8.1 that serves as a <strong>message record boundary flag</strong>. It is set automatically by <code>.31</code> when the message delimiter byte, previously tested as <code>CHR$(14)</code> in version 8.0, is encountered.
<strong>!55 – Message Record Delimiter Flag</strong>
<code>!55</code> is an ML variable introduced in Version 8.1 that serves as a '''message record boundary flag'''. It is set automatically by <code>.31</code> when the message delimiter byte (previously tested as <code>CHR$(14)</code> in Version 8.0) is encountered.


: <code>!55 = 0</code> → No delimiter encountered
: <code>!55 = 0</code> → No delimiter encountered
Line 285: Line 336:


When <code>!55</code> is detected:
When <code>!55</code> is detected:
* The current message scan loop updates counters
* the current message-scan loop updates counters
* The system transitions to the next message record
* the system transitions to the next message record
* Display or processing routines advance accordingly
* display or processing routines advance accordingly
|}
|}
|}
|}


<span id="dot36"></span>
<span id="dot36"></span>
{| class="wikitable
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>.36 </strong>
| style="vertical-align: top;" | <strong>.36</strong>
| <strong>√bbs.init</strong>
| <strong>√bbs.init</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 309: Line 361:
| [[File:dot36_ex1_81.png|center|300px]]
| [[File:dot36_ex1_81.png|center|300px]]
|}
|}
''' .36 – Prompt-Cycle Housekeeping (Behavior Unconfirmed) '''
''' .36 – Prompt-Cycle Housekeeping (Behavior Unconfirmed) '''


'''Category:''' ML Command
'''Category:''' ML Command<br>
'''Seen in:''' All Main Overlays (prompt printing routine)
'''Seen in:''' All Main Overlays (prompt printing routine)


Line 318: Line 371:
'''Overview'''
'''Overview'''


The <code>.36</code> command is called immediately after printing the command prompt
The <code>.36</code> command is called immediately after printing the command prompt and just before entering the main command-input polling loop (<code>.9</code>).
and just before entering the main command input polling loop (<code>.9</code>).


In testing within the live BBS environment, removing <code>.36</code> did not alter
In testing within the live BBS environment, removing <code>.36</code> did not alter normal command-prompt behavior, local keyboard input, or remote input handling. This suggests <code>.36</code> is either redundant in v8.1, reserved for edge cases, or included for compatibility with earlier ML builds.
normal command prompt behavior, local keyboard input, or remote input handling.
This suggests <code>.36</code> is either redundant in v8.1, reserved for edge cases,
or included for compatibility with earlier ML builds.


----
----
Line 330: Line 379:
'''Observed Call Pattern'''
'''Observed Call Pattern'''


* Prompt is printed (PETSCII-dependent)
* Prompt is printed (PETSCII-dependent)
* <code>.36</code> executes unconditionally
* <code>.36</code> executes unconditionally
* Return into the <code>.9</code> command polling loop
* Control returns into the <code>.9</code> command polling loop


----
----
Line 340: Line 389:
* With <code>.36</code> present:
* With <code>.36</code> present:
** Pressing a command key results in <code>A$</code> being set to high-bit PETSCII
** Pressing a command key results in <code>A$</code> being set to high-bit PETSCII
** <code>P</code> variable functions normal (remains 0) at command prompt operations
** <code>P</code> functions normally and remains 0 during command-prompt operations


* With <code>.36</code> removed:
* With <code>.36</code> removed:
** No visible change under normal BBS operation
** No visible change under normal BBS operation
** <code>.9</code> functioned normally.
** <code>.9</code> continued to function normally
 
----
----


'''Working Hypothesis'''
'''Working Hypothesis'''


<code>.36</code> likely performs a defensive reset of internal prompt/input state
<code>.36</code> likely performs a defensive reset of internal prompt or input state, such as clearing a latch, normalizing editor mode, or handling rare typeahead or carrier-transition conditions. No definitive visible effect has been confirmed under standard test conditions.
(e.g., clearing a latch, normalizing editor mode, or handling rare typeahead /
carrier-transition conditions). No definitive functional effect has been
confirmed under standard test conditions.


----
----
Line 358: Line 405:
'''Summary'''
'''Summary'''


<code>.36</code> is executed as part of the prompt cycle in v8.1 but does not appear
<code>.36</code> is executed as part of the prompt cycle in v8.1 but does not appear necessary for normal command entry. Further testing under stress conditions, such as typeahead flooding, carrier transitions, or mode switching, may reveal its purpose.
necessary for normal command entry. Further testing under stress conditions
(typeahead flooding, carrier transitions, mode switching) may reveal its purpose.
|}
|}


<span id="dot38"></span>
<span id="dot38"></span>
{| class="wikitable
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>.38 / .39 / .40 / .41 and “;” variables</strong>
| style="vertical-align: top;" | <strong>.38 / .39 / .40 / .41 and “;” variables</strong>
| <strong>√bbs.msgs</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 378: Line 424:
|-
|-
| 1
| 1
| (current message vs high message):  
| (current message vs high message):<br>
[[File:38_39_40_41_ex1_80.png|center|300px]]
[[File:38_39_40_41_ex1_80.png|center|300px]]
| (current message vs high message):
| (current message vs high message):<br>
[[File:38_39_40_41_ex1_81.png|center|300px]]
[[File:38_39_40_41_ex1_81.png|center|300px]]
|-
|-
| 2
| 2
| (reading message):
| (reading message):<br>
[[File:38_39_40_41_ex2_80.png|center|300px]]
[[File:38_39_40_41_ex2_80.png|center|300px]]
| (reading message):
| (reading message):<br>
[[File:38_39_40_41_ex2_81.png|center|300px]]
[[File:38_39_40_41_ex2_81.png|center|300px]]
|-
|-
| 3
| 3
| (storing message):
| (storing message):<br>
[[File:38_39_40_41_ex3_80.png|center|300px]]
[[File:38_39_40_41_ex3_80.png|center|300px]]
| (storing message):
| (storing message):<br>
[[File:38_39_40_41_ex3_81.png|center|300px]]
[[File:38_39_40_41_ex3_81.png|center|300px]]
|}
|}
Line 400: Line 446:
{| class="wikitable"
{| class="wikitable"
|-
|-
! Command !! Purpose
! Command
! Purpose
|-
|-
| .38 || Initialize / bind relink iterator operands
| .38
| Initialize / bind relink iterator operands
|-
|-
| .39 || Perform iterator scan step
| .39
| Perform iterator scan step
|-
|-
| .40 || Advance iterator (skip / continue)
| .40
| Advance iterator (skip / continue)
|-
|-
| .41 || Finalize relink process
| .41
| Finalize relink process
|}
|}


Line 415: Line 466:
----
----


The <code>.38</code> command was introduced in Color64 v8.1 as part of the internal message relinking system and is the entry point of the entire process. It does not perform file I/O directly and does not read or write messages itself. Instead, it initializes and binds internal machine-language structures used by the message relinking iterator.
The <code>.38</code> command was introduced in Color 64 v8.1 as part of the internal message relinking system and serves as the entry point for that process. It does not perform file I/O directly and does not read or write messages itself. Instead, it initializes and binds internal machine-language structures used by the relinking iterator.


It is designed to be used as the first step in a command sequence:
It is designed to be used as the first step in a command sequence:


: .38 .39 .40 / .41
: <code>.38 → .39 → .40 / .41</code>


This sequence replaces the more BASIC-driven record scanning logic found in v8.0.
This sequence replaces the more BASIC-driven record-scanning logic found in v8.0.


----
----
Line 427: Line 478:
'''What .38 Does'''
'''What .38 Does'''


* Binds specific BASIC variables/arrays to ML-side descriptors
* Binds specific BASIC variables or arrays to ML-side descriptors
* Registers operands for the relink iterator
* Registers operands for the relink iterator
* Initializes scratch registers used by subsequent .39 operations
* Initializes scratch registers used by subsequent <code>.39</code> operations
* Prepares the ML environment for scanning and linking old message records
* Prepares the ML environment for scanning and linking old message records


In BBS.MSGS, this binding typically associates:
In <code>BBS.MSGS</code>, this binding typically associates:


: Slot 0 → MN   (message number)
: Slot 0 → <code>MN</code> (message number)
: Slot 1 → MR% (message read flags array)
: Slot 1 → <code>MR%</code> (message-read flags array)


The ML iterator then uses internal scratch registers such as:
The ML iterator then uses internal scratch registers such as:


: ;0K
: <code>;0K</code>
: ;1K
: <code>;1K</code>
: ;0F
: <code>;0F</code>


These are later examined by BASIC to determine loop control and branching.
These are later examined by BASIC to determine loop control and branching.
Line 449: Line 500:
In v8.0, message scanning and linking logic was performed directly in BASIC, including character comparisons and explicit loop control.
In v8.0, message scanning and linking logic was performed directly in BASIC, including character comparisons and explicit loop control.


In v8.1, this logic was moved into machine language for speed and structural cleanliness. BASIC now acts primarily as a decision layer while ML handles the iteration mechanics.
In v8.1, that logic was moved into machine language for speed and structural cleanliness. BASIC now acts primarily as a decision layer while ML handles the iterator mechanics.


----
----
Line 455: Line 506:
'''Important Notes'''
'''Important Notes'''


* .38 must precede .39 in relink routines
* <code>.38</code> must precede <code>.39</code> in relink routines
* .38 does not itself advance or scan records
* <code>.38</code> does not itself advance or scan records
* It prepares the ML environment used by the iterator
* It prepares the ML environment used by the iterator
* It is not a general-purpose file command
* It is not a general-purpose file command
* It is specific to the message relinking system
* It appears specific to the message relinking system


----
----
Line 465: Line 516:
'''Summary'''
'''Summary'''


The <code>.38</code> command initializes the v8.1 message relink iterator by binding
The <code>.38</code> command initializes the v8.1 message relink iterator by binding BASIC variables to ML-side structures. It marks the transition from the BASIC-driven record-scanning model of v8.0 to the ML-driven iterator model of v8.1.
BASIC variables to ML-side structures. It marks the transition from the
 
BASIC-driven record scanning model of v8.0 to the ML-driven iterator model of
It should be understood primarily as a setup command rather than an action command.
v8.1.
|}
 
<span id="mlvariables"></span>
----
'''ML Variables'''
 
<span id="bang8"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>!8</strong>
| <strong>Wrap/Width Threshold</strong><br><br>
 
<code>!8</code> was originally documented in 8.0 as “reserved for future use,” but it is now used in places where a string is checked against the value of <code>!8</code> to determine how it should be printed.
 
Example:
: <code>IF LEN(A$)&lt;!8 THEN #:£$</code>
 
In the example above, if a line is shorter than <code>!8</code>, the code forces an explicit newline behavior. If it is longer, natural wrapping is allowed to do the work.
|}
 
<span id="bang46"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>!46</strong>
| <strong>Scratch Register</strong><br><br>
 
<code>!46</code> was originally documented in 8.0 as unused. However, the 8.1 version uses it in disk operations across all overlays at the disk routine lines 710-740 as well as the log routine lines 8003-8040.
 
[[File:bang46_line710.png|center|300px]]
 
In those routines, <code>!46</code> holds a temporary value. The lines around 710 use it to preserve a disk channel number, while the lines around 8000 use it as temporary variable storage.
 
It can hold values in the range 0-255. Any other value results in an “illegal quantity” error.
 
[[File:bang46.png|center|300px]]
|}
 
<span id="bang55"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>!55</strong>
| <strong>!55 – Message Record Delimiter Flag</strong><br><br>
 
Refer to the <code>.31</code> command above.
|}
 
<span id="bang56"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>!56</strong>
| <strong>!56 - Message Editor Command State (True/False) (Editor)</strong><br><br>
 
Used in conjunction with <code>!57</code> and <code>!60</code>. When true, this appears to monitor for <code>!57</code> in order to invoke command-state behavior.
 
See <code>!57</code> and <code>!60</code> for more information.
|}
 
<span id="bang57"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>!57</strong>
| <strong>!57 - Prefix Trigger Assignment (Editor)</strong><br><br>
 
This works in concert with <code>!56</code> and <code>!60</code> in the message-editor command logic. In the unmodified 8.1 code, the prefix trigger assignment is <code>47</code>, which corresponds to <code>/</code>. This makes <code>/</code> the command prefix used in the message editor when <code>!56</code> is true. The command value itself is stored in <code>!60</code>.
 
See <code>!56</code> and <code>!60</code> for more information.
|}
 
<span id="bang58"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>!58</strong>
| <strong>!58 - ?? (Editor)</strong><br><br>
 
Present in editor functions, specifically during text entry after pressing RETURN on a line, but its overall function remains unknown. It appears only in <code>bbs.msgs</code> in a subroutine beginning at line 310.
|}
 
<span id="bang59"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>!59</strong>
| <strong>!59 - Text-entry mode flag (Editor)</strong><br><br>
 
Present in editor functions. This appears to be set high by ML routines while in text-entry mode so code that deals with the command menu can be bypassed.
|}
 
<span id="bang60"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>!60</strong>
| <strong>!60 - Menu Selection Holder (Editor)</strong><br><br>
 
<strong>Overview</strong><br><br>
 
In Color 64 v8.1, <strong>!60</strong> acts as a <strong>state variable for the message editor command interface</strong>. It is used to control, and dispatch, the editor’s <strong>slash-command / CMD&gt; menu</strong> behavior, and appears to be treated as a small integer mode or selection value.
 
This logic does not exist in the v8.0 editor flow, indicating it was introduced or substantially expanded in v8.1.
 
<strong>Observed behavior in bbs.msgs (v8.1)</strong><br><br>
 
The editor command-prompt section sets up a list of command keywords, reads user input, and then stores the selected command number into <code>!60</code>. Later code uses <strong>ON !60 GOTO</strong> to jump to the appropriate command handler.
 
Key excerpt (v8.1, around 2930–2939):
 
  2931 !60,.:II$="divider,rap,elete,dit,end,merge":&"...CMD> ..."
  2932 [.9,I$: ... :IF!60THEN&@3(DE$,LG)
  2933 ... ]2935:\!60,II: ...  (stores selection into !60)
  2936 IFII<11 !60,.:!56,-(II=9):!57,47
  2937 I$="":II$="":RETURN
 
Important notes:
* <code>!60,.</code> clears or resets the state (sets it to 0)
* <code>\!60,II</code> stores the selected menu item index (<code>II</code>) into <code>!60</code>
* The prompt offers 6 commands: <code>divider, wrap, delete, edit, end, merge</code>
 
<strong>Dispatcher usage</strong><br><br>
 
Version 8.1 uses <code>!60</code> as the selector in a computed jump:
 
  1302 ON!60 GOTO 1314,1305,1306,1365,1310,1312:!60,1:@
 
This strongly indicates:
* <code>!60</code> holds a value in the range <strong>1–6</strong> representing the selected command
* After a handler runs, code commonly resets <code>!60</code> back to <strong>1</strong> as the default state


It should be understood as a setup command rather than an action command.
Based on the command list order from line 2931, the implied mapping is:


{| class="wikitable"
|-
! !60 Value
! Command
! Notes
|-
| 1
| DIVIDER
| Insert or manage message divider
|-
| 2
| WRAP
| Wordwrap toggle / behavior
|-
| 3
| DELETE
| Delete operation (line / section)
|-
| 4
| EDIT
| Edit operation
|-
| 5
| END
| End editor / finish
|-
| 6
| MERGE
| Merge behavior (message / text merge)
|}
|}


<strong>Slash-command prefix interaction ("/")</strong><br><br>
<nowiki>!60</nowiki> is also used as a boolean-style flag to enable slash-style command entry behavior. One observed usage is:
  311 II=GO(!60,47,.)
Where:
* <code>47</code> is ASCII <code>/</code>
* This suggests that when <code>!60</code> is active (non-zero), <code>/</code> is used as the command-prefix character by the editor logic
This supports the interpretation that <code>!60</code> is not merely a one-shot selection value, but the <strong>editor command-mode state</strong> that can be:
* cleared (0) while collecting or editing input, or performing screen cleanup
* set (1..6) when a command has been selected and needs to be dispatched
<strong>Additional references in the editor flow</strong><br><br>
Line 1300 shows <code>!60</code> being initialized prior to the editor loop and used with other state variables:
  1300 !7,FM:A=I:!60,1:[GOSUB311:IFP]...
Lines 2885 / 2888 show the same “set <code>!60</code>, dispatch, then reset” pattern:
  2885 ... :!60,1:[GOSUB311:IFP]...
  2888 ON!60 GOTO 2890,1305,2889,2895:!60,1:@
<strong>Working conclusion</strong><br><br>
In Color 64 v8.1, <code>!60</code> is a <strong>message-editor command state / selector variable</strong>:
* It enables slash-command style operation (<code>/</code> prefix) when active
* It holds the selected editor-command index (1..6)
* It is used in ON-GOTO dispatch tables to jump to the correct handler
* It is frequently reset back to 1 after a handler executes
<strong>Open questions</strong><br><br>
* Whether <code>!60</code> is also modified by the <code>.9</code> input routine, or by other ML routines, to signal screen-edit cleanup, such as controlling the delete-echo behavior at line 2932
* Whether <code>!60</code> has additional meanings beyond editor-related command selection
This is also used in conjunction with <code>!56</code> and <code>!57</code>.
|}
<span id="mlfunctions"></span>
----
----
''' ML Variables '''
'''ML Functions'''


<span id="bang8"></span>
<span id="at31"></span>
{| class="wikitable  
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>@31</strong>
| <strong>@31 – Sequential Read (Enhanced)</strong><br><br>
 
<strong>Overview</strong><br>
<code>@31</code> is a machine-language function introduced in later Color 64 versions that replaces the older <code>@5 + !40</code> sequential line-read pattern used in version 8.0. It retrieves the next logical record from an open sequential file and updates <code>ST</code> as a side effect.<br><br>
 
<strong>Higher-Level Replacement for @5</strong>
* Encapsulates record retrieval and length handling internally
* Reduces BASIC-level string churn
* Improves performance and garbage-collection stability
 
It is used prominently in merge-message routines within <code>BBS.MSGS</code>.
 
----
 
<strong>Behavior</strong>
 
* Returns a string, typically assigned to <code>I$</code>
* Updates <code>ST</code> (disk / file status)
* Designed for use inside <code>ST</code>-controlled loops
* Commonly paired with <code>@9</code> (enhanced <code>FRE</code>) for memory safety
 
<strong>Example Usage (v8.1a):</strong>
 
2330 T=@9:[I$=@31:II=ST:GOSUB2400
2335 T=T-LEN(I$):A$(A)=I$:A+:@[II] AND A<ML+4 AND T>=CM%(7,.):GOTO505
 
<strong>Functional Characteristics</strong>
 
1) Sequential File Read
* Retrieves the next record or line from the currently open sequential file
* Replaces the older <code>@5 + !40</code> logic
* <code>ST</code> must be checked after each call
 
2) Status-Driven Looping
 
: Typical pattern:
:: <code>I$=@31</code>
:: <code>II=ST</code>
:: <code>@[II]</code>
:: Loop continues while <code>ST</code> indicates a valid read
 
This is frequently paired with the enhanced <code>FRE</code> function <code>@9</code> and the maximum-message-lines value <code>CM%(7,.)</code>, as seen in the merge-message function of <code>bbs.msgs</code> starting at line 2330.
 
In comparison:
 
{| class="wikitable"
|-
! 8.0
! 8.1
|-
| <code>2330 I$=@5:IF !40&lt;LEN(TX$) THEN I$=I$+CR$</code>
| <code>2330 T=@9:[I$=@31:II=ST:GOSUB2400</code>
|}
 
<strong>Notes</strong>
 
* <code>@31</code> is not a pure function
** It requires an open file context
** It updates <code>ST</code>
** It should be used within the normal BBS runtime environment
 
<strong>Conclusion</strong>
 
<code>@31</code> is an enhanced sequential-record read function used primarily in message handling and merge routines. It streamlines record retrieval, updates <code>ST</code> for loop control, and is typically combined with <code>@9</code>-based memory-budget safeguards.
|}
 
<span id="at32"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Notes
! Notes
|-
|-
| style="vertical-align: top;" |<strong>!8 </strong>
| style="vertical-align: top;" | <strong>@32</strong>
| <strong>Wrap/Width Threshold</strong>
| <strong>@32(2,2) – Return Block Count</strong><br><br>
 
The <code>@32</code> ML function is used with an open directory listing, specifically the <code>"$"</code> directory stream, to read and parse a directory entry. It returns a numeric value and advances the internal “current directory entry” pointer so that subsequent calls read the next entry.
 
In Color 64 v8.1, <code>@32</code> is commonly used as a fast replacement for the older BASIC parsing method in which a program would <code>GET#</code> fields from a <code>"$"</code> listing and use <code>@6(low$,high$)</code> to build a 16-bit value. In practice, <code>@32</code> is used to obtain the directory entry’s block count, or file size in blocks, as an integer.
 
<strong>Syntax:</strong> <code>A=@32(2,2)</code><br>
<strong>Return Value:</strong> Returns the current or next directory entry’s <strong>block count</strong> as an integer.
 
<strong>Status / End-of-List Behavior:</strong><br>
<code>@32</code> works as an iterator over directory entries. When there are no more matching entries, or the end of the directory stream is reached, BASIC’s <strong>ST</strong> is set. Code typically tests <code>ST</code> immediately after calling <code>@32</code>.
 
Typical pattern:
 
  A=@32(2,2)
  IF ST THEN ...  :rem end of directory (or no match)
 
<strong>Common Usage Patterns</strong>
 
1) Check if a file exists, or get its size
* Open a filtered directory listing and attempt to read the first match
* If <code>ST</code> is set after the call, the file was not found
 
  OPEN 8,DV,8,"$"+DR$+F$+"*"
  GOSUB 770          :rem read/skip directory header (implementation-specific)
  A=@32(2,2)
  IF ST THEN ER=62:A$="NOT IN DIRECTORY: "+F$:GOTO <error handler>
 
2) Display a directory-style listing (blocks + filename)
* Call <code>@32</code> repeatedly until <code>ST</code> is set
* The returned value is typically printed as the blocks column
* The filename is commonly retrieved via <code>@5</code> after each call, since <code>@32</code> updates the current-entry context
 
  B=-3
  B=B+1
  C=@32(2,2)
  IF ST THEN PRINT B;" FILES SELECTED":RETURN
  PRINT C;TAB(6);@5
 
3) Maintenance checks based on file size (example: caller-log trimming)
* Compare <code>@32</code>’s returned block count against a configured maximum
* Also used in free-space safety checks to avoid dropping below <code>MU</code>, the minimum number of blocks required for uploads
 
  F$="✓CALLER LOG":GOSUB 710
  P=A-CM%(8,.)
  P=-P*(P>.)
  :rem P is positive only when the file exceeds the configured limit
 
<strong>Notes</strong>
 
* <code>@32(2,2)</code> is always used in conjunction with an open <code>"$"</code> directory stream
* The parameters <code>(2,2)</code> are used in v8.1 code for directory-entry parsing; other parameter combinations, if any, are currently undocumented
* <code>@32</code> is generally paired with other ML functions that return fields for the current directory entry, commonly <code>@5</code> for the filename. <code>@32</code> updates that current-entry context each time it is called
 
<strong>8.0 Comparison</strong>
 
{| class="wikitable"
|-
! Version
! Typical Technique
! Result
|-
| 8.0
| Parse the <code>"$"</code> listing using <code>GET#</code> and build a 16-bit value using <code>@6(low$,high$)</code>
| File block count as an integer
|-
| 8.1
| Read and parse the directory entry directly using <code>@32(2,2)</code>
| File block count as an integer (faster, no manual <code>GET#</code> parsing)
|}


The <code>!8</code> was originally documented in 8.0 "reserved for future use" but is now utilized in some sections where it is used to check if a string is less then the value of !8 and decides how to print the string based on that check.
|}


Example: <code>if len(a$)<!8 then #:£$</code>
<span id="at33"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>@33</strong>
| <strong>@33 - Return CHR$(0) Null</strong><br><br>


In the example above, if a line is shorter than !8, they force an explicit newline behavior; if it’s longer, they let natural wrapping do the work.
<code>@33</code> is used exclusively in the editor portion of message composition and appears to be involved when the user is utilizing the <code>/</code> command within the editor, where <code>@33</code> is part of removing the prompt from the editing screen. It returns a string of length 1 containing <code>CHR$(0)</code>.


There is no comparative code from earlier versions of Color 64 currently known.
|}
|}

Latest revision as of 21:05, 7 March 2026

At the time of this revision for Color 64 v8.1a, several ML-related commands and variables are notably absent from the original 8.0 manuscript. In addition, some BASIC shortcuts appear to have been introduced or expanded as part of the 8.1 upgrade. Much of the information below comes from reverse-engineering performed by comparing 8.1 code to predecessor versions.

Below are notes and observations comparing what the code did in 8.0 or 7.37 with the shortcuts and behaviors observed in 8.1.

Please note that this section is a work in progress and is updated frequently. Some observations may still be incomplete or under active investigation. Even so, understanding some of the modified BASIC can be relatively straightforward.

If the ML is loaded into your system, for example by loading and running +SHELL, you can write your own program to test the modified BASIC by calling the ML routine in the first line:

10 SYS49923
20 #"Test of program"
30 ETC....

Topics:


General Programming

Topic Notes
Simple Addition All overlays

Color 64 allows simple numeric addition without always using the full:

A=A+12

In some cases, this can instead be written as:

A+12

This appears to work only with numeric variables, not strings, and success has not been completely consistent. Use with caution.

Topic Notes
Branch Shortcuts All Main Overlays

Example 8.0 8.1
1
2
3
4

Conclusion: [ and @ are used for looping, with [ marking the loop anchor and @ providing the condition that causes execution to return to that anchor.

Also note, in line 8220, how the RETURN statement moved from line 8230 into the 8220 loop in version 8.1 (Example 2), indicating that it will execute the return if A$<>"" and A$ is not the HOME key.

[ starts the loop (the anchor)
@ is the loop condition and jumps back to the last anchor
@[x] jumps back if x is non-zero
] is the Color 64 BASIC conditional-action delimiter; it separates an IF test from the statement list executed when the test is true

This is used heavily with status values:

  • @[SR] means: if SR<>0, jump back to the last [ anchor.
  • If SR=0, execution falls through and the loop ends naturally.

So you will see patterns such as:

  1. perform read / set SR=ST
  2. use @[SR] to continue while status says “keep going”
Topic Notes
"THEN" with IF All Main Overlays

8.0 8.1

Conclusion: THEN is not required in many cases. A form like:

IF <condition> <action>

is legal in most observed uses.

Topic Notes
if...£ √bbs.msgs

Example 8.0 8.1
1

Observation: The 8.1 authors often reversed the comparison order in variable checks while preserving the same end result.

Conclusion: This appears to serve as a not function.

Example meaning:

“LV is not less than CM%(2,2), and LV is not less than CM%(29,2), and FR does not equal 1, then print (P)rivate.”

Another example:

Topic Notes
@ √bbs.msgs

Example 8.0 8.1
1

Conclusion: This seems to act somewhat like an IF keyword in certain contexts, although testing this idea in a traditional standalone sense resulted in a syntax error.

Topic Notes
[var$] √bbs.msgs

Example 8.0 8.1
1

Conclusion: This can serve as an empty-variable or null-string check.


ML Commands

Topic Notes
.8 All Main Overlays

.8 - Session/Input Poll

Previously documented in 8.0 as the “equivalent of the % command,” this appears to have been rewritten in version 8.1. It is especially noticeable in bbs.msgs, where comparison shows that .8 has replaced the GOSUB110 routine, which in 7.37 called SYSC(4) or, in 8.0, .00.

7.37 8.1


and routine at 110....

No use of routine at 110....

Polls for typed input in a non-blocking manner, whether local or remote, normalizes transient input-status states, and refreshes session status. It is typically used inside scrolling output or file-display loops and before slow operations.

Observed side effects include updating P:

  • 0 = OK
  • 1 = user abort
  • 255 = carrier lost / timeout

It may also update the same underlying status and character registers used by .00.

While further testing is still required, this appears to be the practical replacement for GOSUB110.

Topic Notes
.9 All Main Overlays

Previously documented in 8.0 as a “do not use” command that replaced the & function, this appears to have been repurposed in 8.1 for single-key command input, replacing the traditional GOSUB110 routine.

.9 – Single-Key Command Input Poll


Overview

The .9 command polls for a single keypress and stores the result in the BASIC string variable A$. It is used at the command prompt to capture one-character command input from either the local keyboard or the remote modem connection.

Previous versions of Color 64 used GOSUB110 in the same areas.


When a key is pressed:

  • A$ is set to the key pressed
  • The character is stored in high-bit PETSCII format
  • Example:
    • Pressing "X" gives ASC(A$)=216
    • Pressing "O" gives ASC(A$)=207
(standard ASCII value + 128)

When no key is pressed:

  • A$=""
  • The command does not block execution

Examples (bbs.msgs):

Usage Example
Bare Poll
110 .9:RETURN
995 .9:IF A$<>NU$ OR P=1 THEN 995:RETURN
(loop until a key appears or abort)
Filtered Keys
1020 .9,"YN":RETURN
3715 .9,"12345"+CR$:IF P ...
(menu choices plus Enter)
Space-as-abort convention
9132 .9:IF A$=" " THEN P=1
(and several more spots do the same)

So .9 is essentially the modern ML command that replaced the old SYSC(4) “get typed character” behavior, with an added feature: it can be instructed to accept only a defined set of characters.

Topic Notes
.31 and !55 √bbs.msgs

Example 8.0 8.1
1

Conclusion: .31 – Message-Aware Disk Input (Version 8.1)

Earlier documentation listed ML command .31 as “not used.” Analysis of version 8.1 confirms this is incorrect. In Color 64 v8.1, the .31 command is actively used within message-handling overlays, especially BBS.MSGS, and functions as a specialized disk-input routine. It replaces the earlier .01 disk-input command used in version 8.0 when scanning and reading private messages.

Comparison: Version 8.0 vs Version 8.1

8.0 8.1

Message scanning used: .01.

After each read, BASIC manually checked for a message delimiter:

IF @0 = CHR$(14) THEN ...

The byte {0E} (CHR$(14)) acted as the message record separator. When this character was encountered, the system incremented or decremented message counters, control flow moved to the next message record, and the loop continued scanning. Delimiter detection was handled explicitly in BASIC.

In version 8.1, .01 is replaced in message routines by .31.

The .31 command performs the disk input operation and internally detects the message delimiter. Instead of BASIC checking @0 = CHR$(14), version 8.1 uses the ML variable IF !55 THEN .... When !55 becomes non-zero, the system has reached the end of the current message record, message counters are updated, and control moves to the next message or exits the loop. Delimiter detection is now handled inside the ML routine rather than in BASIC.

!55 – Message Record Delimiter Flag
!55 is an ML variable introduced in version 8.1 that serves as a message record boundary flag. It is set automatically by .31 when the message delimiter byte, previously tested as CHR$(14) in version 8.0, is encountered.

!55 = 0 → No delimiter encountered
!55 ≠ 0 → End of message record reached

When !55 is detected:

  • the current message-scan loop updates counters
  • the system transitions to the next message record
  • display or processing routines advance accordingly

Topic Notes
.36 √bbs.init

Example 8.0 8.1
1

.36 – Prompt-Cycle Housekeeping (Behavior Unconfirmed)

Category: ML Command
Seen in: All Main Overlays (prompt printing routine)


Overview

The .36 command is called immediately after printing the command prompt and just before entering the main command-input polling loop (.9).

In testing within the live BBS environment, removing .36 did not alter normal command-prompt behavior, local keyboard input, or remote input handling. This suggests .36 is either redundant in v8.1, reserved for edge cases, or included for compatibility with earlier ML builds.


Observed Call Pattern

  • Prompt is printed (PETSCII-dependent)
  • .36 executes unconditionally
  • Control returns into the .9 command polling loop

Testing Notes

  • With .36 present:
    • Pressing a command key results in A$ being set to high-bit PETSCII
    • P functions normally and remains 0 during command-prompt operations
  • With .36 removed:
    • No visible change under normal BBS operation
    • .9 continued to function normally

Working Hypothesis

.36 likely performs a defensive reset of internal prompt or input state, such as clearing a latch, normalizing editor mode, or handling rare typeahead or carrier-transition conditions. No definitive visible effect has been confirmed under standard test conditions.


Summary

.36 is executed as part of the prompt cycle in v8.1 but does not appear necessary for normal command entry. Further testing under stress conditions, such as typeahead flooding, carrier transitions, or mode switching, may reveal its purpose.

Topic Notes
.38 / .39 / .40 / .41 and “;” variables √bbs.msgs

Example 8.0 8.1
1 (current message vs high message):
(current message vs high message):
2 (reading message):
(reading message):
3 (storing message):
(storing message):

Message Relink Commands in v8.1

Command Purpose
.38 Initialize / bind relink iterator operands
.39 Perform iterator scan step
.40 Advance iterator (skip / continue)
.41 Finalize relink process

.38 – Relink Iterator Initialization (v8.1)


The .38 command was introduced in Color 64 v8.1 as part of the internal message relinking system and serves as the entry point for that process. It does not perform file I/O directly and does not read or write messages itself. Instead, it initializes and binds internal machine-language structures used by the relinking iterator.

It is designed to be used as the first step in a command sequence:

.38 → .39 → .40 / .41

This sequence replaces the more BASIC-driven record-scanning logic found in v8.0.


What .38 Does

  • Binds specific BASIC variables or arrays to ML-side descriptors
  • Registers operands for the relink iterator
  • Initializes scratch registers used by subsequent .39 operations
  • Prepares the ML environment for scanning and linking old message records

In BBS.MSGS, this binding typically associates:

Slot 0 → MN (message number)
Slot 1 → MR% (message-read flags array)

The ML iterator then uses internal scratch registers such as:

;0K
;1K
;0F

These are later examined by BASIC to determine loop control and branching.


In v8.0, message scanning and linking logic was performed directly in BASIC, including character comparisons and explicit loop control.

In v8.1, that logic was moved into machine language for speed and structural cleanliness. BASIC now acts primarily as a decision layer while ML handles the iterator mechanics.


Important Notes

  • .38 must precede .39 in relink routines
  • .38 does not itself advance or scan records
  • It prepares the ML environment used by the iterator
  • It is not a general-purpose file command
  • It appears specific to the message relinking system

Summary

The .38 command initializes the v8.1 message relink iterator by binding BASIC variables to ML-side structures. It marks the transition from the BASIC-driven record-scanning model of v8.0 to the ML-driven iterator model of v8.1.

It should be understood primarily as a setup command rather than an action command.


ML Variables

Topic Notes
!8 Wrap/Width Threshold

!8 was originally documented in 8.0 as “reserved for future use,” but it is now used in places where a string is checked against the value of !8 to determine how it should be printed.

Example:

IF LEN(A$)<!8 THEN #:£$

In the example above, if a line is shorter than !8, the code forces an explicit newline behavior. If it is longer, natural wrapping is allowed to do the work.

Topic Notes
!46 Scratch Register

!46 was originally documented in 8.0 as unused. However, the 8.1 version uses it in disk operations across all overlays at the disk routine lines 710-740 as well as the log routine lines 8003-8040.

In those routines, !46 holds a temporary value. The lines around 710 use it to preserve a disk channel number, while the lines around 8000 use it as temporary variable storage.

It can hold values in the range 0-255. Any other value results in an “illegal quantity” error.

Topic Notes
!55 !55 – Message Record Delimiter Flag

Refer to the .31 command above.

Topic Notes
!56 !56 - Message Editor Command State (True/False) (Editor)

Used in conjunction with !57 and !60. When true, this appears to monitor for !57 in order to invoke command-state behavior.

See !57 and !60 for more information.

Topic Notes
!57 !57 - Prefix Trigger Assignment (Editor)

This works in concert with !56 and !60 in the message-editor command logic. In the unmodified 8.1 code, the prefix trigger assignment is 47, which corresponds to /. This makes / the command prefix used in the message editor when !56 is true. The command value itself is stored in !60.

See !56 and !60 for more information.

Topic Notes
!58 !58 - ?? (Editor)

Present in editor functions, specifically during text entry after pressing RETURN on a line, but its overall function remains unknown. It appears only in bbs.msgs in a subroutine beginning at line 310.

Topic Notes
!59 !59 - Text-entry mode flag (Editor)

Present in editor functions. This appears to be set high by ML routines while in text-entry mode so code that deals with the command menu can be bypassed.

Topic Notes
!60 !60 - Menu Selection Holder (Editor)

Overview

In Color 64 v8.1, !60 acts as a state variable for the message editor command interface. It is used to control, and dispatch, the editor’s slash-command / CMD> menu behavior, and appears to be treated as a small integer mode or selection value.

This logic does not exist in the v8.0 editor flow, indicating it was introduced or substantially expanded in v8.1.

Observed behavior in bbs.msgs (v8.1)

The editor command-prompt section sets up a list of command keywords, reads user input, and then stores the selected command number into !60. Later code uses ON !60 GOTO to jump to the appropriate command handler.

Key excerpt (v8.1, around 2930–2939):

 2931 !60,.:II$="divider,rap,elete,dit,end,merge":&"...CMD> ..."
 2932 [.9,I$: ... :IF!60THEN&@3(DE$,LG)
 2933 ... ]2935:\!60,II: ...  (stores selection into !60)
 2936 IFII<11 !60,.:!56,-(II=9):!57,47
 2937 I$="":II$="":RETURN

Important notes:

  • !60,. clears or resets the state (sets it to 0)
  • \!60,II stores the selected menu item index (II) into !60
  • The prompt offers 6 commands: divider, wrap, delete, edit, end, merge

Dispatcher usage

Version 8.1 uses !60 as the selector in a computed jump:

 1302 ON!60 GOTO 1314,1305,1306,1365,1310,1312:!60,1:@

This strongly indicates:

  • !60 holds a value in the range 1–6 representing the selected command
  • After a handler runs, code commonly resets !60 back to 1 as the default state

Based on the command list order from line 2931, the implied mapping is:

!60 Value Command Notes
1 DIVIDER Insert or manage message divider
2 WRAP Wordwrap toggle / behavior
3 DELETE Delete operation (line / section)
4 EDIT Edit operation
5 END End editor / finish
6 MERGE Merge behavior (message / text merge)

Slash-command prefix interaction ("/")

!60 is also used as a boolean-style flag to enable slash-style command entry behavior. One observed usage is:

 311 II=GO(!60,47,.)

Where:

  • 47 is ASCII /
  • This suggests that when !60 is active (non-zero), / is used as the command-prefix character by the editor logic

This supports the interpretation that !60 is not merely a one-shot selection value, but the editor command-mode state that can be:

  • cleared (0) while collecting or editing input, or performing screen cleanup
  • set (1..6) when a command has been selected and needs to be dispatched

Additional references in the editor flow

Line 1300 shows !60 being initialized prior to the editor loop and used with other state variables:

 1300 !7,FM:A=I:!60,1:[GOSUB311:IFP]...

Lines 2885 / 2888 show the same “set !60, dispatch, then reset” pattern:

 2885 ... :!60,1:[GOSUB311:IFP]...
 2888 ON!60 GOTO 2890,1305,2889,2895:!60,1:@

Working conclusion

In Color 64 v8.1, !60 is a message-editor command state / selector variable:

  • It enables slash-command style operation (/ prefix) when active
  • It holds the selected editor-command index (1..6)
  • It is used in ON-GOTO dispatch tables to jump to the correct handler
  • It is frequently reset back to 1 after a handler executes

Open questions

  • Whether !60 is also modified by the .9 input routine, or by other ML routines, to signal screen-edit cleanup, such as controlling the delete-echo behavior at line 2932
  • Whether !60 has additional meanings beyond editor-related command selection

This is also used in conjunction with !56 and !57.


ML Functions

Topic Notes
@31 @31 – Sequential Read (Enhanced)

Overview
@31 is a machine-language function introduced in later Color 64 versions that replaces the older @5 + !40 sequential line-read pattern used in version 8.0. It retrieves the next logical record from an open sequential file and updates ST as a side effect.

Higher-Level Replacement for @5

  • Encapsulates record retrieval and length handling internally
  • Reduces BASIC-level string churn
  • Improves performance and garbage-collection stability

It is used prominently in merge-message routines within BBS.MSGS.


Behavior

  • Returns a string, typically assigned to I$
  • Updates ST (disk / file status)
  • Designed for use inside ST-controlled loops
  • Commonly paired with @9 (enhanced FRE) for memory safety

Example Usage (v8.1a):

2330 T=@9:[I$=@31:II=ST:GOSUB2400
2335 T=T-LEN(I$):A$(A)=I$:A+:@[II] AND A<ML+4 AND T>=CM%(7,.):GOTO505

Functional Characteristics

1) Sequential File Read

  • Retrieves the next record or line from the currently open sequential file
  • Replaces the older @5 + !40 logic
  • ST must be checked after each call

2) Status-Driven Looping

Typical pattern:
I$=@31
II=ST
@[II]
Loop continues while ST indicates a valid read

This is frequently paired with the enhanced FRE function @9 and the maximum-message-lines value CM%(7,.), as seen in the merge-message function of bbs.msgs starting at line 2330.

In comparison:

8.0 8.1
2330 I$=@5:IF !40<LEN(TX$) THEN I$=I$+CR$ 2330 T=@9:[I$=@31:II=ST:GOSUB2400

Notes

  • @31 is not a pure function
    • It requires an open file context
    • It updates ST
    • It should be used within the normal BBS runtime environment

Conclusion

@31 is an enhanced sequential-record read function used primarily in message handling and merge routines. It streamlines record retrieval, updates ST for loop control, and is typically combined with @9-based memory-budget safeguards.

Topic Notes
@32 @32(2,2) – Return Block Count

The @32 ML function is used with an open directory listing, specifically the "$" directory stream, to read and parse a directory entry. It returns a numeric value and advances the internal “current directory entry” pointer so that subsequent calls read the next entry.

In Color 64 v8.1, @32 is commonly used as a fast replacement for the older BASIC parsing method in which a program would GET# fields from a "$" listing and use @6(low$,high$) to build a 16-bit value. In practice, @32 is used to obtain the directory entry’s block count, or file size in blocks, as an integer.

Syntax: A=@32(2,2)
Return Value: Returns the current or next directory entry’s block count as an integer.

Status / End-of-List Behavior:
@32 works as an iterator over directory entries. When there are no more matching entries, or the end of the directory stream is reached, BASIC’s ST is set. Code typically tests ST immediately after calling @32.

Typical pattern:

 A=@32(2,2)
 IF ST THEN ...   :rem end of directory (or no match)

Common Usage Patterns

1) Check if a file exists, or get its size

  • Open a filtered directory listing and attempt to read the first match
  • If ST is set after the call, the file was not found
 OPEN 8,DV,8,"$"+DR$+F$+"*"
 GOSUB 770          :rem read/skip directory header (implementation-specific)
 A=@32(2,2)
 IF ST THEN ER=62:A$="NOT IN DIRECTORY: "+F$:GOTO <error handler>

2) Display a directory-style listing (blocks + filename)

  • Call @32 repeatedly until ST is set
  • The returned value is typically printed as the blocks column
  • The filename is commonly retrieved via @5 after each call, since @32 updates the current-entry context
 B=-3
 B=B+1
 C=@32(2,2)
 IF ST THEN PRINT B;" FILES SELECTED":RETURN
 PRINT C;TAB(6);@5

3) Maintenance checks based on file size (example: caller-log trimming)

  • Compare @32’s returned block count against a configured maximum
  • Also used in free-space safety checks to avoid dropping below MU, the minimum number of blocks required for uploads
 F$="✓CALLER LOG":GOSUB 710
 P=A-CM%(8,.)
 P=-P*(P>.)
 :rem P is positive only when the file exceeds the configured limit

Notes

  • @32(2,2) is always used in conjunction with an open "$" directory stream
  • The parameters (2,2) are used in v8.1 code for directory-entry parsing; other parameter combinations, if any, are currently undocumented
  • @32 is generally paired with other ML functions that return fields for the current directory entry, commonly @5 for the filename. @32 updates that current-entry context each time it is called

8.0 Comparison

Version Typical Technique Result
8.0 Parse the "$" listing using GET# and build a 16-bit value using @6(low$,high$) File block count as an integer
8.1 Read and parse the directory entry directly using @32(2,2) File block count as an integer (faster, no manual GET# parsing)

Topic Notes
@33 @33 - Return CHR$(0) Null

@33 is used exclusively in the editor portion of message composition and appears to be involved when the user is utilizing the / command within the editor, where @33 is part of removing the prompt from the editing screen. It returns a string of length 1 containing CHR$(0).

There is no comparative code from earlier versions of Color 64 currently known.