Ira Goldklang's TRS-80 Revived Site

Level II Tips & Tricks

       



         System Status/ID
PEEK 14316      The disk status register =255 when there is no expansion interface conncected or powered on.
PEEK 16549      If <66 then this is not Disk BASIC
PEEK 125      If = 2, its a MODEL II
If = 4, its a MODEL 4/4D
If = 5, its a MODEL 4P
If = 12, its a MODEL 12
PEEK &H85      If = &H61 THEN System is TRSDOS 6.1.x
If = &H62 THEN System is TRSDOS 6.2.x
If = &H63 THEN System is LS-DOS 6.3.x
(PEEK(124)AND &H40)<>0      Extended Error Message IS displayed.
(PEEK(119)AND 128)<>0      Full File Access is ENABLED
PEEK(&HB94)<>0      Special Character Mode is ON

Top of Page




         Keyboard Tips/Tricks
Disable The Keyboard (Programs Still Run)      POKE 16405, 0
Enable The Keyboard      POKE 16405, 1
Disable the Break Key (L2)      POKE 16396, 23
Disable the Break Key (DOS)      POKE 17170, 175
POKE 17171,201
Disable the Break Key (NewDOS v2.1)      POKE 23461,0
Disable the Break Key (TRSDOS v2.3)      POKE 23886,0
Enable the Break Key (L2)      POKE 16396, 201
Break Key is ENABLED IF      (PEEK(124)AND &H10)<>0
Change BREAK to SHIFT-BREAK      POKE 16396, 165
Change BREAK to RESET      POKE 16396, 233
Causes BASIC to reinitialize when the BREAK key is hit (L2)      16396,199
Determine if ANY key is pressed      IF PEEK (14463) = 0
Determine if ANY key other than SHIFT is pressed      IF PEEK (14591) = 0
Change the JUMP location on pressing the RESET button      POKE 16391, LSB
POKE 16392, MSB
Turn Special Character Set to ON      ON: POKE &HB94,(PEEK(&HB94) OR 8 )
OFF: POKE &HB94,(PEEK(&HB94) AND 247)
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)
OFF: POKE 124,(PEEK(124) AND &HBF)
Three Line Scroll Protect      ON: POKE &HB94,(PEEK(0) OR 8)
OFF: POKE &HB94,(PEEK(0) AND 8)
Change Cursor Character to XX      POKE &HB98,nn

Top of Page




         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

Top of Page




         Printer Tips/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)



         Key Word Tips/Tricks
Disable List Command      POKE 16863, 145
POKE 16864, 25
POKE 16865, 26
Enable List Command      POKE 16863, 201
Disable LLIST Command      POKE 16422, 103
POKE 16423, 00
Recover a BASIC program which has been destroyed by typing "NEW"?      POKE 17130,1
SYSTEM
* / 11395
LIST
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.
LIST = L.
END = F.
THEN = T.
GOTO = G.
INPUT = IN.
MEM = M.
FOR = F.
         NEXT = N.
STEP (after FOR) = S.
STOP = ST.
CONT = C.
TAB (after PRINT) = T.
INT = I.
GOSUB = GOS.
RETURN = RET.
READ = REA.
DATA = D.
         RESTORE = REST.
ABS = A.
RND = R.
SET = S.
RESET = R.
POINT = P.
PRINT AT = P.A.
CLOAD = CL.
CSAVE = CS.



         Input/Output Tips/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
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
Latches Cassette 2      POKE 14308,1



         Misc. Tips/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 your in DOS BASIC      SYSTEM
/ 20992



         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




         Multiple USR Calls
The following heading in the machine program permits as many USR calls as memory allows. A call for USR(0) goes to program 0, a call for USR(1) goes to program 1, etc. As it stands it can be used for graphics. If data needs to be passed to the machine program then Memory Size shoul dbe set to the appropriate number of bytes below the origin of the heading, the data poked into this "scratchpad" before calling USR(n), and program (n) then loads from teh "scratchpad" as desired.

The first line of each program should bear the appropriate label - PRGO, PRG1, etc. It is, of course, imperative that no changes be made between CALL 2687 and JP PRGn.

Assembly language heading for multiple USR calls.
                ORG     nnnn
(LABELS)        EQU     (as desired)
                 "              "
                CALL    2687
                XOR     A
                LD      B,3
        DISPL   ADD     A,L
                DEC     B
                JP      NZ,DISPL
                LD      L,A
                LD      BC, $+5
                ADD     HL, BC
                JP      (HL)
                JP      PRG0
                JP      PRG1
                JP      PRG2



                JP      PRGn




         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    12763
Sound255191

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 T R 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:
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.