# Design notes found by inspection - these MUST be honoured by the SwiftLink driver

## 1. The NMI handler has to survive the I/O area being banked out

The game keeps its "game film" / saved-game buffer in the RAM *underneath* the I/O area, at
`$D000-$DFF0`.  `readFilmByte` ($5866) and `writeFilmByte` ($5893) in
`disassembly/game/mainProgram0800.s` therefore do this around every single byte:

    sei                     ; NMI is NOT blocked by this - see below
    stx CIA2_ICR            ; disable every CIA2 interrupt source (written twice as a guard)
    stx CIA2_ICR
    ldx #$34                ; bank RAM in over the whole $D000-$DFFF I/O area
    stx CPU_PORT
    lda (filmPtr),y         ; touch the film buffer
    inc CPU_PORT            ; back to $35, I/O visible again
    ldx ciaIcrShadow        ; $E033 - the module's copy of the CIA2 mask it wants
    stx CIA2_ICR            ; re-enable the modem's NMI sources
    cli

For the stock driver this is airtight: its UART interrupt *is* a CIA2 interrupt, so disabling CIA2
sources really does stop it firing while the registers are hidden.

**A SwiftLink interrupt is not a CIA2 interrupt.**  Nothing in that sequence stops the ACIA asserting
NMI, and `sei` does not mask NMI.  So the handler can and will fire while `$01 = $34`, at which point
`$DE00-$DE03` are ordinary RAM and the handler would read garbage, lose the received byte and
possibly wedge the receiver.

**Requirement:** the SwiftLink NMI handler must be bank-safe.  On entry save `$01`, force it to `$35`
so the ACIA is visible, do the work, then restore the saved value before `RTI`.  Do this before
touching any ACIA register.  Remember `$01` is also the 6510 port used for the tape motor and
character-ROM banking, so save and restore the whole byte, do not just write `$35` and `$34` back.

**Also:** `$E033` (`ciaIcrShadow`) is still written into `CIA2_ICR` by those two routines, so it must
hold a value that is correct for this driver.  This driver wants no CIA2 interrupts at all, so it
should hold `$7F` (clear every CIA2 source).  Set it at run time - its stored byte in the module image
is inside the frozen region and must not change.

## 2. Prefer base $DE00, and never index into the ACIA page by accident

`loadBaudParameters` ($E353) in the stock module writes its three bytes with `sta $DF59,y` where Y is
$FD/$FE/$FF, so the effective addresses are $E056-$E058.  That is fine on the stock hardware, but an
indexed *store* on a 6502 performs a dummy READ from the un-carried address first - here `$DF56`,
`$DF57` and `$DF58`.  With a SwiftLink strapped to `$DF00` those land on the ACIA's mirrored
registers, and `$DF58` mirrors the **data register**, whose read consumes a received byte and clears
RDRF.

The replacement for `loadBaudParameters` must not use that trick.  Address `$E056-$E058` directly.
More generally: default the driver to `$DE00`, and document that `$DF00` is second choice.

## 3. The game also copies pages across `$D000-$DF00`

`mapGenerator6F00.s` walks a source and a destination page over `$D000..$DF00` ($7F66, $816E) for the
film snapshot.  Those go through the same bank-out dance.  Nothing extra to do, but it is another
reason the handler must be bank-safe rather than relying on interrupts being masked.
