Level II Tips & Tricks – Menu


SYSTEM TAPE Tips and Tricks:

BASIC Tips and Tricks:

Miscellaneous Routines:

System Status/ID

What Model TRS-80 Is It

Model I      PEEK(293) <> 73
Model II      PEEK(125) = 2
Model III      PEEK(293) = 73
Model 4/4D      PEEK(125) = 4
Model 4P      PEEK(125) = 5
Model 12      PEEK(125) = 12

What Peripherals/Mods Are Attached/Status

No expansion interface connected or powered on      PEEK(14316) = 255
Not Disk BASIC      PEEK(16549) < 66
TRSDOS 6.1.x      PEEK(&H85) = &H61
TRSDOS 6.2.x      PEEK(&H85) = &H62
TRSDOS 6.3.x      PEEK(&H85) = &H63
Will print a 1 if the keyboard has the Radio Shack lower-case modification. If the modification has not been made, the result will be 65.      POKE 15360,1: PRINT PEEK (15360)
Will print a 1 if the keyboard has the Radio Shack lower-case modification. If the modification has not been made, the result will be 65.      PRINT@0, CHR$(65): PRINT PEEK (15360)


Extended Error Message IS displayed      (PEEK(124) AND &H40)<>0
Full File Access is ENABLED      (PEEK(119)AND 128)<>0
Special Character Mode is ON      PEEK(&HB94)<>0
Will give a 0 if the keyboard is generating both upper and lower case. Any other value returned indicates that the keyboard is locked into upper-case only.      PEEK (16409)

Reset Button Pokes

NOTE: These pokes will work only if there is no expansion interface connected.

RESET BUTTON = NEW      POKE 16830, 195
POKE 16831, 73
POKE 16832, 27

RESET BUTTON = RUN      POKE 16830, 195
POKE 16831, 163
POKE 16832, 30

RESET BUTTON = SYSTEM      POKE 16830, 195
POKE 16831, 178
POKE 16832, 2


RESET BUTTON = Make a L2 Machine Language program restart on hitting reset      1) Load machine language program
2) At second *? hit break

3) POKE 16830, 195 : POKE 16831, PEEK(16607): POKE 16832, PEEK(16608)

Break Key Pokes

POKE 16396, 23      BREAK Key = Disabled (L2)
POKE 16396, 201      BREAK Key = Enabled (L2)
POKE 17170, 175
POKE 17171, 201
     BREAK Key = Disabled (DOS)
POKE 17170, 195
POKE 17171, 164
     BREAK Key = Re-Enabled (DOS)
POKE 16396, 10 (or 58)      BREAK Key = REVERSE TAB
POKE 16396, 15      BREAK Key = <SPACE>
POKE 16396, 47 (or 147 or 223)      BREAK Key = Reverse Stars
POKE 16396, 118      BREAK Key = READY
POKE 16396, 133      BREAK Key = U, Shift BREAK = V
POKE 16396, 165      BREAK Key = DISABLED, Shift BREAK = OK
POKE 16396, 227      BREAK Key = SN ERROR
POKE 16396, 228 (or 51)      BREAK Key = MEMORY SIZE
POKE 16396, 199      Causes BASIC to reinitialize when the BREAK key is hit (L2)
POKE 23461,0      Disable the Break Key (NewDOS v2.1)
POKE 23886,0      Disable the Break Key (TRSDOS v2.3)
POKE 16396, 165      Change BREAK to SHIFT-BREAK
POKE 16396, 233      Change BREAK to RESET
(PEEK(124) AND &H10) <> 0      Break Key is ENABLED IF

Keyboard Tips and Tricks

POKE 16405, 0      Disable The Keyboard (Programs Still Run)
POKE 16405, 1      Enable The Keyboard
IF PEEK(14463) = 0      Determine if ANY key is pressed
IF PEEK(14591) = 0      Determine if ANY key other than SHIFT is pressed

