Updates and corrections are gratefully accepted. Last modify 13 April 2016.
Back to "How To Program In GBASIC" | Back to "Programming the Tomy Tutor" | Back to the main page
Tomy GBASIC, as shown in the
original Tutti.
Historically, the major problem has been no surviving significant documentation of GBASIC (that we know of), so there's no comprehensive description of its keywords and capabilities available. This incomplete treatise is based upon experimentation and derivation from the manual's sparse GBASIC programming examples as well as careful bytewise analysis of tape dumps from XTOMYDEV.
All MONitor commands are four characters long. Any trailing characters
are ignored (e.g., GBASIC
== GBAS
).
Command | Description |
BASI | Switches to regular Tomy BASIC mode (on those machines [American Tutors and upgraded Grandstand Tutors] that support it). |
DIRC | Undocumented and does not seem to work on English GBASIC systems, but early Japanese GBASIC had a katakana command 'oshiete' ('listing'). Junya notes this command in his table, but it does not work on either of my American systems. |
EDIT | Enters the GBASIC editor, keeping any program in memory resident. |
GBAS | Enters the GBASIC editor and clears any program in memory. |
GRAP | Exits the monitor. This seems to clear any program in memory, so save it first. |
GRUN | Starts a program in memory (if one does not exist, it generates a
COMD ERR ). |
LOAD | Loads a file from tape. You are prompted for the filename. |
MENU | Returns to the main menu. |
SAVE | Saves a file to tape. You are prompted for the filename. This saves screen, sprite and GBASIC data, all in one piece. |
STEP | Undocumented. Enables step-by-step traced execution. Each line is displayed in green one line up from the bottom. Step through the code with the RT key. |
VERI | Verifies a file on tape. You are prompted for the filename. |
GBASIC has an rather unusual memory format. Program lines are encoded in VDP RAM as groups of 8-byte octets. Each octet has a two-byte header, either the line number (a 16-bit big endian short with the high bit set) or two nulls indicating a "continuation" from the previous octet. The variable table starts at byte offset 1600 in the 1960 bytes available for GBASIC programs, so there can be a maximum of 200 octets and thus (at least in theory) 200 lines. Lines are padded out to the full octet multiple with nulls, which is terribly inefficient for storage, but seems to be a concession to allow faster line editing.
Each GBASIC line has a "leader token" which immediately follows the line
number in the first octet. Only certain keywords are allowed
in this position. The low nybble is the actual token; the high nybble is
the total number of octets in the line. If the high nybble is greater than 1,
then various continuation octets (with null line numbers) follow. Multiple
statements per line are not permitted. The last line is always an
END
token.
There is no explicit line delimiter since the end of a program line can always be determined from its internal structure.
The program variable table starts at offset 1600 (0x640). It consists of six byte entries, with the four byte variable name (space padded) followed by a 16-bit reference count. The actual variable type is encoded in the program text. All variables are referenced by index into this variable table, which saves valuable space within the octets. Under this scheme, 60 unique variable names are available.
STOP
, END
,
etc.). Other tokens are displayed as the entire byte. Some
tokens mean different things depending on the context: $1A as the leader
token is END
,
but $1A in the left side or right side of a LET
statement is
ANIM
.
Many keywords share a common 16(?)-byte work area in VDP RAM for their
manipulations. This is
important not only from an interference point of view, but it also indirectly
allows more direct control over screen data; with a little thought,
clever ordering of keyword sequences can allow arbitrary
bytes to be written to VDP RAM
(see CELL
for an example).
In general, entering an expression or an unexpected or out-of-range value where a literal is expected causes an entry error.
Keyword | Token | Description |
ANIM a | $1A |
When used on the right side of an assignment (i.e., LET ...=ANIM
... ), it
returns a 16-bit quantity corresponding to the X (LSB) and Y (MSB) position
of sprite number a (1-4). When used on the left, it acts as a
variable reference to one of the same four sprites.
(ANIM expr is illegal and causes an entry error; a must be an integer literal.)
This can be used to grab a sprite location e.g. 5 LET X=1 6 LET Y=41 210 KEY 1 J,K 220 IF J=0 THEN GOTO 210 230 IF J>5 THEN GOTO 260 240 LET X=X+1 250 GOTO 270 260 LET X=X-1 270 LET ANIM 4=POST(Y,X) 280 LET ANIM 3=ANIM 4 290 GOTO 210 1000 ENDExpressions like ANIM 4=3+(X*3) are legal (though, oddly,
ANIM 4=(X*3) causes a runtime error), as is
ANIM 4=POST(3,4)+2 (puts the sprite at 6,3), and it can
also be used on the right-hand side X=(ANIM 3)+4*5 of
an expression as well.
See the |
CELL(a) | $1B |
When used on the right side of an assignment (i.e., LET
...=CELL(...) ), it
loads the 16(?)-byte image of 8x8 screen cell a (1-768) into the workspace.
The last eight bytes consist of the bit pattern in the cell, and the first
eight consist of the colour data. a may be an expression. When used on the
left side, it acts as a reference for that same screen cell. (If a is
less than one or a is greater than 768, a blank black cell is returned.)
The documented use in the manual is for simple copying of screen data
using assignment operations 10 FOR 30 A=2 TO 768 20 CELL(A)=CELL(1) 30 NEXT 1000 ENDHowever, clever manipulation of the workspace means we're not limited to simply copying what's on screen already. Because string and integer operations affect only part of the workspace area, they can be thus used to change portions of a screen cell independently. To wit, 10 X=CELL(5) 20 E$="ABCDEFGH" 30 CELL(6)=E$ 1000 ENDThis code fragment copies the bit pattern from cell 5 (X is just thrown away), but replaces its colour data with the colour set represented by the ASCII values of string E$, and copies the hybrid cell to cell 6. By the same token (no pun intended), it is also possible to set the bitmap data, using a slightly different idiom: 10 E$="ABCDEFGH" 20 CELL(5)=E$ 1000 ENDor set them simultaneously: 10 E$="ABCDEFGH" 20 CELL(5)=E$ 30 X=CELL(5) 40 CELL(5)=E$ 1000 ENDCells cannot be compared in IF-THEN using the CELL
operator overtly (e.g., IF CELL(5)=X and
IF CELL(5)=CELL(6) both cause entry errors). While using
CELL in an expression like A=CELL(85)+3 causes
no entry error, it causes a runtime error.
|
END | $1A |
Standard BASIC, with the added side effect of terminating the editor and
returning to the MONitor when this command is entered as a program
statement.
If you just want to enter a command to halt the program's execution and are
not finished in the editor, try STOP .
|
FOR next var=from TO to STEP step, NEXT | $x3, $13, $14, $14 |
Standard BASIC, with the addition of the next parameter, which
tells GBASIC the line number where the NEXT is for this
loop, e.g. (same as the initial CELL example),
10 FOR 30 A=2 TO 768 20 LET CELL(A)=CELL(1) 30 NEXT 1000 ENDNote that the next parameter isn't for compile mode, but rather for entry mode. If you enter a NEXT on a line that hadn't been
previously
declared as a NEXT in a preceding FOR statement,
an entry error results (so NEXT-w/o-FOR is thus handled during entry mode, not
runtime mode).
Loops are nestable. Unlike most BASICs, however, from, to and step must all be integer literals: expressions generate an entry error.
|
GOTO | $11 |
Standard BASIC. Serious undocumented crash bug: a GOTO pointing
to a non-existent line number causes the computer to lock up during
compile mode!!! There is no runtime error for undef'ed statement
error because GBASIC never gets that far! This bug is also present in
GSUB and THEN .
Calculated branches ( The line number is encoded as a big-endian 16-bit integer with the most significant bit set, as is true for all branching instructions. |
GSUB, RTN | $15, $16 |
Same as GOSUB and RETURN in standard BASIC. Serious undocumented crash bug
in all branching instructions; see GOTO !!
RTN -w/o-GSUB
causes a runtime error.
The line number is encoded as a big-endian 16-bit integer with the most
significant bit
set, as is true for all branching instructions.
|
HORZ(a) | $1D |
Undocumented. Returns the X coordinate of a 16-bit sprite
position quantity (e.g., HORZ(ANIM 3) gives the X
position of sprite 3). See
POST for the sprite coordinate system. a can be an
expression, and HORZ can be used in expressions too (basically
a rapid equivalent to taking the LSB of a 16-bit integer).
|
IF, THEN | $x2 |
Standard BASIC, but with a limited comparison syntax; IF
can only compare variables with variables, or one literal with one
variable (IF 5=3 , bizarrely, generates an entry error).
Worse, you cannot do string comparisons (either literal vs.
variable, or variable vs. variable).
However, IF is the only keyword that can read the current
value of a timer (see TIME ).
Comparators are limited to = > < <> >= and
<= as all others generate an entry error.
The line number is encoded as a big-endian 16-bit integer with the most significant bit set, as is true for all branching instructions. |
KEY a b,c | $x8 |
Reads controller a (1 or 2)
and places the joystick direction value into variable b and the
button value into variable c. See ANIM for an example. a
must be an integer literal, and unlike BASIC, you cannot use KEY 0
to read the keyboard (bummer); using a variable or using 0 (or 3+) will
generate entry errors. With a single joystick, it is read using
either controller value.
The directional values are arranged clockwise 1-8, starting with 1 for North, and ending at 8 for NW. The button values are 1 for SR, 2 for SL and 3 for both. Zero in either indicates no button and/or direction. The keyboard situation is not a total loss, as some keys can be read on the controllers (the number given is the value in the variable):
10 PRNT 1,"STICK 1" 20 PRNT 33, "STICK 2" 30 KEY 1 A,B 40 KEY 2 C,D 50 PRNT 8, A 60 PRNT 16, B 70 PRNT 40, C 80 PRNT 48, D 90 GOTO 30 100 END |
LET | $x0 |
Assignment of expressions to variables.
LET is optional, but is a true token even though
it never appears in listings even when explicitly entered.
For integer variables,
You can assign integer quantities to string variables,
but this doesn't act like BASIC
Assigning string literals to integer variables causes an entry error. |
OVFL [ON/OFF] | $1B [$11/$10] |
Undocumented. This enables runtime math errors (what a pleasant, uh,
feature ...), which default to OFF on each GRUN . When enabled
with OVFL ON , math operations that would cause a math
overflow (such as 65535+1 or 1/0) now generate a runtime error instead of
being silently ignored and/or wrapping. This program generates a runtime
error on line 3:
1 OVFL ON 2 A=65535 3 A=A+1 4 END |
POST(y,x) | $1F |
Turns an ordered pair (x,y) into a 16-bit quantity
(note that the Y-coordinate is specified
first) which can used directly in calculations, or
be passed to ANIM to set a sprite position
(see ANIM for an example). x and y may be regular integer
expressions, and POST can be used itself in expressions
(e.g. ANIM 4=POST(3,4)+2 is legal and executable).
POST uses at a minimum the first two bytes of the workspace
region as a scratch pad.
As mentioned under The sprite coordinate system is a little strange and does not seem to match up fully with documented 9918A behaviour. As expected from 9918A documentation, a Y of 0 is on the second scan line from the top, 1 on the third, 2 on the fourth, etc., down to 192 which is now fully off-screen. 255 is exactly on the top scan line, 254 moves it up one into the border so the top sprite pixels are off-screen, 253 moves it up two, 252 moves it up three, and so on until it is completely obscured at 224 in the border. X, however, is not standard. An X coordinate of zero always hides the sprite, no matter what the Y coordinate is. There is no support for the Early Clock bit, so an X of 1 is at the left hand side, though the sprite may be scrolled into the right hand border (up to 255). Thus, after all that, in GBASIC the upper left hand corner is at
|
PRNT a,b | $x9 |
Prints b to cell position a (1-761); e.g., PRNT 44,"GBASIC"
prints the string GBASIC at cell position 44.
b must either be a string literal (no longer than eight characters), an
integer variable, or a string variable (entry error otherwise).
Strangely, integer literals are
not accepted and cause entry errors, but Strings are left justified; integers are right justified.
|
RAND(a) | $1E |
Returns a random number between 0 and a, inclusive. a may be an expression,
and RAND may be used in expressions itself (e.g.
A=(4*RAND(Q)-3) is legal). There is no RANDOMIZE .
|
STOP | $17 |
Standard BASIC, but when entered as a keyword (unlike END ), the
editor is not terminated. During runtime, when a STOP is found,
the line is displayed, and execution halts.
|
TIME a {ON} | $xC [$11] |
When used with the optional ON parameter,
enables one of the built-in timers, of which five are documented but
seven appear to exist, specified
by a (e.g., TIME 5 ON enables timer 5). a must be a literal
(1-7); otherwise, an entry error occurs.
Each timer counts up by one every 1/100 sec, up to a maximum value of 4000.
Irritatingly, the actual value of the timer cannot be directly
referenced (let alone altered) in expressions (
There is no way to reset the timers except to stop the program, and
|
TONE NOa | $1D ($21, $22, $23, $24) |
Plays predefined sound a (1-4). Note that there is no space between NO and
the a parameter -- it's TONE NO1 and not TONE NO 1
as it occasionally appears or at least looks like in the manual. a must be
an integer literal; otherwise, an entry error occurs.
Tone 1 is the key beep; tone 2 is the error buzz; tone 3 is the 'da da da'
three-tone acknowledge sound; and tone 4 is the buzz'n'hiss crash sound (like
the one you get from biffing it in Traffic Jam). Playback is asynchronous
and goes in the background; a new
Even though a could have have been represented as an integer,
|
VERT(a) | $1C |
Undocumented. Returns the Y coordinate of a 16-bit sprite
position quantity (e.g., VERT(ANIM 3) gives the Y
position of sprite 3). See
POST for the sprite coordinate system. a can be an
expression, and VERT can be used in expressions too (basically
a rapid equivalent to taking the MSB of a 16-bit integer).
|
Symbol | Token |
=, <, > | $01, $08, $09 |
), ( | $02, $07 |
+, -, *, / | $03, $04, $05, $06 |
, | $0B |
" | $0E |
$ | $0F |
Token | Description |
$30 | Indicates an unsigned 16-bit big-endian integer follows (negative quantities have a unary negation operator instead, prior to the $30 token). |
$4x | Indicates an integer variable reference. The index into the variable table is stored in the lower 6 bits, but since there are only 60 variable table slots, only indices 0-59 are valid. |
$Cx | Indicates a string variable reference (a $ token always follows). The index into the variable table is stored in the lower 6 bits, but since there are only 60 variable table slots, only indices 0-59 are valid. |