15

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?

  • 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 Dec 23 '19 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 Dec 23 '19 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 Dec 23 '19 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 Dec 23 '19 at 16:11
17

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.

| improve this answer | |
  • I get that, but why was it used? It required a tiny bit more effort from the user - especially those who wouldn't be used to the Spectrum's keyword-based input, where "typing" the CODE parameter required going into Extended Mode. Why didn't publishers just include a tiny BASIC loader which then loaded the main machine code block? – KenD Dec 23 '19 at 15:26
  • 2
    If I had to guess, this is because typing 5 more keystrokes was not considered a great effort. – Andrew Savinykh Dec 24 '19 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 Dec 24 '19 at 7:36
  • 2
    @Andrew Savinykh it's only 3 keypresses - Shift, Symbol Shift (release) + i – harlandski Dec 24 '19 at 8:17
  • I'd also wonder why the Spectrum needs telling whether it is loading BASIC or machine code? Given it must know what address to load it to and and start it at from the header, why can't it tell it is code? – Mark Williams Apr 23 at 13:18
9

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...

| improve this answer | |
  • 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 Dec 24 '19 at 13:38
  • 3
    "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 Dec 24 '19 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. – Martin Maly Dec 24 '19 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 Jul 2 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.

| improve this answer | |
1

The panoply of software titles needing LOAD "" CODE to be loaded, is 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 knew, 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).

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 is doing).

Also, saving as SAVE "" CODE seems to be used in some 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 in line 40.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.