Change the JUMP location on pressing the RESET button      POKE 16391, LSB
POKE 16392, MSB
FULL File Access:      ENABLED: POKE 119,(PEEK(119) OR &H80)
Extended Error Messages:      ON: POKE 124,(PEEK(124) OR &H40)
OFF: POKE 124,(PEEK(124) AND &HBF)
To get print arrows to print in a BASIC program      Press the Z and 2 keys and the 3 or 4 or 5 or 6 keys at the same time. You will get 2 characters printed and one will be the arrow. Just edit out the other character.
To use arrow keys for a program control      PEEK(14400) = 8 for up
PEEK(14400) = 16 for down
PEEK(14400) = 32 for left
PEEK(14400) = 64 for right.
To use arrow keys for a program control      PEEK(14537) = 1 for ENTER
PEEK(14537) = 2 for CLEAR
PEEK(14537) = 4 for BREAK
PEEK(14537) = 8 for up
PEEK(14537) = 16 for down
PEEK(14537) = 32 for left
PEEK(14537) = 64 for right
PEEK(14537) = 128 for SPACE.

Video Tips and Tricks
Disable the display      POKE 16413, 0
NOTE: 16413 is 401D in Hex which is the beginning the of Video DCB.
Enable the display      POKE 16413, 7
Turn Special Character Set to ON      ON: POKE &HB94,(PEEK(&HB94) OR 8 )
OFF: POKE &HB94,(PEEK(&HB94) AND 247)
Three Line Scroll Protect      ON: POKE &HB94,( PEEK(0) OR 8 )
OFF: POKE &HB94,( PEEK(0) AND 8 )
Change Cursor Character to nn      POKE &HB98,nn
To determine the current cursor position      PEEK(16416) + 256*PEEK(16417) – 15360

Determine DATE and TIME via PEEK
To determine MM/DD/YY HH:MN:SS on a Model I, PEEK the following locations:
MM – 16454
DD – 16453
YY – 16452
HH – 16451
MN – 16450
SS – 16449

To determine MM/DD/YY HH:MN:SS on a Model III, PEEK the following locations:
MM – 16924
DD – 16923
YY – 16922
HH – 16921
MN – 16920
SS – 16919

Model 4 Speed-Up
To speed up the Model 4, issue the following commands from basic:
     X=X OR 64
     OUT 235,X

Printer Tips and Tricks
To set SCREEN PRINTER to automatically print      OUT 254, 255

Determine the current line position for a Line Printer      PEEK (16425)

Determine the position of the print head on the current printer line      PEEK (16539)

Determine the lines per page on a line printer      PEEK (16424)
>= Lines per Page + 1 (so normal return is 67)

Determine the status of a line printer      PEEK (14312) = 63 (Ready)
PEEK (14312) = 255 (Printer is off)
PEEK (14312) = 191 (Printer Buffer is Full)
PEEK (14312) = 223 or =233 (Out of Paper or offline)
PEEK (14312) > 127 (NOT ready)

To turn off the JKL function in a basic program (if you don,t have a printer and don’t want any hangups)      POKE 16422,216 (Turn it off)
POKE 16422,41 (Turn it on/Reset It)

Key Word Tips and Tricks
AUTO Command
Start AUTO Command      POKE 16609, 1
AUTO Command Increment Set to 0      POKE 16612, 0 : POKE 16613, 0
LIST Command
Disable List Command      POKE 16863, 145
POKE 16864, 25
POKE 16865, 26
Disable List Command      POKE 16863, 195
POKE 16864, 114
POKE 16865, 0

NOTE: 16863 is 41DF in Hex.

Enable List Command      POKE 16863, 201
LLIST Command
Disable LLIST Command      POKE 16422, 103
POKE 16423, 00
RND Function
Change the first 8 numbers resulting from RND(100) to 80, 78, 91, 88, 70, 91, 25, 30      POKE 16554, 5
POKE 16555, 10
POKE 16556, 15

NOTE: 16544 is 40AA in Hex. This is the ROM location for the 3 byte random seed number.

TRON Command
Start TRON      POKE 16667, 1
Stop TRON      POKE 16667, 0

NOTE: 16667 is 411B in Hex. This is the ROM location for the TRON Flag; 0 is off, 175 is on.

