19

Most ZX Spectrum games were loaded from tape, and the traditional way of starting the loading process (at least in the 48K era) was to type

LOAD ""

and then start the tape. This would normally load a small BASIC loader, sometimes containing more sophisticated (and normally faster) custom loading routines.

However, some 16K games (for example, QuickSilva's Meteor Storm) required

LOAD "" CODE

to be used instead. I can only remember a handful of games that required CODE to be included - what was the reason for this? Given that it seemed to only be required for 16K games, was it to save memory?

4
  • 1
    I guess that you could always write a BASIC program 10 LOAD "" CODE and save that as the first item on the tape so you're never going to save memory, but you might save loading time?
    – Tommy
    Commented Dec 23, 2019 at 15:19
  • 1
    @Tommy: that's what I don't understand - it would only add ~10 seconds to loading time, and to the novice finding CODE on the Spectrum keyboard would have been fairly confusing - hence my suspicion there might have been a more technical reason for it.
    – KenD
    Commented Dec 23, 2019 at 15:30
  • 2
    I'd be prone to guess it was just a case of the conventions not yet having been cemented — that with little to compare to you might well reason that if you're launching a machine-code program then you should just save it as a machine-code file and tell the user to type the right thing. And the correlation with 16kb software is just a correlation with earliness, not an indication of causation. But, just a guess. So not an answer.
    – Tommy
    Commented Dec 23, 2019 at 15:47
  • It could be a question about incompetence at some software houses. Could also be a question about how the tapes where produced/duplicated. Large companies most probably had high speed cassette copiers, but small companies might gave made the cassettes directly from a computer. Don't know if that is the reason.
    – UncleBod
    Commented Dec 23, 2019 at 16:11

4 Answers 4

21

As you guessed,

LOAD "" 

loads a BASIC loader.

LOAD "" CODE 

loads a machine code program saved on the tape straight into memory, at the addresses given when using

SAVE name CODE start, length

Doing it this way means you can squeeze the most code into the memory, not wasting any on the loader or a loading screen.

8
  • 2
    If I had to guess, this is because typing 5 more keystrokes was not considered a great effort. Commented Dec 24, 2019 at 5:58
  • 3
    I can't remember the exact key combination for "CODE" but you'd have to search for it on the keyboard then enter some finger-twisting combination.
    – harlandski
    Commented Dec 24, 2019 at 7:36
  • 5
    @Andrew Savinykh it's only 3 keypresses - Shift, Symbol Shift (release) + i
    – harlandski
    Commented Dec 24, 2019 at 8:17
  • 2
    @MarkWilliams - it can distinguish, and in fact will reject a file if the header indicates a different type to what it expects; I suspect this was added as a way to prevent the wrong type of data being loaded accidentally.
    – occipita
    Commented Jun 28, 2023 at 20:23
  • 1
    @supercat - there was a hack: the return address of the tape loader routine would be at a predictable location in the stack, so if you overwrote that location you could get it to immediately start your program rather than dropping back into the BASIC interpreter.
    – occipita
    Commented Jun 28, 2023 at 20:29
11

I'd bet on some kind of prehistoric "copy protection", or the oddity of the software house production process.

The most usual way was to have a short BASIC loader (e.g. 10 CLEAR 24899: LOAD "" CODE: RANDOMIZE USR 24900) saved with LINE 10 for autostart after load. The second file was a code itself. BASIC made the necessary operations: prepare the memory space, load the code and run the machine code.

To save "just a code, with autostart" you need to save the code with some system variables. Then you will get something like a "snapshot". You can try it too - try to write something like

10 SAVE "test" CODE 16384,16384: PRINT "AUTO-RUN"

and run it. This program saves the whole memory of 16k Spectrum, from the screen through the system variables, the BASIC program itself and a lot of empty space. When you want to load this program back, you have to enter LOAD "" CODE. During load, the computer restores all the variables to the exactly same state as they were in the moment of saving. So the BASIC program will continue directly after the SAVE command. Et voila...

IMHO the main reason was those games were the first games ever wrote for ZX Spectrum and their authors had no "best practices" yet, so they had tried different ways...

4
  • 1
    I bet your guess about copy protection is right. Simply saving the game with SAVE "" CODE addr, len won't create an auto-starting code file, but I've seen such auto-starting files before and they would be pretty confusing to a wanna be hacker.
    – introspec
    Commented Dec 24, 2019 at 13:38
  • 4
    "The second file was the code itself". As I recall typically the second file was actually a splash screen loaded directly at the video memory address, and the third file typically was the actual code.
    – Rodney
    Commented Dec 24, 2019 at 15:45
  • You're right, Rodney. I have omitted the splash screen for simplification. I am not sure the splash screen was so common in 1982 when Meteor Storm has been published. Commented Dec 24, 2019 at 15:58
  • Save some loading time by skipping the screen memory (which is 6912 bytes starting at 16384). So, something like: 10 SAVE "test" CODE 23296,9472":PRINT "AUTO-RUN"
    – Soruk
    Commented Jul 2, 2020 at 22:22
4

It was a vague anti tampering thing although there was no sane excuse not to have had a tiny piece of regular Basic before it.

In most tapes using this "code loading" the actual code is usually only a few hundred bytes. It is actually just the system variables area and the Basic itself so it auto runs similar to Basic . The main erm advantages of a code like this was you could not easily "merge" it to prevent it auto running and because it had the system vars in it , various "pokes" could be applied before saving it too giving it an added layer of protection. Even back then it was trivial to defeat though .

I can't go into huge detail now but on a generic level saving a small Basic program can be done with CODE 23550, length . Getting the accurate length requires a calculation I have but not in my head . 500 will suffice if it's only a few statements.

It is very important to note that the Save ommand for the code itself -must- be followed immediatey by the next command on the same line as when the code is loaded back in it will carry on from there . The easy way to do this is to have the first Basic program line being the actual save ( say line 10 for example ) then the rest of the Basic would start at line 20 . This way when it is loaded back having been saved as code the save has been already executed and the next line to deal with is 20 .

If that does not make a huge deal of s sense try thinking of the small piece of code as a snapshot, although technically it is not it can help explain it.

I am not immediately aware of this method working on other machines although lack of detailed knowledge of other platforms likely explains that.

3

The panoply of software titles needing LOAD "" CODE to be loaded, is mainly centred around the early ZX Spectrum years, 1982-1984.

While LOAD "" also exists in the ZX81, the technique seems to be a remnant of a wide practice of writing games in assembly together with system variables, for that machine.

That allied with the platform being relatively new, BASIC offering no intrinsic strong anti-tampering protections, and more advanced BASIC obfuscation techniques not being yet widely known, it might explain placing BASIC loaders in CODE blocks (together with LOAD"" not being yet a de facto standard after being used by default by the 128K models loader menu).

In addition, by loading tape CODE blocks, you can obfuscate somewhat where the execution point takes off. Once the code is loaded, you can continue BASIC execution:

  • in the line buffer;
  • in a BASIC line and position of your choice.

Furthermore, using a CODE block, you can play with variables, like (PROG) and change BASIC location or like ERR_SP, and the BASIC listing (if any), won't have a hint of where the machine code is being entered. Or you can even smash the machine code/CPU stack, and not even return to the BASIC interpreter, using the variable and BASIC area for storing machine code (eg using the address from 16384 as contiguous RAM, if the programmer knows what he is doing).

Also, saving as SAVE "" CODE seems to be used by some software titles to hide the fact they are in fact, BASIC programs.

By the time the 128K models start to be widespread used, they make it mandatory using a BASIC loader; they do not load automatically a starting LOAD "" CODE block.

Taking the aforementioned METEOR STORM as an example, that has one block of CODE from 23500 with a length of 8700 bytes.

tape

Once the LOAD "" CODE block is loaded from tape, and doing a breakpoint in ROM immediately after, you have got the following BASIC program:

From (PROG)

10 CLEAR 24900
11 PRINT "LOADING MACHINE FILE"
12 LOAD ""CODE 
13 CLS 
15 PRINT "METEOR STORM MASTER"
20 PRINT 
25 PRINT " QUICKSILVA 1982"
30 PRINT :PRINT :PRINT 
35 PRINT "INSERT BLANK CASSETTE"
40 SAVE "METEOR"CODE 23500,8700:LET L=USR 28000
100 SAVE "MET.MASTER"LINE 1
110 SAVE "MET.MFILE"CODE 25000,7200

and in the line buffer (E_LINE) memory area:

LOAD ""

Analysing the rest of the ZX Spectrum system variables, relevant for this discussion:

40 - (5C45) PPC - Line number of statement being executed
01 - (5C47) SUBPPC - Number within line of statement being executed
24900 - (5CB2) RAMTOP - Address of last byte of BASIC system area

There are no integer numbers obscuration, as in later titles, so we can take the ASCII BASIC listing at face value.

For building the METEOR CODE block in tape, that we have today, the programmers:

  • ran the BASIC code from LINE 100, saving to tape both the BASIC+the MC block;
  • restarted the machine
  • loaded the saved BASIC block from tape
  • that in turn loaded the M/C block at line 12
  • and then saved system variables+BASIC+machine code at the beginning of line 40

We can then see, confirmed by the values of the system variables, that the machine will return upon completion of LOAD "" CODE, to the instruction calling machine code at LET L=USR 28000 at line 40.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .