Undocumented 8.1 commands: Difference between revisions
No edit summary |
No edit summary |
||
| (49 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
At the time of this revision for Color 64 v8.1a, | 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 <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 | 30 ETC.... | ||
Topics: | |||
* General Programming (below) | |||
* [[#mlcommands|ML Commands]] | |||
* [[#mlvariables|ML Variables]] | |||
* [[#mlfunctions|ML Functions]] | |||
---- | |||
'''General Programming''' | |||
{| class="wikitable | {| class="wikitable" | ||
|- | |- | ||
! Topic | ! Topic | ||
! | ! 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 < | : <code>A=A+12</code> | ||
In some cases, this can instead be written as: | |||
: <code>A+12</code> | |||
This appears to work only with numeric variables, not strings, and success has not been completely consistent. Use with caution. | |||
|} | |} | ||
{| class="wikitable | {| class="wikitable" | ||
|- | |- | ||
! Topic | ! Topic | ||
! | ! Notes | ||
|- | |- | ||
| <strong>Branch Shortcuts </strong> | | style="vertical-align: top;" | <strong>Branch Shortcuts</strong> | ||
| <strong> | | <strong>All Main Overlays</strong><br><br> | ||
{| class="wikitable | |||
{| class="wikitable" | |||
|- | |- | ||
! Example | ! Example | ||
| Line 50: | Line 65: | ||
|} | |} | ||
<u>Conclusion</u>: | <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 | 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$<>""</code> and <code>A$</code> is not the HOME key. | ||
: <strong>]</strong> | |||
: | : <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<>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 | ||
! | ! Notes | ||
|- | |- | ||
| <strong> | | style="vertical-align: top;" | <strong>"THEN" with IF</strong> | ||
| <strong> | | <strong>All Main Overlays</strong><br><br> | ||
{| class="wikitable | |||
{| 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 <condition> <action></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 | ! Example | ||
| Line 71: | Line 122: | ||
|- | |- | ||
| 1 | | 1 | ||
| [[File: | | [[File:britishpoundif_ex1_80.png|center|300px]] | ||
| [[File: | | [[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" | |||
|- | |||
! Topic | |||
! Notes | |||
|- | |||
| style="vertical-align: top;" | <strong>@</strong> | |||
| <strong>√bbs.msgs</strong><br><br> | |||
{| class="wikitable" | |||
|- | |||
! Example | |||
! 8.0 | |||
! 8.1 | |||
|- | |||
| 1 | |||
| [[File:at_ex1_80.png|center|300px]] | |||
| [[File:at_ex1_81.png|center|300px]] | |||
|} | |} | ||
<u>Conclusion</u>: | |||
<u>Conclusion</u>: This seems to act somewhat like an <code>IF</code> keyword in certain contexts, although testing this idea in a traditional standalone sense resulted in a syntax error. | |||
|} | |} | ||
{| class="wikitable | {| class="wikitable" | ||
|- | |- | ||
! Topic | ! Topic | ||
! | ! Notes | ||
|- | |- | ||
| <strong> | | style="vertical-align: top;" | <strong>[var$]</strong> | ||
| <strong>√bbs. | | <strong>√bbs.msgs</strong><br><br> | ||
{| class="wikitable | |||
{| class="wikitable" | |||
|- | |- | ||
! Example | ! Example | ||
| Line 91: | Line 175: | ||
|- | |- | ||
| 1 | | 1 | ||
| [[File: | | [[File:var_ex1_80.png|center|300px]] | ||
| [[File: | | [[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>&</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) | |||
|} | |} | ||
< | |||
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="dot31"></span> | ||
{| class="wikitable" | |||
|- | |- | ||
! Topic | ! Topic | ||
! | ! 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 114: | Line 308: | ||
| [[File:31and55_ex1_81.png|center|300px]] | | [[File:31and55_ex1_81.png|center|300px]] | ||
|} | |} | ||
<u>Conclusion</u>: | |||
<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 | |||
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 | ||
! | ! Notes | ||
|- | |- | ||
| <strong>. | | style="vertical-align: top;" | <strong>.36</strong> | ||
| <strong>√bbs. | | <strong>√bbs.init</strong><br><br> | ||
{| class="wikitable | |||
{| class="wikitable" | |||
|- | |- | ||
! Example | ! Example | ||
| Line 131: | Line 358: | ||
|- | |- | ||
| 1 | | 1 | ||
| (current message vs high message): | | [[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. | |||
|} | |||
<span id="dot38"></span> | |||
{| class="wikitable" | |||
|- | |||
! Topic | |||
! Notes | |||
|- | |||
| style="vertical-align: top;" | <strong>.38 / .39 / .40 / .41 and “;” variables</strong> | |||
| <strong>√bbs.msgs</strong><br><br> | |||
{| class="wikitable" | |||
|- | |||
! Example | |||
! 8.0 | |||
! 8.1 | |||
|- | |||
| 1 | |||
| (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]] | ||
|} | |} | ||
'''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 | |||
|} | |} | ||
{| class="wikitable | ''' .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 | ! Topic | ||
! | ! Notes | ||
|- | |- | ||
| <strong> | | style="vertical-align: top;" | <strong>!8</strong> | ||
| <strong> | | <strong>Wrap/Width Threshold</strong><br><br> | ||
{| class="wikitable | |||
<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$)<!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> | ||
! 8.0 | | <strong>!55 – Message Record Delimiter Flag</strong><br><br> | ||
! 8.1 | |||
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> 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 | | 1 | ||
| | | DIVIDER | ||
| | | Insert or manage message divider | ||
|- | |||
| 2 | |||
| WRAP | |||
| Wordwrap toggle / behavior | |||
|- | |||
| 3 | |||
| DELETE | |||
| Delete operation (line / section) | |||
|- | |||
| 4 | |||
| EDIT | |||
| Edit operation | |||
|- | |||
| 5 | |||
| END | |||
| End editor / finish | |||
|- | |||
| 6 | |||
| MERGE | |||
| Merge behavior (message / text merge) | |||
|} | |} | ||
< | <strong>Slash-command prefix interaction ("/")</strong><br><br> | ||
<nowiki>!60</nowiki> is also used as a boolean-style flag to enable slash-style command entry behavior. One observed usage is: | |||
311 II=GO(!60,47,.) | |||
Where: | |||
* <code>47</code> is ASCII <code>/</code> | |||
* This suggests that when <code>!60</code> is active (non-zero), <code>/</code> is used as the command-prefix character by the editor logic | |||
This supports the interpretation that <code>!60</code> is not merely a one-shot selection value, but the <strong>editor command-mode state</strong> that can be: | |||
* cleared (0) while collecting or editing input, or performing screen cleanup | |||
* set (1..6) when a command has been selected and needs to be dispatched | |||
<strong>Additional references in the editor flow</strong><br><br> | |||
Line 1300 shows <code>!60</code> being initialized prior to the editor loop and used with other state variables: | |||
1300 !7,FM:A=I:!60,1:[GOSUB311:IFP]... | |||
Lines 2885 / 2888 show the same “set <code>!60</code>, dispatch, then reset” pattern: | |||
2885 ... :!60,1:[GOSUB311:IFP]... | |||
2888 ON!60 GOTO 2890,1305,2889,2895:!60,1:@ | |||
<strong>Working conclusion</strong><br><br> | |||
In Color 64 v8.1, <code>!60</code> is a <strong>message-editor command state / selector variable</strong>: | |||
* It enables slash-command style operation (<code>/</code> prefix) when active | |||
* It holds the selected editor-command index (1..6) | |||
* It is used in ON-GOTO dispatch tables to jump to the correct handler | |||
* It is frequently reset back to 1 after a handler executes | |||
<strong>Open questions</strong><br><br> | |||
* Whether <code>!60</code> is also modified by the <code>.9</code> input routine, or by other ML routines, to signal screen-edit cleanup, such as controlling the delete-echo behavior at line 2932 | |||
* Whether <code>!60</code> has additional meanings beyond editor-related command selection | |||
This is also used in conjunction with <code>!56</code> and <code>!57</code>. | |||
|} | |} | ||
{| class="wikitable | <span id="mlfunctions"></span> | ||
---- | |||
'''ML Functions''' | |||
<span id="at31"></span> | |||
{| class="wikitable" | |||
|- | |- | ||
! Topic | ! Topic | ||
! | ! Notes | ||
|- | |- | ||
| <strong>@ </strong> | | style="vertical-align: top;" | <strong>@31</strong> | ||
| <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" | |||
|- | |- | ||
! 8.0 | ! 8.0 | ||
! 8.1 | ! 8.1 | ||
|- | |- | ||
| | | <code>2330 I$=@5:IF !40<LEN(TX$) THEN I$=I$+CR$</code> | ||
| [ | | <code>2330 T=@9:[I$=@31:II=ST:GOSUB2400</code> | ||
|} | |} | ||
< | |||
<strong>Notes</strong> | |||
* <code>@31</code> is not a pure function | |||
** It requires an open file context | |||
** It updates <code>ST</code> | |||
** It should be used within the normal BBS runtime environment | |||
<strong>Conclusion</strong> | |||
<code>@31</code> is an enhanced sequential-record read function used primarily in message handling and merge routines. It streamlines record retrieval, updates <code>ST</code> for loop control, and is typically combined with <code>@9</code>-based memory-budget safeguards. | |||
|} | |} | ||
{| class="wikitable | <span id="at32"></span> | ||
{| class="wikitable" | |||
|- | |- | ||
! Topic | ! 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 | |||
|- | |- | ||
| 1 | | 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) | ||
|} | |} | ||
|} | |} | ||
{| class="wikitable | <span id="at33"></span> | ||
{| class="wikitable" | |||
|- | |- | ||
! Topic | ! Topic | ||
! | ! Notes | ||
|- | |- | ||
| <strong> | | style="vertical-align: top;" | <strong>@33</strong> | ||
| <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>. | |||
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 (below)
- ML Commands
- ML Variables
- ML Functions
General Programming
| Topic | Notes |
|---|---|
| Simple Addition | All overlays Color 64 allows simple numeric addition without always using the full:
In some cases, this can instead be written as:
This appears to work only with numeric variables, not strings, and success has not been completely consistent. Use with caution. |
| Topic | Notes | ||||
|---|---|---|---|---|---|
| "THEN" with IF | All Main Overlays
Conclusion:
is legal in most observed uses. |
| Topic | Notes | ||||||
|---|---|---|---|---|---|---|---|
| if...£ | √bbs.msgs
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:
Another example: |
| Topic | Notes | ||||||
|---|---|---|---|---|---|---|---|
| @ | √bbs.msgs
Conclusion: This seems to act somewhat like an |
| Topic | Notes | ||||||
|---|---|---|---|---|---|---|---|
| [var$] | √bbs.msgs
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
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
It may also update the same underlying status and character registers used by While further testing is still required, this appears to be the practical replacement for |
| Topic | Notes | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| .9 | All Main Overlays Previously documented in 8.0 as a “do not use” command that replaced the .9 – Single-Key Command Input Poll Overview The Previous versions of Color 64 used When a key is pressed:
When no key is pressed:
Examples (
So |
| Topic | Notes | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| .31 and !55 | √bbs.msgs
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 Comparison: Version 8.0 vs Version 8.1
|
| Topic | Notes | ||||||
|---|---|---|---|---|---|---|---|
| .36 | √bbs.init
.36 – Prompt-Cycle Housekeeping (Behavior Unconfirmed) Category: ML Command Overview The In testing within the live BBS environment, removing Observed Call Pattern
Testing Notes
Working Hypothesis
Summary
|
| Topic | Notes | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| .38 / .39 / .40 / .41 and “;” variables | √bbs.msgs
Message Relink Commands in v8.1
.38 – Relink Iterator Initialization (v8.1) The It is designed to be used as the first step in a command sequence:
This sequence replaces the more BASIC-driven record-scanning logic found in v8.0. What .38 Does
In
The ML iterator then uses internal scratch registers such as:
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
Summary The It should be understood primarily as a setup command rather than an action command. |
ML Variables
| Topic | Notes |
|---|---|
| !8 | Wrap/Width Threshold
Example:
In the example above, if a line is shorter than |
| Topic | Notes |
|---|---|
| !46 | Scratch Register
In those routines, 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 |
| Topic | Notes |
|---|---|
| !56 | !56 - Message Editor Command State (True/False) (Editor) Used in conjunction with See |
| Topic | Notes |
|---|---|
| !57 | !57 - Prefix Trigger Assignment (Editor) This works in concert with See |
| 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 |
| 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 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:
Dispatcher usage Version 8.1 uses 1302 ON!60 GOTO 1314,1305,1306,1365,1310,1312:!60,1:@ This strongly indicates:
Based on the command list order from line 2931, the implied mapping is:
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:
This supports the interpretation that
Additional references in the editor flow Line 1300 shows 1300 !7,FM:A=I:!60,1:[GOSUB311:IFP]... Lines 2885 / 2888 show the same “set 2885 ... :!60,1:[GOSUB311:IFP]... 2888 ON!60 GOTO 2890,1305,2889,2895:!60,1:@ Working conclusion In Color 64 v8.1,
Open questions
This is also used in conjunction with |
ML Functions
| Topic | Notes | ||||
|---|---|---|---|---|---|
| @31 | @31 – Sequential Read (Enhanced) Overview Higher-Level Replacement for @5
It is used prominently in merge-message routines within Behavior
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
2) Status-Driven Looping
This is frequently paired with the enhanced In comparison:
Notes
Conclusion
|
| Topic | Notes | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @32 | @32(2,2) – Return Block Count The In Color 64 v8.1, Syntax: Status / End-of-List Behavior: 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 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)
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)
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
8.0 Comparison
|
| Topic | Notes |
|---|---|
| @33 | @33 - Return CHR$(0) Null
There is no comparative code from earlier versions of Color 64 currently known. |






