Recover a BASIC program which has been destroyed by typing “NEW”?      POKE 17130,1
* / 11395

NOTE: 17130 is 42EA in Hex which is 1 above the normal start of BASIC program.
11395 is 2C83 in Hex.

Change the JUMP location on pressing / to answer a SYSTEM question      POKE 16607, LSB
POKE 16608, MSB
Level I Keyword Shortcuts
         PRINT = P.
NEW = N.
RUN = R.
END = F.
MEM = M.
FOR = F.
         NEXT = N.
STEP (after FOR) = S.
TAB (after PRINT) = T.
INT = I.
         RESTORE = REST.
ABS = A.
RND = R.
SET = S.

Input/Output Tips and Tricks
To turn on Cassette Recorder      OUT 255, 4

Stop a Disk Drive from starting and stopping
while reading or writing data.
     POKE &H37E1,0

To select Disk Drive 0, 1, 2, or 3      POKE 14304, number

To start disk drives.      POKE 14305 with 1,2,3 for drive 0,1, and 0+1 respectivly

If you want everything which is supposed to go
to the lineprinter to be sent to the video
     POKE 16422, 88 : POKE 16423, 4

To restore the lineprinter use:      POKE 16422, 141 : POKE 16423, 5

If you want everything which is supposed to go
to the video sent to the lineprinter, use:
     POKE 16414, 141 : POKE 16415, 5

To restore the video use:      POKE 16414, 88 : POKE 16415, 4

Latches Cassette 1      POKE 14308,0

NOTE: 14308 is 37E4 in Hex. 37E4 is the Model I cassette 1 or 2 select (0 or 1).

Latches Cassette 2      POKE 14308,1

NOTE: 14308 is 37E4 in Hex. 37E4 is the Model I cassette 1 or 2 select (0 or 1).

To set memory size from basic:
1. Set your MEMORY SIZE as normal.
2. PEEK 16562 and 16561 and note their values
3. Add a line in your program that POKEs those values into those corresponding locations
4. Add a more command after the POKEs that says CLEAR0:CLEAR50
From now on your basic program will set its own MEMORY SIZE. Be sure to put the pokes and clears at the beginning of the program.
For a more visual method, the following program might be useful:
10 ME = xxxxxxx : ‘ This is your desired memory size
20 MS = INT (ME / 256) : ‘ This will get the MSB of the Memory Size
30 LS = ME – (MS * 256) : ‘ This will get the LSB of the Memory Size
40 POKE 16561, LS : POKE 16562, MS

NOTE: 16561 is 40B1 in Hex. 40B1 and 40B2 are the pointers to highest address available for string storage (set by MEMORY SIZE).

Cause a TRS-80 to Reset
To cause a TRS-80 to reset:      POKE 16415, 5

Note: 16415 is 410F in Hex. 410FH is the second of a two-byte video driver vector which normally points to 0458H which is the video driver for Model I (the 2 peeks are 88 and 4 which is 1112 in Decimal or 0458 in Hex).
When changing the 88 and 4 to 88 and 5 you change the jump from 0458H to 0558H. I don’t know what that means, but it is apparently bad.

Routing between Video and Line Printer
Send all LINE PRINTER output to the VIDEO DISPLAY:      POKE 16422, 88
POKE 16423, 4

NOTE: 16422 is 4026 in Hex. 4026H is the two byte printer driver vector.
88 and 4 is the LSB/MSB of 1112 which is 0458 in Hex. 0458H is the video driver for Model I.

Send all LINE PRINTER output to the LINE PRINTER:      POKE 16422, 141
POKE 16423, 5

NOTE: 16422 is 4026 in Hex. 4026H is the two byte printer driver vector.
141 and 5 is the LSB/MSB of 1421 which is 058D in Hex. 058DH is the line printer driver for Model I.

Send all VIDEO DISPLAY output to the LINE PRINTER:      POKE 16414, 141
POKE 16415, 5

NOTE: 16414 is 401E in Hex. 401EH is the two byte video driver vector.
141 and 5 is the LSB/MSB of 1421 which is 058D in Hex. 058DH is the line printer driver for Model I.

