mirror of
https://github.com/mi57730/a2d.git
synced 2024-11-25 10:30:50 +00:00
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.pl
can 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_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 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
%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.
- Use
.struct
definitions 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
impl
if 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.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:
.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 :-