Резидент: pop_redraw + холодная половина pop_level в банки (902 -> 3525 Б кучи)

MEM-COLD3, шаг 1-2 из плана разгрузки резидента:

* pop_redraw.c целиком -> банк 7 (к pop_room.c: он и есть единственный
  потребитель разбора пометок).  Два модуля в одном банке линкуются в один
  сегмент — проверено на .map (BANK7 7928 -> 8556).
* pop_level.c расколот по частоте вызова: горячая половина (чтение тайлов,
  связи, дверные таблицы, живые стражи — зовут все банки, местами на каждый
  тайл) осталась в резиденте, холодная (чтение файла уровня, разбор комнаты,
  рестарт, потабличные различия) уехала в pop_level_cold.c -> банк 8.
  Общее состояние объявлено в _pop_level.h: данные банковых модулей всё
  равно линкуются в общий _DATA, в банк уехал только КОД.

Побочно найден баг кодогена SDCC: `return 1;` из ветки не кладёт 1 в A —
до __banked он маскировался случайным ненулевым остатком в A.  Репро и
разбор — docs/bugs/sdcc-z80-ret-const-lost/, стаб t_char починен одним
выходом через переменную.  Аудит всех .asm roomtest: других мест нет.

_CODE 25628 -> 23005, куча 902 -> 3525 Б.  tests-host 6/6.
This commit is contained in:
2026-08-12 21:53:08 +03:00
parent f541c0aad9
commit 5d31ed086f
13 changed files with 884 additions and 426 deletions
+16 -11
View File
@@ -132,7 +132,7 @@ uint8_t tk_modif[30];
uint8_t tk_start_room;
uint8_t *pop_trob_modif(uint8_t room) __banked { (void)room; return tk_modif; }
uint8_t pop_level_start_room(void) { return tk_start_room; }
uint8_t pop_level_start_room(void) __banked { return tk_start_room; }
/* Журнал: что физика попросила у соседей. Тест сверяет ФАКТ и параметры
* (какой тайл помечен, где заспавнен кусок) — заглушка-пустышка этого не
@@ -170,10 +170,10 @@ void pop_trigger_button(uint8_t room, uint8_t tilepos,
uint8_t button_type, uint8_t modifier) __banked
{ (void)modifier; log_put(TK_BUTTON, room, tilepos, button_type); }
void pop_set_redraw(uint8_t tilepos, uint8_t kind, uint8_t pages)
void pop_set_redraw(uint8_t tilepos, uint8_t kind, uint8_t pages) __banked
{ log_put(TK_REDRAW, tilepos, kind, pages); }
void pop_set_redraw_above(uint8_t col, uint8_t kind, uint8_t pages)
void pop_set_redraw_above(uint8_t col, uint8_t kind, uint8_t pages) __banked
{ log_put(TK_REDRAW_ABOVE, col, kind, pages); }
void pop_loose_mob_spawn(int row, int col) __banked
@@ -217,8 +217,8 @@ uint8_t tk_link_down;
uint8_t pop_room_link(uint8_t room, uint8_t side)
{ (void)room; return side == 3 ? tk_link_down : 0; }
int8_t pop_level_guard_type(uint8_t level) { (void)level; return 0; }
uint8_t pop_level_guard_hp(uint8_t level) { (void)level; return 3; }
int8_t pop_level_guard_type(uint8_t level) __banked { (void)level; return 0; }
uint8_t pop_level_guard_hp(uint8_t level) __banked { (void)level; return 3; }
/* Тайлы «уровня» для соседних комнат: pop_map_set_edges забирает fg соседей
* слева/справа сам (кэш на входе в комнату), значит тесту нужен источник.
@@ -263,19 +263,24 @@ void tk_guard_state_clear(void)
tk_guard_room = 0;
}
/* ВНИМАНИЕ на форму возврата: результат собирается в res и отдаётся ОДНИМ
* выходом. С `return 1;` прямо в ветке SDCC 4.5 не кладёт единицу в A —
* функция возвращает мусор (docs/bugs/sdcc-z80-ret-const-lost). Без
* __banked баг маскировался: в A случайно оставался ненулевой байт от
* `*tile = 11`, и проверка «истина» проходила. */
uint8_t pop_level_guard(uint8_t room, uint8_t *tile, int8_t *dir,
uint8_t *color, uint8_t *skill)
uint8_t *color, uint8_t *skill) __banked
{
uint8_t res = 0;
if (room < 1 || room > TK_ROOMS) return 0;
if (tk_gs_tile[room - 1] < 30) { /* запомненный (в т.ч. труп) */
*tile = tk_gs_tile[room - 1]; *dir = 0; *color = 0; *skill = 1;
return 1;
}
if (room == tk_guard_room) { /* страж из данных уровня */
res = 1;
} else if (room == tk_guard_room) { /* страж из данных уровня */
*tile = 11; *dir = 0; *color = 0; *skill = 1;
return 1;
res = 1;
}
return 0;
return res;
}
void pop_guard_state_save(uint8_t room, uint8_t tile, int8_t dir, uint8_t x,
uint8_t skill, uint16_t seq, uint8_t dead)