One of the obvious applications of a monitor is the creation of a backup copy. Here, I take "Las Vegas 20" by Anirog as example. The game comes along on tape, with
forced autostart and with a fast tape loader, of course the STOP key and STOP/RESTORE are also blocked.
So then, let's roll up the sleeves and play hardball: instead of having LOAD start through into the fast tape loader, we just load in the header, with
SYS 63407, and then start MINIMON with SYS 38912:
The fast tape routine now already resides in the tape buffer, behind the file name. As we inspect the tape buffer at $033C, we see this:
The $03 byte in $033C signifies that the following start and end addresses
always determine where the payload is being loaded to, even if the secondary address is 0! That means, even a simple LOAD + [RETURN] forces the autostart. The payload is supposed to load to $0300 (inclusive) up to $0334 (exclusive). That address range contains the BASIC and KERNAL vectors, this way the fast tape routine takes over the computer. We don't want this to happen, for this reason we instead load the payload to $1300 by changing the high bytes at $033E and $0340 to $13:
Actually, for later we also need to know the execution start address of the fast tape loader. With
SYS 62980, we load the payload to $1300 ...
... and inspect it there:
Wow! The fast tape loader just makes short work of the BASIC and KERNAL vectors! Basically, most of them are overwritten with $0351 - you can't make the execution start address more obvious.
As a side note: the KERNAL tape routines run under interrupt control. Here, the values in $0314/$0315 are kept 'life' for the load action - normally, during SAVE, they contain other values! The payload thus had been written to tape separately from the header, in a similar fashion we both loaded separately.
Now for a sharp look into the fast tape loader itself: if we just start it with
G 0351 we would have gained nothing, as it then still would start through to the game:
The sub-routine at $03AF initializes the fast tape loader, and then each call of JSR $03D8 loads a single byte from tape. The first four bytes are start and end address in memory, the start address is stored as (running) pointer to $C1/$C2, the end address goes to $2D/$2E ... is this a BASIC program going to be loaded?
Continuing the disassembly:
Indeed. The instructions at $0397..$03A0 contain a variant of the standard idiom to run a BASIC program from machine code (re-link BASIC text, CLR, set TXTPTR, re-enter interpreter loop).
JSR $FD52 at $0386 and JSR $E45B at $038C restore the KERNAL and BASIC vectors, respectively. Before those, JSR $FDF9 at $0383 takes care of the VIA I/O registers. So, everything's in order again. Though, the fast tape loader then again manipulates $0328 (STOP vector) and $0302 (BASIC warm start vector) - we don't want this and use
F 038F 0396 EA to remove the offending instructions.
As a check, we also fill BASIC memory with the value $2A (
F 1203 7FFF 2A) and, as a last preparation, the fast tape loader may return to MINIMON by placing a
JMP $9800 at $03A0.
G 0351 and drum roll ...
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
... and here's MINIMON back in charge, with the game in memory. Let's take a look at $2B..$2E for BASIC start and "end of program" (a.k.a. "start of variables"):
$2D/$2E point to $47F2 and the memory dump shows a $2A at $47F2 after two zeroes in $47F0 and $47F1, that's looking good. Back to BASIC, ...
... using
SAVE for the backup copy. With
LIST, we wave the BASIC stub a quick "Hello!" and with
RUN we allow ourself a nice game of Slot Machine.