Links to other parts of this web site are at the bottom of the page.

Other TI99/4A sections:
Book- Getting Started   |    Articles   |   Resources Page    |   PC99 Review    |   Programs for the TI99/4A and emulations

Read Vol 1 issue 5

TIHOME Tidings Volume 1
Volume 1 Number 6. December 6, 1981


In this issue: Editorial | Articles by Mike O'Regan,
Pete Brooks   |   Two state toggling   | Segsort (substring sorting)   |    Quicksort  ;
Comments (Rambles) by Stephen Shaw   ||   Letters    ||   Postscript

Editorial

Editorial
First, the bad news! This is the last newsletter you will be getting for free. With the decrease in the price of the 99/ 4 has come an increase in TIHOME membership. From a static 19 members for best part of the first year, the membership has risen to approximately 130 in the last 2 months and is still rising. I have therefore registered TIHOME as a business name at Companies House and opened a bank account in its name and now intend to run it on a businesslike basis, not for the profits it might make, but rather for a better and better service to TI-99/ 4 Users.

I have, with TI's advice, tried to pitch subscriptions at a reasonable level to ensure the continued existence of TIHOME, but not to deter membership. The scale of charges is as follows:

Subscriptions The British Isles gbp 9. 50 per year Rest of the world gbp 12.00 per year

Programs Price per program gbp 1.00 Price per listing gbp 0. 50 Please note that postage and packing is extra on programs. If you only want listings please enclose a S. A. E. in addition to the price of the listings. If you want tapes of programs please don't forget to send your tape. TIHOME is not in the business of giving away free tapes. Also, don't forget to include postage for the return of your tape. You may think I am being a bit severe, but, be assured, it is very necessary considering the price of photocopying, printing and posting the minimum of 6 newsletters a year you will receive. * * *

Now for other things:
If you use the A=A+8 dodge to check the size of a program and also use disks the following procedure will be of use to you.

1. Enter CALL FILES(X)
where X = the number of files you intend to have open at any one time.

Enter NEW

2. Load your program from tape as per usual, or load your program from disk.
3. Enter:
1 A=A+8
2 GOSUB 1

4. Enter RUN The screen will go green and then cyan and display the message MEMORY FULL IN 1.

5. Enter PRINT (N-A)/1024 where N = the memory available depending on the number of files you have specified in your CALL FILES statement. Check the value of N from the following table.

CALL  MEM   MEMORY
FILES AV    USED

1     13736 1056
2     13224 512
3     12704 520
4     12184 520
5     11664 520
6     11152 512
7     10632 520
8     10112 520
9      9592 520

So, if you have 4 files open then enter PRINT(12184-A)/1024. Needless to say, remember to delete lines 1 and 2 before you run your program or you will be in for a very frustrating time. If you have no disks but would still like to know the size of a program, then follow the above procedure and then enter PRINT (14792-A)/1024.

* * *

I understand that some people have had some difficulty reading tapes I have sent them. Needless to say, if you have a tape I have sent you and you cannot read any portion of it, please send it back with a note of explanation and I will re-record the offending programs.
In case it is my equipment that is the problem (!), I am in the process of changing my twin JVC cassette recorders for twin Marantz cassettes. I hope this will clear the problem.

* * *
I have just completed 6 weeks at TI's Education Centre in Bedford learning all about the operating system and languages on their TI 990 series of computers. You may not know, but I am a Data Processing Manager in my spare time, and among the computers in my charge at the company I work for is a TI DS990/ 12 with 512K of memory, 600 Megabytes of disk, a 600 line a minute printer, 2 810 serial printers and 16 VDUs.
Have you stopped drooling yet? Anyway, 2 of the 6 weeks were devoted to learning the TMS9900 Assembly Language. Very interesting and extremely powerful. Admittedly, a very low level language.
Nowhere near as sophisticated as the Singer System 10 Assembly Language. I found I missed the ability to read a maximum of 9999 characters from the screen with one instruction. The TMS9900 reads only 1 character at a time, so you are forever getting involved in indexed loops.
Of course, the 990/12 is a 16-bit slice machine, so how to adapt the Assembly Language to a parallel 8 pretending it is a 16 should be interesting to see. The 990/12 can also be programmed in Basic, Cobol, Pascal, Fortran, etc.
When you have dealt with the Assembly Language you realise how much is being done for you behind a simple statement like

A=(23*Z(Q-R))/(23*Z((Q-R)-1))

Programming that in Assembler would be horrific. Come to that, it would not be so easy in Cobol. Professor Djikstra, who said "it is not possible to make good programmers out of people that have had exposure to Basic; they are mentally crippled beyond regeneration", does not know what he is talking about. You should hear him on Cobol.


For Pete's Sake

First, a couple of points which might be of interest to some of you.
One of the more annoying omissions from the 99/4's version of Basic (like true high resolution plottable graphics) is the lack of provision of a command giving the space occupied, in bytes, by a given program.
Such a command can be invaluable, if only when it comes to transferring a program written for one machine to another; with around 16K to play with, we don't notice it so much, but with smaller capacity machines it can be a bind not knowing whether a published program will fit in your 4K or 8K Mighty Zappo II until you try running it. And if one of us manages to get someone to publish our latest version of Alien Mothers-in-law, the publisher will want something more specific than "Well, I know it runs in 16K" when he asks for size details.

However, there is a way to estimate the size in bytes of your program, although I must emphasise that it is only an approximation, accurate to within a handful of bytes. It could in fact be used as a tool in a statistical determination of the numbers of bytes occupied by given commands, but I'm still working on that one.

