/*
 * 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 <stdint.h>
#include <string.h>
#include <sprinter.h>
#include <sprinter_mem.h>

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);
}
