zero page addresses help please

bbc micro/electron/atom/risc os coding queries and routines
Post Reply
fuzzel
Posts: 545
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

zero page addresses help please

Post by fuzzel » Tue Mar 17, 2020 9:08 pm

I'd like to use more zero page memory addresses for my assembly language only text adventure game.
Currently I'm using &50 to &9F (no need for econet at the mo) and was wondering which other addresses I could safely use?
My only requirement is I need to save and load games using the standard Acorn DFS. I've used some of the &40 memory locations to store the score and this seems to work without any hitches. Ideally, for the purposes of saving and loading games I'd want to use a continuous area of memory which would minimise the size of the routine for a save game file so &40 and &A0 would be good (but not vital).

User avatar
dv8
Posts: 297
Joined: Mon Jun 22, 2009 10:07 pm
Contact:

Re: zero page addresses help please

Post by dv8 » Tue Mar 17, 2020 10:10 pm

Since your game is in assembly it's effectively taking over from the current language so the workspace from &00 through &8F is available to you. Just make sure you don't RTS out of the game.

Avoid using &90-&9F, you may not be using Econet but someone running your game might be.

If you still need more storage, the transient command workspace at &A8-&AF should be okay as long as you're not issuing * commands from the game.

At a pinch the filing system scratch space at &B0-&BF can be used for temporary storage in between filing system calls. For example if you need a pointer to copy some memory or to traverse a data structure.

Everything else should be avoided.

User avatar
jgharston
Posts: 3934
Joined: Thu Sep 24, 2009 12:22 pm
Location: Whitby/Sheffield
Contact:

Re: zero page addresses help please

Post by jgharston » Tue Mar 17, 2020 11:41 pm

What dv8 said.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.32
(C) Copyright J.G.Harston 1989,2005-2020
>_

julie_m
Posts: 141
Joined: Wed Jul 24, 2019 9:53 pm
Location: Derby, UK
Contact:

Re: zero page addresses help please

Post by julie_m » Wed Mar 18, 2020 12:16 am

Yes, you can use what's normally BASIC workspace, &00-&6F as long as you don't need to drop back and forth in and out of BASIC. (Depending what your code touches, you can corrupt pointers used by BASIC and end up with the dreaded Bad program, or loss or corruption of variables; or BASIC will be able to recover but in doing so mess up one or more of your zero page variables.) Above &90 is used by the Acorn MOS and various filing system and utility ROMs. Some of them can be used for temporary storage but only between system calls, which will change their contents. Best avoided unless you know exactly what you're doing.

In BCP (which has to co-exist with a BASIC wrapper), I'm using zero page addresses &80-&8F for base addresses for instructions such as LDA (zp),Y and &70-&7F for storing values that need the fastest access within heavily-used loops, with another 256-byte page for my main workspace variables; and I have a bunch of general-purpose subroutines for things like mathematical operations, copying, plotting points, printing decimal values to the screen &c. that take in X and possibly Y, the low byte of one or two addresses within the workspace where the values are to be found to do with whatever the subroutine does.

User avatar
EdwardianDuck
Posts: 91
Joined: Thu Aug 10, 2017 9:07 pm
Location: Northamptonshire
Contact:

Re: zero page addresses help please

Post by EdwardianDuck » Wed Mar 18, 2020 8:51 am

My approach during program development (and I admit that I may be over-concerned about returning cleanly to the BASIC prompt given that any program I write will have trampled over any BASIC program loaded), is to make a copy of $00 to $6F during program initialisation and restore it before the final RTS. Assuming you can spare the memory elsewhere.

More experienced developers will be able to comment on the suitability of this approach.

Once development is complete, I review zero page usage and try to trim it down to fit the official space if possible, but if not, and based on a sample size of two programs, the approach does seem to work. For example, in my Skirrid work in progress, the player score isn't updated in a performance critical situation and I can spare the extra bytes for absolute addressing, so it's not stored in zero page.

But based on comments above, simply not returning to BASIC would seem a more sensible strategy.

Just random thoughts...

Jeremy
Master 128 + RetroClinic DataCentre + Internal Pi Zero Coprocessor, MiST
BBC & Atari Software

fuzzel
Posts: 545
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: zero page addresses help please

Post by fuzzel » Wed Mar 18, 2020 9:42 am

Many thanks all for the tips. I've freed up &90-&9F to allow econet users to play the game. I was going to dabble with an econet multi-user version of the game at some point so this was useful advice. I've also noticed that in some subroutines I've saved A,X and Y temporarily in say &CC1, &CC2 and &CC3 and then restored them at the end of the routine (18 bytes). The reason for this is I tried PHA:TXA:PHA:TYA:PHA / PLA:TAY:PLA:TAX:PLA (10 bytes) but this caused the program to crash. Any reason for this (and how many times can this be accommodated by the stack? i.e. what is its capacity?)?

fuzzel
Posts: 545
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: zero page addresses help please

Post by fuzzel » Wed Mar 18, 2020 10:07 am

Further to my message above, I incorporated the following into the start of my subroutine (taken from the Advanced User Guide) which prints the objects in the location:
PHP:PHA:TXA:PHA:TYA:PHA

and then the following at the end of the routine:

PLA:TAY:PLA:TAX:PLA:PLP

and as I mentioned before I get the following error:
Load and Save from Stack Error.jpg
Any idea what the issue might be?

User avatar
dv8
Posts: 297
Joined: Mon Jun 22, 2009 10:07 pm
Contact:

Re: zero page addresses help please

Post by dv8 » Wed Mar 18, 2020 10:30 am

These kind of crashes are usually caused by unbalanced stack operations.

