Memory questions

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
w00tguy
Drutt
Posts: 4
Joined: Tue Apr 03, 2018 2:57 am

Memory questions

Post by w00tguy »

I'm new to the spectrum, and I've been trying to find a detailed memory map of the 48k so I know what I'm allowed to use. These are the best resources I could find, but some areas are still unclear:

http://www.worldofspectrum.org/ZXBasicM ... hap25.html
http://www.breakintoprogram.co.uk/compu ... memory-map

The 0x0000-0x5BFF range is clear enough (ROM + screen memory + printer buffer), but after that I'm not sure. Is there a document/manual I'm missing that explains all the special memory areas? These are the questions I'm trying to answer:

1) What is 0x5CC0-0x5CCA reserved for?
2) What is 0xFF58-0xFFFF reserved for?
3) The blog says system variables are from 0x5C00-0x5CBF, but the manual stops at 0x5CB5. What are those undocumented 10 bytes for? I at least know to poke 111 into 0x5CBB to disable the "bytes: ___" messages (so said the loading screen tutorial), but I don't know why that works.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Memory questions

Post by Nomad »

The Devil is in the detail. :lol:

Like when you buy a car from a dealer, you got a whole bunch of different configurations depending on what options you selected. The same goes for the spectrum. Depending on what widgets you have connected to it alters in very subtle ways how the memory map works.

Do you have Interface I or II connected? how about the printer? That can change how the map looks.

In general terms, from a high level then sure it all looks kinda the same but its when you get down to levels of greater detail that these differences come into play.

Even assuming you are using Interface I, its not so simple - what device is connected and how many can alter the map.
w00tguy
Drutt
Posts: 4
Joined: Tue Apr 03, 2018 2:57 am

Re: Memory questions

Post by w00tguy »

Let's say I've only got a tape recorder connected. Without a printer I assume that means the printer buffer area is free for me to use. Are the other reserved areas meant for device I/O?
AndyC
Dynamite Dan
Posts: 1388
Joined: Mon Nov 13, 2017 5:12 am

Re: Memory questions

Post by AndyC »

The printer buffer is replaced by additional system variables on 128K machines, so it's best avoided unless you're disabling the system routines entirely. The memory directly after the system variables is the channel information. There is a more comprehensive memory map in Chapter 24 of the Speccy manual (I'd recommend the +2A/+3 version which is similar in detail to the original 48K manual, but highlights the variances on the 128K machines).

http://www.worldofspectrum.org/ZXSpectr ... 8pt24.html
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Memory questions

Post by Ast A. Moore »

What Andy said above, plus the following. The idea of a memory map becomes mostly moot once your code abandons the BASIC interpreter. System variables is the only area of any interest, provided you make extensive use of ROM routines. Note, however, that some system variables will differ on different Spectrum models. There are several, however, that are universal and helpful for, say, creating custom loaders with a small footprint.

Other than that—especially if you’re redirecting the stack pointer and use a custom font—the only aspect of the “memory map” concept that is of any import is the screen file (well, duh) and keeping track of which bank you page in on 128K machines (noting that contention patterns differ between the original 128K/+2 Spectrums and the +2A/+3).
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Ralf
Rick Dangerous
Posts: 2279
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: Memory questions

Post by Ralf »

One comment - all these things like printer buffer, system variables,UGD and so on are important when you work in Basic. It's the Basic interpreter running in ROM which uses parts of memory this way.

If you run your own program In assembler you can ignore it all if you wish and use memory for your own goals. In such case everything above attribute area will be just free memory to use. You need to setup some things first but it it possible.
User avatar
Joefish
Rick Dangerous
Posts: 2042
Joined: Tue Nov 14, 2017 10:26 am

Re: Memory questions

Post by Joefish »

As a footnote to this, there will probably be a little bit of BASIC you load in to load and kick off your machine code routine. While that BASIC is running, it'll need the system variables and some memory to run in. But once it calls your machine code routine, so long as you have no intention of returning to BASIC, you can then use the whole memory for whatever you want. The screen is always drawn from the memory starting at 16384 and you can't change that.

One way to exploit it might be to use it as a buffer or calculation scratchpad. Another method might be to copy some data that you loaded into upper memory to free up some upper memory to use as a buffer. And why would you do that?

Well, there's another issue. The first 16K of memory needs to be read by the ULA to generate the screen (even though the screen only occupies 6.75K); this can slow down access to it (called 'contention') so anything you want to operate at the fastest possible speed (be that program code or graphics buffering) should be placed in the top 32K of memory. It's a bad idea to run game code anywhere below 32768.

So once your game's loaded, you can copy non-critical data down to lower memory, and free up some upper memory for faster graphics buffering, etc.
User avatar
Guesser
Manic Miner
Posts: 639
Joined: Wed Nov 15, 2017 2:35 pm
Contact:

Re: Memory questions

Post by Guesser »

Don't forget that unless you change interrupt mode and provide your own interrupt service routine that will be using the ROM and accessing some of the variables
w00tguy
Drutt
Posts: 4
Joined: Tue Apr 03, 2018 2:57 am

Re: Memory questions

Post by w00tguy »

Lots of useful info, thanks everyone!

I don't want to break compatibility with the 128k so I'll avoid touching the printer buffer.

I don't plan to use BASIC outside of the loader, but I have noticed I need to leave some room after 0x5CCB to allow BASIC to load my code. Good to know that it's free to use it after my program starts.

It looks like the 0xFF58-0xFFFF area is for the GO SUB stack and UDG, so that answers #2.

Knowing that the area after system variables is for channels answers #3 and explains why poking 0x5CBB disables the loading messages (redirects a stream). If the channel info area is exactly 21 bytes long then that also answers #1. However, I don't know how to read this bar from the +3 manual:

Code: Select all

--+-------------+-----+-------+------+-----+-------------------+----+-----+--
  |   Channel   | 80h | BASIC | Vars | 80h | Command or prog.  | NL | 80h |
  | information |     | prog  |      |     | line being edited |    |     |
--+-------------+-----+-------+------+-----+-------------------+----+-----+--
      ^                                                                   ^
      |                                                                   |
    5CB6h                                                             WORKSP
   (23734)
    CHANS
Does this mean the size of "Channel information" is variable? What are the "80h" blocks for? I might use the built-in print function in my code so I think I should avoid overwriting this area.
AndyC
Dynamite Dan
Posts: 1388
Joined: Mon Nov 13, 2017 5:12 am

Re: Memory questions

Post by AndyC »

Yes, the channel area can expand to accommodate additional channel definitions (if you have an interface 1 attached for example). The 80h bytes, I believe, are just end markers so the ROM knows when to stop iterating (without having to do a compare of the address with another system variable)
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Memory questions

Post by Ast A. Moore »

w00tguy wrote: Wed Apr 04, 2018 2:17 am I don't plan to use BASIC outside of the loader, but I have noticed I need to leave some room after 0x5CCB to allow BASIC to load my code. Good to know that it's free to use it after my program starts.
Well, it’s not 0x5CCB per se, but rather whatever’s held in the PROG system variable. The value will change depending on which peripherals are attached to the Spectrum (and initialized), so don’t just assume it’s 23755.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Ralf
Rick Dangerous
Posts: 2279
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: Memory questions

Post by Ralf »

If you don't need ALL existing memory you can safely do for example in standard Spectrum 48kB

Code: Select all

1 CLEAR 24000
2 LOAD "" SCREEN$
3 LOAD "" CODE
4 RANDOMIZE USR 24000
This leaves area above 24000 for machine code. Your tiny Basic loader starts at 23755 and will fit below 24000

And if your machine code program is short just place it above 32768 so it runs in memory not slowed down by ULA.
User avatar
Morkin
Bugaboo
Posts: 3251
Joined: Mon Nov 13, 2017 8:50 am
Location: Bristol, UK

Re: Memory questions

Post by Morkin »

IIRC, for Balachor's Revenge I started the program at 24500 and pointed the stack pointer just below it. The stack isn't particularly big during the game, <100 bytes.

I figured that'd be pretty safe for most models, peripherals etc. as I didn't need to return to BASIC for anything. Though it was more a rough guess than anything else.
My Speccy site: thirdharmoniser.com
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: Memory questions

Post by Einar Saukas »

Ralf wrote: Wed Apr 04, 2018 1:33 pm If you don't need ALL existing memory you can safely do for example in standard Spectrum 48kB

Code: Select all

1 CLEAR 24000
2 LOAD "" SCREEN$
3 LOAD "" CODE
4 RANDOMIZE USR 24000
This leaves area above 24000 for machine code. Your tiny Basic loader starts at 23755 and will fit below 24000

And if your machine code program is short just place it above 32768 so it runs in memory not slowed down by ULA.
It should be CLEAR 23999 :)
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Memory questions

