Мигание тени: кадр приходил из кэша, а снимок писался по Guard.frame
Тень на уровне 6 стояла на двух страницах дабл-буфера в разных позах. Отрисовка брала image из кэша kid_frame/pop_gframe, который наполняет тик, а снимок пропуска кадра писала по Char.frame — расхождение застревало навсегда, потому что снимок совпадал и страница больше не перерисовывалась. Кадр теперь грузит сама отрисовка, как в оригинале (add_*_to_objtable → load_fram_det_col, seg008:22F0/2324). Разбор — BUGS_CLOSED.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -317,10 +317,12 @@ void pop_char_heal(uint8_t who) __banked { cd_heal(who); }
|
||||
|
||||
/* ---- Пропуск неизменившегося кадра (DRAW-COST; контракт — pop_cdraw.h) -- */
|
||||
|
||||
/* Снимок ВХОДОВ отрисовки слота. Кадр анимации (kid_frame/pop_gframe)
|
||||
* однозначно определяется полем frame, поэтому его самого в снимке нет;
|
||||
* тайлы вокруг персонажа (clip_char, fore-проход) в снимок тоже не входят —
|
||||
* их изменение ловит pop_cd_dirty. */
|
||||
/* Снимок ВХОДОВ отрисовки слота. Картинки (image) в снимке нет: её
|
||||
* однозначно определяет пара (charid, frame), и это ГАРАНТИРУЕТ pop_load_frame
|
||||
* в самой отрисовке — без него кадр приходил из кэша, который мог отстать, и
|
||||
* снимок описывал не то, что нарисовано (BUG-SHADOW-STALE-FRAME, разбор в
|
||||
* pop_char_draw). Тайлы вокруг персонажа (clip_char, fore-проход) в снимок
|
||||
* тоже не входят — их изменение ловит pop_cd_dirty. */
|
||||
typedef struct {
|
||||
uint8_t frame, x, y, action, sword, charid, room, hurt;
|
||||
int8_t dir, ccol, crow;
|
||||
@@ -528,6 +530,33 @@ void pop_char_draw(uint8_t who) __banked
|
||||
pages = kidp; npages = kid_npages;
|
||||
}
|
||||
}
|
||||
/* load_fram_det_col (seg008:22F5 / 2329) — кадр грузит САМА отрисовка,
|
||||
* сразу после loadkid/loadshad. У нас его не было: kid_frame/pop_gframe
|
||||
* считались кэшем, который наполняет тик (play_seq -> load_frame), а
|
||||
* отрисовка берёт готовое. Кэш лагает — тот, кто пишет Char.frame МИМО
|
||||
* play_seq, кадр не перезагружает, и рисуется прошлая картинка:
|
||||
*
|
||||
* do_init_shad (guards.c) кладёт тени frame = 15 (стойка) прямой
|
||||
* записью, а pop_gframe в этот момент держит кадр 185 УБИТОГО СТРАЖА
|
||||
* с прошлого уровня (после его смерти pop_guard_tick выходит по
|
||||
* `charid == 0` РАНЬШЕ pop_load_fram_det_col, и кэш не трогается
|
||||
* вообще). В кадре входа в комнату тень рисуется картинкой 33
|
||||
* (34x38, dx 3, dy 4) вместо 12x41 — да ещё из атласа КИДА, потому что
|
||||
* набор выбирается по Guard.frame, а image приходит из кэша.
|
||||
*
|
||||
* Само по себе это моргнуло бы один кадр. Смертельным его делает
|
||||
* пропуск неизменившегося кадра: снимок пишется по Guard.frame, то есть
|
||||
* страница запоминает «нарисован кадр 15», хотя на ней чужой спрайт.
|
||||
* Тень дальше стоит, снимок совпадает — страница НИКОГДА не
|
||||
* перерисовывается, и дабл-буфер вечно мигает двумя разными позами
|
||||
* (BUG-SHADOW-STALE-FRAME, уровень 6 комната 1).
|
||||
*
|
||||
* Лечим корень, а не симптом: после этой строки image ОДНОЗНАЧНО
|
||||
* определяется парой (charid, frame), и снимок cd_sig снова описывает
|
||||
* ровно то, что нарисовано. determine_col из связки НЕ берём: он пишет
|
||||
* Char.curr_col, которую тут же читает clip_char, а физика колонку ведёт
|
||||
* сама (расхождение с оригиналом — ../docs/impl_diff.md). */
|
||||
pop_load_frame();
|
||||
if (fr->image == 255) return; /* пустой кадр */
|
||||
|
||||
/* load_frame_to_obj (seg008:1728): НИЗ спрайта на obj_y, левый край на
|
||||
|
||||
Reference in New Issue
Block a user