Undocumented 8.1 commands: Difference between revisions

From Color 64 BBS Wiki
No edit summary
No edit summary
 
(38 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]]


{| class="wikitable
----
'''General Programming'''
 
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <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:
Color 64 allows simple addition without using < var >=< same var >+< value >
: <code>A=A+12</code>
 
In some cases, this can instead be written as:
So "a=a+12" can alternately just be: "a+12". This only works with numbers (not strings) and other times, this just fails completely. Buyer beware.
: <code>A+12</code>
This appears to work only with numeric variables, not strings, and success has not been completely consistent. Use with caution.
|}
|}


{| class="wikitable
{| class="wikitable"
|-
|-
! Topic  
! Topic
! Found in
! Notes
|-
|-
| <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 52: 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  
 
: <strong>@</strong> loop condition – goes back to bracket when used after “@, consider an “ELSE” statement in this loop (example 2)
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>]</strong> breaks loop condition (Example 3)
 
: A break “<strong>]</strong>” can occur as part of an IF statement to exit prior to “<strong>@</strong>” for loop (example 4)
: <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 used heavily with status values:
* <code>@[SR]</code> means: if <code>SR&lt;&gt;0</code>, jump back to the last <code>[</code> anchor.
* If <code>SR=0</code>, execution falls through and the loop ends naturally.
 
So you will see patterns such as:
# perform read / set <code>SR=ST</code>
# use <code>@[SR]</code> to continue while status says “keep going”
|}
 
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>"THEN" with IF</strong>
| <strong>All Main Overlays</strong><br><br>
 
{| class="wikitable"
|-
! 8.0
! 8.1
|-
| [[File:ifthen_ex1_80.png|center|300px]]
| [[File:ifthen_ex1_81.png|center|300px]]
|}
 
<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"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>if...£</strong>
| <strong>√bbs.msgs</strong><br><br>
 
{| class="wikitable"
|-
! Example
! 8.0
! 8.1
|-
| 1
| [[File:britishpoundif_ex1_80.png|center|300px]]
| [[File:britishpoundif_ex1_81.png|center|300px]]
|}
 
<u>Observation</u>: The 8.1 authors often reversed the comparison order in variable checks while preserving the same end result.
 
<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:
 
[[File:If_not_observation.png|center|300px]]
|}
|}


{| class="wikitable
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>Use of "THEN" in IF </strong>
| style="vertical-align: top;" | <strong>@</strong>
| <strong>all</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 73: Line 153:
|-
|-
| 1
| 1
| [[File:ifthen_ex1_80.png|center|300px]]
| [[File:at_ex1_80.png|center|300px]]
| [[File:ifthen_ex1_81.png|center|300px]]
| [[File:at_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>: 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
! Found in
! Notes
|-
|-
| <strong>.36 </strong>
| style="vertical-align: top;" | <strong>[var$]</strong>
| <strong>√bbs.init</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 93: Line 175:
|-
|-
| 1
| 1
| [[File:dot36_ex1_80.png|center|300px]]
| [[File:var_ex1_80.png|center|300px]]
| [[File:dot36_ex1_81.png|center|300px]]
| [[File:var_ex1_81.png|center|300px]]
|}
 
<u>Conclusion</u>: This can serve as an empty-variable or null-string check.
|}
 
<span id="mlcommands"></span>
----
'''ML Commands'''
 
<span id="dot8"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>.8</strong>
| <strong>All Main Overlays</strong><br><br>
 
''' .8 - Session/Input Poll '''
 
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"
|-
! 7.37
! 8.1
|-
| [[File:737_msgs_9010.png|center|350px]]<br><br>
and routine at 110....<br>
[[File:737_msgs_110.png|center|350px]]
| No use of routine at 110....<br>
[[File:81_msgs_9010.png|center|350px]]
|}
 
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 still required, this appears to be the practical replacement for <code>GOSUB110</code>.
|}
 
