Since the program was using all the area from $400 to $bfdf, when loading it the page 4 used by Sedoric was overwritten, meaning that you could not save it to disk after that.
Fortunately since the source code was available I was able to find a way to solve the problem. The secret? Use the BSS section!
I guess you already know about the .text and .zero directives when using XA.
.text defines the area where the code goes. So typically in this program the .text section was defined to start at $400
.zero defines the location of variables in zero page. Everything declared after the .zero is going to be allocated from $00 to $ff
There are two other directives that can be used, namely .data and .bss, and most people don't use them because they don't know what they can be used for.
Truth be told, on the Oric you can do without .data. It's used to differentiate the actual code and the data. It does matter on machines where you can relocate the code to load at various location, but on the Oric we don't really need that one.
Now, what about .bss?
Well, BSS means "Block Storage Section". This section is for non initialized data, things like temporary buffers, unpacking areas, save game status, things that contains zeroes at the start of the program.
By definition you can't have instructions, or data defined by .byt or .word in the BSS section. All you can use is the *=value, .dsb, etc...
The trick is that the assembler groups together all the things by sections (all the .zero together, all the .text together, all the .data together, all the .bss sections together) and only saves in the final executable the content of .data and .text.
The content of .zero and .bss is not saved. All it does is to compute the addresses of the various elements defined, and make sure the code works fine when you try to use them.
So how to use that? Guess an example will help.
Let's say you have this program:
Code: Select all
.text
*=$500
Start
; Save the screen content to the buffer
ldx #0
loop
lda $bb80+256*0,x
sta Buffer+256*0,x
lda $bb80+256*1,x
sta Buffer+256*1,x
lda $bb80+256*2,x
sta Buffer+256*2,x
lda $bb80+256*3,x
sta Buffer+256*3,x
dex
bne loop
rts
Buffer
.dsb 1000
Do you really need to save the 1000 bytes full of zeroes in the tape file ???
Not really
So instead you can rewrite this program like this:
Code: Select all
.text
*=$500
Start
; Save the screen content to the buffer
ldx #0
loop
lda $bb80+256*0,x
sta Buffer+256*0,x
lda $bb80+256*1,x
sta Buffer+256*1,x
lda $bb80+256*2,x
sta Buffer+256*2,x
lda $bb80+256*3,x
sta Buffer+256*3,x
dex
bne loop
rts
.bss
*=$1000
Buffer
.dsb 1000
In this particular case the program will work because it does not assume that the buffer contains zeroes. If your program really needs the buffer to be full of zeroes, then you have to add a manual clean-up code for the BSS data.
On machines like the Atari ST, the program header contains information about the sections, this is used to "relocate" the program to whatever address is available (on the Atari ST you can have more than one program in memory at any given time, so you can't use absolute addresses), and the system will know where the BSS section is and how large it is, so it will clear it for you.
On the Oric we do not have such system, so you have to clean the bss yourself, else it will contains whatever was there before the loading, which most probably will be the value $55 all over the place (the famous UUUUUUUUU pattern you can see when things go wrong).
To solve this problem, I generally have in my code a StartBSS label, and a EndBss label, and a "clear BSS" routine that makes sure that everything between the two labels is forced to zero
To go back to the first paragraph, I found out that in the program there was about 10 kilobytes of buffers containing zeroes, so all I did was to create a BSS section (set to the address $400), moved the declarations for the various buffers to the BSS section, then I modified the program so it loads higher in memory, and added some code to clear the BSS area on start-up.
Doing that gave me two benefits:
- The program was reduced from 48k to 40k, which is a real benefit from people still wanting to load it from tape (significantly reduced loading time)
- The program can now be loaded from tape and saved to disk, because until you actually run it the operating system is not trashed (of course you have to disable the auto-run in the header first !)
Hope this was informative