From 78f2aaec1a3ea1b216658276ff33182bbae045e9 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Fri, 17 Jul 2026 21:34:32 +0300 Subject: [PATCH] =?UTF-8?q?applications/PoP/roomtest:=20fore-=D1=81=D0=BB?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=BF=D0=BE=D0=B2=D0=B5=D1=80=D1=85=20Kid=20(?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B0?= =?UTF-8?q?=D0=B9=D0=BB=D1=8B)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Порт SDLPoP seg003 redraw_at_char + seg008 set_char_collision: после kid_draw передний слой (fore_id = foretable-кусок) тайлов ФУТПРИНТА спрайта Kid перерисовывается ПОВЕРХ него — то, что по изометрии перед персонажем (передние грани колонн/ворот/большой колонны/щебня). Стены и факелы имеют fore_id=0 → остаются сзади (в статическом фоне). - pop_bg: pop_fore_over_kid(obj_x,obj_y,w,h,dir) — считает футпринт (char_x_left/right, col_from_x, y_to_row_mod4) рядов top..bottom × колонок left..right (≤2×2=4 тайла) и рисует fore_id каждого в GFX_BANK_SPRITE (видео-ОЗУ; kid_heal восстановит из теневого фона, fore в нём запечён pop_room_draw). - pop_kid: kid_fp_obj_x/y/width/height — метрики последнего кадра (obj_x ЛОГИЧЕСКАЯ, до ×8/7) для футпринта. - roomtest: вызов pop_fore_over_kid после kid_draw. Проверено в MAME: Kid, идя влево мимо колонны под навесом (row1 col3), корректно уходит ЗА её переднюю грань (скрывается) и выходит с другой стороны; задние колонны/факелы остаются сзади. Co-Authored-By: Claude Opus 4.8 --- applications/PoP/roomtest/pop_bg.c | 51 ++++++++++++++++++++++++++++ applications/PoP/roomtest/pop_bg.h | 6 ++++ applications/PoP/roomtest/pop_kid.c | 12 +++++++ applications/PoP/roomtest/pop_kid.h | 8 +++++ applications/PoP/roomtest/roomtest.c | 4 +++ 5 files changed, 81 insertions(+) diff --git a/applications/PoP/roomtest/pop_bg.c b/applications/PoP/roomtest/pop_bg.c index 91cd722..8b8d737 100644 --- a/applications/PoP/roomtest/pop_bg.c +++ b/applications/PoP/roomtest/pop_bg.c @@ -392,3 +392,54 @@ void pop_room_draw(uint8_t room_num, draw_tile(row, col); gfx_set_bank(GFX_BANK_NORMAL); } + +/* ---- fore-over-Kid (порт seg003 redraw_at_char + seg008 set_char_collision) -- + * Передний слой (fore_id = foretable-кусок) тайлов ФУТПРИНТА спрайта Kid + * — рядов top..bottom × колонок left..right (<= 2×2 = 4 тайла) — рисуется + * ПОВЕРХ Kid: то, что по изометрии перед ним (передние грани колонн/ворот/ + * большой колонны/щебня). Стены и факелы имеют fore_id=0 → остаются сзади. + * Рисуем в GFX_BANK_SPRITE (видео-ОЗУ, 0xFF прозрачен); kid_heal восстановит + * из теневого фона (fore в нём уже запечён pop_room_draw). obj_x — ЛОГИЧЕСКАЯ + * X кадра Kid (до ×8/7), obj_y — низ спрайта, w/h — размер, dir — направление. */ +static int8_t col_from_x(int xpos) /* get_tile_div_mod: колонка (58/14) */ +{ + int x = xpos - 58; + int xh = x / 14; + if (x % 14 < 0) xh--; /* округление вниз для отрицательных */ + return (int8_t)xh; +} + +static int8_t y_to_row(int y) /* y_to_row_mod4 (TILE_SIZEY=63) */ +{ + return (int8_t)((y + 60) / 63 % 4 - 1); +} + +static void fore_tile(int row, int col) /* fore одного тайла, если fore_id≠0 */ +{ + uint8_t code = tile_code(row, col); + const piece *t = &tile_table[code]; + if (t->fore_id) { + int x = COL_XH[col] * 8; + int dmy = 63 * row + 62; + fore_b(t->fore_id, t->fore_x * 8 + x, t->fore_y + dmy); + } +} + +void pop_fore_over_kid(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, rT, rB, r, c; + if (dir >= 0) xl -= wh; /* лицом вправо: левый край внутрь */ + xr = xl + wh; + cL = col_from_x(xl); if (cL < 0) cL = 0; else if (cL > 9) cL = 9; + cR = col_from_x(xr); if (cR < 0) cR = 0; else if (cR > 9) cR = 9; + rB = y_to_row(obj_y); if (rB < 0) rB = 0; else if (rB > 2) rB = 2; + rT = y_to_row(obj_y - (int)h + 1); if (rT < 0) rT = 0; else if (rT > 2) rT = 2; + gfx_set_bank(GFX_BANK_SPRITE); /* видео-ОЗУ, heal восстановит */ + for (r = rT; r <= rB; r++) + for (c = cL; c <= cR; c++) + fore_tile(r, c); + gfx_set_bank(GFX_BANK_NORMAL); +} diff --git a/applications/PoP/roomtest/pop_bg.h b/applications/PoP/roomtest/pop_bg.h index 464f17a..f91001e 100644 --- a/applications/PoP/roomtest/pop_bg.h +++ b/applications/PoP/roomtest/pop_bg.h @@ -29,4 +29,10 @@ void pop_room_draw(uint8_t room_num, const uint8_t *fg, const uint8_t *bg, const uint8_t *lcol_fg, const uint8_t *lcol_bg); +/* Перерисовать передний слой (fore) тайлов футпринта Kid ПОВЕРХ него — + * звать ПОСЛЕ kid_draw. obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ + * спрайта, w/h — размер кадра, dir — направление Kid (<0 влево). Метрики + * берутся из pop_kid (kid_fp_*). См. redraw_at_char/set_char_collision. */ +void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h, int8_t dir); + #endif diff --git a/applications/PoP/roomtest/pop_kid.c b/applications/PoP/roomtest/pop_kid.c index ec345a2..39deb84 100644 --- a/applications/PoP/roomtest/pop_kid.c +++ b/applications/PoP/roomtest/pop_kid.c @@ -167,6 +167,15 @@ static int kid_lx, kid_ly; static uint16_t kid_lw, kid_lh; static uint8_t kid_lvalid; +/* Метрики последнего kid_draw для футпринта fore-over-Kid (pop_bg): + * obj_x — ЛОГИЧЕСКАЯ X кадра (ДО ×8/7), obj_y — низ, w/h — размер. */ +static int kid_fp_x, kid_fp_y; +static uint16_t kid_fp_w, kid_fp_h; +int kid_fp_obj_x(void) { return kid_fp_x; } +int kid_fp_obj_y(void) { return kid_fp_y; } +uint16_t kid_fp_width(void) { return kid_fp_w; } +uint16_t kid_fp_height(void) { return kid_fp_h; } + /* Восстановить фон из теневой копии на месте ПРЕДЫДУЩЕГО кадра Kid. */ void kid_heal(void) { @@ -190,6 +199,8 @@ void kid_draw(void) obj_y = (int)Kid.y + fr.dy; if ((int8_t)(fr.flags ^ Kid.direction) >= 0) obj_x++; /* even/odd pixel (в ЛОГИЧЕСКОЙ координате) */ + kid_fp_x = obj_x; /* ЛОГИЧЕСКАЯ X (до ×8/7) — для футпринта fore */ + kid_fp_y = obj_y; /* seg008 calc_screen_x_coord: логическая X (280 шир = 28px/тайл) -> * экран (320 шир = 32px/тайл), ×320/280 = ×8/7. БЕЗ этого Kid уезжает * влево от тайлов тем сильнее, чем правее (col9 ~36px). Коллизия — в @@ -215,6 +226,7 @@ void kid_draw(void) gfx_set_bank(GFX_BANK_NORMAL); kid_lx = bx; kid_ly = top; kid_lw = w; kid_lh = h; kid_lvalid = 1; + kid_fp_w = w; kid_fp_h = h; /* размер кадра для футпринта fore */ } gfx_w0_unmap(); } diff --git a/applications/PoP/roomtest/pop_kid.h b/applications/PoP/roomtest/pop_kid.h index 3ae3e32..ed0b262 100644 --- a/applications/PoP/roomtest/pop_kid.h +++ b/applications/PoP/roomtest/pop_kid.h @@ -60,4 +60,12 @@ void kid_draw(void); * вместо перерисовки всего экрана. Звать ПЕРЕД kid_tick/kid_draw. */ void kid_heal(void); +/* Метрики последнего kid_draw для футпринта fore-over-Kid (pop_bg + * pop_fore_over_kid): obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ + * спрайта, w/h — размер кадра. */ +int kid_fp_obj_x(void); +int kid_fp_obj_y(void); +uint16_t kid_fp_width(void); +uint16_t kid_fp_height(void); + #endif diff --git a/applications/PoP/roomtest/roomtest.c b/applications/PoP/roomtest/roomtest.c index b9ab979..8e4fddb 100644 --- a/applications/PoP/roomtest/roomtest.c +++ b/applications/PoP/roomtest/roomtest.c @@ -49,6 +49,8 @@ int main(void) pop_map_set(room1_fg); /* карта для коллизии/падения (K3) */ kid_init(SEQ_STAND, 1, 1, 0); kid_draw(); + pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(), + kid_fp_width(), kid_fp_height(), Kid.direction); if (pop_ctrl_init() != 0) { /* raw-канал клавиатуры (забирает ввод у DSS) */ closegraph(); @@ -69,6 +71,8 @@ int main(void) kid_init(SEQ_STAND, 1, 1, 0); } kid_draw(); /* нарисовать новый кадр */ + pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(), + kid_fp_width(), kid_fp_height(), Kid.direction); } pop_ctrl_close();