501 lines
No EOL
8.2 KiB
Markdown
501 lines
No EOL
8.2 KiB
Markdown
# Syntax Reference
|
|
|
|
## Comments
|
|
|
|
C65GM uses C-style line comments.
|
|
|
|
**Syntax:**
|
|
```
|
|
// <comment text>
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
BYTE counter = 0 // Initialize counter
|
|
// This is a full line comment
|
|
FOR i = 0 TO 10 // Loop through values
|
|
counter++ // Increment
|
|
NEXT
|
|
```
|
|
|
|
**Notes:**
|
|
- Comments start with `//` and continue to end of line
|
|
- Comments in ASM blocks use assembly syntax: `;`
|
|
- Comments in SCRIPT blocks use Starlark syntax: `#`
|
|
|
|
---
|
|
|
|
## Preprocessor Directives
|
|
|
|
### #DEFINE
|
|
|
|
Defines a text substitution macro.
|
|
|
|
**Syntax:**
|
|
```
|
|
#DEFINE <n> [= <value>]
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
```
|
|
#DEFINE MAX_SPEED = 10
|
|
#DEFINE HELLO = GOODBYE // Will replace the text HELLO in all source with GOODBYE (except ASM and SCRIPT blocks)
|
|
#DEFINE HELLO2 = GOOOOOODBYE // Longest match wins. If HELLO2 is encountered this will be the match not the HELLO define above
|
|
#DEFINE SCREEN = $$0400 // Notice $$, see below.
|
|
#DEFINE OFFSET = 255
|
|
```
|
|
|
|
Note: Replacements are not recursive. Once a match is found, it's replaced, and processing starts after the replacement.
|
|
|
|
**Special Characters in Values:**
|
|
|
|
Define values support `$` escape sequences for special characters:
|
|
- `$XX` (two hex digits) = character with code XX
|
|
- `$$` = literal `$` character
|
|
```
|
|
#DEFINE SPACE = $20 // space character
|
|
#DEFINE NEWLINE = $0D // carriage return
|
|
#DEFINE TAB = $09 // tab character
|
|
#DEFINE HEXADDR = $$D020 // stores "$D020" as text
|
|
```
|
|
|
|
**Notes:**
|
|
- Optional `=` separator
|
|
- Value can contain previously defined macros
|
|
- Macros are expanded in source lines
|
|
- Case sensitive
|
|
- `$` escapes are processed when the define is created, not when used
|
|
- For most purposes, use `WORD CONST` or `BYTE CONST` instead of preprocessor defines to define constant named values
|
|
|
|
---
|
|
|
|
### #UNDEF
|
|
|
|
Undefines a previously defined macro.
|
|
|
|
**Syntax:**
|
|
```
|
|
#UNDEF <n>
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
#DEFINE DEBUG = 1
|
|
#UNDEF DEBUG
|
|
```
|
|
|
|
---
|
|
|
|
### #IFDEF
|
|
|
|
Conditional compilation if macro is defined.
|
|
|
|
**Syntax:**
|
|
```
|
|
#IFDEF <n>
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
#IFDEF DEBUG
|
|
BYTE debugFlag = 1
|
|
#IFEND
|
|
|
|
#IFDEF PAL
|
|
BYTE scanlines = 312
|
|
#IFEND
|
|
```
|
|
|
|
---
|
|
|
|
### #IFNDEF
|
|
|
|
Conditional compilation if macro is not defined.
|
|
|
|
**Syntax:**
|
|
```
|
|
#IFNDEF <n>
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
#IFNDEF __INCLUDED_SPRITE_LIB
|
|
#DEFINE __INCLUDED_SPRITE_LIB = 1
|
|
FUNC drawSprite
|
|
; sprite code
|
|
FEND
|
|
#IFEND
|
|
```
|
|
|
|
**Notes:**
|
|
- Common pattern for include guards
|
|
- Prevents multiple inclusion
|
|
|
|
---
|
|
|
|
### #IFEND
|
|
|
|
Ends conditional compilation block.
|
|
|
|
**Syntax:**
|
|
```
|
|
#IFEND
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
See #IFDEF and #IFNDEF
|
|
```
|
|
|
|
---
|
|
|
|
### #INCLUDE
|
|
|
|
Includes another source file.
|
|
|
|
**Syntax:**
|
|
```
|
|
#INCLUDE <filename>
|
|
#INCLUDE <libfile>
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
#INCLUDE sprites.c65
|
|
#INCLUDE lib/math.c65
|
|
#INCLUDE "constants.c65"
|
|
#INCLUDE <stdlib.c65>
|
|
```
|
|
|
|
**Notes:**
|
|
- Relative path: resolves relative to current file
|
|
- Angle brackets `<file>`: searches in library path defined by C65LIBPATH environment variable
|
|
- Supports nested includes
|
|
- Use with #IFNDEF for include guards
|
|
|
|
---
|
|
|
|
### #PRINT
|
|
|
|
Prints message during compilation.
|
|
|
|
**Syntax:**
|
|
```
|
|
#PRINT <message>
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
#PRINT Compiling main module
|
|
#PRINT MAX_VALUE
|
|
#PRINT Debug build enabled
|
|
```
|
|
|
|
**Notes:**
|
|
- Useful for debugging preprocessor
|
|
- Macros expanded before printing
|
|
|
|
---
|
|
|
|
### #HALT
|
|
|
|
Stops compilation immediately.
|
|
|
|
**Syntax:**
|
|
```
|
|
#HALT
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
#IFDEF INCOMPLETE
|
|
#PRINT Feature not implemented
|
|
#HALT
|
|
#IFEND
|
|
```
|
|
|
|
**Notes:**
|
|
- Halts entire compilation process, not just preprocessing
|
|
- Returns exit code 2
|
|
|
|
---
|
|
|
|
### #PRAGMA
|
|
|
|
Sets compiler pragmas (options).
|
|
|
|
**Syntax:**
|
|
```
|
|
#PRAGMA <n> [<value>]
|
|
```
|
|
|
|
**Available Pragmas:**
|
|
|
|
**_P_USE_LONG_JUMP**
|
|
- Uses JMP instead of branch instructions for IF/WHILE/FOR
|
|
- Needed when branch targets exceed 127 byte range
|
|
- Value: any non-zero value enables
|
|
|
|
**_P_USE_IMMUTABLE_CODE**
|
|
- Prevents self-modifying code generation
|
|
- Required for ROM-based code
|
|
- Errors on PEEK/POKE/GOSUB with variable addresses
|
|
|
|
**_P_USE_CBM_STRINGS**
|
|
- Encodes strings in CBM PETSCII format
|
|
- Default: ASCII encoding
|
|
- Value: any non-empty value enables
|
|
|
|
**Examples:**
|
|
```
|
|
#PRAGMA _P_USE_LONG_JUMP 1
|
|
#PRAGMA _P_USE_IMMUTABLE_CODE 1
|
|
#PRAGMA _P_USE_IMMUTABLE_CODE 0 //turn off pragma
|
|
#PRAGMA _P_USE_CBM_STRINGS 1
|
|
```
|
|
|
|
---
|
|
|
|
## Code Blocks
|
|
|
|
### ASM...ENDASM
|
|
|
|
Inline assembly code block.
|
|
|
|
**Syntax:**
|
|
```
|
|
ASM
|
|
<assembly code>
|
|
ENDASM
|
|
```
|
|
|
|
**Examples:**
|
|
```
|
|
ASM
|
|
lda #$00
|
|
sta $d020
|
|
jsr $ffd2
|
|
ENDASM
|
|
|
|
BYTE temp = 5
|
|
ASM
|
|
lda temp
|
|
clc
|
|
adc #10
|
|
sta temp
|
|
ENDASM
|
|
|
|
FUNC calculate(value)
|
|
BYTE local = 10
|
|
ASM
|
|
lda |local| ; Reference local variable
|
|
clc
|
|
adc value
|
|
sta |local|
|
|
ENDASM
|
|
FEND
|
|
```
|
|
|
|
**Notes:**
|
|
- Assembly code passed through to ACME assembler unchanged
|
|
- Can reference global variables by name
|
|
- Local variables inside FUNC must use `|varname|` syntax
|
|
- Comments in ASM blocks use `;` (assembly syntax)
|
|
- No macro expansion inside ASM blocks
|
|
|
|
---
|
|
|
|
### SCRIPT...ENDSCRIPT
|
|
|
|
Starlark script code block for generating assembly code.
|
|
|
|
Scripts are written in Starlark (Python-like language) and executed at compile time. Output from `print()` statements is fed directly into the assembler.
|
|
|
|
**Syntax:**
|
|
```
|
|
SCRIPT
|
|
<starlark code>
|
|
ENDSCRIPT
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
**Simple data generation:**
|
|
```
|
|
SCRIPT
|
|
for i in range(256):
|
|
print(" !8 %d" % i)
|
|
ENDSCRIPT
|
|
```
|
|
|
|
**Sine table generation:**
|
|
```
|
|
SCRIPT
|
|
import math
|
|
print("sintable:")
|
|
for i in range(256):
|
|
angle = (i * 2.0 * math.pi) / 256.0
|
|
sine = math.sin(angle)
|
|
value = int((sine + 1.0) * 127.5)
|
|
print(" !8 %d" % value)
|
|
ENDSCRIPT
|
|
```
|
|
|
|
**Using compiler variables:**
|
|
```
|
|
BYTE tableSize = 64
|
|
|
|
SCRIPT
|
|
# Reference variables in generated assembly
|
|
print("lookup:")
|
|
for i in range(64):
|
|
print(" !8 %d" % (i * 2))
|
|
print(" ; Table size is stored in |tableSize|")
|
|
ENDSCRIPT
|
|
```
|
|
|
|
**Notes:**
|
|
- Scripts use Starlark language (Python-like subset)
|
|
- Comments in SCRIPT blocks use `#` (Python syntax)
|
|
- Output from `print()` goes directly to assembler
|
|
- Can reference compiler variables using `|varname|` syntax
|
|
- Math module available: `import math`
|
|
- Maximum 1 million execution steps (prevents infinite loops)
|
|
- Executed at compile time, not runtime
|
|
|
|
---
|
|
|
|
## Expression Syntax
|
|
|
|
Expressions evaluate left to right with no operator precedence.
|
|
|
|
### Number Formats
|
|
|
|
**Decimal:**
|
|
```
|
|
123
|
|
0
|
|
255
|
|
65535
|
|
```
|
|
|
|
**Hexadecimal ($-prefix):**
|
|
```
|
|
$FF
|
|
$D020
|
|
$C000
|
|
$00
|
|
```
|
|
|
|
**Binary (%-prefix):**
|
|
```
|
|
%11111111
|
|
%10000000
|
|
%00000001
|
|
%11110000
|
|
```
|
|
|
|
### Operators
|
|
|
|
Evaluated strictly left to right:
|
|
|
|
- `+` Addition
|
|
- `-` Subtraction
|
|
- `*` Multiplication
|
|
- `/` Division
|
|
- `|` Bitwise OR
|
|
- `&` Bitwise AND
|
|
- `^` Bitwise XOR
|
|
|
|
### Constants
|
|
|
|
Named constants defined with BYTE CONST or WORD CONST:
|
|
|
|
```
|
|
BYTE CONST MAX_SPEED = 10
|
|
WORD CONST SCREEN = $0400
|
|
|
|
speed = MAX_SPEED
|
|
pointer = SCREEN
|
|
```
|
|
|
|
### Expression Examples
|
|
|
|
```
|
|
value = 100+50
|
|
result = $FF-10
|
|
address = $D000+32
|
|
mask = %11110000&$0F
|
|
combined = base|offset
|
|
calculated = start+length*2
|
|
```
|
|
|
|
**Critical:** No operator precedence. Evaluation is strictly left to right:
|
|
```
|
|
result = 2+3*4 ; evaluates as (2+3)*4 = 20, not 2+(3*4) = 14
|
|
value = $10|$20&$0F ; evaluates as ($10|$20)&$0F, not $10|($20&$0F)
|
|
```
|
|
|
|
### Usage Contexts
|
|
|
|
Expressions accepted anywhere a numeric literal is expected:
|
|
|
|
**Variable initialization:**
|
|
```
|
|
BYTE count = 10+5
|
|
WORD addr = $C000+$100
|
|
```
|
|
|
|
**Absolute addresses:**
|
|
```
|
|
BYTE screen @ $0400+40*10
|
|
INC $D000+20
|
|
```
|
|
|
|
**Command parameters:**
|
|
```
|
|
FOR i = 0 TO MAX_VALUE-1
|
|
IF x > THRESHOLD+10
|
|
POKE $D020+offset WITH value
|
|
result = PEEK $0400+index
|
|
```
|
|
|
|
**Arithmetic operations:**
|
|
```
|
|
sum = value1+value2
|
|
product = base*factor
|
|
adjusted = original+OFFSET
|
|
```
|
|
|
|
### Limitations
|
|
|
|
**No parentheses for grouping:**
|
|
```
|
|
; NOT SUPPORTED:
|
|
result = (a+b)*c
|
|
value = base+(offset*2)
|
|
```
|
|
|
|
**No nested expressions in assignments:**
|
|
```
|
|
; NOT SUPPORTED:
|
|
x = y + z ; only single value or constant expression
|
|
x = a+b ; constant expression (no spaces) OK if a,b are constants
|
|
```
|
|
|
|
**Workaround for complex expressions:**
|
|
Use temporary variables:
|
|
```
|
|
temp = a + b
|
|
result = temp - c
|
|
```
|
|
|
|
### Constant Expressions
|
|
|
|
Expressions without spaces are treated as constant expressions:
|
|
```
|
|
value = 100+50 ; OK - constant expression
|
|
value = 100 + 50 ; ERROR - not a simple assignment
|
|
value = MAX+10 ; OK if MAX is constant
|
|
``` |