The principle of the technique revolves around the fact that the 99/ 4 appears to require 8 bytes (8-bit bytes, that is, bearing in mind that the 99/ 4 is a 16-bit machine pretending to be an 8-bit) to store the return address whenever it encounters a GOSUB instruction.
We are fortunate on the 99/4 that the size of the "stack" for these return addresses is not preset, but is determined by the RAM currently available (or so it would appear from my researches), so that a nested series of GOSUB commands (i. e., a recursive GOSUB where the subroutine contains the command to jump to the same subroutine) coupled to a counter (i. e., a numeric variable incremented each time the subroutine is entered) will "fill up" the available RAM until the "MEMORY FULL IN line number" error message is produced.
At this point the counter contains the value corresponding to the number of times the subroutine was accessed, or, looked at another way, the number of 8-byte blocks which the 99/4 was able to use for stacking return addresses.
If we make the incremental value for the counter 8, that will save us having to multiply things out at the end. Try running this program, starting from either NEW or the title page (the line numbers don't matter so much, as long as the GOSUB address is the same address as the previous incremental statement):

100 A=A+8
110 GOSUB 100

The screen will go green for a few seconds, then blue again as the tone sounds and the "MEMORY FULL IN LINE" error message appears. Now type PRINT A and press ENTER. The magic number 14792 will appear on screen. Those of you who have the July issue of Tidings (Vol. 1, issue 4) will be able to check the "Quotes. from U. S. User-group Newsletters", in which it is stated that:

". . . The 99/4 is not a 16K machine. Basic language resides in 1,208K so we start with 14,792K . . ."

Although it would appear that the U. S. newsletter is referring to decimal fractions of K (using the continental comma in place of the decimal point), it is just too much of a coincidence that the number of bytes obtained by the method given here is identical to the size given by the Americans.
Perhaps they even used a similar approach; however, this means that Basic cannot reside in "1,208K", as 16K is not 16,000 bytes, but 16,384 (16 times 1024).
Obviously the two-line program occupies some of the missing bytes, but it would appear that the item gobbling up our RAM is the "symbol table" or variable list, together with other system variables. If anybody knows otherwise, please write in. There are at least four members who would be very interested to hear more.

Placing the two lines at the beginning of one of your own programs and RUNning until the Memory Full error occurs, then printing not only A but 14792-A will give you the rough size of RAM left, plus the rough size of your program. Don't forget to edit out the two lines when it comes to using your program!

There's nothing to stop you placing the two lines in the middle of your program, where it will be executed while your program is running, and give you some idea of the RAM in use at different points in the program, provided you observe some simple and fairly obvious restrictions; like choosing the variable name in the first of the two lines so that it doesn't conflict with any name used in your program.
And don't edit anything until you have printed out the counter values, otherwise you'll lose them; likewise don't LIST to an external device, like the Thermal Printer, as this also clears all variables.

There's a lot of mileage left in this yet, and I hope to have set some of you off on a trail of discovery which could lead us into the interior of the 99/4. (As I write this, I haven't yet seen the September issue of Tidings, but I understand that member Paul Karis has been uncovering some interesting things with one of the GROMS (more power to his elbow!)

One thing that has come out of this is that it is pointless RESequencing your programs to low line numbers with small increments, as the 99/4 appears to use two 8-bit bytes to store line numbers, with 15 bits for the line number (2 to the power 15 is 32768, and 32767 is as high as we can go) and probably 1 bit to signal that the other fifteen represent a line number. If anybody knows different, let everybody else know: write to us and tell us.

We will eventually elicit much more information (like maybe Basic interaction with GROMs is possible after all) either from TI direct, or by trial and error and not a little detective work on the part of those members who are interested in these things.
If anyone does have some little snippets of information, no matter how trivial you may think they are, please write in to Paul Dicks or even me; which reminds me: I recently moved house at very short notice, and for once the GPO acted intelligently and didn't pour post into an empty house. Instead they returned it to the senders if there was a sender's address, so if anyone did try writing to me (I live in hope) my apologies for not replying to you and please can you try again.
Double apologies to anyone who tried ringing me. The new address is:

68 xyzaurne Road
Cowley
Oxford OX4 9zz

No telephone I'm afraid, unless you're desperate, in which case ring me at work on Oxford 698N1, Ext. 3N5, and if the answering machine is on, please leave a message.

The opening line of this tortuous article mentioned there were a couple of points: here is the second. Page 151 of the manual states that when INPUTting from a file to the 99/4 it is not possible to give user prompts. That isn't strictly true.
As far as producing a user prompt WITHIN the INPUT statement, as in

INPUT "ENTER YOUR DOG'S INSIDE LEG :": D

it IS true; but, as I pointed out none too clearly in the last article, if you preface the INPUT statement with a line containing a pending PRINT statement (i. e., with a trailing semi-colon print separator), then a user prompt IS possible, in fact a more detailed and more flexible user prompt than otherwise possible.
That means that if you haven't got your cassette recorder under software control (i. e., via the remote socket), you can put up your own PRESS PLAY, AND PRESS ENTER message, and use CALL KEY to wait until you press a key, and respond as necessary.

I'm hoping that sufficient information about the workings of the 99/4 as not told by TI will become available that the newsletter might run a separate column for details of the latest discoveries of intrepid explorers; also perhaps a troubleshooting page for members' queries/ problems to be answered/ solved.

And now, the continuing saga of Luigi Space-Invader, and his sideways motions. No comments, please.
In the last article I rather grandly stated that I would be revealing all about the production of sideways motion of shapes within characters, and that much I hope to do.
However, I also intended to provide working examples of what can be done; I reckoned without my Skantic monitor, which chose that moment to die on me, and had to be sent off for a little surgery.

The result is that I haven't had time to check the routines I was going to give for sideways motion: I have though managed to include one program which shows vertical motion of a shape down through several characters - the shape moves, the characters don't, but hopefully you will understand the explanation of the principles behind the technique sufficiently well to make example programs unnecessary (Ho, ho, ho!).

The kind of hexstring/ binary manipulations required to produce sideways movement of a shape (NOT a character) are more complex and time-consuming than for simple vertical movement, so real-time manipulation and re-drawing are out of the question, at least until we are given access to the apparently marvellous graphics handling which the 99/4 already possesses, but which have been placed off-limits for some reason, so what follows is an example of what could be possible, given the right tool - i. e., increased execution speed - and can be used to give the necessary hexstrings for subsequent use as DATA statements in your own programs.

Whereas modifying a definition hexstring to produce movement up or down of a shape (within the "window" afforded by a screen character) consisted simply of either tacking leading/ trailing zeroes onto the hexstring and lopping off the relevant trailing/ leading hexpair - for a 1-off movement - or cycling hexpairs around a long definition string, for repeated movement, things are not quite so easy in practice for sideways movement.

The principle is probably easier to visualise in the above diagram. If we take as our first example the short-lived motion of a shape from full-blown existence to oblivion, the shuffle sideways affects the character matrix as shown, by removing the column of binary characters on the left, and replacing it with a column of binary zeroes on the right.
The new shape then needs to be translated into hex, and the relevant character redefined. (Movement to the right is achieved by reversing the procedure; remove the right hand column, and add a left column of zeroes).

In mathematical terms, the effect is one of multiplying (or dividing) by two, and ignoring the extreme left or right carry.
It is complicated by the fact that the block corresponding to the right-most character in a hexpair may produce a carry which then has to be incorporated into the character corresponding to the left-most character in a hexpair. This is carried out 8 times until the shape has shuffled off. In fact, DOING it in terms of hex is almost as obscure as it is to explain.
We could, however, keep our definition strings not as 16 (or more) character hexadecimals, but as their binary equivalents, and store them in a string array in such a way that each 8 digit binary string (equivalent to a 2-digit hex string) is stored in a separate element.

This may not seem overly intelligent at first, but when it comes to cycling a multi-digit binary string to give a large range of characters the dreaded sideways movement, doing it this way is many times faster than doing it in hex, simply because SEG$ can be used to cycle 1 digit (or more) around for each element of the array, and then only the first 8 digits are required to produce a hexpair, one for each of eight elements, to produce the final 16-character definition hexstring. Up to a point, once you have the required definition hexstrings, you can compress the information into 16 digit hexstrings and place them in DATA statements in the relevant program.

Vertical motion can be produced by cycling the elements of the array around, and diagonal motion by combining both vertical and sideways operators on a large array of binary digits, where only the first eight digits of the first eight elements are actually translated into hex.

So far the shape manipulation has been limited to movement within a single screen character; if we placed different screen characters in the relevant positions, we could translate more 8 by 8 blocks from our array, and distribute the resulting definition strings among the different characters, although at this level the speed of redefinition is very much slower, and begins to look more like the leisurely screen update seen on sweep-scan radar screens.
This format however opens up the possibility of having your screen shapes change colour a bit at a time as they are transferred from say the character in one set to the character in another, where the two sets are assigned different colours using the CALL COLOR command. With a black background this can enhance the color change, as the shape appears to "immerse" itself in another color as it moves. The vertical movement example program given overleaf makes use of this effect.

100 CALL CLEAR
110 B$="0000000000000000"
120 FOR I=1 TO 4
130 B$= B$& B$
140 NEXT I
150 INPUT A$
160 INPUT C$
170 A$=SEG$(A$&C$&B$,1,128)
180 CALL SCREEN(2)
190 CALL CLEAR
200 FOR I=1 TO 8
210 CALL COLOR(I+8,I+2,2)
220 FOR J=1 TO 31 STEP 2
230 CALL HCHAR(I+14,J,88+I*8)
240 NEXT J
250 NEXT I
260 FOR I=1 TO 113 STEP 16
270 CALL CHAR(96+INT(I/2),SE
G$(A$,I,16))
280 NEXT I
290 A$=SEG$(A$,127,2)&SEG$(A
$,1,126)
300 GOTO 260

The program permits entry of hexstrings via two "user-promptless" INPUT statements, so that the maximum of 128 hex characters can be used.
The maximum is dictated by the number of characters on screen (here there are 8 screen characters, repeated 16 times across the screen), but although the program is primitive and slow, it should demonstrate what can be done with a lot of time and masses of patience.
In order to try and elicit some kind of response I am not going to explain how the program works; if you really want to know how, you'll have to write in and ask (there's cunning!); if more than say one of you responds, I'll give an explanation in a future article. By way of introduction, use the following hexstring in the program:

