SE3K Survivors Experience 3000

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

============================================================================