Assuming a program consisting of a unique big block of 49152
bytes (the whole RAM space). A routine that may be used for a copier to copy this block would sit at the top memory, say at address 64000
along with the stack. Prior to that, the copier asks the user to start loading the big block, just to get the flag byte (which may be different than 255
). This first load is very short, as the flag byte is the first byte present after the sync pulse.
Then, the copier sets the computer to load a block starting at address 9472
, with a length of 49152
bytes and a flag as got in the first stage. That is: the block starts loading into ROM. Obviously, the first 6912
bytes won't be actually copied, but this is just the screen, which may or may not be needed to run the program. The rest of the program is therefore loaded from address 16384
to 58623
, making a total length of 42240
bytes. The screen will surely show garbage during the load process.
The copier is still safe beginning at address 64000
. It will craft a header block of type 3
(Bytes), a file name, start address of 23296
and length according to the number of bytes actually copied (worst case it's 42240
bytes). It will save the header, then the block just loaded beginning from 16384
.
To recover the original screen content (which might have code hidden in it, or used by the initialization routines to check for integrity as a copy countermeasure), the copier would ask the user to load the big block for a second time, but this time the loader would load only 6912
bytes to address 16384
, discarding the rest of the big block. The copier then, would make another header for the screen file, saving it.
At the end we end up with two blocks: the first one is a big block of 42240
bytes that will start at 23296
, and the second one, smaller, containing the screen, that will start at 16384
with the standard length for a screen of 6912
bytes.
Using a copier or by other means, the user would swap the blocks in tape so the screen block comes first, then the big block. A BASIC loader for the whole program would be something like:
10 POKE 23729,111: LOAD ""SCREEN$: LOAD ""CODE
The POKE
command modifies the address of the output routine for the "S" channel to point to an address in ROM in where a RET
instruction is stored. The effect of this is to silent any text output to the screen, which would corrupt the screen loaded when the second block loads its header and prints the "Bytes: ....
" text.
This loader assumes that the stack pointer doesn't get changed from its default value at boot, which will be case for some programs. Others may need the user to get access to the original loader to see what number the CLEAR
statement has.
A example routine that performs the copy of the big block is now presented. It is from the spanish magazine "Microhobby" and belongs to a series of articles collectively called "The Bible of the Hacker". The routine is featured in the XIV issue.
As presented here, the routine is meant to be used from plain BASIC
. It uses the DEF FN
method so one can run the routine with an argument, in this case, the flag needed for the big block. So, to use the routine you would set up a small BASIC
program as this:
10 DEF FN A(N) = USR 64000
So, assuming the flag is 255
, you would start the routine by typing:
RANDOMIZE FN A(255)
Link to the scanned article (spanish):
http://microhobby.speccy.cz/mhf/088/MH088_21.jpg