4.1 KiB
4.1 KiB
Coding Style
Review the ca65 Users Guide for syntax details.
Formatting
- Spaces, not tabs
- "Tab" stops for alignment are 8 characters (Emacs asm-mode default)
res/asmfmt.plcan be used for formatting- No trailing whitespace
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 - Use
?for questions in comment text,???for questions about the code:
lda value
cmp #limit ; less than the limit?
bcc less ; yes, so go do that
rol $1234 ; what does this do ???
Naming
- Prefer
snake_casefor 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 for local loops and forward branches to avoid pointless names. Only use one level.
;; Copy the thing
ldy #7
: lda (src),y
sta (dst),y
dey
bpl :-
lda flag
bne :+
inc count
: rts
- Do use cheap local labels to higlight repeated patterns. For example, retries:
@retry: MLI_CALL GET_FILE_INFO, params
beq :+
jsr show_error_alert
jmp @retry
Literals
- Use binary
%00110110for 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.
- Use
.structdefinitions to define offsets into structures - Use math where necessary (e.g.
ldy #offset2 - offset1) - Use
.sizeof()(or math if needed) rather than hardcoding sizes
- Define local variables (e.g.
Structure
- Delimit code blocks with
.proc:
.proc some_routine
lda $06
rol
rts
.endproc
- Try to encapsulate locally used data as much as possible.
.proc some_routine
ptr := $06
lda ptr
sta stash
rts
stash: .byte 0
.endproc
- Use
implif the entry point is not at the start:
.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.incand 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
.procblocks:
.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.
Self-modifying code
- Add a label for the value being modified (byte or address). Use
cheap local labels via the
@-prefix where possible so make self-modification references more visible.
sta @jump_addr
stx @jump_addr+1
@jump_addr := *+1
jmp $0000
sty @count
ldy #0
: sta table,y
iny
@count := *+1
cpy #00
bne :-