選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

8.8KB


name: basic-programming description: > Use this skill for Commodore 64 BASIC 2.0 programming, extending BASIC with new commands, BASIC internals (tokenization, interpreter), math routines, floating-point access from ML, and BASIC program structure. Sources: COMPUTE!‘s VIC-20 and C64 Tool Kit: BASIC, The Advanced ML Book, The Anatomy of the C64.

BASIC 2.0 Programming on the Commodore 64

BASIC Overview

The C64's BASIC 2.0 (Microsoft BASIC) resides in ROM at $A000–$BFFF. It is a tokenized interpreter: typed commands are compressed into single-byte tokens before storage.

Program Storage Format

Each BASIC line in memory has this structure:

[link_lo][link_hi][line_lo][line_hi][tokens...][00]
  • link: 16-bit pointer to next line (absolute address)
  • line number: 16-bit line number
  • tokens: statement tokens and literal data
  • 00: end of line marker

The program ends with a double $00 byte.

Variable Storage

Variables follow the program in memory:

  1. Numeric variables: 7 bytes each (2-char name + 5-byte float or 4-byte int)
  2. String variables: 7 bytes (2-char name + length + 2-byte pointer)
  3. Arrays: variable-length (name + dimension info + elements)

Key BASIC Locations

Address Name Description
$2B-$2C (43-44) TXTTAB Start of BASIC program text
$2D-$2E (45-46) VARTAB Start of variable area
$2F-$30 (47-48) ARYTAB Start of array area
$31-$32 (49-50) STREND End of array area
$33-$34 (51-52) FRETOP Top of free string storage
$37-$38 (55-56) MEMSIZ Top of BASIC RAM
$39-$3A (57-58) CURLIN Current executing line number ($FF = immediate mode)
$3B-$3C (59-60) OLDLIN Previous line number
$43-$44 (67-68) DATPTR Pointer into DATA statements
$60-$66 (96-102) FAC#1 Floating-point accumulator 1 (5 bytes+sign+exp)
$61-$66 (97-102) FACEXP FAC1 exponent and mantissa
$69-$6E (105-110) FAC#2 Floating-point accumulator 2

BASIC Token Table

BASIC keywords are stored as single bytes ($80–$CB) in tokenized programs.