Send all VIDEO DISPLAY output to the LINE PRINTER:      POKE 16414, 88
POKE 16415, 4

NOTE: 16414 is 401E in Hex. 401EH is the two byte video driver vector.
88 and 4 is the LSB/MSB of 1112 which is 0458 in Hex. 0458H is the video driver for Model I.

Rescue a Program after typing NEW
To bring back a program after NEW has been typed:
1. POKE 17130, 1
2. SYSTEM / 11395

Renumbering a BASIC Program

Simple Renumbering
     P=17129 : FOR L = 1 TO 9000: IF PEEK(P+1) > 0 THEN POKE P+3,PEEK(P+3)+125 : P = PEEK (P) + 256 * PEEK (P+1) : NEXT

NOTE: 17129 is 42E9 in Hex. 42E9H is the memory location of the start of a BASIC program.

Another Example
     10000 L = 10
10010 C = 17129
10020 N = PEEK (C)
10030 N = N + (PEEK(C+1) * 256)
10040 POKE C+2, L
10050 POKE C+3, H
10060 L = L + 10
10070 IF L > 250 THEN L = 0 : H = H + 1
10090 C = N
10100 GOTO 10020
NOTE: Start by doing a RUN 10000, but since it will renumber itself, the routine will end in a ?UL Error. Only line numbers are changed; GOTOs and GOSUBs remain as they were..

Change the Cursor in Non-DOS Basic (AWFUL)

This nasty little routine will change the cursor in non-DOS BASIC. It will ALSO have the designated cursor character end each line on the screen, but rather than toss this fairly useless code, here it is …
20 FOR X = 32512 TO 32522 : READ A : POKE X, A : NEXT
30 POKE 16414, 0 : POKE 16415, 127
40 DATA 205, 88, 4, 229, 42, 32, 64, 54
60 DATA 225, 201

Append Two Programs Together in Level II BASIC

To append two programs together in LEVEL II BASIC, do the following steps:
     1. CLOAD the first program
2. Note the PEEK values of 16633 and 16634
3. If PEEK(16633) > 1 then subtract 2 from it
4. If PEEK(16633) less than or equal to 1 then add 254 to it and subtract 1 from the PEEK(16634)
5. POKE the modified PEEK(16633) number into 16548
6. POKE the modified PEEK(16634) number into 16549
7. CLOAD the second program
8. POKE 16548,233
9. POKE 16549,66

NOTE: I can’t get this to work. However, 16633 is 40F9 in Hex and 16548 is 40A4 in Hex. 40F9H is the 2-byte end of basic program pointer, so writing it down tells you where your first program ends.

I think the math is designed to move you two bytes before the end, arguably to overwrite a 2 byte end of program code.

You then change the pointer to beginning of a BASIC program located at 40A4 to the 2-bytes-short of the end of the original code, and the CLOAD in your next program

Steps 8 and 9 reset the pointer of the beginning of a BASIC program back to 17129 (233 + 256*66) which is 42E9 in Hex and which is the normal value in LEVEL II for the start of BASIC pointer.

Finding the START and END of a BASIC Program

Find the Starting Address of a BASIC Program:
     PEEK (16548) + 256*PEEK(16549)

NOTE: 16548 is 40A4 in Hex. 40A4H is the start of BASIC program pointer. Normally it would be 42E9H

Find the Ending Address of a BASIC Program:
     PEEK (16633) + 256*PEEK(16634)

NOTE: 16633 is 40F9 in Hex. 40F9H is the top of BASIC program plus 1

Make Level II BASIC and Model III BASIC Crash      Level II BASIC and Model III BASIC will crash if you do the following from a READY prompt:
1. Type
(that is 3 spaces and an apostrophe)
2. Type
(that is 4 spaces and an apostrophe)
That’s it. The computer will not return to READY. Following a pause, the computer will restart.
Matthew Reed advised that this is one of the few major bugs in TRS-80 BASIC. It was due to a flaw in the handling of the apostrophe, which was not treated the same as REM for some reason. It was present in multiple versions of Microsoft BASIC.

