8.9 KiB
c65gm Agent Instructions
Project Overview
c65gm is a high-level 6502 cross-compiler targeting the ACME Cross-Assembler for Commodore 64 and similar 6502-based platforms. It provides a more expressive language for writing 6502 assembly programs with modern programming constructs.
Key Documentation Locations
Primary Documentation
- README.md - Project overview, building, usage, and requirements
- language.md - Complete language reference with examples (1091 lines)
- syntax.md - Syntax rules and preprocessor directives (646 lines)
- commands.md - Complete command reference (776 lines)
Code Structure
- main.go - Entry point and command-line interface
- internal/compiler/ - Core compiler implementation
- internal/preproc/ - Preprocessor implementation
- internal/commands/ - Individual command implementations
- internal/utils/ - Utility functions
- lib/ - Standard library files for C64 development
- examples/ - Example programs demonstrating language features
Standard Library (lib/)
- c64start.c65 - Required for C64 executables (BASIC loader setup)
- c64defs.c65 - C64 hardware definitions (colors, addresses, etc.)
- c64kernal.c65 - Kernal routine wrappers
- c64scr.c65 - Screen manipulation functions
- string.c65 - String handling functions
- memlib.c65 - Memory management functions
- fat16/ - FAT16 filesystem support
- koalalib.c65 - Koala graphics support
Language Features to Note
Key Concepts
- Type system: BYTE (8-bit) and WORD (16-bit) variables with scope resolution
- Functions: Named functions with parameters and call graph analysis
- Control flow: IF/ENDIF, WHILE/WEND, FOR loops, SWITCH/CASE
- Memory operations: PEEK/POKE/PEEKW/POKEW with zero-page optimization
- Preprocessor: File inclusion, macros, conditional compilation, Starlark scripting
- Optimizations: Constant folding, self-assignment detection
- Safety features: Compile-time detection of overlapping absolute addresses
Important Syntax Rules
- No operator precedence: Expressions evaluate strictly left-to-right
- Memory-mapped variables: Use
@to place variables at specific addresses - Constants: Prefer
BYTE CONST/WORD CONSTover#DEFINE - Zero-page optimization: Place frequently accessed pointers in zero page ($00-$FF)
- Include guards: Always use
#IFNDEFin library files
Special Blocks
- ASM blocks: Inline assembly code
- SCRIPT blocks: Starlark code for compile-time code generation
- SCRIPT LIBRARY blocks: Reusable Starlark functions
- SCRIPT MACRO blocks: Parameterized macros for inline expansion
Common Patterns
Program Structure
#INCLUDE <c64start.c65>
#INCLUDE <c64defs.c65>
GOTO start // Jump over function definitions
// Variables and functions here
LABEL start // Program entry point
main()
Library Structure
#IFNDEF __MY_LIBRARY
#DEFINE __MY_LIBRARY = 1
GOTO lib_mylib_skip
// Library code here
LABEL lib_mylib_skip
#IFEND
Memory Operations
- Use
PEEK/POKEfor byte access - Use
PEEKW/POKEWfor word (16-bit) access - For indexed access, address must be a WORD variable in zero page
Development Guidelines
Environment Constraints
CRITICAL - NO GO TOOLS AVAILABLE: The agent runs in a Docker container without access to compilers, testing tools, or external build systems. The container does NOT have Go installed (go command not found). All compilation and testing must be performed by the user. The agent can only:
- Read and analyze source code
- Make code changes
- Provide instructions for the user to compile and test
NEVER attempt to run go build, go test, or any Go commands - they will fail with "go: not found".
File Access Restrictions
CRITICAL: The agent must only access normal project files within the current working directory. The agent must NEVER:
- Look at files outside the project directory (e.g.,
/tmp/,/etc/,/home/, etc.) - Read or attempt to access system files, environment files (
.env), or configuration files outside the project - Search for or read files containing secrets, credentials, or sensitive information
- Attempt to access files in parent directories or unrelated paths
All file operations must be restricted to the project's source code and documentation files only.
When Modifying the Compiler
- Check
internal/commands/for command implementations - Check
internal/compiler/for core compiler logic - Check
internal/preproc/for preprocessor functionality - DO NOT run tests - provide instructions for the user to run tests
When Adding New Features
- Follow existing patterns in command implementations
- Add comprehensive tests
- Update documentation in appropriate .md files
- Consider adding examples in
examples/directory
Testing and Rebuilding
CRITICAL: The agent cannot run tests or compile code. The container has no Go installation. Provide these instructions to the user:
Testing:
- Run all tests:
go test ./... - Run specific package tests:
go test ./internal/compiler - Test with verbose output:
go test -v ./...
Rebuilding c65gm:
When making changes to the compiler or library files, ask the user to rebuild c65gm using the build script:
./build_c65gm.sh
The build script copies lib/ into internal/preproc/lib/ (for embedding into the binary) and then runs go build -o c65gm.
IMPORTANT: Library files (lib/*.c65) are embedded into the binary at build time. After modifying any .c65 file in lib/, you MUST use build_c65gm.sh (not go build directly) to ensure the updated library is embedded. The agent should:
- Make code changes
- Ask the user to rebuild c65gm:
./build_c65gm.sh - Check file datetime: Verify the c65gm binary was recently updated (use
ls -la c65gmor similar) - Ask the user to run tests:
go test ./... - Test the changes with example .c65 files
IMPORTANT: Always check the file datetime of the c65gm binary after asking for a rebuild. If the timestamp hasn't changed, the user may have forgotten to rebuild, or the build may have failed. Testing with an old version is wasteful and can lead to incorrect conclusions.
Compiling .c65 files:
C65LIBPATH=/app/lib ./c65gm -in input.c65 -out output.asm
Common Pitfalls
- Expression evaluation: Remember no operator precedence
- Zero-page requirements: Indexed memory operations require zero-page addresses
- Include guards: Essential for library files to prevent multiple inclusion
- Program structure: Always use
GOTO startto jump over function definitions - String handling: Strings are passed as pointers to WORD parameters
Quick Reference
Compilation
IMPORTANT: The agent cannot compile code. Provide these instructions to the user:
New Self-Contained Method (Recommended)
./c65gm myprogram.c65 # Creates myprogram.prg (compile + assemble)
./c65gm build -i myprogram.c65 # Same as above
./c65gm compile -i myprogram.c65 # Creates myprogram.asm only
Legacy Method (Still Supported)
./c65gm -in myprogram.c65 -out output.asm
acme -f cbm -o output.prg output.asm
Environment Variables
C65LIBPATH: Library search path for#INCLUDE <file>
Editor Support
- Kate syntax:
editor_syntaxes/kate/ - Sublime syntax:
editor_syntaxes/sublime/
Where to Look for Specifics
Language Syntax
language.md: Sections 1-10 cover all language featuressyntax.md: Detailed syntax rules and preprocessor directivescommands.md: Complete command reference with examples
Implementation Details
internal/compiler/compiler.go: Main compiler logicinternal/commands/*.go: Individual command implementationsinternal/preproc/preproc.go: Preprocessor implementation
Examples
examples/: Working example programslib/: Standard library usage examples
Testing
*_test.gofiles throughout the codebaseexamples/: Functional test programs
Tool Notes
Shell Environment
- Shell: Only
/bin/sh(BusyBox) is available, not bash - The
bashtool in the interface runs commands through/bin/sh(BusyBox) - BusyBox limitations: Many GNU extensions are not available
grep Limitations
The environment uses BusyBox grep which doesn't support GNU grep extensions:
- NOT supported:
--include="*.go",--exclude="*.md", etc. - Use instead:
find /app -name "*.go" -type f -exec grep -l "pattern" {} \; - Example: Instead of
grep -r "CheckUnusedFunctions" /app --include="*.go", use:find /app -name "*.go" -type f -exec grep -l "CheckUnusedFunctions" {} \;
File Operations
- Use
findwith-execfor pattern-based file searches - Use
grepwithout GNU extensions for simple pattern matching - Prefer the
bashtool with proper BusyBox-compatible commands