Undocumented 8.1 commands: Difference between revisions

From Color 64 BBS Wiki
No edit summary
No edit summary
 
(54 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 that never received any manual documentation. 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 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.


10 SYS49923
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.
20 #"Test of program"
30 etc....


{| class="wikitable
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
20 #"Test of program"
30 ETC....
 
Topics:
* General Programming (below)
* [[#mlcommands|ML Commands]]
* [[#mlvariables|ML Variables]]
* [[#mlfunctions|ML Functions]]
 
----
'''General Programming'''
 
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| Simple Addition
| <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).
: <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 50: 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
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>Use of "THEN" in IF </strong>
| style="vertical-align: top;" | <strong>"THEN" with IF</strong>
| <strong>all</strong>
| <strong>All Main Overlays</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! 8.0
! 8.0
! 8.1
! 8.1
|-
|-
| 1
| [[File:ifthen_ex1_80.png|center|300px]]
| [[File:ifthen_ex1_80.png|center|300px]]
| [[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  
 
<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
! Found in
! Notes
|-
|-
| <strong>.36 </strong>
| style="vertical-align: top;" | <strong>if...£</strong>
| <strong>√bbs.init</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 91: Line 122:
|-
|-
| 1
| 1
| [[File:dot36_ex1_80.png|center|300px]]
| [[File:britishpoundif_ex1_80.png|center|300px]]
| [[File:dot36_ex1_81.png|center|300px]]
| [[File:britishpoundif_ex1_81.png|center|300px]]
|}
|}
<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.
 
<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>.31 and !55</strong>
| style="vertical-align: top;" | <strong>@</strong>
| <strong>√bbs.msgs</strong>
| <strong>√bbs.msgs</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 111: Line 153:
|-
|-
| 1
| 1
| [[File:31and55_ex1_80.png|center|300px]]
| [[File:at_ex1_80.png|center|300px]]
| [[File:31and55_ex1_81.png|center|300px]]
| [[File:at_ex1_81.png|center|300px]]
|}
|}
<u>Conclusion</u>: Documentation originally stated “.31” was not used - but it clearly is - and may be a more-refined or customized version of inputting data from disk (.01). “!55” was undocumented and appears to be a variable replacement for “@0=<reverse n>, where @0 is for disk-and-key input and stores a result. There are several cases where “.31” and “!55” are used in conjunction with each other.
 
<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>.38 / .39 / .40 / .41 and “;” variables</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 131: Line 175:
|-
|-
| 1
| 1
| (current message vs high message):  
| [[File:var_ex1_80.png|center|300px]]
[[File:38_39_40_41_ex1_80.png|center|300px]]
| [[File:var_ex1_81.png|center|300px]]
| (current message vs high message):
|}
[[File:38_39_40_41_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)
|-
|-
| 2
| Filtered Keys
| (reading message):
|
[[File:38_39_40_41_ex2_80.png|center|300px]]
1020 .9,"YN":RETURN
| (reading message):
3715 .9,"12345"+CR$:IF P ...
[[File:38_39_40_41_ex2_81.png|center|300px]]
:(menu choices plus Enter)
|-
|-
| 3
| Space-as-abort convention
| (storing message):
|
[[File:38_39_40_41_ex3_80.png|center|300px]]
9132 .9:IF A$=" " THEN P=1
| (storing message):
:(and several more spots do the same)
[[File:38_39_40_41_ex3_81.png|center|300px]]
|}
|}
<u>Observation (no conclusion)</u>: This is one of the more intriguing finds and it’s a hot mess – lines 3140, 3555 and 1525 are obviously the topics of interest. I can’t tell you what’s going on here, but here are some observations from my research:
 
* Example 1 is very close to Example 2, so read on….
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.
* Example 2 is reading a message after the user has selected a message number.
:: From 8.0, <strong>m</strong>=last message read, <strong>mn(.)</strong> is our message numbers array, <strong>mr%(m)</strong> tracks messages that have been read, and mn (not arrayed) is undocumented, but suspect it is “current message number”.
* Breaking down line 3140:
:: You can see the loop function “<strong>[</strong>“, “<strong>@</strong>” and “<strong>]</strong>” replacing our for-next in line 3140, and in same line variable “<strong>m</strong>” is being decremented, replacing the “<strong>step -1</strong>”. “<strong>@m</strong>” appears to be our “<strong>next m</strong>” of the for next loop replacement.
:: Our preparation for the loop is present:
::: 8.0 statement for <strong>m=mn(.)</strong> can be tied to 8.1 statement <strong>m=mn(.)</strong>.
::: I suggest the following matches from line 3140 comparison:
:::* 8.0 statement <strong>ifmn(m)>ithennext</strong> = 8.1 statements <strong>if;0f<=I]£ and @m</strong>
:::* 8.0 statement <strong>mr%(m)=.</strong> = 8.1 statement <strong>;1k=.</strong>
:::* both of these statements are occurring inside the loop; and that covers all of the original 8.0 line of 3140.
:: So what are the 8.1 statements <strong>.38,0mn</strong>,<strong>1mr%</strong> and <strong>.39,fm,km</strong> doing before we enter the loop? There is no equivalent statement I can derive from 8.0. Printing the value of these parameters did not provide any insight either, although we know what <strong>mn</strong> and <strong>mr%</strong> are, and <strong>fm</strong> – if being used correctly – is word-wrap. Variable <strong>km</strong> is undefined and it is not set anywhere in the basic code of √bbs.msgs.  
* Example 3 is storing a new message and updating the message links
:: It appears the 8.1 version of line 1525 uses “old to new” assignments to replace the incrementation we see in the 8.0 version. The 8.1 statement <strong>.40,fgkl</strong> is a mystery, but appears to be a new ML routine to use the new assignments of the variables <strong>f</strong>, <strong>g</strong>, <strong>k</strong>, and <strong>l</strong> that occurred on the same line.
* Examples 1 & 2 appear to use different subject parameter for parameter #2 in the <strong>.38</strong> function. Example 1 shows <strong>.38</strong> receiving last message read as parameter 1 and category as parameter 2. Example 2 shows message number as parameter 1 and <strong>.38</strong> is taking two parameters: “<strong>0mr%</strong>” and “<strong>1ca%</strong>” separated by a comma
|}
|}


{| class="wikitable
<span id="dot31"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>£if </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 181: Line 305:
|-
|-
| 1
| 1
| [[File:britishpoundif_ex1_80.png|center|300px]]
| [[File:31and55_ex1_80.png|center|300px]]
| [[File:britishpoundif_ex1_81.png|center|300px]]
| [[File:31and55_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 “and not” function 
<u>Conclusion</u>: .31 – Message-Aware Disk Input (Version 8.1)
 
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>
 
{| class="wikitable"
|-
! 8.0
! 8.1
|-
| style="vertical-align: top;" |
Message scanning used: <code>.01</code>.<br><br>
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>
 
<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.
 
: <code>!55 = 0</code> → No delimiter encountered
: <code>!55 ≠ 0</code> → End of message record reached


“(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)”
When <code>!55</code> is detected:
* the current message-scan loop updates counters
* the system transitions to the next message record
* display or processing routines advance accordingly
|}
|}
|}


{| class="wikitable
<span id="dot36"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>@ </strong>
| style="vertical-align: top;" | <strong>.36</strong>
| <strong>√bbs.msgs</strong>
| <strong>√bbs.init</strong><br><br>
{| class="wikitable
 
{| class="wikitable"
|-
|-
! Example
! Example
Line 205: Line 358:
|-
|-
| 1
| 1
| [[File:at_ex1_80.png|center|300px]]
| [[File:dot36_ex1_80.png|center|300px]]
| [[File:at_ex1_81.png|center|300px]]
| [[File:dot36_ex1_81.png|center|300px]]
|}
|}
<u>Conclusion</u>: Can serve as an “if” keyword
 
''' .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>[var$] </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 225: Line 424:
|-
|-
| 1
| 1
| [[File:var_ex1_80.png|center|300px]]
| (current message vs high message):<br>
| [[File:var_ex1_81.png|center|300px]]
[[File:38_39_40_41_ex1_80.png|center|300px]]
| (current message vs high message):<br>
[[File:38_39_40_41_ex1_81.png|center|300px]]
|-
| 2
| (reading message):<br>
[[File:38_39_40_41_ex2_80.png|center|300px]]
| (reading message):<br>
[[File:38_39_40_41_ex2_81.png|center|300px]]
|-
| 3
| (storing message):<br>
[[File:38_39_40_41_ex3_80.png|center|300px]]
| (storing message):<br>
[[File:38_39_40_41_ex3_81.png|center|300px]]
|}
 
'''Message Relink Commands in v8.1'''
 
{| class="wikitable"
|-
! 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 <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:
 
: <code>.38 → .39 → .40 / .41</code>
 
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 <code>.39</code> operations
* Prepares the ML environment for scanning and linking old message records
 
In <code>BBS.MSGS</code>, this binding typically associates:
 
: Slot 0 → <code>MN</code> (message number)
: Slot 1 → <code>MR%</code> (message-read flags array)
 
The ML iterator then uses internal scratch registers such as:
 
: <code>;0K</code>
: <code>;1K</code>
: <code>;0F</code>
 
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'''
 
* <code>.38</code> must precede <code>.39</code> in relink routines
* <code>.38</code> 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 <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.
 
It should be understood primarily as a setup command rather than an action command.
|}
 
<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
 
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)
|}
|}
<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>] as goto </strong>
| style="vertical-align: top;" | <strong>@31</strong>
| <strong>√bbs.msgs</strong>
| <strong>@31 – Sequential Read (Enhanced)</strong><br><br>
{| class="wikitable
 
<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"
|-
|-
! Example
! 8.0
! 8.0
! 8.1
! 8.1
|-
|-
| 1
| <code>2330 I$=@5:IF !40&lt;LEN(TX$) THEN I$=I$+CR$</code>
| [[File:asgoto_ex1_80.png|center|300px]]
| <code>2330 T=@9:[I$=@31:II=ST:GOSUB2400</code>
| [[File:asgoto_ex1_81.png|center|300px]]
|}
 
<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
! Notes
|-
| style="vertical-align: top;" | <strong>@32</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)
|}
|}
<u>Conclusion</u>: Can serve as a “goto” function
 
|}
|}


{| class="wikitable
<span id="at33"></span>
{| class="wikitable"
|-
|-
! Topic
! Topic
! Found in
! Notes
|-
|-
| <strong>.32</strong>
| style="vertical-align: top;" | <strong>@33</strong>
| <strong>√bbs.msgs</strong>
| <strong>@33 - Return CHR$(0) Null</strong><br><br>
 
<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>.


<u>Researching / Unknown</u>
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.