Updated language guide slightly
This commit is contained in:
parent
b54183aab4
commit
4319373828
1 changed files with 121 additions and 29 deletions
144
language.md
144
language.md
|
|
@ -12,46 +12,73 @@ c65gm is a high-level language for 6502 assembly programming that combines moder
|
|||
6. [Memory Operations](#memory-operations)
|
||||
7. [Code Blocks](#code-blocks)
|
||||
8. [Preprocessor](#preprocessor)
|
||||
9. [Common Patterns](#common-patterns)
|
||||
9. [Writing Libraries](#writing-libraries)
|
||||
10. [Common Patterns](#common-patterns)
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Your First Program
|
||||
### Your First C64 Program
|
||||
|
||||
Here's a simple program that changes the screen border color on a Commodore 64:
|
||||
Here's a simple complete program that changes the screen border color:
|
||||
|
||||
```c65
|
||||
ORIGIN $0801
|
||||
#INCLUDE <c64start.c65>
|
||||
#INCLUDE <c64defs.c65>
|
||||
|
||||
GOTO start
|
||||
|
||||
FUNC main
|
||||
BYTE borderColor @ $D020
|
||||
borderColor = color_green
|
||||
FEND
|
||||
|
||||
borderColor = 5 // Set border to green
|
||||
LABEL start
|
||||
main()
|
||||
```
|
||||
|
||||
### Creating a C64 Executable
|
||||
|
||||
To create a runnable C64 program, always start with:
|
||||
|
||||
```c65
|
||||
#INCLUDE <c64start.c65>
|
||||
```
|
||||
|
||||
This creates a valid C64 executable with a BASIC loader (`0 SYS 2064`) and sets up the proper memory layout.
|
||||
|
||||
### Program Structure
|
||||
|
||||
A typical c65gm program consists of:
|
||||
|
||||
1. **ORIGIN directive** - Sets where code will be placed in memory
|
||||
2. **Variable declarations** - Define your data
|
||||
3. **Code** - Functions and statements that do the work
|
||||
A typical c65gm program for C64 follows this pattern:
|
||||
|
||||
```c65
|
||||
ORIGIN $0801
|
||||
#INCLUDE <c64start.c65>
|
||||
#INCLUDE <c64defs.c65> // Optional: standard C64 definitions
|
||||
|
||||
GOTO start // Jump over your function definitions
|
||||
|
||||
// Variables
|
||||
BYTE counter = 0
|
||||
WORD screen = $0400
|
||||
|
||||
// Main code
|
||||
FUNC main
|
||||
// Functions - must be declared before we use them.
|
||||
FUNC processData
|
||||
// Do something
|
||||
FEND
|
||||
|
||||
FUNC initialize
|
||||
counter = 10
|
||||
processData()
|
||||
FEND
|
||||
|
||||
// Entry point - execution starts here
|
||||
LABEL start
|
||||
initialize()
|
||||
```
|
||||
|
||||
**Important:** The `GOTO start` jumps over your function definitions. Without it, the CPU would try to execute directly into your function code, causing a crash. Always put `GOTO start` before your functions, and `LABEL start` before your actual program entry point.
|
||||
|
||||
---
|
||||
|
||||
## Variables and Types
|
||||
|
|
@ -120,8 +147,6 @@ value = %11111111 // Binary (% prefix)
|
|||
```c65
|
||||
result = 10 + 5 // Addition
|
||||
result = 100 - 5 // Subtraction
|
||||
result = 4 * 10 // Multiplication
|
||||
result = 100 / 5 // Division
|
||||
```
|
||||
|
||||
### Bitwise Operators
|
||||
|
|
@ -153,20 +178,11 @@ value = 100 - 20 + 5 // Evaluates as (100-20)+5 = 85
|
|||
For complex expressions, use temporary variables:
|
||||
|
||||
```c65
|
||||
// Instead of: result = a + b * c (which doesn't work as expected)
|
||||
temp = b * c
|
||||
// Instead of: result = (b - c) + a
|
||||
temp = b - c
|
||||
result = a + temp
|
||||
```
|
||||
|
||||
### Constant Expressions
|
||||
|
||||
Expressions without spaces are treated as compile-time constants:
|
||||
|
||||
```c65
|
||||
value = 100+50 // OK - constant expression, evaluated at compile time
|
||||
value = 100 + 50 // ERROR - spaces make it a runtime expression
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Control Flow
|
||||
|
|
@ -581,8 +597,84 @@ Control compiler behavior:
|
|||
|
||||
---
|
||||
|
||||
## Writing Libraries
|
||||
|
||||
When creating a library file to be included by other programs, use this structure:
|
||||
|
||||
```c65
|
||||
#IFNDEF __MY_LIBRARY
|
||||
#DEFINE __MY_LIBRARY = 1
|
||||
|
||||
GOTO lib_mylib_skip // Jump over library code
|
||||
|
||||
// Library variables
|
||||
WORD lib_mylib_buffer
|
||||
|
||||
// Library functions
|
||||
FUNC lib_mylib_initialize
|
||||
lib_mylib_buffer = $C000
|
||||
FEND
|
||||
|
||||
FUNC lib_mylib_process(value)
|
||||
// Do something
|
||||
FEND
|
||||
|
||||
// Skip label - execution continues here after GOTO
|
||||
LABEL lib_mylib_skip
|
||||
|
||||
#IFEND
|
||||
```
|
||||
|
||||
**Key points for libraries:**
|
||||
|
||||
1. **Include guard** - Use `#IFNDEF` to prevent multiple inclusion
|
||||
2. **GOTO skip** - Jump over all library code immediately
|
||||
3. **LABEL skip** - Place at the end so GOTO jumps past everything
|
||||
4. **Naming convention** - Prefix all names with `lib_yourlib_` to avoid conflicts
|
||||
|
||||
This ensures when someone does `#INCLUDE <mylib.c65>`, the library functions are defined but not executed.
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Complete Working Example
|
||||
|
||||
Here's a complete C64 program showing all the pieces together:
|
||||
|
||||
```c65
|
||||
#INCLUDE <c64start.c65>
|
||||
#INCLUDE <c64defs.c65>
|
||||
|
||||
GOTO start
|
||||
|
||||
// Variables
|
||||
BYTE frameCount = 0
|
||||
WORD screenPtr @ $FB
|
||||
|
||||
// Functions
|
||||
FUNC initialize
|
||||
BYTE borderColor @ $D020
|
||||
borderColor = color_black
|
||||
POINTER screenPtr TO $0400
|
||||
FEND
|
||||
|
||||
FUNC updateScreen
|
||||
BYTE color
|
||||
color = frameCount & $0F
|
||||
POKE screenPtr[0] WITH color
|
||||
frameCount++
|
||||
FEND
|
||||
|
||||
// Entry point
|
||||
LABEL start
|
||||
initialize()
|
||||
|
||||
WHILE 1
|
||||
updateScreen()
|
||||
WEND
|
||||
```
|
||||
|
||||
### Screen Manipulation
|
||||
|
||||
```c65
|
||||
|
|
|
|||
Loading…
Reference in a new issue