Page Index:

Game Bugs


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.

128     END
129     FOR             170     KILL            211     OR
130     RESET           171     LSET            212     >
131     SET             172     RSET            213     =
132     CLS             173     SAVE            214     <
133     CMD             174     SYSTEM          215     SGN
134     RANDOM          175     LPRINT          216     INT
135     NEXT            176     DEF             217     ABS
136     DATA            177     POKE            218     FRE
137     INPUT           178     PRINT           219     INP
138     DIM             179     CONT            220     POS
139     READ            180     LIST            221     SQR
140     LET             181     LLIST           222     RND
141     GOTO            182     DELETE          223     LOG
142     RUN             183     AUTO            224     EXP
143     IF              184     CLEAR           225     COS
144     RESTORE         185     CLOAD           226     SIN
145     GOSUB           186     CSAVE           227     TAN
146     RETURN          187     NEW             228     ATN
147     REM             188     TAB             229     PEEK
148     STOP            189     TO              230     CVI
149     ELSE            190     FN              231     CVS
150     TRON            191     USING           232     CVD
151     TROFF           192     VARPTR          233     EOF
152     DEFSTR          193     USR             234     LOC
153     DEFINT          194     ERL             235     LOF
154     DEFSNG          195     ERR             236     MKI$
155     DEFDBL          196     STRING$         237     MKS$
156     LINE            197     INSTR           238     MKD$
157     EDIT            198     POINT           239     CINT
158     ERROR           199     TIME$           240     CSNG
159     RESUME          200     MEM             241     CDBL
160     OUT             201     INKEY$          242     FIX
161     ON              202     THEN            243     LEN
162     OPEN            203     NOT             244     STR$
163     FIELD           204     STEP            245     VAL
164     GET             205     +               246     ASC
165     PUT             206     -               247     CHR$
166     CLOSE           207     *               248     LEFT$
167     LOAD            208     /               249     RIGHT$
168     MERGE           209     ^               250     MID$
169     NAME            210     AND             251     (REM QUOTE)

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)

PEEK 14312
If the line printer status port is > 63 then the printer is not on or ready to print. Power off =255; print inhibit switch (off line) enabled =233 or 223; print buffer full =191; ready to accept data =63 (normal).
PEEK 14316
The disk status register =255 when there is no expansioninterface conncected or powered on.
POKE 14308,0
Latches cassette #1
POKE 14308,1
Latches cassette #2
POKE 16396,23
Disable the BREAK key (Level II)
POKE 16396,199
Causes BASIC to reinitialize when the BREAK key is hit (Level II)
POKE 16405,0
Locks up the keyboard, but lets your program keep running
PEEK 16549
If < 66 then this is not Disk BASIC
POKE 17170,175
POKE 17171,201
Disable the BREAK key
POKE 23461,0
Disable the BREAK key (NEWDOS 2.1)
POKE 23886,0
Disable the BREAK key (TRSDOS 2.3)

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:

Sequence
Function
{ESC}{ESC}O
Open RAM buffer
{ESC}{ESC}C
Close RAM buffer
{ESC}{ESC}Z
Zero RAM buffer
{ESC}A
Cursor up
{ESC}B
Cursor down
{ESC}C
Cursor right
(ESC)D
Cursor left
{ESC}G4
Semi-graphics 4 mode
{ESC}GN
Text mode
{ESC}H
Home cursor
{ESC}J
Clear to end of page
{ESC}K
Clear to end of line
{ESC}Y line col
Position cursor
{ESC}b
Lock keyboard
{ESC}c
Unlock keyboard
{ESC}e
Disable display
{ESC}f
Enable display
{ESC}g
Restart VIDTEX
{ESC}j
Clear Page
{ESC}l
Normal character width
{ESC}m
Wide character width
{DC1}
XON
{DC2}
Printer on
{DC3}
XOFF
{DC4}
Printer off

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.