Classic Computer Magazine Archive ANTIC VOL. 3, NO. 8 / DECEMBER 1984

WORD STORAGE SPACE SAVER

by SCOTT SHECK

A 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