DOS Oddity re Hexadecimal      When using the hex to decimal conversion in a DISK BASIC or LEVEL 3 BASIC program you will not be able to enter any hex number with the &h notation that has a “DEF” embedded (e.g., FDEF, DEF1, etc). Since DEF is a reserved word you will get an incorrect (partial) hex conversion, and then a SYNTAX ERROR!!!

Easy Way to Load a SYSTEM Tape
When loading a system program one normally must enter the proper embedded filename at the first prompt, or the program will not load. However, this is not (entirely) necessary!

Instead, if you type only the first letter of the program you are loading, it will work.

As an example, if the program name is “CLONE” you can enter C, CL, CLO, CLON, or CLONE after the *? and ALL OF THEM WILL WORK.

However, if you enter CLA it will not work. Why? The computer only checks for as many characters of the name as you type in after the *? but loads only in if the same length of characters match. You must enter at least 1 character name.

Get your 48K if your Expansion Interface was Off:
If your expansion interface is off and you suddenly wish it had been on when you started doing whatever you were doing, and you need the RAM it has right now without restarting your computer and losing what you have, do the following:

1) Turn on the expansion interface
2) POKE 16561, 255
3) POKE 16562, 255
4) CLEAR 50

That’s it … you should have your RAM.

Note: George Philips has advised that it is very very bad to turn on your E/I while your Model I is powered on. He also advised that the reason this works is that when the machine starts it decides how much RAM it has by stepping through all possible RAM addresses and seeing if RAM is there by writing a test value or two and seeing that you get the result back. If you don’t get what you wrote, there’s no RAM there (or it is faulty). That highest available RAM location is stored in 16561, 16562.

If you boot without the E/I then it will look to BASIC as if you only have 16K. Poking in the 255’s makes it think you have 48K because 255 * 256 + 255 == 65535 which is the highest possible address on the TRS-80 Model I. Note that this won’t work if your E/I has only 16K in it as you’ll have 32K total and the machine will crash trying to access the uninitialized memory.

The “CLEAR 50” is important because BASIC keeps track of another pointer and that command serves to update it. You need to give it the “50” (or some other parameter) so that it makes the change. Otherwise it will just reset your BASIC program’s variables and do nothing else.

Misc. Tips and Tricks
To convert betweek (X,Y) and PRINT@      The PRINT@ is INT(Y/3) * 64 + INT(X/2)
The X and Y are Y=3*INT(P/64) : X=2*(P-64*Y/3)

To change the NUMBER OF FILES under TRSDOS once you are in DOS BASIC      SYSTEM
/ 20992

To JUMP back into BASIC from a SYSTEM program, the best address is:      0072

If you accidentally typed in SYSTEM and cannot get out of it (can’t reset; BREAK is disabled, etc), re-enter BASIC by entering:      /1740

NOTE: 1740 is 06CC in Hex. 06CCH is an alternative address for entering BASIC.

Screen Print Routines
Jay Reso of Metairie, La. suggests the following routine for printing the contents of the video display to a lineprinter:

1000 DIM S$(15)
1010 FOR T=0 TO 15
1020 S$(T) = “”
1030 POKE VARPTR(S$(T)),64
1040 POKE VARPTR(S$(T))+1, (T*64 + 15360) AND 255
1050 POKE VARPTR(S$(T))+2, (T*64 + 15360) / 256
1060 NEXT T
1100 FOR T=0 TO 15 : LPRINT S$(T) : NEXT

Line 1020 establishes S$(T) with a location in memory. Line 1030 sets the length of the string to 64 bytes. Lines 1040 and 1050 set the string pointer to the location of the first byte of a video line.

Once you have executed lines 1000-1060, you can execute 1100 at any time and you will get a printed copy of the screen. Remember that you cannot print graphic characters to a lineprinter. One other caution is that you may not ASSIGN values to the strings S$(T). If you try to as-sign values to these strings, you will reset the pointers and you will have to rerun lines 1000-1060.

Print the Concents of the Screen on a Line Printer

