8.2 KiB
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 CONSTorBYTE CONSTinstead 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
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