This web page contains the text of articles I wrote for Personal Computer News and an Australian review of my book. It is of use to users of the TI-99/4a emulators and of historic interest regarding home computer use in the UK in 1983.
Jump to How programs are stored in memory
Everything from Texas is big except the 99/4A memory. Stephen Shaw shows how to save it
The TI99/4A MEMORY MISER
The Texas Instruments TI99/4A home computer is provided with 16K of RAM with the console. Expansion is quite expensive and it pays to learn memory-saving procedures as soon as possible.
The basic 16K of RAM is not completely available for your programs. The computer uses some of the RAM for the screen display, leaving 14847 bytes for programs. Some of this will be used to store return addresses, variable values and extra character definitions (referred to as value stack, and string space).
When you key a program into your 99/4A, the computer stores each line input in the order you key it in - that is, if you key in line 200 before line 100, line 200 will occupy the first memory area. The computer keeps track of the program lines by means of a line number table.
The line number table uses two bytes to indicate the line number, and two bytes to indicate the memory location of that line- so each line occupies four bytes immediately (and a few bytes more, as will be shown shortly). The line number table is in line number order.
In TI Basic your program is in what is known as VDP RAM and occupies memory addresses 1536 to 16383 (hex 0600 to 37FF). If no disk controller is connected, the first line entered begins at 16383.
In Extended Basic with 32K memory expansion connected, your program is in CPU RAM, addresses -1 to -24576 (hex A000 to FFFF). The stack is separated from your program and occupies the VDP RAM. (The other 8K of the 32K expansion is reserved for machine code programs). The first program line entered starts at location -25.
With Extended Basic and 32K RAM, or with TI Basic and the 4K Mini Memory, you may look at the coding or your program using PEEK and PEEKV respectively. It is also possible to amend a program with LOAD and POKEV. (With Extended Basic Version 110, the first 24 bytes of program space are used by the computer, that is why your program starts at -25, not -1).
Interesting - but what about saving memory? To save memory you need to know how the computer actually uses it. As an example, the TI99/4A is probably the most accurate computer around for mathematical use, partly because of the way it stores numbers. The manual gives information on this.
When you use a variable, a full 8 bytes of memory is used to store the value whatever it is.
MEMORY SAVER 1
Use as few variables as possible -every one used knocks off 8 bytes.
MEMORY SAVER 2
If a number is used frequently, it may be more economic to set a variable and use that instead.
A = 128 as a program line will use 13 bytes for the line plus 8 bytes for the variable value -total 21 bytes.
The number 128 uses 5 bytes every time it is used, the variable A just one byte, so every time you substitute the variable A for the number 128, you save 4 bytes. If the number occurs in your program six times, you save a total of 24 bytes, which you offset against the memory used to set the variable A (21 bytes) for a net saving of 3 bytes.
That isn't much, but some numbers occur many more than six times in a program (eg 1 ,2,28,32 etc). And you do not need to set a variable to zero -just use a Z (not used elsewhere) and the 'overhead' is only 8 bytes, not 21 bytes as previously. Similar principles apply to strings, which are sometimes quite long. I have seen too many programs setting characters to the same definition using the same string again and again, instead of setting a variable and using that.
MEMORY SAVER 3
Keep variable names short
MEMORY SAVER 4
LET is not required with the 99/4A: do not use it, it occupies a byte. GO TO uses 2 bytes but GOTO only one byte - use the single word.
A frequent bug I have found is very heavy on memory: using GOSUB and then not using RETURN. Every GOSUB adds to the stack a return address, which can only be cancelled with a RETURN. Watch out for that.
The 99/4A uses a lot of subprograms, eg CALL SCREEN, CALL COLOR and so on. Although the command CALL uses only 1 byte, the next word uses up as many bytes as it is long plus one (it is treated as an unquoted string, using the same program format as a number). So a lot of subprogram calls can use up memory.
CALL COLOR (1,1,1) CALL COLOR (2,1,1) CALL COLOR (3,1,1) CALL COLOR (4,1,1) or FOR I=1 TO 4 CALL COLOR (1, 1, 1) NEXT IWhich uses the least memory? The second version actually uses 51 bytes less than the first. It may take an odd microsecond longer, but what an easy saving.
If a loop cannot be used, it may sometimes be worthwhile to READ a DATA statement with a loop - for instance:-
FOR I =1 TO 4
CALL SOUND (A, B, C)
The only trouble with this approach is that the 99/4A is incredibly slow at reading DATA.It is often worth using up memory to increase execution speed.
Programmers quite frequently use the CALL KEY command and follow it with many lines of IF ... THEN, branching in various directions if a particular key is pressed.
The 99/4A has a much more compact way of tackling this.
In this example, the program is to branch if keys representing the numbers 1,2,3 or 4 are pressed, otherwise to read the keyboard again.
100 CALL KEY (0, A, B) 110 IF A = 49 THEN 200 120 IF A = 50 THEN 300 130 IF A = 51 THEN 400 140 IF A = 52 THEN 500 ELSE 100Better, especially if more keys could be pressed:-
100 CALL KEY (0, A, B)Some examples much longer than the one shown here (above) have been seen. The POS function returns a value of 0 if the key pressed is not in the quoted string, so we need to add one to go back to the call key routine (+1 at the end - you did notice it?).
110 ON POS("1234",CHR$(A),1)
+1 GOTO 100,200,300,400,500
Very often you need to branch to another part of your program if both of two conditions are met or if either is met - this can be done with a great many IF ... THEN tests, but the programmer does have AND and OR.
In TI Basic it is necessary to use a little logical manipulation, whereby a TRUE statement is evaluated as -1 and a FALSE statement as 0.
Try PRINT 2=2 and PRINT 2=3 to prove that statement.
The line 'IF X=3 THEN 100' is treated by the Computer as 'IF (X=3) THEN 100'.
If (X=3) evaluates as TRUE (-1) the line transfer takes place.
The 99/4A treats any non-zero value as true, so instead of 'IF (A<>0) THEN 100' you could simply use 'IF A THEN 100'.
Remember this - it is useful in Extended Basic when using CALL COINC with sprites, where the return value is - 1 if there is a coincidence and 0 if none.
Where this leads is to:-
To use OR in TI Basic, use the sign + between the tests - which must be in brackets to ensure correct evaluation.
For instance, Extended Basic
IF A=3 or A= 4 THEN 100
becomes in TI Basic
IF (A=3) + (A=4) THEN 100
Similarly. AND can be emulated with a *
In Extended Basic
IF A=3 AND B=4 THEN 100
Becomes in TI Basic
IF (A=3) * (B=4) THEN 100
Using this form can save a great deal of memory when testing several variables/ values.
If you are the lucky owner of an Extended Basic module, ensure you fully utilise the memory-saving devices provided.
Instead of :- CALL CHAR(33, "FFFFFFFFFFFFFFFF") use: CALL CHAR(33,RPT$("F", 16))This uses several bytes less memory.
In Extended Basic several of the CALLS can be used for several items at one time - for example, CALL COLOR (1,1,1,2,1,1,3,1,l,4,1,1) and so on. Read the manual very carefully.
CALL PEEK and CALL LOAD are especially powerful as the memory locations need not be consecutive: CALL PEEK (100,A,B,C,"" 200,D,E,F) will return to A,B,C,D,E,F, the values in memory locations 100,101,102,200,201, 202- Idon't think any other computer can do that in one command.
Shorter hints DIM - If you DIM an array A(3,9,3) how many bytes does that use? In default the lowest value is A(0,0,0) and each numeric variable occupies 8 bytes, so that's 4 x 10 x 4 x 8 bytes = 1280 bytes.
If you are not using the 0 value of the array, you may reset the lowest value to 1 by using OPTION BASE 1.
This really reduces memory usage - with the SAME DIM statement we are now only using 3 x 9 x3 x 8 bytes = 648 bytes (saving: 632 bytes).
If memory is still scarce, look to see if you can use a string array - numbers can still be used, with use of the VAL function as required.
Using option base 1, and single digit numbers, the array A$(3,9,3) uses: 3 x 9 x3 x 2 = 162 bytes (saving 1118 bytes on the original).
GOSUB: If you find lines of coding appearing several times, see if you can put them in once and then use GOSUB.
In Extended Basic you may input a line up to five screen lines long, instead of four in TI Basic. Using editing features you can extend some lines to six or even seven screen lines. Sometimes your entry of four and a half lines will return 'Line Too Long'. The reason is that the internal limit on the length of the line is the number of bytes the line occupies - not the number of characters on the screen.
TI Basic plays safe and gives you only four. Extended Basic allows you another line - perhaps. But by bringing the line back onto the screen and using INSERT you can often make it longer.
Make your lines as long as possible; each line less saves at least 6 bytes.
[2014 note: If the above looks familiar, I have found a very similar article (even with headings eg MEMORY SAVER A, MEMORY SAVER B etc) in TI Lines V1 No 6 dated September 1st 1984 under the pen of David Brown. No acknowledgement to PCN or Stephen Shaw. It is said that "Imitation is the sincerest form of flattery" . The same copy of TI Lines also refers to commercial piracy of Stainless Software computer programs. I don't need all this flattery... send cheques to...].
From the UK magazine Personal Computer News, September 1st to September 7th 1983, page 20:
(refer to wikipedia article on Personal Computer News)
(this issue - pages marked as above, referred to as: Issue 26 - September 1st to 7th, 1983)
See full index to issue and cover jpg at: http://www.bobmockford.co.uk/pcn/026/
Plug in the TI Mini Memory Module and your Basic programming takes off, says Stephen Shaw
TI memory jogger
The TI Mini Memory Module may be used as a file for data or programs; as a means of writing and running machine code programs; or as a means of extending the features of TI Basic. It is this last facility that we are about to look into.
When the Mini Memory Module is inserted into the cartridge slot, what difference does it make to programs in TI Basic?
Seven new commands are added, five of which are relevant to programs in TI Basic:
CALL LOAD, CALL PEEK, CALL POKEV, CALL PEEKV, and CALL CHARPAT. The other two, CALL UNIT and CALL LINK, are concerned only with assembly-language programming.
CHARPAT is used to return to a string variable the current definition of a character. For example:
CALL CHARPAT (65,A$)
will place the string '003844447C444444' into the variable A$.
It is also possible to use the subprogram to return several definitions in one go:
CALL CHARPAT (65,A$, 66, B$, 67, C$, 68, D$, 69, E$) and so on.
By being able to return a character definition in this way, it is possible for a program to return a character on the screen using CALL GCHAR and then, using CALL CHARPAT, to return the definition. The program can then modify the definition.
This can be used in a pseudo high-resolution drawing routine, where characters are continually redefined as the cursor is directed around the screen.
The other four commands are of great interest, as they permit you to look at and amend the contents of the machine's memory.
In TI Basic, the program resides in visual display processor RAM, and the Mini Memory command CALL PEEKV provides the only way to look at this area of memory.
The console has '16K of RAM' but this is not directly accessible to the CPU. The on-board RAM is controlled by the visual display processor (VDP) and the CPU has access to only two bytes at a time.
In issue 8 of PCN I gave a program to investigate the storage of programs in the Expansion Memory. Here is a program to look at programs stored when using Mini Memory.
If you have a disk controller, it should be switched off before you switch the console on, as memory is otherwise used differently.
Key in the program in this order and do not edit it.
100 REM PCN 110 A=B+2 120 C$=D$&"E" 130 FOR I= 16383 TO 16350 STEP -1 140 CALL PEEKV (I, V) 150 PRINT I; V; CHR$(V) 160 NEXT IHere is the result Mem=memory location address.
If you compare the above result with the similar list in PCN issue 8, it is interesting to note that TI Basic has added a space after the REM text of line 100.
Once the means has been provided to look at the program in memory, it is possible to amend the program: a program can, with care, write a completely new program over itself.
Here is an example. Type in the following program in this order:
100 REM PCN 110 CALL POKEV (16379, 77, 65, 71)Before you RUN the program, LIST it
This is a very simple example, but the means has been provided to carry out some very serious programming.
You will note the instruction not to edit these examples: the computer holds the program lines in the order that they are keyed in. Try the above two-line program again, but before you RUN it, edit the first line to read say PCW, and try again.
The computer can find its way about the program lines by means of a line index, which appears below the program in memory. If you are rewriting a program line using POKEV, you must either ensure the new line occupies the SAME number of bytes as the old one, or you face the task of rewriting the line index as well.
Extended Basic uses a different memory map from TI Basic. When TI Basic is selected, some of the memory used by sprites is not in use, and it is possible to POKEV values there to provide limited sprites using TI Basic.
The TI Basic interpreter does not recognise sprites, and in some instances you could cause a system lock-out. If you do, switch off and start again.
The examples given below will work without fuss.
Sprite information is divided into three areas of memory:
How many sprites are moving?
The initial positions of the sprites are kept in an area of memory which is above the TI Basic screen map but below the TI Basic colour tables. There is enough unused memory for three sprites to be defined.
The velocity values are kept in an area used by TI Basic for the value stack, but it is possible to push the stack down by redefining characters, to leave the velocities free from stack interference.
The number of sprites moving is loaded in the small CPU RAM in the CPU.
Here is a simple example, placing one sprite on screen and moving it:
100 CALL CLEAR 200 CALL PEEKV (768,98,128,161,1 208) 300 CALL POKEV (1920,20,20) 400 CALL LOAD (-31878,1) 500 GOTO 500Line 200 defines the initial sprite position, its colour and shape:
Line 300 provides the sprite with a velocity: 1920 is the base address , and each sprite then occupies four bytes. The last two are used by the computer and can be loaded as zeros in the POKEV. The two values are row and column velocities from 0 to 255, which represent - 127 to +128 in Extended Basic.
Line 400 tells the CPU that one sprite should be moved.
For more than one sprite, the equivalent lines would be:
200 CALL POKEV (768,98,128,
If you wish to use moving sprites in a TI Basic program, first define the following characters:
300 CALL POKEV (1930,50,50,0
400 CALL LOAD (-31878,3)
Here are some sample programs to try
100 CALL CLEAR
120 FOR X=0 TO 3
130 CALL POKEV (MEM+X*4,20+
140 NEXT X
150 CALL POKEV (780,208)
160 GOTO 160
100 CALL CLEAR
110 FOR T=1TO 150
120 CALL POKEV (768,30+T,40+
130 NEXT T
100 FOR T=96 TO 159 110 CALL CHAR (T, "0") 120 NEXT TCharacters up to 140 or so can be subsequently redefined without halting your sprites. The other null definitions serve to keep the variable stack from growing so that it overwrites the data, thus halting your sprites or crashing your program.
The screen resides in VDP RAM 0 to 767, but using POKEV is no faster than using CALL HCHAR.
The Colour Table follows the screen, and TI says it starts at 768. In fact it starts at 783, which is why we can use those sprites.
One byte is used to define the foreground and background colour of each character set. VDP RAM location 783 is where the cursor and edge character colours are defined, We can therefore change the cursor colour by POKEVing here.
[[ revised 2014- the magazine rewrote my work and got it horribly wrong - confusing binary and hex and introducing a strange $ symbol! - sjs ]]
Turn each colour value into a 4-bit binary number, after subtracting 1 from the usual value, eg:
BLACK = normal code 2 less 1 = BINARY of 0001
WHITE = normal code 16 less 1 = 15 = BINARY of 1111
To define the cursor as black on white, we place the black binary number before the white binary number:
Now this 8-bit binary number is converted to decimal:
00011111 = digital 31
So: CALL POKEV (783,31) will change the cursor colour.
TI says the Character Tables run from VDP RAM 1024 to 1535. As each character occupies eight bytes, this covers only characters 32 to 96.
What of the rest?
It seems the smaller characters are normally derived from the large ones by the removal of two bytes of information, thus allowing an extra set of characters with no loss of memory.
However, when it is necessary to define the small characters and ASCII codes above them, the definitions are placed above VDP RAM 1536. Then follows value stack, string space, symbol tables, line index and finally your program.
The cursor is also defined in VDP in RAM in eight bytes from 1008, while the edge character (31) is from 1016.
The normal character definition is in 16 hexadecimal characters.
VDP stores the definition in 8 numbers, the digital equivalent of eight binary numbers with one number for each of the 8 rows of 8 pixels.
Each row of pixels for a character is defined in one byte. In an 8-digit binary number, each number has a specific digital value:
Each on pixel in the line is summed with the others, giving a full line total of 255 if all the dots are on.
128 ... 64 ... 32 ... 16 ... 4 ... 2 ... 1
If the left-most pixel only is on, the value placed in VDP RAM is 128, and so on.
Thus a box cursor can be defined as
CALL POKEV (1008,255,129,129,129 129,129,129,255)
To revert to normal cursor and definition use QUIT or switch off. Or redefine!
As you can see, the Mini Memory Module can be used to make your TI Basic programs much more interesting.
Read about addfreestats visitor tracker, the data your browser reveals and how you may control it.
[ TI Book front page | TI Resources Page | TI Articles | PC99 and MESS Programs ]