<span id="dot9"></span>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>.9</strong>
| <strong>All Main Overlays</strong><br><br>
 
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 '''
----
 
'''Overview'''
 
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.
 
----
 
When a key is pressed:
 
* <code>A$</code> is set to the key pressed
* The character is stored in high-bit PETSCII format
* Example:
** Pressing "X" gives <code>ASC(A$)=216</code>
** Pressing "O" gives <code>ASC(A$)=207</code>
:: (standard ASCII value + 128)
 
When no key is pressed:
 
* <code>A$=""</code>
* The command does not block execution
 
----
 
Examples (<code>bbs.msgs</code>):
 
{| class="wikitable"
|-
! 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)
|}
|}
<u>Conclusion</u>: Undetermined, although notice line in 8.0 version that line 13645 has been dropped for the 8.1 variant. This command only occurs on this line in the overlays as part of the command prompt. When I dropped everything in line 13640 and just had “.36:return”, there was no box printed (of course), but the command entry functioned normally. This was also true if I just omitted everything except “return” – so I’m not sure what “.36” brings to the table.
 
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.
|}
|}


{| class="wikitable <span id=".31 and !55"></span>
<span id="dot31"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <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 116: 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 <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.
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>


<strong>!55 – Message Record Delimiter Flag</strong>
<strong>!55 – Message Record Delimiter Flag</strong><br>
<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</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.


: <code>!55 = 0</code> → No delimiter encountered
: <code>!55 = 0</code> → No delimiter encountered
Line 139: 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>
{| class="wikitable"
|-
! Topic
! Notes
|-
| style="vertical-align: top;" | <strong>.36</strong>
| <strong>√bbs.init</strong><br><br>
{| class="wikitable"
|-
! Example
! 8.0
! 8.1
|-
| 1
| [[File:dot36_ex1_80.png|center|300px]]
| [[File:dot36_ex1_81.png|center|300px]]
|}
''' .36 – Prompt-Cycle Housekeeping (Behavior Unconfirmed) '''
'''Category:''' ML Command<br>
'''Seen in:''' All Main Overlays (prompt printing routine)
----
'''Overview'''
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>).
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.
----
'''Observed Call Pattern'''
* Prompt is printed (PETSCII-dependent)
* <code>.36</code> executes unconditionally
* Control returns into the <code>.9</code> command polling loop
----
'''Testing Notes'''
* With <code>.36</code> present:
** Pressing a command key results in <code>A$</code> being set to high-bit PETSCII
** <code>P</code> functions normally and remains 0 during command-prompt operations
* With <code>.36</code> removed:
** No visible change under normal BBS operation
** <code>.9</code> continued to function normally
----
'''Working Hypothesis'''
<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.
----
'''Summary'''
<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.
|}
|}


{| class="wikitable
<span id="dot38"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <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 159: 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 181: 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 196: 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 208: 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 230: 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 236: 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 246: 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.


It should be understood as a setup command rather than an action command.
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.
|}
|}


{| class="wikitable
<span id="bang46"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>if...£</strong>
| style="vertical-align: top;" | <strong>!46</strong>
| <strong>√bbs.msgs</strong>
| <strong>Scratch Register</strong><br><br>
{| class="wikitable
 
<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"
|-
|-
! Example
! Topic
! 8.0
! Notes
! 8.1
|-
|-
| 1
| style="vertical-align: top;" | <strong>!55</strong>
| [[File:britishpoundif_ex1_80.png|center|300px]]
| <strong>!55 – Message Record Delimiter Flag</strong><br><br>
| [[File:britishpoundif_ex1_81.png|center|300px]]
 
Refer to the <code>.31</code> command above.
|}
|}
<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
<span id="bang56"></span>
(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)”
{| 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.
|}


Another example:
<span id="bang57"></span>
[[File:If_not_observation.png|center|300px]]
{| 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.
|}
|}


{| class="wikitable
<span id="bang58"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>@ </strong>
| style="vertical-align: top;" | <strong>!58</strong>
| <strong>√bbs.msgs</strong>
| <strong>!58 - ?? (Editor)</strong><br><br>
{| class="wikitable
 
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"
|-
|-
! Example
! Topic
! 8.0
! Notes
! 8.1
|-
|-
| 1
| style="vertical-align: top;" | <strong>!59</strong>
| [[File:at_ex1_80.png|center|300px]]
| <strong>!59 - Text-entry mode flag (Editor)</strong><br><br>
| [[File:at_ex1_81.png|center|300px]]
 
|}
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.
<u>Conclusion</u>: Seems to serve as an “if” keyword - but testing this theory in a traditional sense resulted in a syntax error.
|}
|}


{| class="wikitable
<span id="bang60"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>[var$] </strong>
| style="vertical-align: top;" | <strong>!60</strong>
| <strong>√bbs.msgs</strong>
| <strong>!60 - Menu Selection Holder (Editor)</strong><br><br>
{| class="wikitable
 
<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
 
Based on the command list order from line 2931, the implied mapping is:
 
{| class="wikitable"
|-
|-
! Example
! !60 Value
! 8.0
! Command
! 8.1
! Notes
|-
|-
| 1
| 1
| [[File:var_ex1_80.png|center|300px]]
| DIVIDER
| [[File:var_ex1_81.png|center|300px]]
| 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)
|}
|}
<u>Conclusion</u>: Can serve as an empty variable check (null)
 
<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>.
|}
|}


{| class="wikitable
<span id="mlfunctions"></span>
----
'''ML Functions'''
 
<span id="at31"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>.32</strong>
| style="vertical-align: top;" | <strong>@31</strong>
| <strong>√bbs.msgs</strong>
| <strong>@31 – Sequential Read (Enhanced)</strong><br><br>


The <code>.32</code> command appears in v8.1 message handling code immediately before operations that read or process an individual message record.
<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>


Unlike .31 (which performs record scanning) and .38 (which initializes the relink iterator), .32 establishes the active message context for the current record.
<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 functions as a message-record “attach” or “open” operation.
It is used prominently in merge-message routines within <code>BBS.MSGS</code>.


----
----


'''Observed Behavior in BBS.MSGS (v8.1)'''
<strong>Behavior</strong>


In the message display and processing routines, .32 appears:
* 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


* After a message number has been determined 
<strong>Example Usage (v8.1a):</strong>
* Before message text is accessed 
* Before read-status flags are modified 
* Before counters such as remaining private messages are updated 


The command does not itself loop or branch. It prepares the ML side so that subsequent operations operate on the correct message record.
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.


'''Functional Interpretation'''
In comparison:


Based on comparison with v8.0 behavior:
{| class="wikitable"
{| class="wikitable
|-
|-
! 8.0
! 8.0
! 8.1
! 8.1
|-
|-
|  
| <code>2330 I$=@5:IF !40&lt;LEN(TX$) THEN I$=I$+CR$</code>
* BASIC manually calculated offsets
| <code>2330 T=@9:[I$=@31:II=ST:GOSUB2400</code>
* BASIC performed sequential file positioning
* BASIC handled record boundaries
|  
* .31 scans
* .32 selects/attaches the current record
* ML maintains internal pointers to that record
* BASIC then performs logic based on ML flags
|}
|}


Therefore:
<strong>Notes</strong>


.32 most likely performs one or more of the following internally:
* <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


* Positions the file pointer to the current message record
<strong>Conclusion</strong>
* Loads message header metadata into ML buffers
* Prepares message body reading context
* Updates internal state registers used by !55 and related flags


----
<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.
 
|}
'''Relationship to Other Commands'''


<span id="at32"></span>
{| class="wikitable"
{| class="wikitable"
|-
|-
! Command !! Role in Message Processing
! Topic
! Notes
|-
|-
| .31 || Scan for next message record boundary
| style="vertical-align: top;" | <strong>@32</strong>
|-
| <strong>@32(2,2) – Return Block Count</strong><br><br>
| .32 || Attach/open current message record
 
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"
|-
|-
| .38 || Initialize relink iterator
! Version
! Typical Technique
! Result
|-
|-
| .39 || Execute relink scan step
| 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
|-
|-
| .40 || Advance relink iterator
| 8.1
|-
| Read and parse the directory entry directly using <code>@32(2,2)</code>
| .41 || Finalize relink
| File block count as an integer (faster, no manual <code>GET#</code> parsing)
|}
|}


----
|}


'''Important Notes'''
<span id="at33"></span>
 
{| class="wikitable"
* .32 does not itself advance to the next message.
|-
* It operates on the message selected by the iterator or scan routine.
! Topic
* It prepares the environment for message content access.
! Notes
* It is specific to message-handling routines and does not appear to be a general-purpose file command.
|-
 
| style="vertical-align: top;" | <strong>@33</strong>
----
| <strong>@33 - Return CHR$(0) Null</strong><br><br>
 
'''Summary'''


The <code>.32</code> command establishes the active message record context in
<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>.
Color64 v8.1. It represents the shift from BASIC-managed record positioning
(v8.0) to ML-managed record attachment (v8.1).


It should be understood as a message “open/attach” primitive used internally
There is no comparative code from earlier versions of Color 64 currently known.
by BBS.MSGS.
|}
|}

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.