10 CLS
20 CLEAR 500 : DIM S$(15)
30 FOR T = 0 TO 15 : S$(T)=””
40 POKE VARPTR(S$(T)),64
50 POKE VARPTR(S$(T))+1,(T*64+15360) AND 255
60 POKE VARPTR(S$(T))+2,(T*64+15360) / 256
80 FOR T = 0 TO 15 : LPRINT S$(T) : NEXT
100 GOTO 80

M. Thorpe’s Screen Graphics Hard Copy Generator

3010 ‘
3020 FOR X =15360 TO 16383 STEP 64
3030 A=1: B=2: C=1
3040 FOR K=X TO X+63
3050 IF ((PEEK(K)-128) AND A) = A THEN LPRINT”#”;:GOTO 3070
3060 LPRINT” “;
3070 IF PEEK(K) =32 GOTO 3090
3080 IF ((PEEK(K)-128) AND B) = B THEN LPRINT”#”;:GOTO 3100
3090 LPRINT ” “;
3100 NEXT K
3110 LPRINT ” “
3120 ON C GOTO 3130,3140,3150
3130 A=4: B=8: C=2: GOTO 3040
3140 A=16 : B=32: C=3: GOTO 3040
3150 NEXT X

If you need a sample program to test this with, try the following:

20 CLS
30 FOR I = 0 TO 33
40 FOR J = 0 TO 50
50 A=INT(RND(0)+.5)
80 GOSUB 3000
90 END

Voice Control – by Phillip Case
Recently the latest rage in programming has been the use of sound effects in games. In this issue of SoftSide is a program titled SONIC TORPEDOS which has a unique method of permitting you to control the program by voice Input. This article will show you how to use this technique in your programs.

Believe it or not, this technique was accidentally discovered by myself and Chris Freund (familiar name among SoftSide readers) while working on another program.

First, a microphone is required for voice input. It is to be plugged into the MIC jack of your cassette recorder. Then unplug both the AUX and REM plugs and leave them loose. When this is done, depress the tab sensor in the cassette bay, the RECORD and the PLAY keys all together.

The program commands themselves are relatively simple.

The microphone causes the value of the cassette to change whenever sound is sensed. To check the value of the cassette port use the INP(255) command. This will give you a value to work with in your program. The value of the port will be 255, if sound has been detected, and 127 if not. Use the INP(255) function as you would the INKEY$, i.e., within a loop.

Once sound has been detected, the value of the cassette port will remain at 255 until you either clear the screen (CLS) or home the cursor (PRINTCHR$(28)). This must be done to reset the cassette port for receiving sound. It is suggested that this be done just prior to checking the port so that no background sound be picked up.

There is a little problem that arises if you are in the character mode and you are trying to use this technique. Because the 32 character mode is controlled via the same port as the cassette recorder, the values of the port are different when you are in that mode. For the same reason it is possible to get double size letters on Level I with a little work.

Below is a table showing the various values under different conditions.

Mode     64 Char     32 Char
No Sound     127 63
Sound 255 191

Here are two examples of how to use the sound input in your programs.

The following program will print ‘SOUND!!!’ in the upper-left hand corner of your screen whenever the computer is picking up input from the microphone.
10 CLS: PRINT CHR$(28) : IF INP(255) = 255 THEN PRINT “SOUND!!!” : GOTO 10 ELSE 10

The following program will display a graphic representation of your voice:

10 CLS : FOR X = 0 to 127 : PRINT CHR$(28): IF INP (255)=255 THEN Y=22 ELSE Y=23
20 SET (X,Y): NEXT : RUN

Super Sorting – by TR Dettman
The next time you sort a list of items in your computer, try this experiment. Put an AM radio next to the computer, tuned away from any station. With this, you can actually hear the computer ‘think’.
If you try this, you will find that during the sort, a large amount of time will be spent doing something which changes the pattern of the sound completely. This change is the bane of most sorting techniques on the TRS-80, and it is called “Memory Management”.
Memory Management
To understand memory management, we have to look at how the computer stores information. For numbers this is simple since each variable is assigned space in memory for its value, resetting it doesn’t change where it is.
However, strings are handled differently. When we read in strings, the computer stores them starting at the top of free string memory (remember CLEAR N, it sets aside N bites for strings. RUN automatically does a CLEAR 50). The beginning of each string is recorded along with the length of the string in a location in memory provided for this. The VARPTR function gives you that location
If you have a string in memory called A$, its location is given by:

     PEEK(VARPTR(A$)+1) + PEEK(VARPTR(A$)+2)*256