"7EDBFF66DB818142000000007ED
BFF66DB81814200FF0C"

and just press ENTER when the second INPUT prompt appears.
To stop the cycle you'll need to BREAK with SHIFT C. Try your own shapes and see what happens.

Finally, a little curiosity for the owners of the TI Thermal Printer. Starting from the title page with TP plugged in and switched on (it goes without saying), OLD one of your own programs (using the OLDing monitor if necessary), and add this short program (assuming there are no variable name conflicts with your own program).

nnnn CALL CLEAR
nnnn FOR I=96 TO 104
nann PRINT :CHR$(I); I
nnnn NEXT I
nnnn END

Run this independently of your own program (i. e., RUN nnnn). Immediately list to your TP (LIST "TP. U. S. E") and watch what happens to characters 98, and 100 to 103. As the characters change, observe what is being printed on the TP (without wasting too much precious paper). You may be able to see patterns emerging. If you have some graph paper, or you don't mind drawing out lots of little 8 by 8 grids, you can "draw" the statements which are being passed to your TP by translating the ASCII code for each character into binary and combining those in groups of 8 to make up the same matrix as is used by the 99/4 character set.

The word "RETURN" for example appears to look like "ic" on screen in character 100. So far I haven't been able to discover such a simple relationship between statement contents and screen character shape for either the OLDing monitor or for programs under execution (that's something else you can try: a FOR NEXT loop has a characteristic shape on screen while it is being executed), but I'm hoping that some of you may be galvanised into action, and will soon "tell all" to the rest of us.

If you would consider sending the results of your researches to me, I will collate the information and present it from time to time in the newsletter, together with an acknowledgment of your contribution (there's nothing worse than sending in information only to have it presented as the fruits of someone else's labours), and who knows, you may go down in history as the person who made the 99/4 a "cult" machine (and if you believe that, you're as gullible as I am!).

As a matter of fact, going back to the program for finding "bytes free", you can "see" the subroutine return addresses if you print the user-defined characters by using the OLDing monitor, before you run the two line program (i. e., append it to the OLDing monitor), but don't blink: those addresses are stored pretty fast you can even try adding more subroutine jumps, and watching what shape they take: there is a marked difference in shape for a jump to a subroutine which lies AFTER the current line number, compared with a subroutine which lies BEFORE it.

Enjoy your programming, and don't forget to write.
Pete Brooks

99/4 Routines
Toggling: Two-state
Functions: various
Occasionally it is necessary to use a "toggle" function in programs. Where this toggle has only two states (i. e., ON or its equivalent, and OFF of its equivalent), whether it be as a string or numeric variable, a single statement line suffices, provided that during initialisation (or at least prior to its use if a string) it has been set to one value or the other.

For example, if we wish to toggle the numeric variable A from 0 to 1, we do not have to initialise it (on the 99/4, anyway); the statement line reads:

nnnn A=1-A

It can be seen that if A was 0, after the assignment it becomes 1, and if it was 1, after assignment it becomes 0.

Strings are similarly operated upon, except that string and numeric operators are included: nnnn A$=STR$(1-VAL(A$))

Again, it can be seen that if A$ was "0", VAL(A$) is 0, 1-0=1, and STR$(1)="1". Note though that unless A$ is first set to either "1" or "0" before executing the statement, an error will result, as the 99/4 sets all unassigned strings to NULL, and VAL(NULL) gives an error. Multi-state toggling may require either conditional branching, or modulus equations (q. v.).

The above example shows toggling between two values, 1 and 0, but to toggle between any two values (including alpha-characters) requires a general equation of the form:

Value=(Value1+Value2)-Current value

E. g.: toggling between 65 and 90 is accomplished by: nnnn A=155 (i. e., 65+90)-A

and a similar statement may be derived for string variables. For example, to toggle between "Y" and "N", knowing (or even not knowing) the ASCII character codes: i) knowing the codes are 78 for N and 89 for Y: nnnn A$=CHR$(167-ASC(A$))

ii) not knowing the codes: nnnn A$=CHR$((ASC("Y")+ASC("N"))-ASC(A$))

I have used the toggle function in a graphics program which operated upon the binary representation of a character; toggling between "1" and "0" enabled the program to insert/ delete binary values into/ from definition groups, thus permitting screen drawing/ erasing from one set of subroutines and one toggling routine.
The usual method of controlling bouncing balls (er . . . you know what I mean) or other graphic characters which move around the screen, is to use conditional jumps (IF . . . THEN. . . ELSE) to prevent a crash resulting from an attempt to CALL HCHAR or VCHAR at a location outside the valid screen locations.
The program in the handbook for a bouncing ball does this, but it means checking for a given value against the limit of travel; it uses up program space (each check usually requires 1 program statement, and usually there are at least 4 checks), and it's a drag to key in, and it's often difficult to get right.

What would be nice is a simple "Modulus"-type statement which automatically places the cursor location at the correct point once the limits have been reached; in other words, if the ball is about to go off-screen at line 24, it reappears at line 1, on a column commensurate with its direction of travel.

For example, a character travelling on a diagonal in the direction North East (towards the top right hand corner of the screen) reaches Row 1, Column 26; it needs to continue from Row 24, Column 27 if the direction of travel is to be maintained. Likewise, if it's at Row 1, Column 1, travelling North West (up into the left-hand corner of the screen), it needs to continue from Row 24, Column 32, etc., etc. Confused? I haven't started yet!

There are two simple equations which fulfil both requirements: that is, controlling the travel from position 1 to the end of the row/ column, and the travel from the end to the start of the row/ column.

All you need are three bits of information: the lowest value of the coordinates, the highest, and the "incremental value" � in other words, the size of the jump from one position to the next.

