WORD STORAGE SPACE SAVER
by SCOTT SHECKA programming technique for storage and retrieval of words and sentences in string data without wasting memory space. This BASIC program runs on all Atari computers of any memory configuration. Antic Disk subscribers RUN"D:SAVER.BAS"
If you're writing an adventure game or any
program that deals mainly with words, phrases, and sentences-you need a
memory efficient way to easily store and retrieve your text data.
Many versions of BASIC have string arrays that allow you to store a group
of text items under one variable name and call up any item by an index
number. For instance, in a text adventure, you might wish to use
a list of weapons, including knife, gun, mace, short sword, and magic sword.
You could create string array WEAPON$, and store each weapon name with
a different subscript (e.g. WEAPON$(3) = "MACE").
Unfortunately, Atari BASIC does not have string arrays.
With Atari BASIC, the usual text storage method is to simulate a string
array with one long string. Since strings can be of any length, you
can store a list whose size is limited only by the machine's memory.
But this standard method does not use memory efficiently.
Here's how an Atari BASIC simulation of a string array
would store five names. We'll call the long string NAME$. Since
a name (first and last) usually contains less than 20 characters, NAME$
should be DIMensioned to at least 100 (20 times 5) characters. But
the string will have to be padded with exactly enough spaces to fill out
the total number of characters that we DIMensioned-otherwise data from
a program that was previously stored in memory could "leak" through.
Then we place the names in the string, starting with the first name at
NAME$(1,1), the second at NAME$(21,21), the third at NAME$(41,41), the
fourth at NAME$(61,61), and the fifth at NAME$(81,81). Now we can
easily find, say, the third element and print it with:
ENDPOS=3*20
? NAME$(ENDPOS-19,ENDPOS)
The major disadvantage of this technique is that if any
of the names are less than 20 characters long, space is wasted. You
could reduce the space for each string item to 15 characters, but then
longer names wouldn't fit. It's difficult to choose the most appropriate
field size for items whose length varies.
Another not-so-efficient method might be to store items
in DATA statements in consistent-sized groups (say, 10 items per statement).
You could then locate items by using the RESTORE statement. The code
and time to access a particular item is longer than in the previous method,
but less space is wasted. Still, some space is wasted because of
commas and the DATA in each line so this isn't the efficient method we
are looking for.
INVERSE VIDEO FLAGS
Here's a better way:
Let's return to the method of using a string to store the list of items.
We can solve the problem of wasted space by storing items one right after
the other without a lot of spaces for padding. We need to mark the
beginning location of each item, so we'll store each first character in
reverse video. This is done simply by adding 128 to its ATASCII value.
For an example, try this:
10 DIM CH$(5)
20 CH$ ="ANTIC":PRINT CH$
30 CH$(1,1)=CHR$(128+ASC(CH$(1)))
40 PRINT CH$
With inverse video flags, we can store a list of text items-each of which can be of any length, and it isn't necessary to fill out the string with spaces first. To locate item number X, search from the beginning of the string for the Xth inverse character. Find the length by searching up to the next inverse character. Since the last item isn't followed by air inverse character, we must place one there. To do this, use something like:
NAME$(LEN(NAME$)+1)=CHR$(128)
We could have avoided having to store the final inverse character by storing the last character of each item as an inverse character instead of the first, but the code to locate and print an item would have been longer. Incidentally, Atari BASIC stores variable names this way,.
SAMPLE STORAGE PROGRAM
Since a BASIC-only linear search of the string would be quite time-consuming,
I've written a machine language routine to do this. Here's how you
would use it to locate and print the tenth item in the string NAME$:
BEGIN=USR(ADR(FIND$),
ADR(NAME$),10)
LENGTH=PEEK(1)
? NAME$(BEGIN,BEGIN+LENGTH-1)
Calling the USR routine gives us two numbers: the starting location
of an item, which is placed in the variable to the left of the equal sign
(BEGIN in the above example); and the item's length, which is placed in
memory location 1.
Listing 1 is a short sample BASIC program. Type
it in and RUN it . You can enter as many items as you like, but the total
sum length should not exceed 999 characters, and each item should be no
longer than 100 characters. You can change this by DIMensioning NAME$
and N$ in the first program line to other sizes. First enter the
number of items in your list, then enter the items one at a time.
After you've entered the last item, the program prints out the entire storage
string, then lets you print out individual items by entering the item's
number. Listing 2, provided for your information, is an assembly
language listing for the machine code used in Listing 1. You don't need
to enter Listing 2 to use Listing 1.
Scott Sheck uses his Atari 400 to keep track of and print weekly statistics for his bowling leagues. He also writes game programs and utilities in BASIC and assembly language.
Listing 1: SAVER.BAS Download
Listing 2: SAVER.SRC Download / View