MCLOADER is a machine code entry utility that accepts decimal byte values one at a time and POKEs them into memory starting at a user-specified or automatically calculated address near RAMTOP. The program uses a string array `B$` to buffer entered bytes so they can be reviewed in groups of eight after entry. A running checksum is accumulated and displayed after all bytes are entered, providing a basic integrity check. The tool reads RAMTOP from system variables at addresses 23730–23731 and, if necessary, lowers it via CLEAR to make room for the incoming code. After entry, it prints the exact SAVE…CODE command needed to preserve the loaded machine code to tape.
Program Analysis
Program Structure
The program is organized into a main entry flow and several distinct subroutine-like blocks accessed via GO TO:
- Lines 10–45: Setup — prompts for byte count, dimensions the buffer array, and checks/adjusts RAMTOP.
- Lines 50–80: Determines start address — either user-supplied or auto-calculated as
65368-N. - Lines 85–174: Main entry loop — POKEs each byte, accumulates checksum, then branches to review or list mode.
- Lines 1000–1010: Standalone RAMTOP display utility (not called from the main flow; appears to be a debugging aid reachable only by direct
RUN 1000). - Lines 2000–2030: List mode — prints a user-specified number of bytes from the top of memory.
- Lines 3000–3030: Review mode — dumps all buffered byte strings from
B$. - Line 5000: Common exit — prints the SAVE command with the correct address and length.
Memory Layout and RAMTOP Handling
The program reads RAMTOP from the system variables at addresses 23730 (low byte) and 23731 (high byte), combining them as PEEK 23730 + 256*PEEK 23731. It computes available space above the current program/variable area as 65367 - PEEK 23730 - 256*PEEK 23731 and compares it to N. If there is insufficient room, it prints a warning and instructs the user to hit ENTER, then uses CLEAR 65367-N to lower RAMTOP before halting with STOP. The user must then RUN again to proceed with the newly lowered RAMTOP — a two-pass bootstrapping approach necessitated by the fact that CLEAR and subsequent re-entry cannot easily be automated without a self-modifying loop.
The default start address S = 65368 - N places the code block immediately above RAMTOP at the conventional top-of-RAM location. Note that RAMTOP itself is the byte at address PEEK 23730 + 256*PEEK 23731, so +1 in the final SAVE line correctly gives the first byte above it.
Input Buffering with DIM B$
DIM B$(N,4) at line 42 allocates a two-dimensional string array: N rows of 4 characters each. Each entered decimal string (up to “255”) is stored in B$(I) after being POKEd. This allows the review section (lines 3000–3020) to reprint all entered values without re-reading memory. However, storing the decimal strings rather than the byte values means the review output shows the original typed text, not a formatted hex or decimal column dump.
Key BASIC Idioms and Techniques
- Checksum accumulation:
SUMat line 85 is initialized to zero and incremented byVAL C$at line 140, yielding a simple additive checksum over all entered bytes. No modular reduction is applied, soSUMcan grow large for many bytes. - Address display during entry: Line 100 uses
PRINT INK 3; S+I-1;to display the current target address in a distinct color before theINPUTon the next line, giving visual context without disturbing the input prompt layout. - TAB formatting: Line 120 uses
TAB (10-LEN C$)to right-align the entered value — a neat trick to create a consistent column width for 1-, 2-, or 3-digit decimal numbers. - PAUSE 4E4: Line 45 uses scientific notation (
4E4= 40000) for the pause duration — a common space-saving idiom. At line 172,PAUSE 0is not used; instead, anINPUTdrives the pause.
Notable Anomalies and Bugs
| Location | Issue |
|---|---|
| Line 42 | DIM B$(N,4) is executed before the RAMTOP check at line 45. If N is large, the array itself may consume significant RAM before the check can fire, potentially causing an out-of-memory error prior to the guard condition. |
| Lines 2000–2020 | The list mode asks “HOW MANY BYTES?” and iterates FOR J=B TO 1 STEP -1, printing 65368-J and its PEEK. This always reads from 65368-B to 65367, ignoring the user’s chosen start address S. If the user chose a non-default start address, the listing may not correspond to the entered code. |
| Line 115 | LET B$(I)=C$ stores the raw input. Because B$ columns are 4 wide and BASIC pads with spaces, review output at line 3010 will include trailing spaces between values, making the group display harder to read. |
| Lines 1000–1010 | This block is unreachable from the normal program flow — no GO TO 1000 exists. It appears to be a utility snippet left in for manual invocation. |
| Line 2030 / 3030 | Each review/list block ends with a GO TO 5000 then an unreachable STOP. The STOP statements are dead code but harmless. |
Save Command Generation
Line 5000 prints the exact tape-save command the user needs to type: SAVE "XXX" CODE address, N, substituting the computed start address (PEEK 23730 + 256*PEEK 23731 + 1) and byte count (N). The +1 correctly adjusts from the RAMTOP pointer (which points to the last byte of the BASIC area) to the first byte of the machine code block. This self-documenting approach removes the burden of remembering addresses after a potentially lengthy entry session.
Content
Image Gallery
Source Code
10 REM ***********************
20 REM MCLOADER
30 REM ***********************
40 INPUT "HOW MANY BYTES OF MC?";N
42 DIM B$(N,4)
45 IF 65367-PEEK 23730-256*PEEK 23731<N THEN PRINT "RAMTOP BEING LOWERED TO ";65367-N: PRINT "HIT ENTER THEN ""RUN"" TO CONTINUE": PAUSE 4E4: CLEAR 65367-N: STOP
50 INPUT "ANY SPECIFIC STARTING ADDRESS? (Y/N)";A$
60 IF A$="Y" THEN INPUT "ENTER STARTING ADDRESS ";S: GO TO 80
70 LET S=65368-N
80 PRINT "INPUT CODE (DEC) FOR EA ADDR"
85 LET SUM=0
90 FOR I=1 TO N
100 PRINT INK 3;S+I-1;
110 INPUT C$
115 LET B$(I)=C$
120 PRINT TAB (10-LEN C$);C$
130 POKE (S+I-1),VAL C$
140 LET SUM=SUM+VAL C$
150 NEXT I
160 PRINT
170 PRINT "CHECKSUM= ";SUM
172 INPUT "REVIEW CODE IN GROUPS OF 8? (Y/N)";Z$: IF Z$="Y" THEN GO TO 3000
174 GO TO 2000
200 STOP
1000 PRINT "RAMTOP IS AT ";PEEK 23730+256*PEEK 23731
1010 STOP
2000 INPUT "LIST HOW MANY BYTES?";B
2002 CLS
2005 FOR J=B TO 1 STEP -1
2010 PRINT 65368-J,PEEK (65368-J)
2020 NEXT J
2025 GO TO 5000
2030 STOP
2035 REM
3000 CLS
3005 FOR J=1 TO N
3010 PRINT B$(J);
3020 NEXT J
3025 GO TO 5000
3030 STOP
5000 PRINT AT 20,0;"TO SAVE CODE"'"TYPE: SAVE""XXX""CODE ";PEEK 23730+256*PEEK 23731+1;",";N
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.