Updated language guide slightly
This commit is contained in:
parent
b54183aab4
commit
4319373828
1 changed files with 121 additions and 29 deletions
150
language.md
150
language.md
|
|
@ -12,46 +12,73 @@ c65gm is a high-level language for 6502 assembly programming that combines moder
|
||||||
6. [Memory Operations](#memory-operations)
|
6. [Memory Operations](#memory-operations)
|
||||||
7. [Code Blocks](#code-blocks)
|
7. [Code Blocks](#code-blocks)
|
||||||
8. [Preprocessor](#preprocessor)
|
8. [Preprocessor](#preprocessor)
|
||||||
9. [Common Patterns](#common-patterns)
|
9. [Writing Libraries](#writing-libraries)
|
||||||
|
10. [Common Patterns](#common-patterns)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Getting Started
|
## 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
|
```c65
|
||||||
ORIGIN $0801
|
#INCLUDE <c64start.c65>
|
||||||
|
#INCLUDE <c64defs.c65>
|
||||||
|
|
||||||
BYTE borderColor @ $D020
|
GOTO start
|
||||||
|
|
||||||
borderColor = 5 // Set border to green
|
FUNC main
|
||||||
|
BYTE borderColor @ $D020
|
||||||
|
borderColor = color_green
|
||||||
|
FEND
|
||||||
|
|
||||||
|
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
|
### Program Structure
|
||||||
|
|
||||||
A typical c65gm program consists of:
|
A typical c65gm program for C64 follows this pattern:
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
```c65
|
```c65
|
||||||
ORIGIN $0801
|
#INCLUDE <c64start.c65>
|
||||||
|
#INCLUDE <c64defs.c65> // Optional: standard C64 definitions
|
||||||
|
|
||||||
|
GOTO start // Jump over your function definitions
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
BYTE counter = 0
|
BYTE counter = 0
|
||||||
WORD screen = $0400
|
WORD screen = $0400
|
||||||
|
|
||||||
// Main code
|
// Functions - must be declared before we use them.
|
||||||
FUNC main
|
FUNC processData
|
||||||
|
// Do something
|
||||||
|
FEND
|
||||||
|
|
||||||
|
FUNC initialize
|
||||||
counter = 10
|
counter = 10
|
||||||
processData()
|
processData()
|
||||||
FEND
|
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
|
## Variables and Types
|
||||||
|
|
@ -120,8 +147,6 @@ value = %11111111 // Binary (% prefix)
|
||||||
```c65
|
```c65
|
||||||
result = 10 + 5 // Addition
|
result = 10 + 5 // Addition
|
||||||
result = 100 - 5 // Subtraction
|
result = 100 - 5 // Subtraction
|
||||||
result = 4 * 10 // Multiplication
|
|
||||||
result = 100 / 5 // Division
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Bitwise Operators
|
### Bitwise Operators
|
||||||
|
|
@ -146,27 +171,18 @@ lives--
|
||||||
**Expressions evaluate strictly left to right!** There is no operator precedence.
|
**Expressions evaluate strictly left to right!** There is no operator precedence.
|
||||||
|
|
||||||
```c65
|
```c65
|
||||||
result = 2 + 3 * 4 // Evaluates as (2+3)*4 = 20, NOT 2+(3*4) = 14
|
result = 2+3*4 // Evaluates as (2+3)*4 = 20, NOT 2+(3*4) = 14
|
||||||
value = 100 - 20 + 5 // Evaluates as (100-20)+5 = 85
|
value = 100-20+5 // Evaluates as (100-20)+5 = 85
|
||||||
```
|
```
|
||||||
|
|
||||||
For complex expressions, use temporary variables:
|
For complex expressions, use temporary variables:
|
||||||
|
|
||||||
```c65
|
```c65
|
||||||
// Instead of: result = a + b * c (which doesn't work as expected)
|
// Instead of: result = (b - c) + a
|
||||||
temp = b * c
|
temp = b - c
|
||||||
result = a + temp
|
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
|
## 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
|
## 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
|
### Screen Manipulation
|
||||||
|
|
||||||
```c65
|
```c65
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue