/* * 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 #include #include #include 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; }