http://beebwiki.mdfs.net/index.php?title=Relocating_variables_on_the_6502_Second_Processor&feed=atom&action=historyRelocating variables on the 6502 Second Processor - Revision history2024-03-28T12:22:04ZRevision history for this page on the wikiMediaWiki 1.30.0-rc.0http://beebwiki.mdfs.net/index.php?title=Relocating_variables_on_the_6502_Second_Processor&diff=2707&oldid=prevJgharston: .2016-01-31T00:09:04Z<p>.</p>
<a href="http://beebwiki.mdfs.net/index.php?title=Relocating_variables_on_the_6502_Second_Processor&diff=2707&oldid=2304">Show changes</a>Jgharstonhttp://beebwiki.mdfs.net/index.php?title=Relocating_variables_on_the_6502_Second_Processor&diff=2304&oldid=prevWikiSysop: 1 revision2015-03-08T18:13:30Z<p>1 revision</p>
<table class="diff diff-contentalign-left" data-mw="interface">
<tr style="vertical-align: top;" lang="en">
<td colspan="1" style="background-color: white; color:black; text-align: center;">← Older revision</td>
<td colspan="1" style="background-color: white; color:black; text-align: center;">Revision as of 18:13, 8 March 2015</td>
</tr><tr><td colspan="2" style="text-align: center;" lang="en"><div class="mw-diff-empty">(No difference)</div>
</td></tr></table>WikiSysophttp://beebwiki.mdfs.net/index.php?title=Relocating_variables_on_the_6502_Second_Processor&diff=1064&oldid=prevWikiSysop: 1 revision2015-03-08T00:13:31Z<p>1 revision</p>
<table class="diff diff-contentalign-left" data-mw="interface">
<tr style="vertical-align: top;" lang="en">
<td colspan="1" style="background-color: white; color:black; text-align: center;">← Older revision</td>
<td colspan="1" style="background-color: white; color:black; text-align: center;">Revision as of 00:13, 8 March 2015</td>
</tr><tr><td colspan="2" style="text-align: center;" lang="en"><div class="mw-diff-empty">(No difference)</div>
</td></tr></table>WikiSysophttp://beebwiki.mdfs.net/index.php?title=Relocating_variables_on_the_6502_Second_Processor&diff=29&oldid=prevWikiSysop: .2015-03-08T00:00:49Z<p>.</p>
<table class="diff diff-contentalign-left" data-mw="interface">
<tr style="vertical-align: top;" lang="en">
<td colspan="1" style="background-color: white; color:black; text-align: center;">← Older revision</td>
<td colspan="1" style="background-color: white; color:black; text-align: center;">Revision as of 00:00, 8 March 2015</td>
</tr><tr><td colspan="2" style="text-align: center;" lang="en"><div class="mw-diff-empty">(No difference)</div>
</td></tr></table>WikiSysophttp://beebwiki.mdfs.net/index.php?title=Relocating_variables_on_the_6502_Second_Processor&diff=2303&oldid=prevWikiSysop: 1 revision2013-08-28T22:58:51Z<p>1 revision</p>
<table class="diff diff-contentalign-left" data-mw="interface">
<tr style="vertical-align: top;" lang="en">
<td colspan="1" style="background-color: white; color:black; text-align: center;">← Older revision</td>
<td colspan="1" style="background-color: white; color:black; text-align: center;">Revision as of 22:58, 28 August 2013</td>
</tr><tr><td colspan="2" style="text-align: center;" lang="en"><div class="mw-diff-empty">(No difference)</div>
</td></tr></table>WikiSysophttp://beebwiki.mdfs.net/index.php?title=Relocating_variables_on_the_6502_Second_Processor&diff=1063&oldid=prevJon Ripley: Fixed some spelling errors - please try to spell check submissions and try not to confuse lose and loose.2007-06-25T04:02:56Z<p>Fixed some spelling errors - please try to spell check submissions and try not to confuse lose and loose.</p>
<p><b>New page</b></p><div>[[Category:BASIC]]<br />
A 6502 second processor gives you an extra 64K of memory, but not all<br />
programs take advantage of this. When BASIC is entered, it is copied over<br />
to the second processor and runs from there. If you have HiBASIC, it is<br />
assembled to run at &B800 giving you memory from &800 to &B800 giving 44k<br />
available. However, this means losing a ROM socket, as you need HiBASIC<br />
to run on the second processor and BASIC (assembled to run at &8000) when<br />
running with the second processor turned off. Most people end up using<br />
having BASIC at &8000 as this runs on both sides. Unfortunately, this<br />
means that the spare memory at &C000 to &F800 in the second processor is<br />
wasted.<br />
<br />
FFFF +-----------+ FFFF +-----------+<br />
| CoPro MOS | | CoPro MOS |<br />
F800 +-----------+ F800 +-----------+<br />
| HiBASIC | | Spare RAM |<br />
B800 +-----------+ HIMEM C000 +-----------+<br />
| | | BASIC |<br />
| | 8000 +-----------+ HIMEM<br />
| | | |<br />
|/\/\/\/\/\/| |/\/\/\/\/\/|<br />
| Variables | | Variables |<br />
+-----------+ LOMEM=TOP +-----------+ LOMEM=TOP<br />
| BASIC | | BASIC |<br />
| program | | program |<br />
0800 +-----------+ PAGE 0800 +-----------+ PAGE<br />
<br />
6502 CoPro running HiBASIC 6502 CoPro running BASIC<br />
<br />
The second processor introductory guide suggests putting LOMEM=&C000 and<br />
storing variables above BASIC. This works perfectly well, but it implies<br />
that your program is always going to be massively larger than the<br />
variables it uses. You have 30K for the program but only 14K for<br />
variables. What would be more useful it to put the BASIC program above<br />
BASIC at &C000 and put the variables in &800-&8000, giving more space for<br />
variables than for the program.<br />
<br />
FFFF +-----------+ FFFF +-----------+<br />
| CoPro MOS | | CoPro MOS |<br />
F800 +-----------+ HIMEM F800 +-----------+<br />
| | | |<br />
| | +-----------+ TOP<br />
|/\/\/\/\/\/| | BASIC |<br />
| Variables | | program |<br />
B800 +-----------+ LOMEM C000 +-----------+ PAGE<br />
| BASIC | | BASIC |<br />
8000 +-----------+ 8000 +-----------+ HIMEM<br />
| | | |<br />
+-----------+ TOP | |<br />
| BASIC | |/\/\/\/\/\/|<br />
| program | | Variables |<br />
0800 +-----------+ PAGE 0800 +-----------+ LOMEM<br />
<br />
Variables in high memory Program in high memory<br />
<br />
Initially, it would seem that you would do this with:<br />
<br />
PAGE=&C000:LOMEM=&800<br />
<br />
Unfortunately, it is not quite that simple. BASIC gets confused if PAGE<br />
is higher than HIMEM, you keep getting 'No room' errors whenever you try<br />
to do something as simple as listing the program. Also, you can't just<br />
stick a PAGE move at the start of a program. The program has to be moved<br />
to the new PAGE position. The easiest way of doing this is to load it<br />
again. This then raises the problem of knowing what the program was saved<br />
as.<br />
<br />
Most programs that reload themselves like this hard-wire the name into the<br />
program giving something like this:<br />
<br />
PAGE=&xxxx:CHAIN "MyName"<br />
<br />
However, this doesn't work if you have called it with something like<br />
<br />
CHAIN "$.Users.Jim.Progs1.MyName"<br />
<br />
Fortunately, there's a way of finding this out. When BASIC does a CHAIN,<br />
it passes a string to OSFILE to load the program. This string is stored<br />
in BASIC's string buffer which is at &0600 in 6502-BASIC, and if you don't<br />
do any string operations that file name will still be there. Caution -<br />
string operations include printing numbers! So, to reload the current<br />
program, we can do something like:<br />
<br />
CHAIN $&600<br />
<br />
as long as we haven't done anything to disturb the string buffer.<br />
<br />
So, bearing this in mind, we can construct a program to hold its variables<br />
below its code.<br />
<br />
To start with, we need to see if we are running 6502-BASIC on a second<br />
processor, and change PAGE, HIMEM and LOMEM to suit and reload if<br />
necessary. HIMEM cannot be changed inside a PROCedure or FuNction as you<br />
lose the return address, so the best thing to do is to return a value to<br />
set HIMEM to at the start of the program:<br />
<br />
HIMEM=FNhimem0<br />
<br />
If the program needs to end with the program still in a condition where it<br />
can be LISTed, or you want to load another program in the same space,<br />
HIMEM needs to be set above PAGE otherwise 'No room' errors will occur:<br />
<br />
DEFPROCend:HIMEM=FNhimem1:END<br />
<br />
and<br />
HIMEM=FNhimem1:CHAIN "Program"<br />
<br />
And finally, you may want to exit or chain a program into the 'normal'<br />
memory arrangement:<br />
<br />
HIMEM=FNhimem2:CHAIN "Program"<br />
<br />
As LOMEM will not be at the end of the program, TOP should not be used to<br />
find out how much memory is available - this is sloppy programming<br />
practice anyway. The following should be used in all cases anyway:<br />
<br />
maxmem%=HIMEM-LOMEM<br />
<br />
Now that the structure of the program has been described, here are the<br />
three support functions. They are in the 'HiBASIC' BASIC Library.<br />
<br />
==FNhimem0==<br />
Called to initialise the memory arrangement and reload the program if<br />
necessary. This function will normally actually be called twice on the<br />
second processor, first with PAGE set to &800 when it reloads the program<br />
to &C000, and then with PAGE set to &C000 when LOMEM and HIMEM are<br />
re-arranged.<br />
<br />
DEFFNhimem0:A%=130:IF((USR&FFF4)AND&FFFF00)=&FFFF00:=HIMEM<br />
REM If not running in i/o, just return current HIMEM<br />
IF?&FFF7<>&6C OR HIMEM=&B800:=HIMEM<br />
REM If not running on a 6502, or we are running HiBASIC,<br />
REM return current HIMEM<br />
IFPAGE=&C000:LOMEM=&800:=&8000<br />
REM If we've just been loaded above BASIC, set LOMEM to<br />
REM bottom of memory and return to set HIMEM to bottom of<br />
REM BASIC ROM code<br />
PAGE=&C000:HIMEM=&F800:CHAIN$&600<br />
REM At this point we must be running in 'normal' memory, so<br />
REM move PAGE up, put HIMEM above it and reCHAIN the name<br />
REM stored in the string buffer<br />
<br />
==FNhimem1==<br />
Called to ensure HIMEM is above the program in memory. This is needed if<br />
you want to END and LIST the program, or load another program over the<br />
current program without overwriting any data in the variable space.<br />
<br />
DEFFNhimem1:IFHIMEM<PAGE:=&F800 ELSE =HIMEM<br />
REM If the program is above the variables, return HIMEM<br />
REM above the program, otherwise return the current HIMEM<br />
<br />
==FNhimem2==<br />
Called whenever you want the memory arrangement returned to 'normal', i.e.<br />
to chain another program at the normal memory position. This program will<br />
be loaded over whatever data is in the variable area.<br />
<br />
DEFFNhimem2:IFHIMEM<PAGE:PAGE=&800:=HIMEM ELSE =HIMEM<br />
REM If the program is above the variables, reset PAGE back<br />
REM to the bottom of memory, otherwise return the current<br />
REM HIMEM<br />
<br />
I have tested these functions on the following BASICs:<br />
<br />
BASIC 1, BASIC 2, BASIC 4 (Master), BASIC 40 (Compact), BASIC(Z80),<br />
BASIC 5 (Archimedes)<br />
<br />
and on the following hardware:<br />
<br />
BBC B i/o, BBC B+6502Tube, BBC B+Z80Tube, Master Compact,<br />
Master 128 i/o, Master 128+6502Tube, !Z80Tube, !65Host, !65Tube,<br />
Archimedes<br />
<br />
<br />
==Demonstration Program==<br />
The accompanying program HiDemo (listed below) shows these functions in<br />
operation. They are also used in real applications in the JGH-PD library<br />
in FileIndexer and FormList (on JGH-012) amongst others.<br />
<br />
REM > HiDemo<br />
REM Demonstrates running above BASIC on 6502Tube<br />
:<br />
HIMEM=FNhimem0<br />
ONERRORIFFNerr:PROCend<br />
PRINT"Program is at &";~PAGE<br />
PRINT"Data space is at &";~LOMEM;" to &";~HIMEM<br />
PRINT"Available memory &";~HIMEM-LOMEM;" (";HIMEM-LOMEM;" bytes)"<br />
REPEATUNTILFNmenu:PROCend:END<br />
:<br />
DEFPROCend:HIMEM=FNhimem1:END<br />
:<br />
DEFFNerr:REPORT:PRINT:=INKEY-1<br />
:<br />
DEFFNhimem0:A%=130:IF((USR&FFF4)AND&FFFF00)=&FFFF00:=HIMEM<br />
IF?&FFF7<>&6C OR HIMEM=&B800:=HIMEM<br />
IFPAGE=&C000:LOMEM=&800:=&8000<br />
PAGE=&C000:HIMEM=&F800:CHAIN$&600<br />
DEFFNhimem1:IFHIMEM<PAGE:=&F800 ELSE =HIMEM<br />
DEFFNhimem2:IFHIMEM<PAGE:PAGE=&800:=HIMEM ELSE =HIMEM<br />
:<br />
DEFFNmenu<br />
PRINT"M: Return to 8BS Menu"<br />
PRINT"H: Chain a program in high memory"<br />
PRINT"L: Chain a program in low memory"<br />
PRINT"Q: Quit"<br />
:<br />
REPEAT<br />
A$=GET$:IFA$="*":REPEATINPUTLINE"*"A$:OSCLIA$:UNTILA$="":PRINT":";:A$="*"<br />
A$=CHR$(ASCA$AND(&DF OR(A$<"`"))):UNTILINSTR("MHLQ",A$):P.A$<br />
:<br />
IFA$="M":HIMEM=FNhimem2:CHAIN"$.!Boot"<br />
IFA$="H":INPUT"File to load to high memory: "F$:HIMEM=FNhimem1:CHAINF$<br />
IFA$="L":INPUT"File to load to low memory: "F$:HIMEM=FNhimem2:CHAINF$<br />
:<br />
=A$="Q"<br />
<br />
This also demonstrates a good way of prompting for and getting a key-press<br />
from a menu while also allowing multiple '*' commands. It can get very<br />
annoying when programs that only allow you to issue one '*' command and<br />
then force you back to the menu before you can do anything else. That<br />
means you can't do something like '*.' to see what's there, then '*Info<br />
xxxx' on something.<br />
<br />
'''By JGH, Nov-1997'''</div>Jon Ripley