2018-03-23 04:57:52 +00:00
|
|
|
# Coding Style
|
|
|
|
|
|
|
|
Review the [ca65 Users Guide](http://cc65.github.io/doc/ca65.html) for
|
|
|
|
syntax details.
|
|
|
|
|
|
|
|
|
|
|
|
## Formatting
|
|
|
|
|
2018-03-23 15:24:24 +00:00
|
|
|
* Spaces, not tabs
|
|
|
|
* "Tab" stops for alignment are 8 characters (Emacs asm-mode default)
|
2018-03-23 04:57:52 +00:00
|
|
|
* `res/asmfmt.pl` can be used for formatting
|
2018-03-23 15:24:24 +00:00
|
|
|
* No trailing whitespace
|
2018-03-23 04:57:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
## Assembly
|
|
|
|
|
|
|
|
* Use lowercase opcodes (`lda`, `rts`)
|
|
|
|
* All A2D code is 6502 not 65C02
|
|
|
|
|
|
|
|
|
|
|
|
## Comments
|
|
|
|
|
|
|
|
* Comments are **encouraged**.
|
|
|
|
* End-of-line comments: `;` at a tab stop or aligned with nearby code
|
|
|
|
* Indented stand-alone comments: `;;` at first tab stop (8 chars)
|
|
|
|
* Major comments: `;;;` at start of line
|
2018-03-28 01:19:33 +00:00
|
|
|
* Use `?` for questions in comment text, `???` for questions about the code:
|
|
|
|
```asm
|
|
|
|
lda value
|
|
|
|
cmp #limit ; less than the limit?
|
|
|
|
bcc less ; yes, so go do that
|
2018-06-02 18:32:30 +00:00
|
|
|
|
2018-03-28 01:19:33 +00:00
|
|
|
rol $1234 ; what does this do ???
|
|
|
|
```
|
2018-03-23 04:57:52 +00:00
|
|
|
|
|
|
|
## Naming
|
|
|
|
|
|
|
|
* Prefer `snake_case` for procedures and labels
|
|
|
|
|
|
|
|
NOTE: MGTK uses `TitleCase` for procedures, so that is used in limited
|
|
|
|
cases, e.g. `HideCursor`, `HideCursorImpl`, etc.
|
|
|
|
|
|
|
|
* Equates from ROM (Applesoft, Monitor, Firmware, etc) and ProDOS are in
|
|
|
|
`UPPERCASE`.
|
|
|
|
|
|
|
|
|
|
|
|
## Flow control
|
|
|
|
|
|
|
|
* **Do** make use of [unnamed labels](http://cc65.github.io/doc/ca65.html#ss6.6) for
|
|
|
|
local loops and forward branches to avoid pointless names. Only use one level.
|
|
|
|
|
2018-03-28 01:19:33 +00:00
|
|
|
```asm
|
2018-03-23 04:57:52 +00:00
|
|
|
;; Copy the thing
|
|
|
|
ldy #7
|
|
|
|
: lda (src),y
|
|
|
|
sta (dst),y
|
|
|
|
dey
|
|
|
|
bpl :-
|
|
|
|
|
|
|
|
lda flag
|
|
|
|
bne :+
|
|
|
|
inc count
|
|
|
|
: rts
|
|
|
|
```
|
|
|
|
|
2019-01-15 04:43:17 +00:00
|
|
|
* **Do** use [cheap local labels](https://cc65.github.io/doc/ca65.html#ss6.5)
|
|
|
|
to higlight repeated patterns. For example, retries:
|
|
|
|
|
|
|
|
```asm
|
|
|
|
@retry: MLI_CALL GET_FILE_INFO, params
|
|
|
|
beq :+
|
|
|
|
jsr show_error_alert
|
|
|
|
jmp @retry
|
|
|
|
```
|
|
|
|
|
2018-03-23 04:57:52 +00:00
|
|
|
## Literals
|
|
|
|
|
|
|
|
* Use binary `%00110110` for bit patterns
|
|
|
|
* Use decimal for numbers (counts, dimensions, etc)
|
|
|
|
* Use hex for geeky values, e.g. $7F (bit mask), $80 (high bit),
|
|
|
|
$FF (all bits set) when bits would be less readble.
|
|
|
|
* Avoid magic numbers where possible:
|
|
|
|
* Define local variables (e.g. `ptr := $06`)
|
|
|
|
* Define offsets, constants, etc.
|
2018-06-02 18:32:30 +00:00
|
|
|
* Use `.struct` definitions to define offsets into structures
|
2018-03-23 04:57:52 +00:00
|
|
|
* Use math where necessary (e.g. `ldy #offset2 - offset1`)
|
2018-03-24 02:43:22 +00:00
|
|
|
* Use `.sizeof()` (or math if needed) rather than hardcoding sizes
|
2018-03-23 04:57:52 +00:00
|
|
|
|
|
|
|
## Structure
|
|
|
|
|
|
|
|
* Delimit code blocks with `.proc`:
|
|
|
|
|
2018-03-28 01:19:33 +00:00
|
|
|
```asm
|
2018-03-23 04:57:52 +00:00
|
|
|
.proc some_routine
|
|
|
|
lda $06
|
|
|
|
rol
|
|
|
|
rts
|
|
|
|
.endproc
|
|
|
|
```
|
|
|
|
|
2018-03-28 04:06:44 +00:00
|
|
|
* Try to encapsulate locally used data as much as possible.
|
2018-03-23 04:57:52 +00:00
|
|
|
|
2018-03-28 01:19:33 +00:00
|
|
|
```asm
|
2018-03-23 04:57:52 +00:00
|
|
|
.proc some_routine
|
|
|
|
ptr := $06
|
|
|
|
lda ptr
|
|
|
|
sta stash
|
|
|
|
rts
|
|
|
|
|
|
|
|
stash: .byte 0
|
|
|
|
.endproc
|
|
|
|
```
|
|
|
|
|
|
|
|
* Use `impl` if the entry point is not at the start:
|
|
|
|
|
2018-03-28 01:19:33 +00:00
|
|
|
```asm
|
2018-03-23 04:57:52 +00:00
|
|
|
.proc some_routine_impl
|
|
|
|
stash: .byte 0
|
|
|
|
|
|
|
|
ptr := $06
|
|
|
|
|
|
|
|
start: lda ptr
|
|
|
|
sta stash
|
|
|
|
rts
|
|
|
|
|
|
|
|
.endproc
|
|
|
|
some_routine := some_routine_impl::start
|
|
|
|
```
|
|
|
|
|
|
|
|
## Macros
|
|
|
|
|
|
|
|
* Macro use is **encouraged**.
|
|
|
|
* Use local macros to avoid repeating code.
|
|
|
|
* Use `macros.inc` and extend as needed to capture patterns such as
|
|
|
|
16-bit operations
|
|
|
|
* API calls such as ProDOS MLI calls should be done with macros
|
|
|
|
|
|
|
|
|
|
|
|
## Param Blocks
|
|
|
|
|
|
|
|
Parameter blocks are used for ProDOS MLI calls and MGTK calls.
|
|
|
|
|
|
|
|
* Wrap param data in `.proc` blocks:
|
|
|
|
|
2018-03-28 01:19:33 +00:00
|
|
|
```asm
|
2018-03-23 04:57:52 +00:00
|
|
|
.proc textwidth_params
|
|
|
|
textptr: .addr text_buffer
|
|
|
|
textlen: .byte 0
|
|
|
|
result: .word 0
|
|
|
|
.endproc
|
|
|
|
|
|
|
|
;; elsewhere...
|
|
|
|
MGTK_CALL MGTK::TextWidth, textwidth_params
|
|
|
|
```
|
|
|
|
|
|
|
|
## Namespaces
|
|
|
|
|
|
|
|
Currently, only MGTK constants are wrapped in a `.scope` to provide
|
|
|
|
a namespace. We may want to do that for ProDOS and DeskTop stuff as
|
|
|
|
well in the future.
|
2018-03-24 02:43:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
## Self-modifying code
|
|
|
|
|
2018-11-24 19:17:46 +00:00
|
|
|
* Add a label for the value being modified (byte or address). Use
|
|
|
|
[cheap local labels](https://cc65.github.io/doc/ca65.html#ss6.5) via the
|
|
|
|
`@`-prefix where possible so make self-modification references more
|
|
|
|
visible.
|
2018-03-24 02:43:22 +00:00
|
|
|
|
2018-03-28 01:19:33 +00:00
|
|
|
```asm
|
2018-11-24 19:17:46 +00:00
|
|
|
sta @jump_addr
|
|
|
|
stx @jump_addr+1
|
|
|
|
@jump_addr := *+1
|
2018-03-24 02:43:22 +00:00
|
|
|
jmp $0000
|
|
|
|
```
|
2018-03-28 01:19:33 +00:00
|
|
|
```asm
|
2018-11-24 19:17:46 +00:00
|
|
|
sty @count
|
2018-03-24 02:43:22 +00:00
|
|
|
ldy #0
|
|
|
|
: sta table,y
|
|
|
|
iny
|
2018-11-24 19:17:46 +00:00
|
|
|
@count := *+1
|
|
|
|
cpy #00
|
2018-03-24 02:43:22 +00:00
|
|
|
bne :-
|
|
|
|
```
|