Still confused?
Suppose we intend using the whole screen to bounce our balls around. The lowest value for the Rows will be 1, the highest 24, and the incremental value (how many squares it is going to jump each time) is say 1.
At present, the equations won't actually give you a bounce, they'll work the same way the Videographics module does; by continuing off at one point, and back on at another (I'm not explaining this very well), but before long I'll have worked out how to make things bounce.

Anyway, the information we have so far is for the Rows. Now for the columns. A lowest value will be 1, highest 32, and increment, again, 1.

The program statement looks like this:
For moving from a low value to a high one "INC": nnnn V=ABS(V < MAX)*V+S

where V , is the current value of the row or column, max is the highest value, and S is the incremental value.

For moving from a high value to a low value "DEC": nnnn V=MAX*ABS(V=LOW)+V-S

where V is current value of the row or column, max is the highest value, low is the lowest value, and S is the decremental value.

A restriction on this system is that the low and max values must be integer multiples of the incremental/ decremental values.
All that means is that if low =1, and max =14, then the increment/ decrement must be either 1, 2, or 7. It should become clearer, shortly.

Now does it work? Well, it uses the fact that the 99/4, like many other computers, is capable of producing a numerical value for the conditions TRUE and FALSE. The 99/4 evaluates an expression within brackets usually, involving the relational operators (=, <, >,<>, etc), and returns -1 if the expression is TRUE, and 0 if the expression is FALSE. If you haven't noticed this before, see pages 42 and 79 of the handbook (on Relational Expressions, and IF. . .THEN. . .ELSE).

The ABS() function produces the Absolute Value of whatever is in the brackets, which is defined mathematically as where, whether X is positive or negative, is always positive, so that root gives a positive value for X. In other words, ABS(-23) gives 23, ABS(-17.24) gives 17.24, and ABS(3) gives 3. Used with a relational expression in the brackets, ABS converts the resulting -1 or 0 into 1 or 0.

In the INC equation therefore, (V< max) will return -1 if the current value IS less than the highest, and 0 if the value is equal to, or greater than, the highest. The ABS() function turns those values into 1 and 0, and then is multiplied by the current value, and added to the increment.
Using our values for the Rows of low=1, max=24, S=1, the statement is: nnnn ROW =ABS(ROW < 24) * ROW +1

Let's put in a few values for ROW to see what happens to them. If ROW is currently 4, then ABS(ROW<24) will be 1, 1 times 4 (current ROW) is 4, plus 1 is 5, and that is assigned to ROW to make the new value 5. Ah, but what happens if ROW is 24, I hear you ask (go on, ask, it proves you understand what I'm saying).
Well, ABS(ROW < 24) gives 0 this time (because ROW is NOT less than 24), and 0 times 24(current value of ROW) is 0, plus 1 is 1, so the new value of ROW is 1. ROW has gone from 24 to 1 without missing a beat. (You don't have to use ROW, use R or something short).

I'm probably making more of a meal of this than is necessary, but it's the way I've been trained to explain things; leave nothing to chance, take nothing for granted, and leave the reader to pore over the text to extract all the information � which IS in there, I assure you!

Now let's try the DEC equation to see how that works. We'll use the same values for ROWS as we did before; LOW=1, MAX=24, S=1.

The statement looks like this: nann ROW=24*ABS(ROW=1)+ROW-1

Let's stick in some values as before. If ROW is 24, ABS(ROW=1) will be 0 (because ROW is NOT 1), 0 times 24 will also be 0, plus 24 (current value of ROW) =24, minus 1 is 23.
All right, how about ROW is 1? Well, ABS(ROW=1) will be 1 (because ROW IS 1), 1 times 24 is 24, plus 1 (current value of ROW) is 25, minus 1 is 24. So ROW has gone from 1 to 24 also without missing a beat.

So where is all this leading? Well, if you use the INC and DEC statements as perhaps subroutines in your program, you have control aver the position of graphics on the screen without bothering about IF . . . THEN . . . ELSE lines.
If you want the character to go up the screen by one position, place a call to the DEC routine (going up the screen involves decreasing the row number), and whether the character is in the middle, bottom edge or top edge of the screen, the DEC routine will cover everything.

This means of course that you will need a DEC and INC routine for both rows and columns, a total of 4 lines; using IF statements, you'd need around 4 per routine, so it saves a bit of trouble.
You don't really need to know how the routines operate in order to use them, but as long as you observe the restrictions it should be trouble-free. By the way, one restriction I almost forgot: the starting values for your variables (ROW or whatever) must be exact multiples of the incremental value; in other words, if low is 6, max is 24, and S is 2 (it could also be 3, 4, 6,or 12), the initial value of your variable must be 6, or 8, or 10, . . . or 22 or 24, otherwise funny things may happen.

If you can't make head nor tail of this, and you would like to,(go on, say yes), give me a buzz on't phone; I'm in most evenings during the week, but at the weekends I usually spread sweetness and light by travelling huge distances to play with someone else's computer. That ZX81 I mentioned earlier is a mere 21 miles away, closer than the 30 mile ZX80!

99/4 Routines
Segsort
Functions: substring sorting
Variable list
String arrays: W$()
Strings: none
Numeric arrays: none
Numerics: A, B, C, F

Listing
1 FOR A=1 TO maximum element number
2 C=LEN(W$(A))
3 F=0
4 FOR B=C TO 2 STEP -1
5 IF SEG$(W$(A),B,1)>=SEG$(W$(A),B-1,1) THEN 8
6 W(A)=SEG$(W$(A),1,B-2)&SEG$(W$(A),B,1) & SEG$(W$(A),B-1,1)
& SEG$(W$(A),B +1,C-(B+1))

(this is only true for strict accuracy -- otherwise just use C-B) 7 F=1
8 NEXT B
9 IF F=1 THEN 3
10 NEXT A
11 rest of routine

Protocol The sort can cope with variable length strings without difficulty; however, if the strings to be sorted are all of equal known length, then delete line 2, and replace C in lines 4 and 6 by the length of the string.

The A loop will give all the strings in the array W$(), while the B loop will sort them character by character. This routine could be altered to perform a field sort, and would be capable of similar execution times if the fields were of equal known length, but if time was not an important factor, fields of varying length could also be sorted.

Line 6 is complex, but necessarily so, as the manipulations of the particular substrings must be completed in one statement, unless additional string variables are used to temporarily store intermediate strings for concatenation, but this will unnecessarily extend the processing time.

Whenever two characters (substrings) are to be swapped, the string is divided into 4 sections; the first section covers the beginning of the string up to the character immediately before the first character to be swapped; the second section is the second character to be swapped; the third section is the first character to be swapped; and the fourth is the section of string continuing immediately after the second character, to the end of the string.

For example, in the string "FUN AND GAMES", beginning from the right-hand end, E is less than S (with regard to character codes) so no swap occurs; but M is not less than E, so the swap routine is called.

The first section of the string is "FUN AND GA" (i. e.. up to the first character to be swapped - first in the string, that is), the second section is the E, the third section is the M (thus swapping M and E around in the string), and the fourth section is in fact just S.

This gives us, after concatenation, "FUN AND GAMES"; to continue, A is less than E, so no swap, but G is not less than A, so a swap occurs again. Each time the swap routine is accessed, the flag "F" is set (i. e., becomes 1 instead of 0), but the test for being set is not made until one complete "pass" has been made along the length of the string, during which the flag may be set several times - it doesn't matter how many times it is set.

After one pass, the string might look like: " FUN AND GAMES" - with a leading space, because the first space (which has a code of 32, and is therefore "lower" than any of the letters here) has been bubbled to the first position on the first pass. Now the test is made to see if the flag, F, is set, and it is, so the routine goes back, resets the flag to zero, and makes a second pass. It goes on like this until the test for a set flag gives zero or false as its result, in which case the routine has been all the way along the string without swapping anything, which means that the string is sorted.

The only drawback to this system is that if the last swap to be made places the string in a fully-sorted condition, because the swap flag has been set, a second pass will be made along the already-sorted string; however, this is preferable to some bubble sorts where passes are made (where N is the length of the string), and no flags are used; these systems require passes even if the string is already sorted in the beginning!

99/4 Routines
Quicksort
Functions: sorting, tagsorting
Modified from PCW Numeric Quicksort
Requirements
During initialisation, the upper and lower limits of the sort need to be set; as standard I use the cursor (chr 30) and the underline (chr 95), neither of which is available from the keyboard. Note: If sorting user-programmable characters, be warned that the relational operators return incorrect values on tests on characters with codes greater than 127.

As the sort stands, it is sufficient for sorting 1024 elements; the capacity is determined by the size (in elements) of array "S"; antilog(base 2) of the maximum element number gives the capacity: in this case, the "S" array defaults to 10, and 2 to the power 10 is 1024.
If any increase in capacity is desired, "3" will need to be explicitly dimensioned. Values in the listing which require user-defined limits will be typed in red, lower case letters.

If using the sort as a subroutine, avoid the use of any of the variable names (listed over) which occur in the subroutine, in order to prevent corruption of values in the main routine.

Note that although the arrays are defaulted to OPTION BASE 0, "S(0)" is not utilised. Below a threshold value of items to be sorted, a straight insertion sort is used, as it is faster for small numbers of items; that threshold value (set to 10 in line 6 for a conditional jump) may be altered to achieve the optimum sorting time for a given machine.

The speed of sorting is only marginally affected by the number of characters in a given string, and it is much faster than a bubble sort: 10 secs. for 50 items, 20 for 100 items, 360 for 1000 items. The speed of sorting will also be determined by the proximity of the unsorted state to the sorted state; in other words, how "organised" the items already are.

It is advisable to enter the routine first (i. e. from tape or disk) using the numbering of lines given here, and RESEQUENCE to a suitably high initial line number, and then to enter the main program with calling routines to the Quicksort subroutine, or to embed the sort within the main program. Alternatively, the routine may be inserted within a given RESEQUENCED program by adding the initial line number to the line numbers given here, for jump destinations, etc.

Note that the sort sequence priority is determined by the character codes; thus strings beginning with a leading space, punctuation mark, number, or relational operator symbol, will be given a higher placing than alpha characters.

Variable list
String arrays: W$()
Strings: I$
Numeric arrays: S()
Numerics: A, B, C, D, P

The execution times for large numbers of items are likely to represent an improvement in sorting time by a factor of about 20 or more.
(A slightly slower initial version compared with a bubble sort gave a sort time of 59 seconds for 125 items of between 4 and 12 characters each (used as a Tag sort) compared with over 16 minutes for sorting the same information using a standard bubble sort).

String Quicksort - Listing
1 P=1
2 W$(0)=set lowest character: either CHR$ or " " format
3 W$(1+maximum number of items) =set highest character
4 A=1
5 B=maximum number of items
6 IF B=A < 10 THEN 38
7 C=A
8 D=B
9 I$=W$(A)
10 IF I$ >=W$(D) THEN 13
11 D=D-1
12 GOTO 10
13 IF D > C THEN 16
14 W$(C)=I$
15 GOTO 25
16 REM LINE NOT PRINTED IN ORIGINAL
17 C=C+1
18 IF W$(C) < I$ THEN 17
19 IF D > C THEN 23
20 W$(D)=I$
21 C=D
22 GOTO 25
23 W$(D)=W$(C)
24 GOTO 11
25 IF B -C < C -A THEN 32
26 S(P)=B
27 P=P+1
28 S(P)=C +1
29 P=P+1
30 B=C-1
31 GOTO 6
32 S(P)=C-1
33 P=P+1
34 S(P)=A
35 P=P+1
36 A=C+1
37 GOTO 6
38 D=A
39 D=D+1
40 IF D > B THEN 49
41 I$=W$(D)
42 C=D-1
43 IF W$(C) <=I$ THEN 47
44 W$(C+1)=W$(C)
45 C=C-1
46 GOTO 43
47 W$(C+1)=I$
48 GOTO 39
49 IF P=1 THEN 55
50 P=P-1
51 A=S(P)
52 P=P-1
53 B=S(P)
54 GOTO 6
55 end of routine

For Pete's Sake Postscript This article was written and submitted before the revelations by Paul Karis were published. I think you will agree that he is definitely a contender for the position of the person who can make the 99/4 a cult machine. I have no doubt that by the time you read this, further things will be in the pipeline.

With regard to the subprograms uncovered by Paul, the "E" which had him confused is the exponent: as in 1.25E6 (equivalent to 1.25 times 10 to the 6th power or 1,250,000). In addition, there are a few other subprograms whose titles are single characters: CALL G: H: P: and S.
The G and H subprograms require parameters of the form: (numeric, numeric, numeric, numeric), but they produce the error message NOT ENOUGH MEMORY.
Perhaps they require the 32K RAM add-on to function. The P subprogram is an odd one; its parameters are (numeric) , but if used in immediate mode while a program is resident, an undefined error message ILLEGAL CALL is produced, but if used in immediate mode after NEW or from the title page, is accepted, although I have been unable to discover its purpose or function.
The S subprogram is likewise an odd one. Its parameters are (string, numeric), but for anything other than a null string produces the error message NUMBER T00 BIG, while a null string causes the whole system to hang up.

The BREAK key can still be made to perform by holding it down and pressing certain other keys; for example, ENTER.

Finally, thank you Mike O'Regan for referring to me as an expert (I am far from that, and that's not being modest) and the full character range (0 to 255) was to have been the subject of a future article; however, to prevent the wheel from being re-invented, this is what I have found to date:
character 27: appears to be a form of counter for PRINT instructions.
29: is involved in either Symbol Table generation, or RUN time error checking.
29: signals a Breakpoint.
30: is the cursor (as most of you no doubt found out from the manual).
160 onwards: 160 to 167 are rather odd in that they can be seen to retain their pink color regardless of the screen color; they have a life of their own, but when using the additional facilities; uncovered by Paul Karis, they are altered by the position of the cursor during CALL A.
Peter Brooks



Mike O'Regan

Random Dots by Mike O'Regan
Teepeewotsit
Progress marches on - WORD processing is dead, long live TEXT processing. I have (almost completely) re-written my previous prog. to include such goodies as: Full screen editing, including LOWER CASE . . . instruction set . . . menu selection, using CALL KEY extensively . . . TWO type-faces to pick from for final print . . . deletions of shift and tab characters from char-per-line count new lower case set has true descenders! . . . audio beeps at interaction points . . . screen line count when writing text . . . audio indication of page-full (A4 column)

This new, all-singing-all-dancing program is now available from the Library, (and incidentally was used to produce these pages).

Programming Tips
1. Use REMs generously to explain how things work, for others and for yourself, if you decide to update later.

2. Establish your authorship and date WITHIN the program, either with REMs or on the title page.
3 Never use INPUT when CALL KEY will do.
4 A short way of including pauses is to tag this bit on the end of your program! 10000 CALL SOUND(N0000,10000,30)
10010 RETURN

where "N" is the number of seconds pause you require (1 to 4). Repeat GOSUB 10000 for longer pauses.

5. Try a program RUN, including all options BEFORE submitting to the Library.
6. If possible, for all but the simplest routines, include instructions in English!
7. FINALLY, if you are submitting your program to the Library, then RES 110 to enable the Librarian to label your program on line 100 for uniformity), then send a brief WRITTEN description of the program with the tape, including any essential peripherals (e. g. Speech, Printer).

Joystick Surgery
I mentioned earlier in these pages that I didn't think much of the TI Joysticks. My first set was replaced after I broke a shaft. I was told by TI that the joysticks had been modified, by my replacement was identical to the first set.
The trouble is that the spring against which the joystick has to operate is too strong in proportion to the length and strength of the shaft. If you run Five-A-Side Soccer, the quite vigorous use of the joysticks is to be expected and standard shafts wouldn't have much of a chance. To avoid disaster again, I have cut off the shafts to about an inch, drilled out the knobs and re-fixed them with Araldite.

So far (touch wood!) this seems to have done the trick. I also noticed that the left-hand joystick, being the "solo" one, gets much more hammer than the right, so I change them over occasionally.

Program Editing If you're like my you are an incorrigible program improver. In other words, accepting the idea that no program exists which is incapable of improvement, you cannot resist the temptation to add that "little something extra", not only to your own babies, but to other folks' as well!
Mind you, I'm careful to retain the original on tape, in case my "improvements" are nothing of the sort. Taken to its ultimate conclusion, this attitude could be effectively preventing you from submitting your brainchild to the Software Library.

Obvious Comparisons From time to time, I find that I am comparing the facilities of my other, portable, "computer", a Hewlett-Packard 41C, and those of the 99/4. Some features of the 41C would be an enormous help on the 99/4.
Things such as: non-volatile memory . . . ability to simultaneously store independent programs in memory, deleting or inserting at will, and if needed using these programs interactively . . . indication of free memory size . . . CHEAP RAM expansion . . . ability to download program from GROMs for editing, improvement, etc . . . access to GROM routines called from program . . . FAST program and or data dump or load, using magnetic cards . . . very flexible key assignment (non-volatile, or course) . . . access to "machine code" - need I go on? My only hope is that some of these wishes will be fulfilled by Extended Basic when it finally arrives.

Unconnected Dots "Phantom" CHAR 30 appears in the Char Definition program in the User's Handbook . . . so far, no sign of my Extended Basic module . . . does Text-to-Speech use the Speech Synthesiser . . . Yahtzee is currently the favourite game in our family . . . hands-up those who are taking or have taken their 99/4 with them on holiday, disguised as a Portable Color TV! . . . thank goodness Peter Brooks has had his phone cut off!

Question: How long is roll of thermal paper?
Answer: Not long enough to last until new supplies arrive . . . Help!


Rambles
by Stephen Shaw
A long, long time ago, back in TIHOME (was it No. 1?) when the games etc. library was launched on an unsuspecting world, it was suggested members may wish to advise of BUGS they found in the progs.

Curious silence since!
Speaking to Ted Rowthorn of Computer Contacts recently brought this to mind - I use a monochrome TV which cuts off HCHAR column one - I have to amend some progs to take care of this, but of course everyone will have different TV problems)!

OBSTACLE can become a little pointless - either you can make it or you cannot - it becomes a bit more interesting if you add a clock. Immediately after the CALL KEY, add:

TM=TM+1
FOR CT=1 TO LEN(STR$(TM))
CALL HCHAR (24,2,ASC(SEG$(STR$(TM),CT,1)))
NEXT CT

This should come BEFORE the CALL KEY test. Alternatively, if you would like the time to be displayed only at the end, the last three lines can be placed in an appropriate position.

Equally HAMMURABI can drag a bit. I have limited my copy to finish after 25 "years" with an appropriate report. Increment a counter after each "Hammurabi I beg to report. . ." and if it exceeds whatever period you choose, exit to a final report. You can check per cent changes in population and land and comment appropriately!

Have you noticed that with STAR TREK, if you elect to play again you re-enter the same game? The variables have to be reset! I have retained this bug so that I can check the status of the late Klingons vs. the Enterprise. I could of course exit to a separate "final report" and then reset the variables. I'm lazy though!

If you have a copy of 99'er Magazine No. 1, and have tried Invasion from Space, you may now have flat finger tips. To avoid having to hold a key down all the time, add a "key memory", to repeat last instruction until replaced with a fresh one, e. g.:

1530 CALL KEY(0,KK,S)
1532 IF S<> 0 THEN 1560
1540 K=KK
1550 (delete)
1560 IF K(etc etc. . .)

Press a different command key to change - press any other key to stop ship and not fire. Otherwise last instruction will be repeated.

If you find that you are having to slowly increase the volume control on your cassette recorder, the problem may be a magnetised head. The data signal seems to have a powerful effect! I found I could drop the volume by 15% after demagnetising, using one of those electronic demagnetisers, built into a cassette shell.

Does anyone have technical contacts in TI? TI dismiss the CALL PEEK subroutine in the Extended Manual, but I think it could be used to obtain, in a program, the following information (obtainable with PEEK on the Tandy):

IS THE PRINTER/ EXPANSION MEMORY/ DISK DRIVE PLUGGED IN AND SWITCHED ON?
This information should be somewhere in memory.
WHAT IS "FILES" CURRENTLY DIMENSIONED TO?
Somehow TI omitted this subroutine, but the info should be available with CALL PEEK.
How about a memory map, TI? (Not writing direct - they seem too busy to reply to letters.) Now is the time for all TI owners to call for better service facilities - before our machines break down! My disk drive arrived with the plug broken in transit. Returned to TI by Securicor 24-hr service. Over ONE MONTH later and they still have not managed to fit a new plug (or send a replacement unit). This bodes ill.

More on CALL A (available in TI Basic when using PRK/PRG module)

If the cursor is flashing over a blank field when you press ENTER, the variable you are trying to fill will take the value of 0, even if you have specified a MIN of 1 or more.

If CALL A has been used previously, with the same variable, or if the variable has been defined previously, it will keep its previous value.

The best way out, if using MIN and MAX, seems to be to test the function variable to ensure it is a "1", if not then return to the CALL A line.

When using CALL A, E, + and - are all accepted - E permits entry of numbers in exponential format.


Thanks Paul for the TI Q'aire with free module! Just got mine in in time, for a free games module. Hope TI have obtained helpful information with this exercise, and will now be able to give this product the full support it deserves.

More BUGS: YAHTZEE although a fine prog does not have a test for the initial question on number of players. Entering over 4 will cause a crash, so if you like neat progs, add a test here.

Sent an SAE to the address given by TI for UK distributor of US software a while back - still waiting for a reply. Oh well. Hopefully things will sort themselves out in due course.

In reply to Mike O'Reagan - Character 30 is the cursor! If you have Extended Basic you can change the color - it is in SET 0 (CALL COLOR(0, 2, 4)) - but sadly cannot be redefined. Character 31 is (quote) an edge character (!).


Conversion
or: How a Program can be Improved for its own Benefit to Run without Error on a 99/4 . . .
When faced with a printed program, which is always for some computer OTHER than a 99/4, do you throw your hands up in dismay and go back to Yahtzee?

Never fear. It is possible (but not always worthwhile!). Your basic tools should be The Basic Handbook by David Lien (about gbp 11) [see note below re Vn 2] and the October 1981 issue of Computing Today, which has a useful graphics comparison feature.

I shall leave graphics to later (if they are wanted?) and deal here with some other little things you may stub your toes against.

