ZX Spectrum – Memory saving tips used

You will see a lot of these in some listings and, if your brain is as addled as mine is trying to remember all of these tricks from back in the day, here’s a handy reminder.

How much memory is my program using?

This is a common method of seeing how much memory is used on a 48K Spectrum BASIC program. If you’re using UDGs (168 bytes), a new font (768 bytes) or any Z80 code subroutines, then remember to take those file lengths off the total too.

16K:
PRINT USR 7962-32768 - this will display 24056 bytes free on a newly reset 16K ZX Spectrum.

48K:
PRINT 65536-USR 7962 - this will display 41473 bytes free on a newly reset 48K ZX Spectrum

128K: 
PRINT 65536-USR 7962 - this will display 41471 bytes (oh no, 2 bytes less!) on a newly reset 128K ZX Spectrum.

Using VAL to save memory

VAL “number” – Whilst it can make a listing look unwieldy, it was necessary back in the day. Using VAL with an integer will always be three bytes shorter than that integer used directly. Spectrum BASIC stores numbers like this:

  • 32768 is stored as 11 bytes. One for each digit as ASCII 3, 2, 7, 6 and 8. Then a byte with value 14 which is a marker to show a floating point number follows. Then 5 bytes for the float itself.
  • Whereas using VAL “32768” means 8 bytes are required. One for “VAL” and one byte each for the 5 digits.

Note: It will be slower to use the VAL command as the Spectrum has to calculate the value before using it. But these days, pressing Turbo mode in your emulator and/or running your ZX Spectrum Next at 28Mhz .. it won’t matter that much :)


Working out what it really means

Replacing integers with built-in commands that generated a value, like the following examples:

x = SGN PI (aka x=1)
x = NOT SGN PI (aka x=0)
x = PI-PI (aka x=0)
x = PI/PI (aka x=1)
x = COS PI (aka x=-1)
x = INT EXP SGN PI (aka x=2)
x = INT PI (aka x=3)

The above examples saved you a few bytes compared to using the standard LET X=1 or LET X=0 commands due to the way that ZX BASIC used tokenized keywords.

I have also seen in two programs (Airline and Corn Cropper by CCS) the following examples of calculated GOTO statements using memory saving tips. Both games used these statements, so I’m guessing they were by the same developer.

GO TO CODE "Y"^2 (which is 7921) 
also
GOTO CODE "<"- CODE "6" (which is line 6)

Further Reading

Read the following that I found on StackExchange as it explains why how this works under Spectrum BASIC.

Sinclair (Floating Point) BASIC is better than that. While it also includes the number the same way (1), it is followed by the token 0x0E (2), and the next 5 bytes storing the constant in floating point format. Sinclair BASIC does now only need to read past the ASCII until the 0x0E and take the FP without the need of conversion – so speed is not an issue.

But looking at the encoding shows that every time a constant is used it will take at least 7 bytes of program memory:

1 Byte for the ASCII representation (more for numbers outside the integers 0..9)

1 byte 0x0E

5 byte floating point representation

A variable name is stored within the program as its ASCII representation. So a two letter name (like on, tw, …) occupies just two bytes (*3). Thus any occurrence of on is just two bytes instead of seven. That’s five bytes saved each time on is used.

Of course, this comes with an offset of assigning the variable, which is 5 bytes plus the expression used. So with LET ze=0 that would be 12 bytes, meaning that already using the variable three times will save space.

Using ze=PI-PI saves even further, as this takes only 3 bytes, so the second usages of ze will yield saved program space. Similar for all the other calculations. It’s all about avoiding constants and replacing them by shorter encoded calculations.

In fact, these optimisations also offer some hints about the age of a program, or at least the time its programmer learned the tricks.

  • PI-PI was eventually the first discovered for 0 and it was used a lot – until someone came up with the idea of NOT PI which also results in zero, but needs one byte less.
  • SGN PI gives 1.
  • Two is a bit more complex, but on+on is as good as SGN PI+SGN PI (both 5 bytes) – later INT EXP SGN PI with only 4 bytes was discovered.
  • Three again is just INT PI, and so on.

The origin of these very Sinclair BASIC specific tricks starts with the ZX81 (the same as the ZX80, but with Floating Point BASIC). Here program space was scarily rare, thus every byte saved was worth the extra effort – much more than later on with the ‘huge’ RAM the Spectrum offered (*4).

Back to ZX Spectrum – BASIC Rips