TRS-80 Tips and Tricks – Level II Tips and Tricks

Level II Tips and Tricks – Menu

General:

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)

Other

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, 195POKE 16831, 163
POKE 16832, 30

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

RESET BUTTON = DISABLED
POKE 16830, 201

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)
Jump to a specific memory location on RESET
POKE 16391,LSB of Program
POKE 16392,MSB of Program
Disable RESET and BREAK
10 QQ$=CHR$(42)+CHR$(164)+CHR$(64)+CHR$(43)+CHR$(195)+CHR$(30)+CHR$(29)
20 Q=VARPTR(QQ$):Q1=PEEK(Q+1):Q2=PEEK(Q+2)
30 POKE16812,195:POKE16813,Q1:POKE16814,Q2
40 RETURN’ 4007H-LSB,4008H-MSB

Break Key Pokes

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

Keyboard Tips and Tricks

Disable The Keyboard (Programs Still Run)
POKE 16405, 0
Enable The Keyboard
POKE 16405, 1
Determine if ANY key is pressed
IF PEEK(14463) = 0
Determine if ANY key other than SHIFT is pressed
IF PEEK(14591) = 0
FULL File Access:
ENABLED: POKE 119,(PEEK(119) OR &H80)
DISABLED: POKE 119,(PEEK(119) AND &H7F)
Extended Error Messages:
ON: POKE 124,(PEEK(124) OR &H40)
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
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=PEEK(16912)
X=X OR 64
POKE 16912,X
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.

Misc

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

NOTE: 17130 is 42EA in Hex which is 1 above the normal start of BASIC program.
11395 is 2C83 in Hex.
DO NOT INVOKE THE EDIT COMMAND AFTER DOING THIS.
Change the JUMP location on pressing / to answer a SYSTEM question
POKE 16607, LSB
POKE 16608, MSB

Level I Keyword Shortcuts

ABS = A.
CLOAD = CL.
CONT = C.
CSAVE = CS.
DATA = D.
END = F.
FOR = F.
GOSUB = GOS.
GOTO = G.
INPUT = IN.
INT = I.
LIST = L.
MEM = M.
NEW = N.
NEXT = N.
POINT = P.
PRINT = P.
PRINT AT = P.A.
READ = REA.
RESET = R.
RESTORE = REST.
RETURN = RET.
RND = R.
RUN = R.
SET = S.
STEP (after FOR) = S.
STOP = ST.
TAB (after PRINT) = T.
THEN = T.

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
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).

Set MEMORY SIZE from BASIC

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
50 CLEAR : RESTORE

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


Another way …

10 POKE 16561,LSB : POKE 16562,MSB
20 CLEAR 50
30 END

Set a USR Routine for DOS and Level II

10 A=PEEK(16396):IF A = 195 THEN AD=23316 ELSE AD=16526
20 POKE AD,LSB:POKE AD+1,MSB

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

DO NOT INVOKE THE EDIT COMMAND AFTER DOING THIS.


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
10080 IF H = 255 THEN PRINT "TOO MANY LINES" : END
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.


Poking above 32767

If you try to POKE 65535,0 you will get an overflow error. This is because the PEEK and POKE commands require an integer argument for the memory address. The secret is that you must convert any address above 32767 by subtracting 65536 from the number. Therefore, the proper command to poke zero into the highest address of a 48K TRS-80 is POKE–1,0. To look at the contents of the top byte in a 48K TRS-80, your program can use, PRINT PEEK(-1).

If your program will be doing a lot of peeking and poking to high memory (above 32767), you may want to include the function calls listed below. They let your program handle memory addresses in single precision format so that you don’t have to worry about overflow errors.

To allow peeking or poking any address in the range 0 to 65535, define the following function early in your program:

DEFFNSI%(S1)=-((S!>32767)*(S!-65536))-((S1<32768)*S!)

Then you can PEEK FNSI%(#####) and POKE FNSI%(xxxx),xx


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 …

10 REMEMBER TO CHANGE XX IN LINE 50 WITH THE ASCII VALUE OF WHAT YOU WANT
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
50 DATA XX
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

Jim Swenson explains how this works:

16548 (40A4H) points to the first line of the program in memory, which will be 17129 (42E9H) by default.

16633 (40F9H) will point 1 byte past the end of the program. If you run NEW you will find it will be 17131 (42EBH).

With:

40A4: E9 42 (start of program)

Say your BASIC program is the following:

10 PRINT "HELLO"
20 GOTO 10

In memory, this will actually look like the following:

42E9: F7 42 0A 00 B2 20 22 48 45 4C 4C 4F 22 00
42F7: 00 43 14 00 8D 20 31 30 00
4300: 00 00
4302:
...
40F9: 02 43 (end of program)

The end of program is one byte past the 00 ending at 4301H, so it is 4302H. The TRS-80 ROM puts things LSB (least significant byte) then MSB (most significant byte), so 4302H would be represented as 02 43.

In memory, a line of a BASIC program is stored as follows:

  • 2 bytes: address of the next line
  • 2 bytes: the line number
  • n bytes: the line itself, with reserved words replaced by a single byte code. For example “PRINT” is B2, “GOTO” is 8D
  • 1 byte: 00

Taking the line 10 PRINT “HELLO” as an example:

42E9: F7 42 0A 00 B2 20 22 48 45 4C 4C 4F 22 00

42F7 (in LSB, MSB order) is the address of the next line in memory (i.e. for line 20)

000A is the line number (10, which is 0A in hexidecimal)

B2 20 22 48 45 4C 4C 4F 22 is the line of code:

B2 – PRINT

20 – space

22 – “

48 – H

45 – E

4C – L

4C – L

4F – O

22 – “

00 being the end of the line

The indication of the end of the program is when the address of the next line is 00 00. And 16633 (40F9H) will point 1 byte after that.

CLOAD will start loading data wherever 16548 (40A4H) points. So if you set it to (16633)-2 (which is (40F9H)-2), you’re pointing it to that 00 00 in memory. They when CLOAD completes and you restore the value in memory at 16548 (40A4H), you’re restoring the start of the program to its original value.


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

Finding the current line number being executed in a BASIC Program

In A …
A=PEEK(16546)+256*PEEK(16547)

Finding the current cursor location

In A …
A=PEEK(16416)+256*PEEK(16417)

Finding the current cursor character

In A …
A=PEEK(16418)

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
70 NEXT T
80 FOR T = 0 TO 15 : LPRINT S$(T) : NEXT
90 INPUT A$
100 GOTO 80

M. Thorpe’s Screen Graphics Hard Copy Generator

3000 ' 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
3160 RETURN

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

10 DEFINT I,J
20 CLS
30 FOR I = 0 TO 33
40 FOR J = 0 TO 50
50 A=INT(RND(0)+.5)
60 IF A=1 THEN SET(J,I)
70 NEXT J,I
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

Introduction

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:

TS=A$(I):A$(l)=A$(J):A$(J)=TS

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:

     T1=VARPTR(A$(I))
     T2=VARPTR(A$(J))
     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
		....		....
		END		START

The key is that you have a 3 byte instruction following the ORG 41BEH.