CALL CLEAR. That's clear and easy, but in Apple Basic: CALL-936. Meanwhile in Pet-land chr$(147) does the trick. But in Japan, the MZ 80: chr$(198). In several systems a sort of ASCII standard is: chr$(24) or chr$(12). NB: For future ref: Pet and MZ80 do not use ASCII codes!

Other ASCII codes which you may meet:
7 ring bell
10 line feed
12 clear screen
24 clear screen
13 carriage return

In TANDY:
29 return to start of line
30 erase to end of line
31 erase to end of frame

CALL KEY (0, a, b)
Tandy: k$=INKEY$ (possibly easier than the 99/4)
Apple: k$=chr$(PEEK(-16384)) (whew!)
e. g. instead of 20 CALL KEY (0, a, b)
30 IF B < 1 THEN 20
on the Apple you would use:
20 IF PEEK(-16384) <=127 THEN 20
Pet uses a GET command.

The DAI is a nice computer, quite closely related to the 99/4, but with more subprograms. For instance: ENVELOPE 0 12, 30; 12,40 etc, sets up the amplitude waveform of a sound. To call the sound the DAI uses SOUND 1 0 12 0 4000.

To convert this to TI CALL SOUND, the last figure is the frequency (4000=500 cps. (?)), the 3rd figure is the volume(14 maximum). Duration is set with the envelope command - the sum of the 3rd, 5th, 7th etc. figures, where 1=3. 2ms.

WAIT TIME 20 causes the DAI to pause, where 1=20ms.
* * *
SET and RESET can be implemented on the 99/4, but very, very slowly. Best bet is to find out what is going on and rewrite from start. Also PLOT and LINE. More in "graphics" to follow . . .

* * *
In Pet and Apple Basic, CLR sets all numeric variables to zero (as does CLEAR), and string variables to "". Not to be confused with CLS - used in some systems to clear the screen.

DIM If you are converting an Apple prog, you may find string variables in the DIM statement, which appear in the program without subscripts. Just don't use the DIM statement. In Apple, space has to be reserved for strings.

TAKE CARE also - some systems permit the use of variable a(1) and variable a. 99/4 does not permit this, and one of the variables must be renamed. TRS-80 Level 1 does not need dimensioning - 99/4 does, so if you see a subscript over 10, add a DIM statement. (Level 1 limits arrays to a(n) and b(n)).

* * *
Apple: PRINT d$;" NOMONC, I, O" - opens disk file-update. As we all know by now, only TI uses SEG#. This is directly interchangeable with other systems MID$ (except . . . see below). Other systems also use:

LEFT$(A$,2) use SEG$(A$,1,2)
RIGHT$(A$,N) use SEG$(A$,LEN(A$)-N+1,N)
(the figure added to LEN is the last figure less one.)
(web note- right$ above has been amended from printed copy)

You may sometimes come across MID$(A$,4). For this, use: SEG$(A$,4,LEN(A$)-4+1).
* * *
TRS-80 Model 3 has an amusing use of MID$:
LET MID$(A$,7,4)="YET"
will change the 7th, 8th, 9th, and 10th letters of A$ to "yet". For the 99/4, you have to do this the hard way with SEG$ & concatenation.

* * *
MOD
If you meet a=13 mod 5 or a=mod(13,5), then use:
A=13-INT(13/5)*5
(because of internal rounding it will sometimes be necessary to use a=13-INT(13.000001./ 5) *5)
* * *
ON-GOTO :
Note that 99/4 follows ANSI Basic and if the number is a fraction it will be ROUNDED not subject to INT. To clarify matters you may wish to add INT.
Note that if you have difficulty using a program with this line it may have been written for a computer which uses INT. Also, if the number is greater than the number of line numbers quoted, some computers drop to the next line - the 99/4 will return an error message and stop.

* * *
RND may appear as RND(0) or RND(1).
Sometimes RND(0) repeats the last random no. RND(8) is the same as RND * 8, although in some systems you may find RND(n) will return a RND number only when n is a positive value. Note that in 99/4 RANDOMIZE can be used repeatedly if you wish!

Note that 99/4 departs from the standard for INPUT prompts - where other systems use INPUT "WHAT"; A

we use (more sensibly I think) INPUT "WHAT": A

You can see why I haven't done graphics this time! Let Paul know if you want graphics details, or if there is ANY line in any program that you do not follow or cannot translate. Between us we should be able to do something.

Many programs involve so much translation that it is better to find out what they are doing and rewrite from scratch. I have this strong dislike of Pet programs - they seem designed to be difficult to follow. Apple programs are very easy to translate, especially if you have Extended Basic - the PILOT Interpreter in the library is almost unchanged from an original Apple program. (My ExBas version is available in the Emulator Programs section of this web site)

* * *
Just to fill the page, a quick routine to print out the contents of the screen, which may be called by (say) pressing "p" or you can just insert GOSUBs in your program at appropriate points.

PSS=PSS+1  
OPEN #1:"TP.U.S.E", OUTPUT  
PRINT #1: PSS  
FOR XX=1 TO 24  
FOR YY=1 TO 32  
CALL GCHAR(XX,YY,SC)  
PRINT #1: CHR$(SC);  
NEXT YY  
NEXT XX  
CLOSE #1  
RETURN  

Happy computing . . .

Stephen Shaw

BOOKS: Using Basic - There are two books with this title (at least!) - the one I strongly recommend is written by Page and Didday.

A new version of the Basic Handbook is now out - if you are buying a copy, check - a lot of shops are still selling the first edition. I am ordering a copy shortly and will report in due course. (Now to hand- read on):.

The new edition is much better than the first and reflects the growth of the home computer. The only home computer not included is ours - but then we have our own manuals! There are special sections on the Tandy Color, Atari, Acorn Atom, Tektonix , and a discussion of disk Basic.

Although the main work is in alphabetical order, there is also a separate index, which includes references in the special sections. I have used it successfully to translate a prog. for the ZX81 to Extended Basic.

There are many hints on how to implement commands you don't have, such at the MAT commands. PEEKs and POKEs are not covered.
I am at present collating information to produce a prog to allow the POKE address (and value) to be input and produce the 99/4 equivalent - not too difficult if you allow for reasonable approximations. I'll send a tape in when ready. This will only apply to graphic PEEKs and POKEs!

The Handbook does include the various Tandys, Pets, Apple, Sinclair, TI's 990 computer, SOL, ABC-80 (Swedish!) - the DAI is omitted.

Extended Basic: Faster than TI Basic!
Wot you say? Is he mad? No - running the "space invader" prog from 99er Magazine in TI Basic, under the same conditions, the first ten CALL KEYs took 130 seconds. Adding only one line, and running in Extended Basic, the same run took 85 seconds - quite a bit faster!

a) You need the Expansion Memory
b) Add as line one: CALL INIT :: CALL LOAD(-31878,0)

This stops any sprites moving, but otherwise really speeds up Extended Basic [Update: This only applies to Extended Basic Version 100, Version 110 did it for you].

In Extended Basic:
CALL LOAD(a,b) is not covered in your manual - it is the equivalent of POKE and if used unwisely is a good way to crash your console: (Nasty: but not fatal).

