/*
 * bank1.c — code, const tables AND writable static data all live in the
 * BANK1 page mapped into window 3 while these functions run.
 *
 * Compile flags (see Makefile):
 *   --codeseg BANK1   functions go to _BANK1 area
 *   --constseg BANK1  `static const` tables go to _BANK1
 *   --dataseg BANK1   uninitialized data (BSS) goes to _BANK1
 *
 * mkexe -p 0 zero-pads the bank's image, so any BSS bytes that don't
 * appear in the IHX file are 0x00 when the bank is loaded — free zero
 * init for `uint8_t buf[N];`.
 *
 * Note: a CRITICAL trampoline fix is required (see memory/sdcc_banking)
 * — the old bcall used `pop af; out (n), a` which clobbered the uint8_t
 * return value.  Without that fix, banked functions returning a byte
 * would silently return the saved page number instead.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

uint8_t bank1_buf[16];

static const uint16_t bank1_tab[5] = { 100, 200, 300, 400, 500 };


void bank1_fill(int seed) __banked
{
    uint8_t *p = bank1_buf;
    for (int i = 0; i < 16; i++)
        p[i] = (uint8_t)(seed + i);
}

uint8_t bank1_peek(int idx) __banked
{
    uint8_t *p = bank1_buf;
    if (idx < 0 || idx >= 16) return 0xFF;
    return p[idx];
}

uint16_t bank1_sumtab(void) __banked
{
    uint16_t s = 0;
    for (int i = 0; i < 5; i++) s += bank1_tab[i];
    return s;
}

void bank1_map_print(void) __banked
{
    printf( "bank1_buf = %p\n", bank1_buf);
    printf( "bank1_tab = %p\n", bank1_tab);
    printf( "bank1_fill = %p\n", bank1_fill);
    printf( "bank1_peek = %p\n", bank1_peek);
    printf( "bank1_sumtab = %p\n", bank1_sumtab);
}

/*
 * malloc-from-banked test.
 *
 * SDCC's heap lives in HOME RAM (W2 = 0x8000-0xBFFF, see runtime/heap.s).
 * Window 2 is fixed and stays mapped regardless of W3 page swaps.  So
 * malloc() called from a banked function should:
 *   1. Return a pointer somewhere in 0x80xx..0xBFxx (W2 heap)
 *   2. The pointer is usable both inside the bank (W2 still mapped) and
 *      after returning to HOME (W2 unchanged across trampoline).
 *
 * The function allocates N bytes, fills them with a known pattern, and
 * returns the pointer to the caller for verification.
 */
uint8_t *bank1_alloc_and_fill(int n, uint8_t pattern) __banked
{
    uint8_t *p = (uint8_t *)malloc(n);
    if (p == NULL) return NULL;
    for (int i = 0; i < n; i++)
        p[i] = (uint8_t)(pattern + i);
    printf("  bank1_alloc_and_fill: malloc(%d) -> %p\n", n, p);
    return p;
}

void bank1_free(void *p) __banked
{
    free(p);
}