(see the Level II Reference Manual. p8/9).
The length of the string is:

     PEEK (VARPTR(A$))

As you add strings into string space, they are added one after another as shown in the diagram.
When you reset the value of a string, the pointers to the string in memory are reset to their new values by the interpreter. But this is not all, since the string is treated as a new string and the old location of the string is not recovered.
A typical statement in a sorting program which changes one string for another is:
Even though the strings are already occupying space in memory, this statement generates THREE NEW STRINGS and adds them into the string space at the bottom.
When you fill up the string space (which will happen very quickly), the computer pauses to reorganize the memory and compact the string space by getting rid of unused space. During this time, your program just waits.
Even with the best sorting algorithm, as much as 90% of the computing time for the sort will be in memory management. In order to get efficient sorts we have to get rid of this wasted time.
Sorting with VARPTR
A significant improvement in sorting time (from 4 hrs to 8 ½ minutes, for 450 items), is gained by redoing the program statement above that swaps strings as follows:

     I1= PEEK (VARPTR(A$(I))):
       I2= PEEK (VARPTR(A$(I))+1):
         I3= PEEK (VARPTR(A$(I))+2)
     J1=PEEK (VARPTR(A$(J))):
       J2=PEEK (VARPTR(A$(J))+1):
         J3=PEEK (VARPTR(A$(J))+2)
     POKE (VARPTR(A$(I))),J1:
       POKE (VARPTR(A$(I))+1),J2:
         POKE (VARPTR(A$(I))+2),J3
     POKE (VARPTR(A$(J))),I1:
       POKE (VARPTR(A$(J))+1 ),I2:
         POKE (VARPTR(A$(J))+2),I3

This set of statements creates no new strings in memory. It only changes the pointers to the strings. On large sorts, the improvement by using this technique is phenomenal. On a sort of 450 items in a mailing list, we had an improvement from 4 hours without this technique, to 8½ minutes with it. This sort has now been included in our own mailing list program as well as Peripheral People’s Mailroom.
As this is being typed up for publication, we have seen an article elsewhere giving essentially the same sorting technique. We discovered only one minor problem with the way that it accomplishes the switch.
It uses the following statements to switch the pointers:

     FOR Z=0 TO 2
       A1=PEEK(T1 + Z)
       A2=PEEK(T2 + Z)
       POKE (T1+Z),A2
       POKE (T2+Z),A1
     NEXT Z

I found that the technique works well on long sorts, but that the pointers were dynamically allocated (a 25 cent buzzword for saying that they can move) on short sorts, say less than 10 items.
For short sorts, setting the values T1 and T2 resulted in not getting the pointer correctly. This has disastrous results since the pointers become random and you soon find that your strings begin to take on a funny look.
On one sort, some of the pointers actually wound up saying that the strings they referred to were in Level II ROM! In order to prevent this, the statements can be changed to be equivalent with mine.

     FOR Z = 0 TO 2
     Al = PEEK(VARPTR(A$(I))+Z)
     A2 = PEEK(VARPTR(A$(J))+Z)
     POKE (VARPTR(A$(I)) + Z), A2
     POKE (VARPTR(A$(J)) + Z), A1
     NEXT Z

Further Improvements
Still another improvement comes from changing all of the variables in the program to integers, except those that must be real or string variables.

Automatically Execute Your Machine Language Program on Tape Load
To automatically execute your machine language program once the tape finishes loading, do the following:
    ORG    41BEH   
    JP    7000H   
    ORG    7000H   
START    …    …    ; First Instruction of Your Program
    …    …   
    END    START   
The key is that you have a 3 byte instruction following the ORG 41BEH.