a2d/CodingStyle.md

172 lines
3.6 KiB
Markdown
Raw Normal View History

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
```
## 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
* Add a label for the value being modified (byte or address)
2018-03-28 01:19:33 +00:00
```asm
2018-03-24 02:43:22 +00:00
sta jump_addr
stx jump_addr+1
jump_addr := *+1
jmp $0000
```
2018-03-28 01:19:33 +00:00
```asm
2018-03-24 02:43:22 +00:00
sty count
ldy #0
: sta table,y
iny
count := *+1
cpy #count
bne :-
```