<!-- deft:deposit-link-rewrite v=1 source="content/languages/6502-DASM.md" -->
# 6502 + DASM Standards

Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.

**⚠️ See also**: [main.md](../main.md) | [PROJECT.md](../../PROJECT.md)

## Scope
- This guide covers:
  1. Fundamental 6502 assembly best practices (architecture-agnostic)
  2. DASM-specific authoring and build practices

## Standards

### 1) Fundamental 6502 best practices

#### Correctness and control flow
- ! Initialize execution state explicitly at startup (stack, flags relevant to your platform, and vectors/entry flow).
- ! Keep branch-distance limits in mind: relative branches are signed 8-bit offsets (−128..+127 from next PC).
- ~ Use clear, linear control flow with short local branches and explicit fallthrough comments.
- ~ Prefer `JMP` for tail calls instead of `JSR` + `RTS` chains when behavior is equivalent.
- ⊗ Assume all indirect control transfers are interchangeable; account for instruction-specific behavior and timing.

#### Addressing and data layout
- ! Use zero-page intentionally for hot paths and pointer temporaries.
- ~ Reserve absolute addressing for stable/global data and code readability.
- ~ Split pointer tables into low/high byte tables when speed/size wins matter.
- ! Keep tables and pointer math page-aware to avoid accidental cycle penalties.

#### Flags and arithmetic discipline
- ! Treat status flags (`N,V,B,D,I,Z,C`) as part of function contract when routines are reused.
- ~ Document which flags a routine clobbers or preserves.
- ~ Use `ADC`/`SBC` with explicit carry-state intent (avoid hidden flag dependencies).
- ≉ Use decimal mode (`D`) unless your target/runtime explicitly requires and supports that behavior in-context.

#### Timing and performance
- ! Budget cycles in timing-critical sections (raster/audio/bitbanging/IRQ windows).
- ~ Prefer predictable-cycle constructs when determinism matters (avoid hidden page-crossing penalties).
- ~ Distinguish optimization goals per routine: speed, size, determinism, or RAM footprint.
- ≉ Micro-optimize everywhere; optimize measured hotspots first.

#### Reentrancy, stack, and interrupts
- ! Keep IRQ/NMI-visible shared state minimal and explicit.
- ~ Prefer reentrant patterns for utility routines used from multiple contexts.
- ~ Use stack depth conservatively; document worst-case nesting.
- ⊗ Use scratch RAM assumptions that break under nested interrupts or reused dispatch paths.

### 2) DASM-specific best practices

#### File structure and processor declaration
- ! Put `PROCESSOR` at the top-level entry file, first logical directive.
- ! Declare `PROCESSOR` exactly once per assembly.
- ~ Use one master file that `INCLUDE`s modules in deterministic order.
- ~ Group code/data by `SEG` with explicit intent (ROM code/data vs uninitialized RAM/BSS-style allocation).

#### Expression and syntax discipline
- ! Use DASM expression syntax consistently (`[]` for parenthesized expressions).
- ~ Enable strict syntax checking during CI/release builds (`-S`).
- ~ Prefer explicitness in expressions/macros over terse clever forms.

#### Labels, locality, and subroutines
- ! Use `SUBROUTINE` boundaries to scope and safely reuse local labels (dot-prefixed labels).
- ~ Keep local-label naming simple and repeatable inside each subroutine.
- ~ Use globally unique labels for externally referenced entry points and shared data.

#### Segments, origins, and binary output
- ! Choose output format intentionally:
  - `-f1`: origin header + ascending initialized output
  - `-f2` (RAS): hunked random-access segments (supports non-ascending/reverse-indexed origin workflows)
  - `-f3`: raw data only (no header), with format-1 ordering constraints
- ! Keep initialized segment ordering compatible with selected output format.
- ~ Use uninitialized segments for RAM maps/size accounting without generating bytes.
- ~ Make fill behavior explicit when advancing origins / reserving space (avoid accidental default-fill reliance).

#### Includes, assets, and portability
- ! Use `INCDIR`/`INCLUDE`/`INCBIN` with stable relative project layout.
- ~ Use `INCBIN` skip-offset intentionally when ingesting assets with headers.
- ~ Keep platform/path assumptions out of assembly source where possible.

#### Build and diagnostics
- ! Fail builds on assembler errors; treat warnings as actionable.
- ~ Use symbol/list outputs (`-s`, `-l`/`-L`) for reproducible debugging and review.
- ~ Pin pass limits (`-p`/`-P`) in automation to detect pathological unresolved-symbol loops.
- ? Use `-v` levels >0 in local debugging; keep CI logs concise unless troubleshooting.

## Commands

See [commands.md](./commands.md).

## Patterns

### Routine contract header (recommended)
```asm
; Name: memcpy_zp_ptr
; In:   src ptr in zp $00/$01, dst ptr in zp $02/$03, len in X
; Out:  copied bytes
; Clobbers: A, X, flags N/Z/C
; Preserves: Y
```

### Master-file layout (DASM)
```asm
        PROCESSOR 6502

        INCDIR "src"
        INCLUDE "constants.inc"
        INCLUDE "zeropage.inc"

        SEG CODE
        ORG $8000
Reset:  ; ...

        SEG VECTORS
        ORG $FFFA
        .word NmiHandler, Reset, IrqHandler
```

## Compliance Checklist
- ! Startup/entry code explicitly defines runtime assumptions.
- ! Branch-range and page-crossing behavior considered in hot code.
- ! Routine flag/register clobbers are documented.
- ! `PROCESSOR` is declared once and first in DASM master source.
- ! Segment/output format policy is explicit and consistent with linker/loader expectations.
- ! Strict syntax mode and deterministic build options are used in automation.

## Sources
- MOS Technology, *MCS6500 Microcomputer Family Programming Manual* (1976): https://bitsavers.org/components/mosTechnology/6500-50A_MCS6500pgmManJan76.pdf
- DASM README (project + docs pointers): https://raw.githubusercontent.com/dasm-assembler/dasm/master/README
- DASM user text documentation (`docs/dasm.txt`): https://raw.githubusercontent.com/dasm-assembler/dasm/master/docs/dasm.txt
- NESdev: 6502 optimization patterns: https://www.nesdev.org/wiki/6502_assembly_optimisations
- NESdev: cycle-counting guidance: https://www.nesdev.org/wiki/Cycle_counting
- Obelisk/NESdev timing reference landing (linked from cycle docs): http://www.obelisk.me.uk/6502/
- Masswerk 6502 instruction-set reference: https://www.masswerk.at/6502/6502_instruction_set.html
