VOLUME A1 -- SC-3000 BASIC GUIDE
SC-3000 BASIC Level III-B — part of the SE3K documentation library, also readable inside the emulator.
============================================================================
SC-3000 BASIC LEVEL III-B
VOLUME A1 -- SC-3000 BASIC GUIDE
============================================================================
Level : beginner -- no prerequisites
References : Vol. B (quick syntax) * Vol. D ch. 1 (POKE/CALL)
TABLE OF CONTENTS:
Chapter 1 First contact .............................................. A-3
Chapter 2 Variables, types, operators ................................ A-7
Chapter 3 Flow control ............................................... A-14
Chapter 4 Text and screen ............................................ A-20
4.10 LPRINT -- print to serial printer
4.11 HCOPY -- copy screen to printer
Chapter 5 Graphics ................................................... A-27
Chapter 6 Sound ...................................................... A-38
Chapter 7 Input and timer ............................................ A-43
Chapter 8 Cassette ................................................... A-49
Chapter 9 Direct hardware access ..................................... A-53
Chapter 10 Error table ................................................ A-57
CHAPTER 1 -- FIRST CONTACT
CHAPTER 1 -- FIRST CONTACT ============================================================================
1.1 Start-up
1.1 Start-up
----------------------------------------------------------------------------
Insert the BASIC Level III-B cartridge into the slot on the back of the
SC-3000 before switching on. When you press the power button the welcome
screen appears with a blinking cursor and the message:
SEGA SC-3000 BASIC Level 3 ver 1.0
Export Version With Diereses
Copyright 1983 (C) by MITEC
XXXXX Bytes free
Ready
_
XXXXX is the number of free RAM bytes (depends on the RAM installed).
The "_" symbol means the system is ready. This is direct mode: every
command you type is executed as soon as you press CR.
1.2 Direct mode
1.2 Direct mode
----------------------------------------------------------------------------
In direct mode commands are not stored: they execute immediately.
This is useful for quick calculations or testing individual statements.
Try typing:
PRINT 2+2
and press CR. The result "4" appears on screen at once. Also try:
PRINT "HELLO WORLD"
Text strings must be enclosed in double quotes.
1.3 Screen-based input
1.3 Screen-based input
----------------------------------------------------------------------------
The SC-3000 has no separate line buffer. The text screen itself is the
editing surface: characters you type appear at the cursor position on
screen. Nothing is sent to the interpreter until you press CR.
When you press CR the BASIC interpreter scans upward from the current
screen row to find where the input started, then reads each character
forward from VRAM row by row and passes them to the parser. Because the
screen is the buffer, a single logical line can wrap across multiple
screen rows (the input area is 38 columns wide; a 38-character line
fills one row, longer lines continue on the next). This also means you
can use the four arrow keys to move the cursor anywhere on screen and
overtype, correct, or re-enter text before pressing CR.
Useful keys while editing:
* Arrow keys -- move cursor freely on the screen
* INS/DEL -- delete: cursor moves one position left and
the character there is erased
* SHIFT + INS/DEL -- enter insert mode (cursor blinks faster);
each character typed is inserted at the cursor
and existing text shifts right; exit by
pressing CR, any arrow key, or SHIFT+INS/DEL
* CTRL + E -- erase all characters from cursor to end of row
* CTRL + U -- clear the current row and return cursor to
the start of that row (cancel current input)
* BREAK -- stop a running program (not for line editing)
Important: editing visible characters on screen with the cursor does NOT
update the program in memory until CR is pressed. If you correct a line
after LIST and then move away without pressing CR, the change is lost.
1.4 Writing a program
1.4 Writing a program
----------------------------------------------------------------------------
A program is a numbered sequence of statements. Each line begins with a
line number (a positive integer from 1 to 65535). Lines are executed in
ascending numeric order.
Type these three lines, pressing CR after each one:
10 PRINT "WELCOME"
20 PRINT "TO THE SC-3000"
30 END
To list the program use LIST:
LIST
To run it use RUN:
RUN
The two strings appear on screen, then the cursor returns to the
"Ready" prompt.
1.5 Editing and deleting lines
1.5 Editing and deleting lines
----------------------------------------------------------------------------
To edit a line, retype it with the same number; the new version replaces
the old one.
20 PRINT "IN THE SC-3000 WORLD"
To delete a single line type only its number and press CR:
20
To delete a range of lines use DELETE:
DELETE 10-30
To delete the entire program and all variables use NEW:
NEW
1.6 Automatic line numbering
1.6 Automatic line numbering
----------------------------------------------------------------------------
The AUTO command generates line numbers automatically. Once active, each
time you press CR the next line number appears ready to be filled in:
AUTO 10,10
type the statements and press CR; the cursor moves to line 20, then
30, and so on. Press BREAK to exit AUTO mode.
1.7 Renumbering lines
1.7 Renumbering lines
----------------------------------------------------------------------------
If you have inserted lines in the middle of the program and want to
tidy them up:
RENUM
rewrites all lines starting from 10 with a step of 10. Numbers in GOTO,
GOSUB and IF-THEN are updated automatically.
1.8 File management on cassette
1.8 File management on cassette
----------------------------------------------------------------------------
To save the current program to tape:
SAVE "MYGAME"
To reload the program from tape (start the recorder first):
LOAD "MYGAME"
To verify that the tape matches the program in memory:
VERIFY "MYGAME"
If you omit the name, LOAD loads the first program it finds on the tape.
See Chapter 8 for practical instructions on correct recorder use.
1.9 Commands available in direct mode
1.9 Commands available in direct mode
----------------------------------------------------------------------------
LIST
LIST [m][-[n]] -- m=first line, n=last line
Display program. SPACE pauses, BREAK stops.
LLIST
LLIST [m][-[n]] -- Same as LIST but to serial printer.
AUTO
AUTO [m][, n] -- m=start line (def 10), n=step (def 10)
Auto line-number generation.
DELETE
DELETE m[-n] -- Remove program lines m through n.
RUN
RUN [m] -- m=start line (default=first). Start execution.
CONT
CONT -- Resume after STOP or BREAK.
LOAD
LOAD ["filename"] -- Load program from cassette.
SAVE
SAVE "filename" -- Save program to cassette (name <= 16 chars).
VERIFY
VERIFY ["filename"] -- Compare tape file with program in memory.
NEW
NEW -- Clear program and variables.
RENUM
RENUM [m1][, m2][, m3] -- m1=new start(def 10), m2=from line(def 1st), m3=step(def 10)
Renumber program lines.
CHAPTER 2 -- VARIABLES, TYPES, OPERATORS
CHAPTER 2 -- VARIABLES, TYPES, OPERATORS ============================================================================
2.1 Numeric variables
2.1 Numeric variables
----------------------------------------------------------------------------
A variable is a named memory cell. The first character of a name must
be a letter (A-Z); subsequent characters may be letters or digits.
Any length of name is accepted, but only the first two characters are
significant: SCORE and SCREEN are treated as the same variable (SC),
and AB1, AB2, ABCDE all refer to the same variable (AB). BASIC is not
case-sensitive: everything is converted to uppercase internally.
+----------------------------------------------------------------------+
| RULE: only the FIRST 2 CHARACTERS of a name are significant. |
| Longer names are silently truncated -- no error is ever reported. |
+----------------------------------------------------------------------+
This truncation is the most common source of hidden bugs in SC-3000
BASIC programs. The interpreter never warns about a name clash; it
simply overwrites the earlier value. Example:
100 LET SPEED = 30 : REM stored internally as SP = 30
110 LET SPRITE = 5 : REM stored internally as SP = 5 <- overwrites!
120 PRINT SPEED : REM prints 5, not 30
SPEED and SPRITE share the prefix SP and are the same variable.
Line 110 silently discards the value set in line 100.
The same rule applies to arrays: DIM FRR(11) and DIM FRC(11) both
create an array named FR -- the second DIM overwrites the first,
and one of the two arrays is lost.
String variables follow the same rule. NAME$ and NA$ are the same
string variable (first two chars of the base name: NA).
Naming convention for programs with many variables
----------------------------------------------------------------------------
In very short programs (fewer than 20 lines) any readable name works.
For programs spanning 50+ lines, choose names distinct in their first
two characters:
Good -- all first-two prefixes distinct:
R = current row C = current col
CR = cursor row CC = cursor col
NR = new row NC = new col
PR = player row PC = player col (array)
LR = last cursor row LC = last cursor col
Bad -- collision in the first two characters:
ROW = row (prefix RO)
ROWX = next row (prefix RO -- same! silent clash)
Practical guidelines:
* Use the full 2-char budget: prefer 2-char names (CR, NR, PC, ...).
* Group related constants with a shared first char, unique second:
W1 = wall colour, W2 = open-path colour, W3 = treasure colour
K4 = key matrix row 4, K5 = key matrix row 5
* Never use long names for readability -- put a REM comment instead:
LET CR=0 : REM cursor row
LET MP=&HC880 : REM ML parameter buffer
* Before adding a new variable, check what 2-char prefix it would
use and verify it does not collide with an existing one.
The LET statement assigns a value (the word LET is optional):
LET X = 10
Y = X * 2 + 1
SC-3000 BASIC uses single-precision floating point (~6 significant
digits). Integer values in the range -32768..32767 are stored as 16-bit
integers to save memory.
Examples of valid values:
100 -3.14159 2.5E+10 &HFF (hex = 255)
Note on hexadecimal notation: the prefix &H denotes a base-16 number.
&H0A = 10, &HFF = 255, &H8000 = 32768.
2.2 String variables
2.2 String variables
----------------------------------------------------------------------------
String variable names end with the "$" symbol:
NAME$ = "MARIO"
SURNAME$ = "ROSSI"
PRINT NAME$ + " " + SURNAME$
The "+" operator concatenates strings. Maximum string length is 255
characters. Available functions: LEFT$, RIGHT$, MID$, LEN, ASC, CHR$,
STR$, VAL, HEX$ -- see Chapter 4.
2.3 Arrays
2.3 Arrays
----------------------------------------------------------------------------
An array is an indexed variable. Arrays can be used without a DIM
declaration; in that case BASIC automatically allocates indices 0 to 10
(11 elements). Use DIM to declare a larger or multi-dimensional array.
Arrays support up to 3 dimensions:
DIM A(20) : REM 1-D: 21 elements A(0)..A(20)
DIM M(3,4) : REM 2-D: 4x5 element matrix
DIM C(2,2,2) : REM 3-D: 3x3x3 cube
DIM S$(10) : REM string array of 11 elements
Indices start at 0. DIM allocates memory; each element is initialised
to 0 (numeric) or empty string (string).
Important: a variable name and an array name may be the same. A scalar
A and an array A(n) are two independent objects and can coexist:
A = 99
DIM A(5)
A(0) = 1 : REM A(0) is distinct from A
Example:
10 DIM V(5)
20 FOR I=0 TO 5 : V(I)=I*I : NEXT I
30 FOR I=0 TO 5 : PRINT V(I); : NEXT I
To free array memory use ERASE:
ERASE A, M
2.4 Assignment and LET
2.4 Assignment and LET
----------------------------------------------------------------------------
The keyword LET is optional. These two lines are equivalent:
LET X = 42
X = 42
You can assign the value of any expression:
AREA = PI * R^2
MSG$ = "SCORE: " + STR$(POINTS)
2.5 Operators and precedence
2.5 Operators and precedence
----------------------------------------------------------------------------
Expressions are evaluated according to the priority table below.
Operators with lower priority (higher number) are applied last.
Use parentheses to force evaluation order:
PRINT 2+3*4 : REM prints 14 (multiplication first)
PRINT (2+3)*4 : REM prints 20 (addition first)
Comparisons return -1 (true) or 0 (false):
PRINT 5>3 : REM prints -1
PRINT 5<3 : REM prints 0
The value -1 for "true" is useful in arithmetic expressions:
X = X + (SCORE=100) * 10 : REM adds 10 only if SCORE equals 100
The logical operators AND, OR, XOR operate bit-by-bit on integers and
are commonly used to combine conditions:
IF A>0 AND B>0 THEN PRINT "BOTH POSITIVE"
2.6 Operator precedence table:
2.6 Operator precedence table:
----------------------------------------------------------------------------
Priority Symbol Numeric String Meaning
-------- ------ ------- ------ -------------------------------
1 ^ o x Exponentiation (0^0 = 1)
2 + / - o x Unary sign
3 * / o x Multiply / Divide
4 MOD o x Integer remainder
5 + o o Add / String concatenation
5 - o x Subtract
6 = < > <= >= <> o o Comparison (true=-1, false=0)
7 NOT o x Logical NOT
8 AND o x Logical AND
8 OR o x Logical OR
8 XOR o x Logical XOR
CHAPTER 3 -- FLOW CONTROL
CHAPTER 3 -- FLOW CONTROL ============================================================================
3.1 Comments with REM
3.1 Comments with REM
----------------------------------------------------------------------------
REM (from "remark") inserts a comment: everything that follows on the
same line is ignored by the interpreter. It is good practice to comment
the key points of a program:
10 REM *** PROGRAM: GUESS THE NUMBER ***
20 REM Variables: S=secret, T=try, C=counter
REM has no effect on execution but does occupy memory. In very long
programs you can remove REMs to recover space.
3.2 STOP and END
3.2 STOP and END
----------------------------------------------------------------------------
END terminates the program definitively; the cursor returns to the
prompt. STOP suspends execution and prints "Break in line N"; you can
resume with CONT. STOP is useful as a breakpoint during debugging:
190 STOP : REM pause to inspect variables with PRINT
200 END
3.3 Unconditional jump: GOTO
3.3 Unconditional jump: GOTO
----------------------------------------------------------------------------
GOTO transfers execution to a specified line:
10 PRINT "INFINITE LOOP"
20 GOTO 10
Use it sparingly: programs with many GOTOs are hard to read. Prefer
FOR/NEXT for loops and GOSUB for subroutines.
3.4 Conditional: IF ... THEN
3.4 Conditional: IF ... THEN
----------------------------------------------------------------------------
IF evaluates a condition; if it is true (non-zero) it executes the part
after THEN. This can be a line number or one or more statements:
IF X > 10 THEN PRINT "LARGE"
IF X > 10 THEN PRINT "LARGE" : GOTO 100
IF X > 10 THEN 100 : REM equivalent to GOTO 100
There is no ELSE: to handle the "otherwise" case use a second IF or
structure the program with GOTO:
100 IF X > 10 THEN PRINT "LARGE" : GOTO 120
110 PRINT "SMALL OR EQUAL"
120 REM continues here
Conditions can be combined using AND and OR:
IF X>0 AND X<100 THEN PRINT "IN RANGE"
3.5 Counted loop: FOR ... NEXT
3.5 Counted loop: FOR ... NEXT
----------------------------------------------------------------------------
FOR creates a loop that runs a precise number of times. The loop
variable is incremented (or decremented with a negative STEP) at each
iteration:
10 FOR I=1 TO 10
20 PRINT I
30 NEXT I
With a custom STEP:
FOR I=0 TO 100 STEP 5 : REM 0, 5, 10, ..., 100
FOR I=10 TO 1 STEP -1 : REM 10, 9, 8, ..., 1
FOR loops can be nested up to 16 levels. Each NEXT must match its FOR.
The variable after NEXT is optional but aids readability:
FOR R=1 TO 3
FOR C=1 TO 3
PRINT R*C;
NEXT C
PRINT
NEXT R
3.6 Subroutines: GOSUB ... RETURN
3.6 Subroutines: GOSUB ... RETURN
----------------------------------------------------------------------------
GOSUB jumps to a subroutine and RETURN brings execution back to the
statement after the GOSUB. Subroutines are used to group repeated code
in one place:
10 GOSUB 1000 : PRINT "FIRST RESULT: ";R
20 GOSUB 1000 : PRINT "SECOND RESULT: ";R
30 END
1000 REM --- subroutine: compute something ---
1010 R = SQR(ABS(X))
1020 RETURN
Maximum nesting depth is 8 levels. RETURN without GOSUB causes error [20].
3.7 Computed jump: ON ... GOTO / ON ... GOSUB
3.7 Computed jump: ON ... GOTO / ON ... GOSUB
----------------------------------------------------------------------------
ON executes a GOTO or GOSUB choosing the destination based on the value
of an expression (1=first line, 2=second, etc.):
ON CHOICE GOTO 100, 200, 300, 400
If CHOICE is 1 jumps to 100, if 2 jumps to 200, etc.
If the value is 0, negative or greater than the number of destinations,
execution continues on the next line.
ON LEVEL GOSUB 2000, 2100, 2200
Practical example -- "Guess the number":
10 REM *** GUESS THE NUMBER 1-100 ***
20 N = INT(RND(1)*100)+1
30 T = 0
40 PRINT "I THOUGHT OF A NUMBER BETWEEN 1 AND 100."
50 INPUT "YOUR GUESS: ";G
60 T = T+1
70 IF G < N THEN PRINT "TOO LOW!" : GOTO 50
80 IF G > N THEN PRINT "TOO HIGH!" : GOTO 50
90 PRINT "WELL DONE! YOU GOT IT IN ";T;" TRIES."
3.8 DEF FN -- user-defined functions
3.8 DEF FN -- user-defined functions
----------------------------------------------------------------------------
DEF FN lets you define a single-expression numeric function and assign it
a name. The function can then be called like any built-in function.
DEF FNname(arg) = expression
The name follows the same two-character rule as all variable names.
The argument (arg) is a dummy variable -- any name can be used and it
does not conflict with program variables of the same name.
10 DEF FNA(X) = X*X*3.14159 : REM area of a circle
20 INPUT "Radius: "; R
30 PRINT "Area = "; FNA(R)
Calling a DEF FN recursively (the function calling itself) causes
error [08] (Stack overflow). DEF FN must be defined before it is called;
calling an undefined function causes error [32].
Only numeric functions are supported; DEF FN cannot return a string.
CHAPTER 4 -- TEXT AND SCREEN
CHAPTER 4 -- TEXT AND SCREEN ============================================================================
4.1 The text screen
4.1 The text screen ---------------------------------------------------------------------------- In text mode (SCREEN 1, the default) the screen displays 38 columns and 24 rows. Row 0 is at the top, row 23 at the bottom. (The underlying VRAM name table is 40 characters wide; the first two columns are not shown on a standard display -- see VPOKE in section 5.10 for the address formula.) The cursor is always at the current write position.
4.2 PRINT
4.2 PRINT
----------------------------------------------------------------------------
PRINT is the fundamental output command. It can print numbers, strings
and expressions separated by commas or semicolons:
PRINT 42
PRINT "SCORE:"; P
PRINT A, B, C
Separators:
* Semicolon ";" -- no extra space between values
* Comma "," -- advance to the next tab zone (columns 0, 16, 32)
At the end of each PRINT a carriage return is emitted. To suppress it,
end with a semicolon:
PRINT "CR VALUE: ";
Note: positive numbers are printed with a leading space (sign placeholder).
Use STR$ to control the exact format.
Special output characters:
CHR$(&H10) -- select 8x8 font (compact, 40 columns)
CHR$(&H11) -- select 16x8 font (large, 20 columns)
CHR$(13) -- forced carriage return
4.3 CLS
4.3 CLS
----------------------------------------------------------------------------
CLS (Clear Screen) clears the entire screen and repositions the cursor
in the top-left corner:
10 CLS
20 PRINT "SCREEN CLEARED"
4.4 CURSOR
4.4 CURSOR
----------------------------------------------------------------------------
CURSOR positions the cursor at an absolute coordinate. In text mode
(SCREEN 1): X=0..37, Y=0..23:
CURSOR 0,12 : REM start of the middle row
PRINT "CENTRED TITLE"
In graphics mode (SCREEN 2) coordinates are in pixels: X=0..255,
Y=0..191. CURSOR in graphics mode moves the current drawing position
for LINE, CIRCLE, etc.
4.5 CONSOLE
4.5 CONSOLE
----------------------------------------------------------------------------
CONSOLE sets the scroll limits and two keyboard options:
CONSOLE [startRow][, endRow][, click][, smallcaps]
startRow : first row of the scroll region (0-22, default 0)
endRow : last row of the scroll region (2-24, default 24)
click : 1=key-click sound on, 0=silent
smallcaps : 1=compact 8x8 characters, 0=normal 16x8 characters
To reserve a fixed row at the top (row 0) as a header:
CONSOLE 1,,1,0 : REM scroll from row 1; click enabled
4.6 COLOR
4.6 COLOR
----------------------------------------------------------------------------
COLOR assigns colours to "1" and "0" pixels in graphics mode and can
also set the background colour of the non-drawn area:
COLOR foreground [, background [,(x1, y1)-(x2, y2) [, backdrop]]]
Colours range from 0 to 15 (see the full palette in Vol. C ch. 2).
Main colours: 0=transparent, 1=black, 7=cyan, 9=red, 14=white.
In text mode the colour affects text printed with PRINT.
4.7 SCREEN
4.7 SCREEN
----------------------------------------------------------------------------
SCREEN selects the video mode:
SCREEN 1,1 : REM text 40x25 (default)
SCREEN 2,2 : REM graphics 256x192
With two arguments: SCREEN n, m writes to screen n but displays output
previously prepared on m (double buffer). Normally only the first
argument is used.
4.8 String utility functions (for use with PRINT)
4.8 String utility functions (for use with PRINT)
----------------------------------------------------------------------------
These functions are often used with PRINT to format output:
LEN(S$) -- number of characters in S$
LEFT$(S$, N) -- first N characters of S$
RIGHT$(S$, N) -- last N characters of S$
MID$(S$, P, N) -- N characters of S$ starting at position P
STR$(X) -- converts number X to the equivalent string
VAL(S$) -- converts string S$ to the corresponding number
CHR$(N) -- character with ASCII code N
ASC(S$) -- ASCII code of the first character of S$
HEX$(N) -- converts N to a hexadecimal string
Examples:
PRINT LEN("HELLO") : REM prints 5
PRINT LEFT$("MARIO",3) : REM prints MAR
PRINT MID$("SEGA",2,2) : REM prints EG
PRINT STR$(42)+"!" : REM prints 42! (note the leading space)
PRINT CHR$(65) : REM prints A
4.8 SPC -- insert spaces in PRINT
4.8 SPC -- insert spaces in PRINT
----------------------------------------------------------------------------
SPC(n) inserts n spaces at the current print position. Used inside a
PRINT statement with the semicolon separator:
PRINT "ABC"; SPC(10); "XYZ" : REM prints ABC, 10 spaces, then XYZ
If characters already occupy the positions that SPC would span, those
characters are overwritten with spaces.
4.9 TAB -- set print column
4.9 TAB -- set print column
----------------------------------------------------------------------------
TAB(n) moves the print position to column n (counting from the left of
the current line, starting at column 0). Used inside PRINT:
PRINT TAB(5); "ABC" : REM prints ABC starting at column 5
Unlike SPC, TAB does not erase characters already in the skipped columns;
it simply advances the print cursor. If the cursor is already past column
n, TAB has no effect on that line.
Practical example -- score screen:
10 CLS
20 COLOR 14,1 : REM white on black
30 CURSOR 14,0
40 PRINT "*** GAME OVER ***"
50 CURSOR 12,10
60 PRINT "SCORE:"; P
70 CURSOR 10,20
80 PRINT "PRESS A KEY..."
4.10 LPRINT -- print to serial printer
4.10 LPRINT -- print to serial printer
----------------------------------------------------------------------------
LPRINT sends output to the serial printer connected to the 7-pin DIN
port, instead of to the screen. The syntax is identical to PRINT:
LPRINT [s1{,|;}s2...]
The comma (,) separator advances to the next tab zone; semicolon (;) keeps
the cursor position without a space. A trailing semicolon suppresses the
final carriage return.
Examples:
LPRINT "HELLO WORLD" : REM prints one line on the printer
10 INPUT A, B
20 C = A + B
30 LPRINT C : REM prints result to printer
40 GOTO 10
LLIST (see Chapter 1) is the equivalent of LIST for the printer: it
sends the program listing to the printer rather than to the screen.
Hardware: the printer is connected via the 7-pin DIN serial port on the
back of the SC-3000. Protocol and pinout are documented in Vol. C ch. 4.7
and ch. 6.2.2.
4.11 HCOPY -- copy screen to printer
4.11 HCOPY -- copy screen to printer
----------------------------------------------------------------------------
HCOPY prints a copy of the current text screen to the serial printer:
HCOPY
It can reproduce: digits, uppercase and lowercase Latin letters, standard
ASCII symbols. It cannot reproduce SC-3000 graphic-mode tile symbols or
Dieresis (double-dot) characters -- those positions are skipped or printed
as spaces.
HCOPY works in SCREEN 1 (text mode). Calling it while in SCREEN 2
(graphics mode) prints the text layer only.
CHAPTER 5 -- GRAPHICS
CHAPTER 5 -- GRAPHICS ============================================================================
5.1 Graphics mode SCREEN 2
5.1 Graphics mode SCREEN 2
----------------------------------------------------------------------------
SCREEN 2,2 activates graphics mode at 256x192 pixels. The origin (0,0)
is the top-left corner; X increases rightward (0-255), Y increases
downward (0-191).
SCREEN 2,2
To return to text mode:
SCREEN 1,1
5.2 Colours in SCREEN 2
5.2 Colours in SCREEN 2
----------------------------------------------------------------------------
In SCREEN 2,2 pixels are either "on" (colour 1) or "off" (colour 0).
The COLOR command assigns which physical colour corresponds to each:
COLOR 9,1 : REM on pixels = red (9), background = black (1)
To change colour during drawing, just call COLOR again.
The full 16-colour palette is in Vol. C, chapter 2.
5.3 LINE
5.3 LINE
----------------------------------------------------------------------------
LINE draws a straight line or a rectangle:
LINE (x1, y1)-(x2, y2), colour [, B[F]]
Without option : draws a line from (x1, y1) to (x2, y2).
With B : draws the rectangle with corners (x1, y1) and (x2, y2).
With BF : draws the filled rectangle.
If the start point is omitted, LINE continues from the last used point:
LINE (10,10)-(100,50),9 : REM red line
LINE -(200,50),14 : REM continues to (200,50) in white
LINE (50,50)-(150,100),7, B : REM border rectangle
LINE (50,50)-(150,100),7, BF : REM filled rectangle
BLINE works like LINE but erases (uses colour 0) ignoring the colour
parameter; useful for clearing previously drawn shapes.
5.4 CIRCLE
5.4 CIRCLE
----------------------------------------------------------------------------
CIRCLE draws a circle, ellipse, or arc:
CIRCLE (cx, cy), radius [, colour [, ratio [, start [, end [, B|BE|BF]]]]]
cx, cy : centre in pixels
radius : radius in pixels
colour : 0-15 (default = current colour)
ratio : aspect ratio of the shape:
1.0 = true circle
< 1 = wide (horizontal) ellipse
> 1 = tall (vertical) ellipse
start/end : arc extent, values 0.0 to 1.0 (0.0=east, 0.25=south,
0.5=west, 0.75=north); omit both for a complete circle
flag : optional style:
(none) = circumference only
B = arc with radii drawn (closed pie-slice outline)
BF = entire circle/ellipse filled with colour
Examples:
CIRCLE (128,96),50,14 : REM white circle at centre
CIRCLE (128,96),80,9,0.5 : REM red wide ellipse
CIRCLE (128,96),80,9,2.0 : REM red tall ellipse
CIRCLE (128,96),50,7,,0.0,0.5 : REM open arc (upper half)
CIRCLE (128,96),50,7,,0.0,0.5, B : REM pie-slice outline
CIRCLE (128,96),50,7,,,, BF : REM filled complete circle
BCIRCLE works like CIRCLE but erases (colour 0).
5.5 PAINT
5.5 PAINT
----------------------------------------------------------------------------
PAINT fills a closed area starting from a seed point:
PAINT (x, y), colour
The flood-fill algorithm expands from point (x, y) until it hits a
border of the same colour as the border, or the screen edges. Note: if
the area is not completely closed the fill "leaks" out. Very complex or
large shapes may cause error [08] (stack overflow).
CIRCLE (128,96),60,14 : REM draw the border
PAINT (128,96),7 : REM fill the interior with white
5.6 Sprites
5.6 Sprites
----------------------------------------------------------------------------
Sprites are graphical objects that move on screen overlapping other
shapes without erasing them. The TMS9918A supports 32 sprites but
displays at most 4 per scan line.
SPRITE positions a sprite on screen:
SPRITE n,(x, y), pattern, colour
n : sprite number (0-31)
x, y : pixel position of the top-left corner
pattern : shape pattern number (0-255)
colour : sprite colour (0-15)
MAG sets sprite dimensions:
MAG 0 : REM 8x8 pixels (default)
MAG 1 : REM 16x16 pixels
MAG 2 : REM 8x8 with x2 zoom (16x16 appearance)
MAG 3 : REM 16x16 with x2 zoom (32x32 appearance)
To use a sprite you must first define its pattern with PATTERN or load
an existing pattern from ROM.
5.7 PATTERN -- defining characters and sprites
5.7 PATTERN -- defining characters and sprites
----------------------------------------------------------------------------
PATTERN loads the graphic definition of one 8x8 CELL (a character, or a
sprite cell) into video memory (VRAM). One call takes up to 8 bytes = 16
hex digits (each byte = 8 horizontal pixels, bit 7 = leftmost) and MUST
end with "*" -- after the data the parser requires it, and any unfilled
bytes of the cell are zero-filled. A 16x16 sprite is four cells: four
PATTERN calls for cells n, n+1, n+2, n+3 in TMS9918 order (top-left,
bottom-left, top-right, bottom-right), shown with MAG 1 or MAG 3.
PATTERN C#65,"3C7EFFFFFFFF7E3C*" : REM ASCII character 65 ('A')
PATTERN S#0,"0018243C5A181818*" : REM sprite cell 0
The prefix C# denotes a character, S# denotes a sprite.
The "*" symbol in the hex string stops the parsing:
PATTERN C#65,"00FF*" : REM $00, then $FF then $00 for the rest
5.8 PSET and PRESET
5.8 PSET and PRESET
----------------------------------------------------------------------------
PSET turns on a single pixel with the specified colour:
PSET (x, y), colour
PRESET turns off a pixel (sets it to colour 0):
PRESET (x, y)
5.9 POSITION
5.9 POSITION
----------------------------------------------------------------------------
POSITION sets the origin and direction for subsequent graphics commands
(useful for drawing in different directions):
POSITION (x, y), xdir, ydir
xdir: 0=rightward (default), 1=leftward
ydir: 0=downward (default), 1=upward
5.10 VPOKE and VPEEK
5.10 VPOKE and VPEEK
----------------------------------------------------------------------------
VPOKE writes a byte directly to VRAM:
VPOKE address, value
VPEEK reads a byte from VRAM:
V = VPEEK(address)
These commands allow direct access to video memory without going
through the high-level graphics statements.
Text mode (SCREEN 1) address formula:
address = y * 40 + x + &H3C00 (x=0-39, y=0-23)
Important: the VRAM name table is 40 characters wide, but the display
shows only 38 columns. The visible area starts at VRAM column 2, so
VPOKE column x=2 corresponds to the leftmost visible column (CURSOR x=0).
To write to a character at CURSOR position (cx, cy):
VPOKE cy*40 + (cx+2) + &H3C00, ASC("A")
Graphic mode (SCREEN 2) pattern address formula:
address = INT(y/8)*256 + INT(x/8)*8 + (y MOD 8) (x=0-255, y=0-191)
The VRAM map for SCREEN 1 and SCREEN 2,2 is described in Vol. C, ch. 2.
Practical example -- drawing shapes:
10 SCREEN 2
20 COLOR 14,1
30 LINE (20,20)-(230,170),14,B : REM border rectangle
40 CIRCLE (128,96),60,9 : REM red circle
50 PAINT (128,96),7 : REM white fill
60 SPRITE 0,(112,80),0,14 : REM sprite at top-left of circle
70 GOTO 70 : REM wait (press BREAK to exit)
CHAPTER 6 -- SOUND
CHAPTER 6 -- SOUND ============================================================================
6.1 The SN76489AN sound chip
6.1 The SN76489AN sound chip ---------------------------------------------------------------------------- The SC-3000 is equipped with a Texas Instruments SN76489AN sound generator (PSG -- Programmable Sound Generator). It has three independent tone channels (numbered 1, 2, 3) and one noise channel (white or periodic).
6.2 SOUND
6.2 SOUND
----------------------------------------------------------------------------
The SOUND command controls the PSG directly:
SOUND channel, frequency, volume
channel : 0=silence ALL channels (master off), 1-3=tone,
4=white noise, 5=synchronous (periodic) noise
frequency : for channels 1-3: frequency in Hz (approximated to the
nearest PSG divisor); for channels 4-5: 0-2 = three fixed
noise steps, 3 = noise rate tracks channel 3 frequency
volume : 0=silent, 1=minimum, 15=maximum
To play middle A (440 Hz) on channel 1 at maximum volume:
SOUND 1, 440, 15
To silence a specific channel, set its volume to 0:
SOUND 1, 440, 0
To silence EVERYTHING at once (e.g. to stop a tune), use channel 0:
SOUND 0
6.3 BEEP
6.3 BEEP
----------------------------------------------------------------------------
BEEP produces a short buzzer tone through the internal buzzer:
BEEP : REM single beep
BEEP 0 : REM stop beep
BEEP 1 : REM continuous beep
BEEP 2 : REM double beep
BEEP produces its tone through the PSG sound chip (it shares the SOUND
statement's tone-generation code), not a separate PPI pin.
6.4 Playing a melody
6.4 Playing a melody
----------------------------------------------------------------------------
To play a sequence of notes use SOUND in a loop, with an empty
FOR/NEXT as a delay between notes:
10 DATA &H106,&H126,&H14A,&H15D,&H188,&H1B8,&H1EE,&H20B
20 FOR I=1 TO 8
30 READ F
40 SOUND 1,F,12
50 FOR T=1 TO 500 : NEXT T : REM pause ~0.5 s
60 NEXT I
70 SOUND 1,0,0 : REM final silence
To play a three-note chord simultaneously:
SOUND 1, 262, 10 : REM C
SOUND 2, 330, 10 : REM E
SOUND 3, 392, 10 : REM G
6.5 Noise channel
6.5 Noise channel
----------------------------------------------------------------------------
Channel 4 produces white noise (like a gunshot or explosion):
SOUND 4, 0, 12 : REM white noise, volume 12
Channel 5 produces synchronous (periodic) noise whose rate can track
channel 3's frequency:
SOUND 5, 3, 10
For noise channels (4-5) the frequency parameter selects a rate step:
0 slowest fixed noise rate
1 medium fixed noise rate
2 fastest fixed noise rate
3 noise rate controlled by channel 3's current divisor
SOUND 4, 0, 12 : REM white noise at slowest fixed rate
SOUND 4, 3, 12 : REM white noise rate tracks channel 3
SOUND 5, 3, 10 : REM periodic noise tracks channel 3
6.6 Note on delays
6.6 Note on delays ---------------------------------------------------------------------------- SC-3000 BASIC has no dedicated WAIT command. To create pauses use an empty FOR loop. The duration depends on program speed and is not millisecond-accurate; for precise synchronisation with the timer see Chapter 7 (TIME$).
Frequency table:
Frequency table: ---------------------------------------------------------------------------- Scale f1 f2 f3 f4 f5 f6 C 131 262 523 1047 2094 C+ 139 277 554 1109 2218 D 147 294 587 1175 2350 D+ 156 311 622 1245 2490 E 165 330 659 1319 2638 F 175 349 698 1397 2794 F+ 185 370 740 1480 2960 G 196 392 784 1568 3136 G+ 208 415 831 1661 3322 A 110 220 440 880 1760 3520 A+ 117 233 466 932 1864 B 123 247 494 988 1976 f1=octave 1 (32'), f2=octave 2 (16'), f3=octave 3 (8'), f4=octave 4 (4'), f5=octave 5 (2'), f6=octave 6 (1'). Frequencies in Hz.
6.7 Demo program -- music sequencer
6.7 Demo program -- music sequencer ---------------------------------------------------------------------------- A complete sound demo -- a DATA-driven 4-channel sequencer that plays "Ride of the Valkyries" (singing lead + sustained drone + staccato galloping bass + timpani/cymbal) -- is in Volume A2 (Demos), section 1 "Sound & Music". See VOL_A2_DEMOS.txt, which collects all ready-to-type BASIC demo programs grouped by category (sound, graphics, sprites, games, text).
CHAPTER 7 -- INPUT AND TIMER
CHAPTER 7 -- INPUT AND TIMER ============================================================================
7.1 INPUT
7.1 INPUT
----------------------------------------------------------------------------
INPUT suspends execution and waits for the user to type one or more
values separated by commas, ending with CR:
INPUT A
INPUT "NAME: "; N$
INPUT "X, Y: "; X, Y
If the prompt does not end with ";" BASIC automatically adds a question
mark before the cursor. For a prompt without "?":
PRINT "CR VALUE: ";
INPUT A
Type checking: if a number is expected and the user types a string,
BASIC shows "Redo from start" [35] and asks for re-entry.
7.2 INKEY$
7.2 INKEY$
----------------------------------------------------------------------------
INKEY$ returns the key currently being pressed without waiting
(non-blocking). If no key is pressed it returns the empty string "":
10 K$ = INKEY$
20 IF K$ = "" THEN GOTO 10 : REM wait until a key is pressed
30 PRINT "YOU PRESSED: "; K$
INKEY$ is ideal in game loops where you do not want to block execution
waiting for input. It returns a single ASCII character.
7.3 Joystick: STICK and STRIG
7.3 Joystick: STICK and STRIG
----------------------------------------------------------------------------
STICK(n) returns the direction of joystick n (1=player 1, 2=player 2):
D = STICK(1)
Returned values:
0 = no direction 1 = up 2 = up-right
3 = right 4 = down-right 5 = down
6 = down-left 7 = left 8 = up-left
STRIG(n) returns the state of the fire buttons:
T = STRIG(1)
Returned values:
0 = no button 1 = button 1 2 = button 2 3 = both
Example -- sprite movement with joystick:
10 SCREEN 2,2 : SX=128 : SY=96
20 D=STICK(1)
30 IF D=1 OR D=2 OR D=8 THEN SY=SY-2
40 IF D=4 OR D=5 OR D=6 THEN SY=SY+2
50 IF D=2 OR D=3 OR D=4 THEN SX=SX+2
60 IF D=6 OR D=7 OR D=8 THEN SX=SX-2
70 IF SX<0 THEN SX=0
80 IF SX>247 THEN SX=247
90 IF SY<0 THEN SY=0
100 IF SY>183 THEN SY=183
110 SPRITE 0,(SX,SY),0,14
120 GOTO 20
7.4 TIME$
7.4 TIME$
----------------------------------------------------------------------------
TIME$ is a pseudo-variable representing the current time of the
software timer in "hh:mm:ss" format. It can be read and written:
PRINT TIME$ : REM e.g.: "00:00:37"
TIME$ = "12:30:00" : REM set the time
The timer is incremented every second by an interrupt routine.
It is not a hardware clock; it resets on every NEW or power-on.
To measure the time of an operation:
10 TIME$ = "00:00:00"
20 FOR I=1 TO 5000 : NEXT I : REM operation to measure
30 PRINT "TIME: "; TIME$
To wait a precise number of seconds:
10 T$ = TIME$
20 IF TIME$ = T$ THEN GOTO 20 : REM wait 1 second
30 PRINT "ONE SECOND HAS PASSED"
CHAPTER 8 -- CASSETTE
CHAPTER 8 -- CASSETTE ============================================================================
8.1 Connecting the recorder
8.1 Connecting the recorder
----------------------------------------------------------------------------
The SC-3000 cassette connector uses a 5-pin DIN jack. You need a
recorder with separate audio inputs and outputs. The signals are:
* Output (SC-3000 to tape) : level ~1 V peak-to-peak
* Input (tape to SC-3000) : accepted from ~0.5 V upward
* Motor control : 5V TTL signal for the recorder relay
For best compatibility use recorders at 1x speed (4.75 cm/s), standard
C-60 or C-90 tapes, and a medium-low recording level.
8.2 SAVE
8.2 SAVE
----------------------------------------------------------------------------
SAVE saves the current program to tape. The filename can have at most
16 characters:
SAVE "MYPROG"
Before issuing the command put the recorder in REC/PLAY mode and press
PLAY+REC. BASIC emits a leader tone, then the data. The screen shows
"* Saving start" when it begins and "* Saving end" when complete, then
the "Ready" prompt returns.
8.3 LOAD
8.3 LOAD
----------------------------------------------------------------------------
LOAD reloads a program from tape. Before issuing the command rewind
the tape to the start of the file and press PLAY on the recorder:
LOAD "MYPROG"
If you omit the name the first program found is loaded:
LOAD
LOAD searches for the leader on the tape for several seconds. If no
signal is found it shows "Device not ready" [31]. The screen shows
"* Loading start", then " Found [filename]" when the file is located,
and "* Loading end" on success, then "Ready".
Important: LOAD overwrites the program in memory without asking for
confirmation. If you want to keep the current program, save it first.
8.4 VERIFY
8.4 VERIFY
----------------------------------------------------------------------------
VERIFY compares the file on tape with the program in memory, byte by
byte. Shows "* Verifying start", then "* Verifying end" if they match;
otherwise "* Verifying error" [33]. Run immediately after SAVE to check
the recording:
VERIFY "MYPROG"
8.5 MOTOR
8.5 MOTOR
----------------------------------------------------------------------------
MOTOR controls the recorder motor via software:
MOTOR 0 : REM motor OFF
MOTOR 1 : REM motor ON (any non-zero value)
MOTOR : REM toggle current state
Normally LOAD, SAVE and VERIFY manage the motor automatically.
MOTOR is useful in programs that alternate between listening and pause.
8.6 Practical notes
8.6 Practical notes
----------------------------------------------------------------------------
* If loading fails, try lowering the recorder volume by one or two
notches and retry.
* Keep the power adapter cable away from audio cables: 50/60 Hz can
induce interference.
* Store tapes away from magnetic fields (speakers, monitors,
transformers).
* For important programs always make two copies on separate tapes.
* If the recorder has no automatic level control (ALC), make a test
recording at different volumes and choose the level that gives the
best VERIFY result.
CHAPTER 9 -- DIRECT HARDWARE ACCESS
CHAPTER 9 -- DIRECT HARDWARE ACCESS ============================================================================ This chapter introduces the commands that allow direct access to the computer's hardware. They are powerful tools but require care: writing to wrong RAM addresses or ports can crash the system and force a restart. For detailed technical information on addresses and ports see Vol. C and Vol. D.
9.1 PEEK and POKE -- RAM access
9.1 PEEK and POKE -- RAM access
----------------------------------------------------------------------------
PEEK(address) reads the byte at the specified memory address
(0-65535, or -32768..32767 in two's complement):
V = PEEK(&H9339) : REM read the text colour byte (COLORT)
POKE address, value writes a byte to memory:
POKE &H9339, &HF1 : REM set white (15) text on black (1) background
Note: do not write to ROM (addresses &H0000-&H7FFF); POKEs in that
area are ignored. POKEs to system RAM (&H8000-&H9FFF) can alter
BASIC's behaviour.
Useful RAM variables accessible with PEEK/POKE:
&H9336 VRAMMD : video mode (1=text, 2=graphics)
&H9337 SPRSIZ : sprite size (0=8x8, 1=16x16)
&H9339 COLORT : text colour (hi=background, lo=foreground)
&H9448 GRPOP : graphics operation (0=erase, 1=draw)
&H948E TIMES : timer seconds
&H948F TIMEM : timer minutes
&H9490 TIMEH : timer hours
9.2 INP and OUT -- I/O port access
9.2 INP and OUT -- I/O port access
----------------------------------------------------------------------------
INP(port) reads a byte from a hardware port (0-255):
S = INP(&HBF) : REM read the VDP status register
OUT port, value writes a byte to a port:
OUT &H7F, &HFF : REM write to the PSG sound chip
Main SC-3000 ports:
&H7F -- PSG SN76489AN (write only)
&HBE -- VDP VRAM data (read/write)
&HBF -- VDP register/status
&HDC -- PPI port A (keyboard/joystick)
&HDD -- PPI port B
&HDE -- PPI port C
&HDF -- PPI control
For details on how to use these ports see Vol. C.
9.3 VPOKE and VPEEK -- VRAM access
9.3 VPOKE and VPEEK -- VRAM access
----------------------------------------------------------------------------
VPOKE address, value writes a byte to the video chip's VRAM
(addresses 0-16383):
VPOKE &H1800, &H41 : REM write 'A' -- see NOTE below on SCREEN 2,2
VPEEK(address) reads a byte from VRAM:
C = VPEEK(&H1800) : REM read that same address back
VPOKE/VPEEK operate on VRAM (the VDP's memory), separate from main
RAM. The VRAM layout for SCREEN 1 and SCREEN 2,2 is described in
Vol. C, chapter 2.
NOTE: after "SCREEN 2,2" this ROM's name table is actually at $3800,
not $1800 as the generic TMS9918 example above suggests -- $1800 is
the sprite-pattern table instead. Verified by disassembling SCRINIT/
DSPGRP; see Vol. C section 2.3/2.4 for the corrected register values.
9.4 CALL -- calling machine code
9.4 CALL -- calling machine code
----------------------------------------------------------------------------
CALL executes a Z80 machine-language routine at a specified address.
Use &H hexadecimal notation for addresses above &H7FFF:
CALL &HC000 : REM execute code at address &HC000
The standard technique is to load machine code into RAM with POKE
and then call it with CALL. See Vol. D, chapter 1 for the complete
DATA/POKE/CALL technique with examples for every ROM routine.
Minimal example -- calling an existing ROM routine:
10 POKE &HC000, &HCD : REM CALL opcode
20 POKE &HC001, &H00 : REM low byte of KEYREAD address ($4A00)
30 POKE &HC002, &H4A : REM high byte
40 POKE &HC003, &HC9 : REM RET
50 CALL &HC000 : REM executes: CALL $4A00 + RET
60 PRINT "ROW0="; PEEK(&H9460)
Note: CALL requires the routine to end with a Z80 RET instruction.
If the called ROM routine does not RET the system may crash.
9.5 FRE -- free memory
9.5 FRE -- free memory
----------------------------------------------------------------------------
FRE returns the number of free RAM bytes available for the BASIC
program (variables, arrays, stack):
PRINT FRE
It is good practice to check FRE before declaring large arrays.
With the minimum 2KB RAM, programs with many variables or arrays
quickly exhaust memory (error [09]).
CHAPTER 10 -- ERROR TABLE
CHAPTER 10 -- ERROR TABLE ============================================================================ ============================================================================ [01] System BASIC interpreter internal error [02] N-Formula too complex Numeric expression too complex [03] S-Formula too complex String expression too complex [04] Overflow Value or result out of range [05] Division Zero Division by zero [06] Function Parameter Function argument invalid [07] String too long String exceeds 255 characters [08] Stack overflow Parentheses too deep / paint shape too complex / recursive DEF FN [09] Out of memory Insufficient memory (text, variables, or arrays) [10] Number of Subscripts Array subscript count wrong [11] Value of Subscript Array subscript value wrong [12] Syntax Grammar error in statement [13] Command Parameter Command argument invalid [14] Line number over AUTO/RENUM produced line number > 65535 [15] Illegal line number Line number invalid [16] Line image too long Line too long (e.g. after RENUM) [17] Undefined line number Line number not found (RENUM/GOTO/GOSUB/IF-THEN/RESTORE/RUN) [18] Type mismatch Numeric vs string type conflict [19] Out of DATA READ attempted with no DATA remaining [20] RETURN without GOSUB RETURN without matching GOSUB [21] GOSUB nesting GOSUB nesting exceeded 8 levels [22] NEXT without FOR NEXT has no matching FOR [23] FOR nesting FOR-NEXT nesting exceeded 16 levels [24] Statement Parameter Statement argument invalid [25] Can't Continue CONT not possible [26] For variable name FOR loop variable must be simple numeric variable [27] Array name DIM argument not an array name [28] Redimensioned array ERASE of undefined array [29] No program SAVE attempted with no program in memory [30] Memory write error Error during LOAD [31] Device not ready Printer not connected or error [32] Undefined function Called DEF FN not defined [33] Verification Tape verify mismatch [34] Illegal direct Statement cannot run in direct mode [35] Redo from start INPUT data invalid; re-enter [36] Extra ignored INPUT had extra data; ignored [37] Unprintable Other unclassified error ============================================================================