PoP roomtest: отладочный обход комнат (+/-) + TODO по редрою пик и idle-skip

ROOMNAV (одна строка #define в roomtest.c): '+'/'-' — следующая/предыдущая
комната уровня ПО НОМЕРУ (1..24, с обёрткой), Kid ставится на первый пол,
pop_trob_reset() возвращает пики/ворота в исходное.  Нужен для обхода всех
24 комнат в поиске багов отрисовки, включая недостижимые обычным путём.
Цена — 505 Б кода W1 (22816 -> 23321), они же вычитаются из кучи (4178 ->
3673 Б); W3 не тронут.  Переводить приложение в huge ради этого не стали:
смена модели памяти (банкованный W1 + трамплины) ради полукилобайта —
плохой размен прямо перед прогоном комнат.

Номер комнаты — ПОЛОСКАМИ в верхнем борте (слева десятки, справа единицы),
а не outtextxy: текст тянет системный знакогенератор (_gfx_font_buf, 2 КБ
статики) и сажает кучу до 576 Б.  Цвет полосок 0x57, а не WHITE: палитра
игровая, запись 15 в ней ЧЁРНАЯ (kid.pal 0x0F = 0,0,0) — из-за этого
закомментированный ранее лейбл был бы невидим в любом случае.

bug_list.md: раздел TODO (T-1 редрой пик по причине, T-2 idle-skip) +
пустая таблица на 24 комнаты под результаты обхода.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 11:58:06 +03:00
parent 723da3c5c1
commit 08c6a8504f
2 changed files with 152 additions and 13 deletions
+64 -13
View File
@@ -26,12 +26,19 @@ __sfr __at (0xFE) io_border;
/* Тест-старт для отладки пик (Фаза S): комната 6 = тестовая (пики в col3/col4
* row2, шахта col3). Kid на полу row0 col1, идёт вправо → падает в шахту →
* пики. TODO: вернуть на pop_level_start_room (комната 1) после отладки. */
#define START_ROOM 14 /* ОТЛАДКА: пики (2,7)/(2,8) — редрой каждый кадр */
#define START_COL 9
#define START_ROW 2
#define START_ROOM 1 /* обход комнат: старт с 1-й, дальше +/- (ROOMNAV) */
#define START_COL 3
#define START_ROW 0
#define RESPAWN_DELAY 400 /* авто-респавн (фолбэк), если не нажали ↑ */
#define RESPAWN_SETTLE 20 /* тиков до приёма ↑ (труп успел лечь) */
/* ОТЛАДОЧНЫЙ ОБХОД КОМНАТ: '+'/'-' (цифровой блок либо '='/'-' основного
* ряда) — следующая/предыдущая комната уровня ПО НОМЕРУ (1..24, с обёрткой),
* Kid ставится на первый попавшийся пол. Нужен, чтобы пройти все комнаты и
* собрать список багов отрисовки, включая недостижимые обычным путём.
* Убирается закомментированием ОДНОЙ строки ниже. */
#define ROOMNAV 1
/* Рабочая копия ТЕКУЩЕЙ комнаты (W2, мутабельная: loose→empty) + срезы
* соседей для кромок. Заполняются pop_room_load из уровня. File-scope,
* чтобы enter_room переключал комнату без длинного списка параметров. */
@@ -172,6 +179,9 @@ int main(void)
* отладки багов рисования (edge по sp_prev, чтоб не дёргать). */
uint8_t front = 0, back, dbuf = 1, sp_prev = 0, frozen = 0;
uint16_t dead_frames = 0;
#ifdef ROOMNAV
uint8_t nav_prev = 0;
#endif
if (pop_bg_load() != 0) { /* атласы — ДО initgraph (снимает DSS-страницу W0) */
puts("pop_bg_load failed");
@@ -246,6 +256,37 @@ int main(void)
continue;
}
#ifdef ROOMNAV
/* Обход комнат по номеру: '+' (0x79 numpad / 0x55 '=') — вперёд,
* '-' (0x7B / 0x4E) — назад. Edge по nav_prev: одно нажатие = одна
* комната. pop_trob_reset ДО enter_room — каждая комната смотрится в
* исходном состоянии (пики убраны, ворота закрыты). */
{
uint8_t nav = (uint8_t)((kbd_raw_down(0x79) || kbd_raw_down(0x55)) |
((kbd_raw_down(0x7B) || kbd_raw_down(0x4E)) << 1));
if (nav && !nav_prev) {
uint8_t r = cur_room, i, c, pos = 20, any = 0xFF;
r = (nav & 1) ? (uint8_t)(r == 24 ? 1 : r + 1)
: (uint8_t)(r == 1 ? 24 : r - 1);
pop_trob_reset();
enter_room(r);
/* Предпочитаем обычный пол; иначе — любой tile_is_floor
* (seg001): всё, кроме пустоты/стены/верхов колонны и двери. */
for (i = 0; i < 30; i++) {
c = (uint8_t)(room_fg[i] & 0x1F);
if (c == 1) { any = i; break; }
if (any == 0xFF && c && c != 9 && c != 12 && c != 20 &&
!(c >= 26 && c <= 29)) any = i;
}
if (any != 0xFF) pos = any;
kid_init(SEQ_STAND, (int8_t)(pos % 10), (int8_t)(pos / 10), 0);
pop_kid_hp_reset();
dead_frames = 0;
}
nav_prev = nav;
}
#endif
/* Рисуем в СКРЫТУЮ страницу (при dbuf); в однобуфере — в 0. */
back = dbuf ? (uint8_t)(front ^ 1) : 0;
gfx_set_draw_page(back);
@@ -360,18 +401,28 @@ int main(void)
/* Отладка: номер отрисованной комнаты в верхнем борте — рисуем ТОЛЬКО
* при её смене (change-driven, счётчик 2 = обе страницы дабл-буфера),
* а не каждый кадр (обход sdcc_z80_cmp_store_a_bug: сначала сохранить). */
#ifdef ROOMNAV
{
uint8_t r = cur_room;
// if (r != room_label_sig) { room_label_sig = r; room_label_redraw = 2; }
// if (room_label_redraw) {
// char roomLabel[] = "Room ##";
// roomLabel[5] = (char)(r / 10 + '0');
// roomLabel[6] = (char)(r % 10 + '0');
// setcolor(WHITE);
// outtextxy(100, 0, roomLabel);
// room_label_redraw--;
// }
uint8_t r = cur_room, prev = room_label_sig;
room_label_sig = r; /* СНАЧАЛА сохранить (sdcc_z80_cmp_store_a_bug) */
if (r != prev) room_label_redraw = 2;
if (room_label_redraw) {
/* Номер ПАЛОЧКАМИ, а не outtextxy: текст тянет системный
* знакогенератор (_gfx_font_buf, 2 КБ статики в W2) и сажает
* кучу с 3867 до 576 Б. Слева десятки, справа единицы:
* || |||| = 24. bar/setfillstyle уже используются. */
uint8_t i;
setfillstyle(SOLID_FILL, BLACK);
bar(100, 0, 175, 5);
/* 0x57, а НЕ WHITE: палитра игровая, запись 15 в ней чёрная
* (kid.pal: 0x0F = 0,0,0; чистый белый = 0x57). */
setfillstyle(SOLID_FILL, 0x57);
for (i = 0; i < (uint8_t)(r / 10); i++) bar(100 + i * 5, 0, 101 + i * 5, 5);
for (i = 0; i < (uint8_t)(r % 10); i++) bar(130 + i * 5, 0, 131 + i * 5, 5);
room_label_redraw--;
}
}
#endif
gfx_wait_vsync();
gfx_wait_vsync();