Page Index:
- Tokenized BASIC – Dick Straw
- Tokenized BASIC – Leonard Erickson
- Tokenized BASIC – Pete Cervasio
- Vidtex Escape Sequences
- Pokes and Peeks
- Disk Speed-Up Chart
Tokenized BASIC – Dick Straw
Down at the end of appendix C12 in your Level II BASIC Reference Manual you will discover the information that ASCII codes 129 through 191 are graphics codes, and ASCII 192 through 255 are tab codes. And they are. If you run something like
PRINT CHR$(200); CHR$(140)
You will get a graphic block set spaced appropriately eight spaces from the left margin of your screen. Actually, 128 is a graphics code too — it just doesn’t have any of the six segments of the graphics matrix set, so it comes out blank.
But that only tells part of the story, because those same 128 code values are used by the interpreter as spacesaving symbols equivalent to that list of reserved words on page A115 of the appendix in the manual. Here’s how it works –and how to see it for yourself.
When you start typing a line on your keyboard in the usual fashion, each keystroke is duly recorded in the 110 buffer as its ASCII code equivalent. When you push ENTER at the end of the line, the line you just typed is interpreted right on the spot — in the buffer. Each of the command or instruction words is converted to a single byte equivalent, with values between 128 and 255, inclusive. If there was no number at the beginning of the line, the instructions you just entered will be acted upon at once. If there was a line number, the whole line is transferred to the text memory location and put into its proper place.
Both of those locations can be examined using the PEEK command. The 110 buffer occupies 256 locations beginning at 16870, while the text memory starts at 17129 if you have no disk BASIC entered . I don’t have a printer or a disc, so it takes a lot of staring at the screen, but no big hazards.
Try this: write a short program, say, three lines or so. For example:
10 DEFINTA,L: DIM A(9)
20 FOR L = 0 TO 9: A(L) = 5 * L + 2
30 PRINTA (L);:NEXTL
Then run it. You get the line of ten numbers you expected. Now, in command mode, enter
FOR Z = 0 TO 200 : ?PEEK(17129 + Z);: NEXTZ
I got a string of numbers like the following you should too, if you used the same spacing I did. I will mark some places as I type this, in order to refer to them later, so remember that the underlining and the letters don’t come with the output.
Most of the numbers here are simply the ASCII codes for the individual letters and numbers used in the program — and the punctuation, too, of course. If you look them up in appendix C, you will find, for example, that 32 is a space and 58 a a colon.
First of all, remember that the program had three lines, numbered 10, 20, and 30. We can see those line numbers in the parts of the text marked B. It is easy to see them if you use line numbers below 256, because the numbers are entered in the usual manner for recording integers, with the least significant byte(LSB) first and the most significant byte (MSB) next, in two bytes. For low numbers, the MSB is zero and the LSB comes out as its real number. For higher numbers, you need to multiply the MSB by 256 and add the LSB to see what you have.
The two numbers ahead of the line numbers are marked B. These, In the same integer format, are the pointers to the next line of the program in the text memory. For example, 252 66 translates to 17148. Since the location of the first number, 252, Is 17129, we count over until we reach 17148 and find a 24, the first byte of the pointer to the third line. The pointer at the beginning of the third line points to a pair of zeroes, marked with an M – this means there is no next line, so the line we were in, in this case line 30, is the last in the program. Since every line of the program ends with a zero (marked E, above) you can locate not only the end of each line but the end of the program as well.
All those other big numbers in the program itself are the function codes I referred to earlier, and you can translate them either by comparison with the program itself or by looking them up in the table of function codes listed there. The first, for example, is 153, the equivalent of DEFINT.
Following the program itself you will find all the variables that were assigned values in the program (that Is why it was worth while to run it .before the PEEK). You need to know that every variable has a three-byte “name” that precedes each value itself. The first byte is a digit that both defines the type of variable and tells how many value-bytes there are. For example, the sequence 2 0 76, marked “L”, is the name of the integer variable L used as an index. The 2 tells you it is stored In two bytes. The next byte is the second symbol In the name, here a zero because we didn’t use a second symbol. It would be 49, the ASCII value of 1 if we had called the variable L1. The MSB of the name is 76, which is ASCII “L”.
The next one is something of a surprise at first. It starts out 4 0 90 — 4 is a single precision variable that needs four bytes for the value, and the name is Z – the variable used in the command line to print out the peek was put in here, shoving the other variables aside. If a double precision variable were used, its indicator would be an 8. After the Z valuer (the value it had when the printing command passed it up), we find the array, A. Its name is that of an integer, but the next values are descriptions of the array – two bytes for the length of the storage string (after the MSB of its value), one byte for the number of dimensions (here 1), and two bytes for the number of locations in each dimension. There is only one dimension here, with ten locations (0 to 9). Then come the ten values, two bytes each.
String arrays have a header beginning with 3, meaning three bytes are in storage. Those three bytes are not its value, obviously, but indicate the length of the string in the first byte (thus a limit of 256 characters), and the integer-format location of the first character in the string. If you assign the string value in the program, as in a print statement, the location pointed to will be in the program text. If it is a string whose value is assigned as a variable, it will be found at the end of the RAM memory.
So there is your whole program, laid out in the memory of your processor for the interpreter to read. And you can read it too. I have included the Hex values for the function codes in the table so that those who get a Hex dump say, from the RSM-1S monitor, can translate it also. Those masochists will also need to translate the ASCII values of letters and numbers from and into Hex, of course!
It is also interesting to look at the I/O buffer. If you type in a long command string, such as the PEEK routine we used to look at the text memory, you will discover that the little program is still there. The first parts of it will be written over as the line is shortened by conversion of the functions to their one-byte codes, and will end with three zeroes, but after that you can find the key-by-key entries you put in when typing.
You can also try this: with your program in residence and after a PEEK, as we did before, en-ter NEW, then run the PEEK on the same area again. You will find that the first two numbers are zeroes — meaning, sorry, no program. You will also find the variable you used to PEEK written in there too. But after that, the rest of the program will be in its original form. You can POKE the original numbers back into locations 17129 and 17130 and list the program again, with only the loss of the first line (if it was long enough not to be overwritten in your playing around).
You can figure out what most of the numbers between 128 and 255 mean by PEEKing at them just as described. But a lot of those numbers don’t mean-anything unless you have disc basic. You can still see what they mean if you try the following:
Enter a short program, say, two lines, like this:
10 A = 10
20 PRINT A
You know that the text will be located beginning at location 17129, with the first four bytes devoted to the pointer and line number. So POKE into 17133 (the first byte of the program itself) and maybe a couple of others — but be sure not to get past the end of the line, and then LIST the program. Line 10 will be there, and so will the meanings of the numbers you POKEd in. Most of them won’t run, of course, unless you have disc running, but the listing will still do the translating for you.
Tokenized BASIC – Leonard Erickson (a/k/a Shadow)
Each “line” starts with the 2-byte address of the start of the *next* line. Then there’s the line number. Both are binary integers in LSB MSB format. This is followed by the text of the line, with BASIC keywords replaced by one byte tokens. All tokens have bit 8 set.
Here are the single byte model 4 codes:
128 171 AUTO 214 NOT 129 END 172 RENUM 215 ERL 130 FOR 173 DEFSTR 216 ERR 131 NEXT 174 DEFINT 217 132 175 DEFSNG 218 USING 133 INPUT 176 DEFDBL 219 INSTR 134 DIM 177 LINE 220 ' 135 READ 178 221 VARPTR 136 LET 179 222 137 GOTO 180 WHILE 223 ERRS$ 138 RUN 181 WEND 224 INKEY$ 139 IF 182 CALL 225 MEM 140 RESTORE 183 WRITE 226 TIME$ 141 GOSUB 184 COMMON 227 142 RETURN 185 CHAIN 228 143 REM 186 OPTION 229 144 STOP 187 RANDOM 230 145 PRINT 188 231 146 CLEAR 189 SYSTEM 232 147 LIST 190 233 148 NEW 191 OPEN 234 149 ON 192 FIELD 235 150 WAIT 193 GET 236 151 DEF 194 PUT 237 152 POKE 195 CLOSE 238 153 CONT 196 LOAD 239 154 197 240 > 155 198 241 = 156 OUT 199 NAME 242 < 157 LPRINT 200 KILL 243 + 158 LLIST 201 LSET 244 - 159 CLS 202 RSET 245 * 160 203 SAVE 246 / 161 204 247 ^ 162 ELSE 205 SOUND 248 AND 163 TRON 206 249 OR 164 TROFF 207 TO 250 XOR 165 SWAP 208 THEN 251 EQV 166 ERASE 209 TAB 252 IMP 167 EDIT 210 STEP 253 MOD 168 ERROR 211 USR 254 \ 169 RESUME 212 FN 255 170 DELETE 213 SPC
The 2 byte codes all start with a 255 byte (FFh), the second byte is listed below:
128 146 LEN 164 129 LEFT$ 147 STR$ 165 130 RIGHT$ 148 VAL 166 131 MID$ 149 ASC 167 132 SGN 150 CHR$ 168 133 INT 151 PEEK 169 134 ABS 152 SPACE$ 170 CVI 135 SQR 153 OCT$ 171 CVS 136 RND 154 HEX$ 172 CVD 137 SIN 155 LPOS 173 EOF 138 LOG 156 CINT 174 LOC 139 EXP 157 CSNG 175 LOF 140 COS 158 CDBL 176 MKI$ 141 TAN 159 FIX 177 MKS$ 142 ATN 160 178 MKD$ 143 FRE 161 179 ROW 144 INP 162 145 POS 163
Tokens – Pete Cervasio
REM is 143. The three byte sequence is :, 143, 251 and in the program below I decode 251 as the single quote.
I’ve converted this one and my Model 4 converter to Turbo Pascal recently, and they allow things like having the keywords come out in upper/lower/mixed case, and other fun stuff like that. I’ll put them up on the web when I get them finished up a little more.
One weird thing: Model 1/3 basic stores literal numbers as the ASCII representation of those numbers. Model 4 basic stores them in the binary representation.
' Model 1/3 compresed BASIC to ASCII format converter thingie ' Copyright (c) 1998, Peter Cervasio (cervasio@airmail.net) ' Permission to distribute freely is granted to all. DEFINT A-Z DIM KeyWord$(256) false = 0 true = NOT false READ First%, Last% FOR i = First% TO Last% READ KeyWord$(i) NEXT PRINT "MOD1BAS - Model 1/3 BASIC to ASCII Conversion Program" PRINT "Copyright (c) 1997, Pete Cervasio" PRINT "Distribute freely" PRINT PRINT "Model 1/3 BASIC file to convert: "; LINE INPUT TheFile$ IF TheFile$ = "" THEN END PRINT "Enter output filename: "; LINE INPUT OutFile$ IF OutFile$ = "" THEN IF INSTR(TheFile$, ".") = 0 THEN OutFile$ = TheFile$ + ".qbx" ELSE OutFile$ = LEFT$(TheFile$, INSTR(TheFile$, ".")) + "qbx" END IF END IF OPEN TheFile$ FOR BINARY AS 1 A$ = " " GET 1, , A$ IF A$ = CHR$(255) THEN PRINT TheFile$; " -> "; OutFile$ OPEN OutFile$ FOR OUTPUT AS 2 WHILE NOT EOF(1) GET 1, , i% IF i% = 0 THEN END GET 1, , i% IF i% > 0 THEN PRINT #2, LTRIM$(RTRIM$(STR$(i%))); " "; ELSE PRINT #2, LTRIM$(RTRIM$(STR$(65536! + i%))); " "; END IF linedone = false WHILE NOT linedone GET 1, , A$ IF A$ = CHR$(0) THEN linedone = true ELSE j = ASC(A$) IF (j >= First%) AND (j <= Last%) THEN PRINT #2, KeyWord$(j); ELSE PRINT #2, A$; END IF END IF WEND PRINT #2, "" WEND ELSE PRINT "Could not recognize "; TheFile$; " - 1st byte not 0xFF" END IF CLOSE END DATA 128, 251 DATA END, FOR, RESET, SET, CLS, CMD, RANDOM, NEXT, DATA, INPUT, DIM DATA READ, LET, GOTO, RUN, IF, RESTORE, GOSUB, RETURN, REM, STOP DATA ELSE, TRON, TROFF, DEFSTR, DEFINT, DEFSNG, DEFDBL, LINE, EDIT DATA ERROR, RESUME, OUT, ON, OPEN, FIELD, GET, PUT, CLOSE, LOAD DATA MERGE, NAME, KILL, LSET, RSET, SAVE, SYSTEM, LPRINT, DEF, POKE DATA PRINT, CONT, LIST, LLIST, DELETE, AUTO, CLEAR, CLOAD, CSAVE DATA NEW, "TAB(", TO, FN, USING, VARPTR, USR, ERL, ERR, STRING$, INSTR DATA POINT, TIME$, MEM, INKEY$, THEN, NOT, STEP, "+", "-", "*", "/" DATA "^", AND, OR, ">", "=", "<", SGN, INT, ABS, FRE, INP, POS, SQR DATA RND, LOG, EXP, COS, SIN, TAN, ATN, PEEK, CVI, CVS, CVD, EOF, LOC DATA LOF, MKI$, MKS$, MKD$, CINT, CSNG, CDBL, FIX, LEN, STR$, VAL, ASC DATA CHR$, LEFT$, RIGHT$, MID$, "'"
Pokes and Peeks – Valley TRS-80 Hackers Group (A Levinson and E Bagai)
POKE 17171,201
VIDTEX ESCAPE SEQUENCES – Neil Morrison
VIDTEX lets the host computer perform screen control functions through escape sequences. Remember that these are remote functions executed by the host and cannot be performed from the keyboard. The following table summarizes the screen control sequences and the functions they perform. Note the difference between lower and uppercase.
Escape Control Sequence Summary:
Graphics Mode:
An {ESC}G4 is used by the host to specify semi-graphics 2 x 2 mode. These codes are used internally by the Videotex Plus software and cannot be generated from the keyboard. In this mode the parity bit is used to distinguish between graphic and ASCII characters. If the parity bit is zero, the character is a standard ASCII character. If the parity bit is one, the character is a graphics character.
Model II Videotex Plus does not support graphics or color. When graphics mode is required by the host. similar Model II graphics characters are substituted for the graphics codes. These are not true representations of Videotex’s standard graphics.
DISK SPEEDUP CHART
----------I------------------------------- I Delay in miliseconds Command I 40 20 10 05 ----------I------------------------------- RESTORE I 0B 0A 09 08 ----------I------------------------------- SEEK I 1B 1A 19 08 ----------I-------------------------------
Program I DOS Trk. Sec Byte Org. Ndw Command ----------I------------------------------------------,----- BOOT/SYS I ALL* 0 0 B9 361B 3618 SEEK (except ND80) I NEWDOS 0 0 6A 361B 3618 SEEK (only ND80) I 80.1 0 0 A5 360B 3608 RESTORE (only ND80) ------,---------------------------------------------------- I TRSDOS 0 7 51 3E1B 3E18 SEEK I (ALL) 0 7 C4 3E0B 3E08 RESTORE I ------------------------------------------- I NEWDOS 0 7 0E 3E0B 3E08 RESTORE SYS0/SYS I 2.1 0 9 0E 3E1B 3E18 SEEK H ------------------------------------------- I NEWDOS 0 8 CC 3E0B 3E08 RESTORE I 80.1 0 8 FD 3E1B 3E18 SEEK I ------------------------------------------- I VTOS 0 7 15 3E1B 3E18 SEEK I 3.0 0 7 90 3E0B 3E08 RESTORE ----------I------------------------------------------------
Note: The values under the “new” column are for 5 milisecond operation.
For 20 ms. change 18 to 1A, 08 to 0A.
- Older Shugarts and some newer ones use 40 ms.
- Some newer Shugarts can use 40 or 20 ms.
- Micropolis uses 40 ms.
- Pertecs can use 40 or 20 ms.
- MPIs and Siemens can use 40, 20, 10, or 5 ms.