--- title: "MCLOADER" id: 54534 type: "computer_media" slug: "mcloader" url: "http://localhost/computer_media/mcloader/" markdown_url: "http://localhost/computer_media/mcloader.md" published_at: "2024-06-02T16:35:10+00:00" modified_at: "2026-03-30T21:43:37+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A machine code loader that POKEs decimal bytes into memory near RAMTOP, computes a checksum, and then tells you exactly how to SAVE the result to tape." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Programming" slug: "programming" taxonomy: "genre" url: "http://localhost/type/programming/" media_contents: - id: 51213 title: "CATS Library Tape 3" type: "computer_media" url: "http://localhost/computer_media/cats-library-tape-3/" - id: 64711 title: "Long Island Sinclair Timex (LIST) User Group Library Tape #2.2" type: "computer_media" url: "http://localhost/computer_media/long-island-sinclair-timex-list-user-group-library-tape-2-2/" media_type: "Program" mediadate: "198x" media_type_tags: "Programming" --- # MCLOADER 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:**`SUM` at line 85 is initialized to zero and incremented by `VAL C$` at line 140, yielding a simple additive checksum over all entered bytes. No modular reduction is applied, so `SUM` can 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 the `INPUT` on 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 0` is not used; instead, an `INPUT` drives 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. ## 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