# Syntax Reference ## Comments C65GM uses C-style line comments. **Syntax:** ``` // ``` **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 [= ] ``` **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 ``` **Examples:** ``` #DEFINE DEBUG = 1 #UNDEF DEBUG ``` --- ### #IFDEF Conditional compilation if macro is defined. **Syntax:** ``` #IFDEF ``` **Examples:** ``` #IFDEF DEBUG BYTE debugFlag = 1 #IFEND #IFDEF PAL BYTE scanlines = 312 #IFEND ``` --- ### #IFNDEF Conditional compilation if macro is not defined. **Syntax:** ``` #IFNDEF ``` **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 #INCLUDE ``` **Examples:** ``` #INCLUDE sprites.c65 #INCLUDE lib/math.c65 #INCLUDE "constants.c65" #INCLUDE ``` **Notes:** - Relative path: resolves relative to current file - Angle brackets ``: 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 ``` **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 [] ``` **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 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 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 ```