/* * bank_io_w3.c — far-page accessors that swap window 3 (port 0xE2, * base 0xC000). Save the current W3 page, set the target, do the * byte/memcpy access, restore the saved page. * * Safe in `tiny`, `small`, `big` memory modes (W3 is free for data). * NOT safe in `huge` — there banked code lives in W3. * * No DI/EI around the swap: ISRs that don't touch W3 are unaffected; * concurrent W3 use from an ISR is unsafe. * * The `_w1` family (bank_io_w1.c) is the mirror through W1 and is * `tiny`-only. See sprinter_mem.h for the full safety matrix. */ #include #include #include #include uint8_t bank_load_byte(uint8_t phys_page, uint16_t off_in_window) { uint8_t saved = _io_page_w3; sprinter_page_w3(phys_page); uint8_t v = *((volatile uint8_t *)(0xC000u + off_in_window)); sprinter_page_w3(saved); return v; } void bank_store_byte(uint8_t phys_page, uint16_t off_in_window, uint8_t v) { uint8_t saved = _io_page_w3; sprinter_page_w3(phys_page); *((volatile uint8_t *)(0xC000u + off_in_window)) = v; sprinter_page_w3(saved); } void bank_read(uint8_t phys_page, uint16_t off, void *dst, uint16_t n) { uint8_t saved = _io_page_w3; sprinter_page_w3(phys_page); memcpy(dst, (const void *)(0xC000u + off), n); sprinter_page_w3(saved); } void bank_write(uint8_t phys_page, uint16_t off, const void *src, uint16_t n) { uint8_t saved = _io_page_w3; sprinter_page_w3(phys_page); memcpy((void *)(0xC000u + off), src, n); sprinter_page_w3(saved); }