/*
 * w3bankgfx — пробник раскладки «huge + резидент W3 + банк W3 + графика».
 * См. Makefile: проверяются правила R2/R3/R4 из
 * applications/PoP/docs/layout_plan_v2.md §2.
 *
 * Итог рисуется полосами, чтобы читалось и глазом, и скриптом по VRAM:
 *   y=20  синяя   — рисовал РЕЗИДЕНТ W3 (до банка)
 *   y=40  бирюз.  — рисовал БАНК напрямую примитивом libbgi
 *   y=60  жёлтая  — рисовала функция W1/W2, вызванная ИЗ БАНКА
 *   y=80  зелёная — все проверки прошли (иначе КРАСНАЯ)
 *   y=100 синяя   — резидент W3 жив ПОСЛЕ возврата из банка
 */
#include <graphics.h>
#include <stdio.h>
#include <stdint.h>
#include <sprinter.h>

const uint8_t n_banks = 1;          /* читает crt0_banked */

extern uint8_t res_page_seen;
uint8_t bank_page_before, bank_page_after, bank_page_after_home, bank_alive;
extern uint8_t bank_pages[];

void res_draw(int y, int color);              /* резидент W3 (прямой вызов) */
uint8_t bank_run(uint8_t arg) __banked;       /* банк (через трамплин) */

uint8_t home_page_seen;

/* Текущая страница W3 (порт 0xE2).  ОТДЕЛЬНОЙ __naked-функцией: инлайновый
 * `in a,(0xE2)` посреди тела затирает A, куда SDCC уже положил параметр —
 * в первой версии пробника из-за этого цвет заливки становился номером
 * страницы (0xF3 = чёрный), и «резидент не рисовал». */
static uint8_t w3_page(void) __naked
{
    __asm__("in a, (#0xE2)\n\tret");
}


/* Функция W1/W2, которую зовёт БАНК.  Рисует — то есть внутри неё libbgi
 * подменит W3 на видеобанк и вернёт обратно страницу БАНКА, а не резидента. */
uint8_t home_helper(uint8_t x)
{
    home_page_seen = w3_page();
    setfillstyle(SOLID_FILL, YELLOW);
    bar(130, 60, 180, 72);
    return (uint8_t)(x * 2);
}

int main(void)
{
    uint8_t ret, ok;
    uint8_t res_page, bank_page;

    initgraph();
    setfillstyle(SOLID_FILL, BLACK);
    bar(0, 0, 319, 255);

    res_draw(20, BLUE);                 /* R3-часть: W1/W2 -> резидент W3 */
    res_page = res_page_seen;

    ret = bank_run(21);                 /* R3: резидент/HOME -> банк */
    bank_page = bank_page_before;

    /* Критерии: банк дожил до конца, вернул r+1 = 21*2+1 = 43, страница W3
     * ВНУТРИ банка не менялась вокруг рисования (её вернули), и она НЕ равна
     * резидентной. */
    ok = (uint8_t)(bank_alive == 1 && ret == 43 &&
                   bank_page_after == bank_page &&
                   bank_page_after_home == bank_page &&
                   home_page_seen == bank_page &&
                   bank_page != res_page);

    setfillstyle(SOLID_FILL, ok ? GREEN : RED);   /* зелёная / красная */
    bar(10, 80, 60, 92);

    res_draw(100, BLUE);                /* резидент жив после возврата? */

    printf("res_page=%02X bank_page=%02X after=%02X afterhome=%02X home=%02X ret=%u alive=%u ok=%u\n",
           res_page, bank_page, bank_page_after, bank_page_after_home,
           home_page_seen, ret, bank_alive, ok);
    printf("bank_pages[1]=%02X\n", bank_pages[1]);

    while (1) { }                       /* держим картинку для скрипта */
    return 0;
}
