Sideways RAM Address Database

By Mark Bellis

Originally published in EUG #37

I noted with interest Ron Goad's request for a database for addresses and phone numbers. This database system, which I began last December, can handle international phone numbers - and 522 addresses on a Master 128!

Unfortunately, it's not finished yet. But with me having had very little time in the last two months, I thought I'd submit what's done.

Even using Shadow RAM for the screen on a Master 128 (or BBC B+), you can only usually use about 20K for strings by the time you have a program to manipulate them.

This program uses main RAM, Shadow RAM and all four banks of Sideways RAM, allowing almost 96K for strings. For demo purposes, I've divided the RAM into 522 strings of 188 characters in six banks of 87.

The idea is that each string is a database record and, for sorting purposes, the records could be sorted by a sequence of offets within the string record. My address, including phone number, takes 104 bytes, so perhaps 188 is enough for the longest address.

I don't know how long your Christmas card list is, but I think 522 addresses should be adequate for anyone's address book.

Two functions access the strings:

FNputs(A$,I%)...puts the 188-character string A$ into the string indexed by I%, a number from 0 to 521. To increase the integrity of the systen, the machine code routine saves A$ into pigeon hole I%, but also reads it back, returning it as the result of the function. Therefore to verify a correct string storage:
xyz IF FNputs(A$,I%) <> A$ THEN PROCerror("Bad string push")
would report a storage error.
FNgets(I%)...returns the string in pigeon hole I%, and is called by:
xyz A$ = FNgets(I%)
Two other functions load and save the banks of strings as six files of 16K each. You may choose the filenames - I would suggest "ABBANK0" to "ABBANK5" for an address book.

In order to use sideways RAM, I have not used *SRDATA 4,5,6, and 7, but rather loaded a 16-byte header into each of the 4 banks, so that they look "legal" to the MOS. The headers would still have been there if I'd used *SRDATA, as explained by paragaph 2 on page G7-2 of the Master Reference Manual, so this removed any advantage of using *SRDATA.

Other reasons for not using *SRDATA are as follows:

I considered it easier and quicker to page in RAM banks by changing ?&FE30 (the ROM select register), rather than using *SRREAD and also have used up more RAM with parameter blocks and, as it is, the PUTS and GETS routines use only one page of RAM at &900. Page &A is used as the string buffer.

Also, the memory conveniently divides into six equal banks, with the same amount of memory (&3FF0 or 65472 bytes) used in each. This would have required multiplication of &3FEF in assembler every time a Sideways RAM bank was accessed, in order to move to another absolutely-addressed bank. No multiplication is required if the banks are paged in and out, even though all bank accesses require the multiplication of 188 by (I% MOD 87) to calculate the address within the bank.

For convenience, the banks are loaded and saved as 16K blocks (using &4000, rather than &3FEF as the length), because it is more convenient to keep the ROM header attached to the data, rather than explicitly writing it each time.

HIMEM is set to &3C00, but in theory only two strings, A$ and B$, will be required by a database program, since that is all that is needed for sorting purposes.

Even at 96K, you can still fit six sets of data on a large format ADFS disk. I've decided not to save just the amount of data in memory, because if the data expands, large gaps will be created on the disk when the data is next saved.

Since the system uses absolute pigeon-holes, no string headers are stored, as all the length and address information is inherent to the program.

The maximum length of a conventional string is 238 characters, according to the entry for INPUT on page N5-3 of the Master Reference Manual, so this will fit in page &A quite easily, if the data format were changed to use 238-character strings (408 of them, 68 per bank).

The calculated absolute string address within the bank is stored at &70-71, and these are the only zero-page locations used. I% MOD 87 is stored at &A00-1, and the bank number (top bit set for PUTS, clear for GETS) is stored in &A02. $&A03 is the string buffer, terminated by CHR$13. With a 238 character string, this will leave fourteen free bytes in page &A.

Summary of the files:

?BLANK ... data ... Empty ROM header, with pun title to satisfy Gus' short filename request ;-)
ABOOK1 ... BASIC IV ... Demo of string system.
Loads ?BLANK into each of the four SRAM banks.
Loads ?ABOOK into page &9.
Saves up to five banks of 16K - user-defined filenames.
?ABOOK ... 6502 M/C ... Put, Get and absolute string address calculation.

The sort routine will probably be in a page of machine code, and the printing routine in BASIC - eventually!

Please feel free to suggest additional features...

Mark Bellis, EUG #37