Token Keyword Token Keyword
$80 END $A0 TAB(
$81 FOR $A1 TO
$82 NEXT $A2 FN
$83 DATA $A3 SPC(
$84 INPUT# $A4 THEN
$85 INPUT $A5 NOT
$86 DIM $A6 STEP
$87 READ $A7 +
$88 LET $A8 -
$89 GOTO $A9 *
$8A RUN $AA /
$8B IF $AB ↑ (power)
$8C RESTORE $AC AND
$8D GOSUB $AD OR
$8E RETURN $AE >
$8F REM $AF =
$90 STOP $B0 <
$91 ON $B1 SGN
$92 WAIT $B2 INT
$93 LOAD $B3 ABS
$94 SAVE $B4 USR
$95 VERIFY $B5 FRE
$96 DEF $B6 POS
$97 POKE $B7 SQR
$98 PRINT# $B8 RND
$99 PRINT $B9 LOG
$9A CONT $BA EXP
$9B LIST $BB COS
$9C CLR $BC SIN
$9D CMD $BD TAN
$9E SYS $BE ATN
$9F OPEN $BF PEEK
(more) CLOSE $C0 LEN
$C1 STR$ $C2 VAL
$C3 ASC $C4 CHR$
$C5 LEFT$ $C6 RIGHT$
$C7 MID$ $C8 GO

BASIC Floating-Point Format

BASIC stores all numbers in 5-byte floating-point format:

Byte 0: Exponent (excess-128, 0=zero)
Byte 1: Mantissa byte 1 (bit 7 is sign: 0=positive, 1=negative)
Byte 2: Mantissa byte 2
Byte 3: Mantissa byte 3
Byte 4: Mantissa byte 4

Value = (–1)^sign × 0.1mmmmm... × 2^(exp–128)

Using BASIC Math from ML

The BASIC math routines can be called from machine language. The floating-point accumulator (FAC1) is at $61–$66.

Key math routines: | Address | Routine | Description | |---------|---------|-------------| | $BC0C | GIVAYF | Convert integer in A/Y to FAC1 | | $B391 | FADDH | Add 0.5 to FAC1 | | $B867 | FMULT | Multiply FAC1 by FAC2 | | $BB07 | FDIVT | Divide FAC2 by FAC1 | | $B849 | FADD | Add FAC2 to FAC1 | | $B850 | FSUB | Subtract FAC1 from FAC2 | | $B8D4 | LOG | LOG of FAC1 → FAC1 | | $BF11 | SQR | Square root of FAC1 → FAC1 | | $B9EA | SIN | Sine of FAC1 (radians) | | $BA28 | COS | Cosine of FAC1 | | $BB0F | TAN | Tangent of FAC1 | | $AE33 | AYINT | Convert FAC1 to 2-byte integer in $14-$15 | | $B7F7 | GETADR | Convert FAC1 to 16-bit address in $14-$15 | | $BD7E | FOUT | Convert FAC1 to ASCII string at $0100 | | $B395 | MOVFM | Move 5-byte float from (A,Y) to FAC1 | | $BBD4 | MOVMF | Move FAC1 to 5 bytes at (A,Y) |


Extending BASIC with New Commands

The BASIC interpreter can be extended by patching the BASIC main loop vectors:

RAM Vectors Involved

Address Vector Default Purpose
$0300-$0301 IERROR $E38B Error handler
$0302-$0303 IMAIN $A483 Main interpreter loop
$0304-$0305 ICRNCH $A57C Tokenize (crunch) line
$0306-$0307 IQPLOP $A71A De-tokenize for LIST
$0308-$0309 IGONE $A7E4 Execute statement
$030A-$030B IEVAL $AE86 Evaluate expression

Method 1: Patch IGONE (execute vector)

When BASIC encounters an unrecognized token or wants to execute a statement, it goes through IGONE ($0308/$0309). Patch this to intercept commands.

; Patch BASIC execute vector to add new commands
        LDA #<NEWCMD
        STA $0308
        LDA #>NEWCMD
        STA $0309
        RTS

NEWCMD  ; First, check for our keyword
        ; In BASIC, current token is in A when we arrive here
        CMP #$FE            ; some unused token we assigned
        BEQ DO_NEWCMD
        JMP $A7E4           ; else: jump to original IGONE

DO_NEWCMD:
        ; parse parameters from BASIC line
        ; then execute command
        RTS

Method 2: Using the CHRGET routine

CHRGET ($0073/$0074) gets the next character from the BASIC text. After calling, A contains the next PETSCII character or token.

; Get next character from BASIC program text
        JSR $0073           ; CHRGET — increments and reads next char
        ; A now has next character/token, with Z flag set if it's a space

Defining New Keyword with Token

Full procedure from The Advanced ML Book — adding a REPEAT command:

  1. Intercept ICRNCH to recognize the keyword text and replace with a token byte
  2. Intercept IQPLOP to de-tokenize back to text for LIST
  3. Intercept IGONE to execute when the token is encountered

Useful BASIC Tricks

Fast Screen Clear

PRINT CHR$(147)   ' Home + clear (PETSCII 147)

Peeking Inside Running Program

PRINT PEEK(57):PRINT PEEK(58)   ' Current line number low/high = PEEK(57)+PEEK(58)*256

Finding Free Memory

PRINT FRE(0)     ' Free BASIC RAM in bytes

Placing Program at Custom Address

POKE 43,1        ' Set TXTTAB low byte to 1 (start at $0801+offset)
POKE 44,N        ' High byte: program starts at N*256
NEW              ' Initialize BASIC for new location

Calling ML from BASIC with SYS Register Passing

POKE 780, A_VAL    ' $030C — A register value for SYS
POKE 781, X_VAL    ' $030D — X register
POKE 782, Y_VAL    ' $030E — Y register
SYS ADDRESS
RESULT = PEEK(780) ' A register after SYS

BASIC Error Numbers

Error Number Message
1 TOO MANY FILES
2 FILE OPEN
3 FILE NOT OPEN
4 FILE NOT FOUND
5 DEVICE NOT PRESENT
6 NOT INPUT FILE
7 NOT OUTPUT FILE
8 MISSING FILE NAME
9 ILLEGAL DEVICE NUMBER
10 NEXT WITHOUT FOR
11 SYNTAX
12 RETURN WITHOUT GOSUB
13 OUT OF DATA
14 ILLEGAL QUANTITY
15 OVERFLOW
16 OUT OF MEMORY
17 UNDEF'D STATEMENT
18 BAD SUBSCRIPT
19 REDIM'D ARRAY
20 DIVISION BY ZERO
21 ILLEGAL DIRECT
22 TYPE MISMATCH
23 STRING TOO LONG
24 FILE DATA
25 FORMULA TOO COMPLEX
26 CAN'T CONTINUE
27 UNDEF'D FUNCTION
28 VERIFY
29 LOAD

Triggering BASIC Error from ML

; Cause BASIC error N from machine language
        LDX #N          ; error number
        JMP $A437       ; BASIC error handler entry

PETSCII Control Codes (CHR$() values)

Code Effect Code Effect
5 White text 156 Purple text
13 RETURN 157 Cursor left
14 Lower case 158 Yellow text
17 Cursor down 159 Cyan text
18 Reverse on 28 Red text
19 Home 29 Cursor right
20 Delete 30 Green text
28 Red text 31 Blue text
29 Cursor right 144 Black text
30 Green text 145 Cursor up
31 Blue text 146 Reverse off
133-140 F1-F8 keys 147 Clear screen
148 Insert 149 Brown text
150 LT Red text 151 Dark grey
152 Grey 153 LT green
154 LT blue 155 LT grey

Powered by TurnKey Linux.