Without seeing the whole subroutine, my best guess is that you are prematurely returning out of it somewhere with an RTS or JMP while the registers are still on the stack. Or perhaps there was a branch to the final RTS that would need to be changed to the start of the PLA:TAY...

User avatar
SimonSideburns
Posts: 535
Joined: Mon Aug 26, 2013 9:09 pm
Location: Purbrook, Hampshire
Contact:

Re: zero page addresses help please

Post by SimonSideburns » Wed Mar 18, 2020 10:30 am

The most obvious thing to check is to make sure you're pulling the correct values back off the stack.

If your routine pulls or pushes anything else during operation and you have a mismatched number of pushes or pulls, the registers will end up not containing their original contents.
Just remember kids, Beeb spelled backwards is Beeb!

fuzzel
Posts: 545
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: zero page addresses help please

Post by fuzzel » Wed Mar 18, 2020 11:00 am

dv8 wrote:
Without seeing the whole subroutine, my best guess is that you are prematurely returning out of it somewhere with an RTS or JMP while the registers are still on the stack.
You're quite right dv8, here was the offending bit of code, the first line jumped to the end when X=255 before restoring A,X,Y from the stack:

CPX#255:BEQ fnwc4
LDA&7000,X:CMP&57:BNE fnwc1
STX&CC5
LDA&BA00,X:STA&30:LDA&BB00,X:STA&31
LDY#0
.fnwc2
LDA(&30),Y:CMP#32:BEQ fnwc3
INY:JMP fnwc2
.fnwc3
STY&CC6
PLA:TAY:PLA:TAX:PLA:PLP
.fnwc4
RTS

Many thanks! I'll be more careful in future!

btw the beeb's use of zero page memory is quite fascinating, I need to learn more...

User avatar
roland
Posts: 3760
Joined: Thu Aug 29, 2013 9:29 pm
Location: Born (NL)
Contact:

Re: zero page addresses help please

Post by roland » Wed Mar 18, 2020 1:20 pm

If you really need more zero pages addresses you can also copy them to another block of memory and copy them back after your routine has finished. I did the same in a program for my Atom that might interact with basic and other stuff. So when I enter my routine I start copying the zero page addresses to another place, do my thing, copy the zeropage back and then back to basic.

Be aware, you just have to exit the routine(s) in the same proper way as if you were saving registers in the stack. If you don't copy back properly you might end up with a corrupted zeropage.

Sometimes I really miss the direct page and 16 bit registers of the 6809 .....
FPGAtom: 512 KB RAM, Real Time Clock and 64 colours
MAN WOMAN :shock:

julie_m
Posts: 141
Joined: Wed Jul 24, 2019 9:53 pm
Location: Derby, UK
Contact:

Re: zero page addresses help please

Post by julie_m » Wed Mar 18, 2020 6:48 pm

If you have messed up the stack, there is still a way back to BASIC as follows:

Code: Select all

.error
BRK
EQUW 60 \ custom ERR value
EQUS "Your problem, meatbag" \ custom error message
BRK \ end of message marker
Unless you messed about with system vectors, BASIC catches BRK instructions and displays an error message. The BRK must be followed by an 8-bit error code (which will be copied to the BASIC pseudo-variable ERR), a text string for the error message to be displayed (REPORT will display it again) and finally another BRK to indicate the end of the message. ERL will be populated with the number of the line that first invoked the machine code with a CALL, USR or *command (well, unless you've overwritten the location where it was stored [-X ).

If you haven't messed with &00-&6F then BASIC should be able to trap these homemade errors just as if they were real ones.

User avatar
BigEd
Posts: 2975
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: zero page addresses help please

Post by BigEd » Wed Mar 18, 2020 7:59 pm

Just to note, Basic itself uses up to &6F, but as the language it owns everything up to &8F - Basic allows the user to use &70 to &8F. So machine code that isn't worried about Basic has all the space up to &8F, I think. (I hope that makes sense, is true, and actually helps...)

User avatar
kieranhj
Posts: 869
Joined: Sat Sep 19, 2015 11:11 pm
Location: Farnham, Surrey, UK
Contact:

Re: zero page addresses help please

Post by kieranhj » Wed Mar 18, 2020 8:31 pm

The other thing to note is that very few vars need to be zero page. Obviously anything that’s using an indirected load/store through a pointer has to be in ZP and anything that’s in tight inner loops, like counters, would be advised. But if you’re only touching the var once per frame, or even less, then you’re not going to notice the extra cycle cost when accessing a different page.
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

julie_m
Posts: 141
Joined: Wed Jul 24, 2019 9:53 pm
Location: Derby, UK
Contact:

Re: zero page addresses help please

Post by julie_m » Wed Mar 18, 2020 10:21 pm

What kieranhj said. Zero page is very nice but not always essential. If we look at the "main" instructions LDA, STA, AND, ORA, EOR, ADC, SBC and CMP, the "short" forms zp and zp,X execute in 3 or 4 clock cycles (2 to read the instruction, one to add X to the address and one to read the operand; the result is available on the "tock" immediately following the last "tick") whereas the "long" forms abs and abs,X (and abs,Y which lacks a corresponding short form) require 4 or 5 cycles (the internal partitioning of the 6502 is such that the addition of the index register to the low byte can be done while the high byte is being fetched, but there is still an extra cycle penalty for crossing a page boundary).

Keep zero page for base addresses for (zp),Y instructions (at least 2 bytes for the pointer to the fixed-length record, and 2 bytes for a pointer to the variable-length portion) and temporary storage of values within loops, when you run out of registers and/or still need the values to be available on the other side of a JSR or RTS.

Post Reply

Return to “programming”