PoP roomtest: отрисовка стража в резидент W3 + fore-окклюзия + off-by-one спрайта
Разгрузка W1/W2 перед ИИ стражей (вариант 2 из двух обсуждённых). 1. pop_guard.c разделён по окнам: состояние/логика (Guard, HP, enter, kill, load_frame) остаются в W1/W2 — их обязан видеть банк guards.c; ОТРИСОВКА уехала в новый pop_gdraw.c, собираемый как --w3 (резидент). Правило границы: резидент = только то, что рисует и зовётся исключительно из главного цикла. Кадр стража стал глобальным (pop_gframe): заполняет логика, читает резидент. 2. Страж не окклюдировался передними гранями тайлов — рисовался поверх столба. В оригинале любой Char это запись midtable, а foretable рисуется после всех midtable (draw_tile_fore, seg008:690), т.е. столб перекрывает всех одинаково. Футпринт персонажа выделен из pop_fore_over_kid в char_footprint(), поверх него добавлен pop_fore_over_char() — слой fore + полоса потолка, без оверлеев поз виса/полёта/подъёма (у стража их нет; появятся — портируем redraw_at_char2 общим кодом, а не догадками). 3. Упаковщик стража: тот же off-by-one, что уже ловили у Kid. load_chtab_from_file(id_chtab_5_guard, 750) даёт images[0] = res751, а рисование индексирует images[frame.image] — значит image=N это res(751+N), а не res(750+N). Из-за сдвига frame_166_stand_inactive рисовался как res767 (выпад) вместо res768 (стойка). Проверено в MAME: страж в комнатах 3 и 21 стоит в правильной позе; окклюзия подтверждена патчем Guard.x в живой сессии — при заходе за столб спрайт корректно срезается его передней гранью. Память: _CODE 26 149 -> 25 703, куча W2 805 -> 1245 Б, резидент W3 11 656 -> 12 819 (свободно 3565 Б), банк 1 236/16384 Б. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1325,13 +1325,20 @@ static void other_overlay_tile(int row, int col)
|
||||
}
|
||||
}
|
||||
|
||||
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir, uint8_t frame, uint8_t action)
|
||||
/* Футпринт персонажа в тайлах (порт set_char_collision, seg006:0723).
|
||||
* Выделено из pop_fore_over_kid, потому что тем же счётом пользуется страж
|
||||
* (pop_fore_over_char): в оригинале это общий код для любого Char.
|
||||
* Результат — в файловых статиках, а не через 6 указателей: на Z80 такой
|
||||
* возврат стоил бы дороже самой функции. */
|
||||
static int8_t fp_cL, fp_cR, fp_cLraw, fp_rT, fp_rB, fp_rTraw;
|
||||
|
||||
static void char_footprint(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir)
|
||||
{
|
||||
int wh = (int)((w + 1) >> 1); /* char_width_half */
|
||||
int xl = obj_x / 2 + 58; /* char_x_left (58-база) */
|
||||
int xr;
|
||||
int8_t cL, cR, cLraw, rT, rB, r, c, rTraw;
|
||||
int8_t cL, cR, cLraw, rT, rB, rTraw;
|
||||
if (dir >= 0) xl -= wh; /* лицом вправо: левый край внутрь */
|
||||
xr = xl + wh;
|
||||
cLraw = col_from_x(xl); /* до клампа: <0 = футпринт за левым швом */
|
||||
@@ -1359,6 +1366,17 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
* (нижняя грань стены / кромка пола) не перерисуется поверх Kid. Форсим
|
||||
* включение ряда rB-1. */
|
||||
if (rB > 0 && rT >= rB) rT = rB - 1;
|
||||
fp_cL = cL; fp_cR = cR; fp_cLraw = cLraw;
|
||||
fp_rT = rT; fp_rB = rB; fp_rTraw = rTraw;
|
||||
}
|
||||
|
||||
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir, uint8_t frame, uint8_t action)
|
||||
{
|
||||
int8_t cL, cR, cLraw, rT, rB, rTraw, r, c;
|
||||
char_footprint(obj_x, obj_y, w, h, dir);
|
||||
cL = fp_cL; cR = fp_cR; cLraw = fp_cLraw;
|
||||
rT = fp_rT; rB = fp_rB; rTraw = fp_rTraw;
|
||||
/* set_objtile_at_char (seg006:1833): тайл, при обработке которого спрайт
|
||||
* Kid попадает в midtable — база порядка окклюзии в other_overlay_tile.
|
||||
* run_jump (action 1) — нижний ряд/левая колонка габарита; вис/полёт/
|
||||
@@ -1427,3 +1445,33 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
}
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
}
|
||||
|
||||
/* Передние грани тайлов поверх ПРОИЗВОЛЬНОГО персонажа (страж, дальше —
|
||||
* тень/скелет). В оригинале любой Char — запись midtable, а foretable
|
||||
* рисуется после всех midtable (draw_tile_fore, seg008:690), поэтому
|
||||
* колонна и кромка пола перекрывают всех одинаково.
|
||||
*
|
||||
* Отличие от pop_fore_over_kid: только слой fore (+ полоса потолка).
|
||||
* Оверлеи тела пола (draw_other_overlay) завязаны на позы Kid — вис,
|
||||
* полёт, подъём, — которых у стража нет: он ходит и дерётся на полу
|
||||
* (seq_77..seq_84). Появятся падающие/висящие стражи — тогда и общий
|
||||
* порт redraw_at_char2, а не догадки сейчас. */
|
||||
void pop_fore_over_char(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir)
|
||||
{
|
||||
int8_t r, c;
|
||||
char_footprint(obj_x, obj_y, w, h, dir);
|
||||
gfx_set_bank(GFX_BANK_SPRITE);
|
||||
for (r = fp_rT; r <= fp_rB; r++)
|
||||
for (c = fp_cL; c <= fp_cR; c++)
|
||||
fore_tile(r, c);
|
||||
if (fp_rTraw < 0) {
|
||||
g_clip_top = POP_YOFF;
|
||||
for (c = fp_cL; c <= fp_cR; c++) {
|
||||
ov_mark(COL_XH[c] * 8, 0, 64, CEIL_BAND_H);
|
||||
ceil_over_kid_tile(c);
|
||||
}
|
||||
g_clip_top = 0;
|
||||
}
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user