Уровень 5: тень не дерётся, кнопка в шве, узор паласа после зелья
Три бага одной отладочной сессии, все проверены в MAME пользователем. 1. SHADOW-FIGHT-L5. Кид доставал меч, а тень вставала в боевую стойку и рисовалась спрайтами стража. В pop_check_can_guard_see_kid первым множителем стояло `Guard.charid != 0`, тогда как оригинал (seg003:702) пишет `Guard.charid != charid_1_shadow || current_level == 12`: тень боевая только на 12-м уровне. Оба симптома шли из одной ветки control_standing (seg005:352). Возвращён и пропущенный множитель `Guard.direction != dir_56_none`. 2. SEAM-BUTTON-STALE. Кнопка в шве не меняла вид ни при нажатии, ни при отжатии. Сигнатура редроя шва сравнивала room_modif, а у кнопки modif — это индекс LINKLOC, константа уровня: нажатие живёт в doorlinks2, и в сигнатуру не приходило никогда. seam_row_sig подмешивает бит нажатости. Оригинал шов в этом случае не перерисовывает вовсе — расхождение осознанное, записано как D-2 в docs/impl_diff.md. 3. BUG-POTION-STRIPE. Синяя лента паласа пропадала на месте выпитого зелья и не возвращалась даже после перезахода в комнату. У оригинала curr_room_tiles — сама таблица уровня, у нас fg живёт в двух местах, и страницу правил главный цикл уже после pop_process_trobs. В этот зазор trob зелья крутил фазу пузырька поверх обнулённого модификатора: bubble_next_frame(0) = 1, а для пола в паласе modif 1 означает «узор не рисовать» (seg008:499). do_pickup теперь правит страницу уровня сразу. Тем же лечится меч: animate_sword делал `--mod[tp]` из нуля. tests-host 5/5 (добавлена заглушка pop_level_set_tile), size-check чист. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -236,6 +236,24 @@ static uint8_t guard_over_kid(void)
|
||||
* — изменение приходило в m[19], сигнатура его не видела, редрой не
|
||||
* заказывался, и открытые ворота оставались нарисованными закрытыми
|
||||
* (BUG-GATE-SEAM-ROW1). */
|
||||
/* Кнопка в шве (SEAM-BUTTON-STALE). Сигнатурой служил ТОЛЬКО modif, а у
|
||||
* кнопки modif — это индекс LINKLOC, то есть константа уровня: нажатие живёт
|
||||
* в doorlinks2 (get_doorlink_timer, seg007:0BB6). Изменение в сигнатуру не
|
||||
* приходило, редрой не заказывался — и шов оставался нарисованным в том
|
||||
* состоянии, в каком был на входе в комнату: кнопка (1,9) комнаты 11, она же
|
||||
* (1,−1) комнаты 24, залипала нажатой (или отжатой), хотя связь срабатывала.
|
||||
* Видимой её делает draw_tile: нажатый opener рисуется как ПОЛ (seg008
|
||||
* get_tile_to_draw), а у пола есть правая грань, у кнопки — нет.
|
||||
* Поэтому в сигнатуру ряда подмешиваем бит «кнопка нажата». */
|
||||
static uint8_t seam_row_sig(const uint8_t *m, const uint8_t *lfg, uint8_t r)
|
||||
{
|
||||
uint8_t code = (uint8_t)(lfg[r] & 0x1F);
|
||||
uint8_t mod = m[9 + r * 10];
|
||||
if (code == 0x0F || code == 0x06) /* opener / closer */
|
||||
return (uint8_t)((pop_doorlink2(mod) & 0x1F) > 1);
|
||||
return mod;
|
||||
}
|
||||
|
||||
static uint8_t seam_sig[3]; /* последняя нарисованная openness гейта в шве */
|
||||
static uint8_t seam_rows; /* маска рядов, ждущих редроя (переживает 2 кадра) */
|
||||
static uint8_t seam_redraw; /* оставшиеся кадры редроя (обе страницы) */
|
||||
@@ -346,10 +364,12 @@ static void enter_room_side(uint8_t room, uint8_t side)
|
||||
* pop_room_load заполнил lcol_bg/rcol_bg статикой уровня — перекрываем. */
|
||||
{
|
||||
uint8_t lft = pop_room_link(room, 0), rgt = pop_room_link(room, 1);
|
||||
if (lft) { uint8_t *m = pop_trob_modif(lft);
|
||||
lcol_bg[0] = m[9]; lcol_bg[1] = m[19]; lcol_bg[2] = m[29];
|
||||
/* шов рисуется в обе страницы ниже — синхр. сигнатуру */
|
||||
seam_sig[0] = m[9]; seam_sig[1] = m[19]; seam_sig[2] = m[29]; }
|
||||
if (lft) { uint8_t *m = pop_trob_modif(lft), i;
|
||||
for (i = 0; i < 3; i++) {
|
||||
lcol_bg[i] = m[9 + i * 10];
|
||||
/* шов рисуется в обе страницы ниже — синхр. сигнатуру */
|
||||
seam_sig[i] = seam_row_sig(m, lcol_fg, i);
|
||||
} }
|
||||
if (rgt) { uint8_t *m = pop_trob_modif(rgt);
|
||||
rcol_bg[0] = m[0]; rcol_bg[1] = m[10]; rcol_bg[2] = m[20]; }
|
||||
}
|
||||
@@ -792,7 +812,7 @@ int main(void)
|
||||
/* Все ТРИ ряда колонки 9: ворота в шве бывают в любом из них
|
||||
* (BUG-GATE-SEAM-ROW1, см. объявление seam_sig). */
|
||||
for (i = 0; i < 3; i++) {
|
||||
uint8_t g = m[9 + i * 10], prev = seam_sig[i];
|
||||
uint8_t g = seam_row_sig(m, lcol_fg, i), prev = seam_sig[i];
|
||||
seam_sig[i] = g; /* СНАЧАЛА сохранить (обход SDCC z80 sub-store */
|
||||
/* бага: `if(g!=s)s=g` эмитит store РАЗНОСТИ g-s, */
|
||||
/* не g — sdcc_z80_cmp_store_a_bug) */
|
||||
@@ -906,7 +926,9 @@ int main(void)
|
||||
if (pop_item_taken) { /* предмет поднят → тайл стал полом */
|
||||
item_pos = (uint8_t)(pop_item_taken - 1);
|
||||
item_bake = 2; /* запечь на ОБЕИХ страницах */
|
||||
pop_level_set_tile(cur_room, item_pos, TILE_FLOOR);
|
||||
/* Тайл в странице уровня ставит САМА do_pickup (pop_map.c): здесь
|
||||
* это было бы слишком поздно — между подбором и этим местом
|
||||
* успевает пройти pop_process_trobs (BUG-POTION-STRIPE). */
|
||||
pop_add_trob(cur_room, item_pos, -1); /* меч убран — блеска больше нет */
|
||||
pop_item_taken = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user