/* * pop_redraw.c — пометки перерисовки тайлов и их разбор. См. pop_redraw.h. * * Живёт в W1/W2 (НЕ в резиденте W3): пометки ставит логика, которая должна * оставаться достижимой из будущих __banked-модулей. Сам разбор зовёт * pop_bg (резидент W3) — это законно, потому что разбор дёргает только * главный цикл. */ #include #include "pop_redraw.h" #include "pop_bg.h" #define NTILES 30 #define NCOLS 10 static uint8_t rd_kind[NTILES], rd_cnt[NTILES]; static uint8_t rda_kind[NCOLS], rda_cnt[NCOLS]; /* Сколько всего непустых пометок: без него проход по 40 ячейкам крутился бы * КАЖДЫЙ кадр впустую (замер 2026-07-27 на прежнем rest-цикле: ~12 % кадра). */ static uint8_t rd_pending; void pop_redraw_reset(void) { uint8_t i; for (i = 0; i < NTILES; i++) { rd_kind[i] = 0; rd_cnt[i] = 0; } for (i = 0; i < NCOLS; i++) { rda_kind[i] = 0; rda_cnt[i] = 0; } rd_pending = 0; } void pop_set_redraw(uint8_t tilepos, uint8_t kind, uint8_t pages) { if (tilepos >= NTILES) return; if (!rd_cnt[tilepos]) rd_pending++; rd_kind[tilepos] = kind; if (pages > rd_cnt[tilepos]) rd_cnt[tilepos] = pages; } void pop_set_redraw_above(uint8_t col, uint8_t kind, uint8_t pages) { if (col >= NCOLS) return; if (!rda_cnt[col]) rd_pending++; rda_kind[col] = kind; if (pages > rda_cnt[col]) rda_cnt[col] = pages; } /* redraw_needed (seg008:0178): пройти пометки и нарисовать. row/col ведём * бегущими счётчиками, а не через i/10 и i%10 — у Z80 нет деления, и SDCC * выносит __divuchar/__moduchar в вершину цикла как общее подвыражение * аргументов (30*2 делений за кадр даже когда рисовать нечего). */ void pop_redraw_needed(void) { uint8_t i, row = 0, col = 0, left = 0; if (!rd_pending) return; for (i = 0; i < NTILES; i++) { if (rd_cnt[i]) { switch (rd_kind[i]) { case POP_RD_SPIKE: pop_spike_redraw(row, col); break; case POP_RD_LOOSE: pop_loose_shake_draw(row, col); break; case POP_RD_LOOSE_GONE: pop_loose_bake_empty(row, col); break; case POP_RD_FLOOR: pop_floor_bake(row, col); break; case POP_RD_LEVELDOOR: pop_leveldoor_redraw(row, col); break; default: break; } if (--rd_cnt[i]) left++; else rd_kind[i] = 0; } if (++col == 10) { col = 0; row++; } } for (i = 0; i < NCOLS; i++) { if (rda_cnt[i]) { if (rda_kind[i] == POP_RDA_CEIL) pop_ceil_shake_draw(i); else pop_ceil_bake_empty(i); if (--rda_cnt[i]) left++; else rda_kind[i] = 0; } } rd_pending = left; }