Using CALL LOAD, you can use variables in your progs where TI forbids you to - e. g. DIM(n), GOTO n, RUN DSK1.N,$, by "pokeing" the values into your appropriate memory location.
The catch is that having established where to POKE you cannot edit or amend your prog (lines up to the POKED line as any editing removes the line from its memory location and puts it at the end (suitably indexed of course). Your program appears in memory locations -1 to -24000 (approx). Line One is at -1. Typically, to read your line you will need to read locations -12 to -1, in that order! Line two, say -30 to-14, and so on.

A value of 0 represents the end of the line (usually but not all the time!) For a full discussion, see 99er Magazine Issue 3, which includes progs for auto-catalog and auto-run of any disk, and auto-REMover.

If you are PEEKing outside the program location, keep in mind that some locations may have "high bit on" the equivalent of adding 128 to the true value - so as well as looking at the value returned, look at the value less 128 (if it's over 128 that is).

If you have edited your prog and want it back in order, use:
SAVE DSK1.X, MERGE
NEW
MERGE DSK1.X

Your prog is now in order and can be saved as SAVE DSK1.PROGNAME. Note: merge dsk.1 can take a long time - the drive light on your disk drive goes on and off and on . . . Don't forget the NEW or it takes even longer . . .

WANTED: Memory location details! John Ashley at TI says these are available but restricted (?) - TI UK are trying to obtain consent to release. Meanwhile in the States TI Inc have a newsletter for their 99/4 owners, giving info like this.

Attention US Users Group: Please send us a copy of TI's newsletter. Ta! In theory it should be possible to POKE assembly language progs into memory locations, if you know the language and the locations.

With my Extended Basic I received three sheets of "program errors" but so far I have been unable to repeat any of the error conditions warned against! I suspect the error conditions arose from too much trying to cause an error, and the subsequent problem was not fully understood? Anyone out there had trouble with Extended Basic? I've found it easy to crash TI Basic but so far none with XB -except from badly inserted module.

Happy computing. Stephen Shaw




Letters

Quotes from your Letters
Instead of using the printing facility of the INPUT command use a PRINT state meat terminated by a ";" and followed by an INPUT. This will cause your PRINT statement to be displayed followed by the cursor ready for the INPUT.

Pete Brooks, Cowley, Oxford.
==========================
5 B=20
10 A=-5
20 A$="UP"
30 B$="SD"
40 C$="CD"
50 FOR J=1 TO 2000
60 IF A> 1 THEN 4000
70 IF A$<>"UP" THEN 4000
80 IF B1<=C*D THEN 4000
90 IF B$=C$ THEN 4000
100 NEXT J
4000 PRINT "FINISHED"

Version 2: Replace line 60 with: 60 IF (A> 1)+(A$<>"UP")+(B<=C*D)+B$=C$) THEN 4000

Run both version and check execution times.


Martyn Simpson, 11 Main Street, Belton, Uppingham, Leics.

===========================
Still a bit discumnockerated by the TI price switch, but I suppose someone has to be on the receiving end: bloody knocks the bottom out of the second-hand market though; who's going to pay gbp700 for a second-hand first model when they can pick up a new one for under gbp300?
Pete Brooks, Cowley, Oxford.
==========================
As for the "For Pete's Sake" programming tips column, I say it is the best from all other U. S. Users Groups. Please inform Mr. Pete Brooks I thank him for his marvellous work and the level of standard is clear and just right for a novice user like me.

Danny Leung, 4C Wongneichong Gap Road, 8th Floor, Happy Valley, Hong Kong.

===========================
Dutch info: The PAL version is on the market here for some 6 months. Paul Karis, Brewwgras 2, 39n2 AA Veenendaal, Holland. (25 July 1981)

===========================
Am I the only one to crash "Camel"? MEMORY FULL, just once. So far I've managed 129 miles, but a number of times I've only managed 0 miles! (or is that a record?)

Stephen Shaw, 10 Aderone Road, Stockport, Cheshire.

S. Shaw complains that with the Extended RAM he has only 38440 instead of 48K. He is using a disk controller so the operating system would take 1592 and the disk controller would take 1056 for CALL FILES(1) so 49152-1592-1056=46504. There appears to be a short fall of 8064. Anyone know where it has gone to?

Editor
===========================
I have an idea . . . request through Tidings for interested members to get in touch with me, stating their interest with regard to research they are doing, things they have uncovered, queries they have.

Pete Brooks, 68 westurne Road, Cowley, Oxford, OXn nSH.

===========================
I wonder if there is a routine to CALL KEY instead of CALL JOYST.
R. Sharman, 148 strove Road, Biggleswade, Beds.

==========================
Does anyone collect odd messages? How about BREAKPOINT AT 52196 (where?) or INCORRECT STATEMENT IN 0 (where?).

S. Shaw, Stockport, Cheshire.

===========================
Enter CALL KEY(0,K,"11111111111111111111... 11111111") , fill all 4 lines with 1's. Odd little ghosties will appear on the screen, you . . . get the message INCORRECT STATEMENT . . . and the cursor, but all will not be well.

Pete Brooks, Cowley, Oxford.

===========================
I have converted my ATARI joysticks and can confirm they work very well.
A. Chalcraft, 63 greens Road, North Weald, Essex.

I have managed to connect a B& W VDU to the 99/4 PAL as follows: 2 composite video (blue wire) 6 signal ground (silver wrapped wire) Black wire not connected.

G. Shaw, 30 Leasord Lane, St Johns Green, Writtle, Chelmsford, Essex.
============================
TI News
Coming soon! Pascal will be released for the 99/4. I have heard it is already available in the States. Pascal isn't one of my languages, but any extension on the language front will be very welcome.

Assembler will also soon be available. I understand that this will comprise a GROM and a disk. I would be very interested to see this. See my comments in the Editorial.

That's all for this time, for reason, see below.


Postscript

Postscript
I have been having more talks with TI and it appears that there is a possibility of TI printing our newsletter along with their printing requirements. TIHOME will pay for the job, of course, and I still have to discuss costs, but it does look promising.
TI have asked if they could insert their own article in each newsletter giving latest news and answering comments and queries that appear. I have agreed on the understanding that nothing TIHOME writes is altered in any way. Apart from it being fair that TI should have the "right of reply" I think we will probably get useful information a lot faster in future.

One further point, A number of you have asked me for back numbers of Tidings. In future, these will cost 50p each plus postage and packing. It costs just as much to get out a back number as a recent one and I think this charge is not unreasonable.

Well, there we are, at the end of the first year of TIHOME. Is it really that long since I started it, in all innocence? We have come a long way in 12 months. You have only to compare this newsletter with No. 1. I had a choice of two ways to go.
I could have formed TIHOME complete with committees and all the trappings. I have spent quite a lot of time on committees of one kind and another. I know the problems of getting to meetings which have to be held in different parts of the country to please all members. Then there are the problems caused by 10% of the people doing 90% of the work.
The other possibility was to turn TIHOME into a business and use any money it made to give an increasingly better service to the users. I thought very carefully, talked it over with TI's legal department and that was the path I finally took. How TIHOME, goes on from now depends on you. I will do all the organization, postage, financial stuff, etc, but the most important part depends on you.

Until the next time, best wishes and good computing.

Best wishes for Christmas and the New Year.
Published by TIHOME. Prop., Paul M. Dicks, 157 rethopssond Rd, Morden, Sy. Reg. No. 2778359.


Access Key Details
Stephen's Entry Page   |    TI99/4a   |  Linux   |  Search   |   History St Thomas Church Heaton Chapel   |   Entertainment
Music Links   |   Light Reference   |   Educational Reference   |   Science Fiction |   Travel   |   News Links |   Anime