Post by RMartins »

Einar Saukas wrote: Wed Apr 04, 2018 1:52 pm ...
It should be CLEAR 23999 :)
Eagle eyes Einar :D
w00tguy
Drutt
Posts: 4
Joined: Tue Apr 03, 2018 2:57 am

Re: Memory questions

Post by w00tguy »

Alright, I think I've got a handle on the "memory map" now. I do plan to use ALL available memory (and then some) since I'll be trying to write my project in C for the most part.
Ast A. Moore wrote: Wed Apr 04, 2018 9:42 am Well, it’s not 0x5CCB per se, but rather whatever’s held in the PROG system variable.
Perfect, that's just what I need. At the moment this reads 0x5CCB for me, but I should check that var in my loader or program code so I know exactly where to place my code/data or wtv ends up in that area.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Memory questions

Post by Ast A. Moore »

w00tguy wrote: Wed Apr 04, 2018 8:21 pm
Perfect, that's just what I need. At the moment this reads 0x5CCB for me, but I should check that var in my loader or program code so I know exactly where to place my code/data or wtv ends up in that area.
For releases, I personally use a machine-code loader placed inside the BASIC file. To run it, I make use of the PROG variable (but there’s an even better way to do it). As for the value that PROG contains, try this experiment (that is, if your emulator can also emulate the Interface 1):

1. “Attach” the Interface 1 and reset the machine
2. Read the PROG system variable: PRINT PEEK 23635+256*PEEK 23636
3. Do CAT 1 (you’ll get an error, but that’s irrelevant)
4. Now read the PROG sys. variable again. The value will change.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
1024MAK
Bugaboo
Posts: 3104
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Memory questions

Post by 1024MAK »

w00tguy wrote: Wed Apr 04, 2018 2:17 am

Code: Select all

--+-------------+-----+-------+------+-----+-------------------+----+-----+--
  |   Channel   | 80h | BASIC | Vars | 80h | Command or prog.  | NL | 80h |
  | information |     | prog  |      |     | line being edited |    |     |
--+-------------+-----+-------+------+-----+-------------------+----+-----+--
      ^                                                                   ^
      |                                                                   |
    5CB6h                                                             WORKSP
   (23734)
    CHANS
In case you have not worked it out, the names in the table in the Spectrum manual that define the location in memory where the boundaries are, are system variables. So to find the current location of said boundary, read the appropriate system variable.

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
Post Reply