Linking in a low memory data section

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
derekfountain
Member
Posts: 121
Joined: Mon Mar 26, 2018 1:49 pm

Linking in a low memory data section

Post by derekfountain »

I've been writing a Spectrum game and I've got as far as needing to position things in memory a bit more carefully than I have been doing. Up until today everything was default and dumb. My program ORGs at 32768, DATA and BSS go above it, the heap's only used for SP1 and the stack is far enough above to not be a problem. I understand the layout, but haven't worried too much about how it actually happens. :)

However, the program's got bigger and now I need to recover some memory otherwise the stack's going to get clobbered. There's an obvious contender: my level data is in an ASM file and is just a whole bunch of defb statements. It currently goes in the DATA section by the magic of, um, the linker, presumably? So, I thought, I should be able to move that down into the area above the screen (and the BASIC loader) and below the main code at 32768. It's contended memory but that's OK since it's just data used to draw the level.

So right at the top of the levels ASM file I put:

Code: Select all

SECTION LEVEL_DATA
ORG 25000
zcc produces a new file called game_LEVEL_DATA.bin. Looking at it with a hexdump tool shows it contains my level data, byte for byte. Good start.

But then I got confused about how to get this piece of binary data into the final TAP file. I sort of expected to be able to just add the new bin filename plus an org argument to a zcc line and have it magically appear in the right place in the output. But the magic failed me. Or at least I couldn't work out the spell. :)

An awful lot of Googling and trawling later I came to a way of making it work. Start by breaking out the appmake from zcc with this:

Code: Select all

appmake +glue -b game --filler 0 --clean
then:

Code: Select all

appmake +zx -b game__.bin --org 25000 --blockname game -o game.tap
and I get a big TAP file loaded into low memory. The Spectrum emulator's memory browser shows the data loads where I expect it to and the program is at 32768.

Only it doesn't run, because, I deduce, the BASIC loader is assuming the bytes at the --org address are the start of the program, not the start of the data. I can't find a way to force "RANDOMISE USR 32768" into the generated BASIC, so I hack a "jp 32768" in at the top of my data file and presto, it works.

Fine, but this strikes me as all a bit hacky. What's the correct approach? Have I missed a zcc flag or two which will make this easier?
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

There's no way to independently set the org address and load address in the tapmaker.

But tap files are very simple. You can make your own basic loader in an emulator like this one:

Code: Select all

10 CLEAR 24999
20 LOAD ""CODE
30 RANDOMIZE USR 32768
and save it to a tap file with:

SAVE "loader" LINE 1

Next turn your binary(-ies) into individual tap files:

appmake +zx -b game__.bin --org 25000 --blockname game --noloader -o game.tap

and then make the final tap file by concatenating all the individual tap files together:

copy /b loader.tap + game.tap output.tap
cat loader.tap game.tap > output.tap

If you have several disparate binaries, it may be quicker to load them in individually with several LOAD""CODE statements. Or you could build an sna instead which will pack all the pieces into a single snapshot.

Because you're using basic to load the bits in, you won't be able to load below a certain address so that the basic loader can run. An alternative is to load from tape from the c program itself then you don't need to worry about overwriting the basic area.
derekfountain
Member
Posts: 121
Joined: Mon Mar 26, 2018 1:49 pm

Post by derekfountain »

OK, thanks. I just wanted to be sure I wasn't missing anything. I did the custom BASIC loader thing at the end of my BiFrost getting started article - I had to go and read it. :D

Here, I ended up creating a new INITIALISATION_CODE section at 24950 which currently only contains the jump to 32768, but could in theory be expanded if I need it to be. I then +glue the bits together and it all works fine.
Post Reply