roomtest: loose-полы — тряска (knock), падение с окклюзией, фикс дабл-буфера

Проваливающиеся полы в roomtest (порт SDLPoP seg007/seg008), проверено в MAME:

- Падающий кусок (mob): правый край env-42 (w=26, доходит до mob_x+57)
  теперь полностью покрыт heal-коридором (MOB_W 56->64) — убран тёмный
  хвост-тень на полу 2,7 ПОСЛЕ падения.
- Окклюзия правого куска во ВРЕМЯ падения: после отрисовки плиты
  перерисовывается сосед-пол draw_tile(row,col+1) в том же кадре — край
  прячется за полом 2,7 (порт redraw_at_cur_mob: set_redraw_full+1).
- Тряска от сотрясения (knock): seqtbl-команды KNOCK_DOWN/UP в play_seq ->
  флаг knock -> do_knock(ряд) трясёт loose ряда из покоя (modif=0x80).
  KNOCK_DOWN в land-seq (приземление) и runcyc (footstep).
- Фикс «бесконечной тряски» (дабл-буфер): при завершении тряски (0x84->0)
  перерисовать покойный кадр плиты на ОБЕИХ страницах (loose_rest, 2 кадра) —
  иначе на одной странице застревает дрожащий кадр правой грани (живёт в
  тайлах col и col+1) -> мерцание через флип.

Инфраструктура/документация:
- app.mk: цель `make hdd` (упаковка в D: для MCP-моста MAME).
- docs: POP-DAT-FormatSpecifications.pdf/.txt как каноническая спецификация
  форматов ресурсов; ссылки в README/MSDOS_RESOURCE_FORMAT.
- README.md/CLAUDE.md для applications/PoP и roomtest (правило «SDLPoP —
  источник истины», порядок слоёв, режим отладки freeze 1/2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 15:27:47 +03:00
parent 5ef084eca4
commit 8b30dc20c8
18 changed files with 3034 additions and 35 deletions
+15 -3
View File
@@ -6,10 +6,15 @@
#include <gfx.h>
#include <sprite.h>
#include "pop_kid.h"
#include "pop_bg.h" /* POP_YOFF — вертикальное центрирование */
#include "kid_data.h"
kid_t Kid;
/* Флаг сотрясения (seg006 knock): ставится seqtbl-командой KNOCK_UP/DOWN
* в play_seq, потребляется pop_check_knock (pop_map) — трясёт loose-полы. */
int8_t knock;
/* Координатные таблицы (data.h). */
static const uint8_t x_bump[20] = {
(uint8_t)-12, 2, 16, 30, 44, 58, 72, 86, 100, 114,
@@ -108,7 +113,11 @@ void play_seq(void)
Kid.fall_x = (int8_t)SEQ(Kid.curr_seq); Kid.curr_seq++;
Kid.fall_y = (int8_t)SEQ(Kid.curr_seq); Kid.curr_seq++;
break;
case 0xF5: case 0xF4: /* KNOCK up/down */
case 0xF5: /* KNOCK_UP: сотрясение трясёт loose РЯДОМ ВЫШЕ (check_knock) */
knock = 1;
break;
case 0xF4: /* KNOCK_DOWN: приземление трясёт loose В СВОЁМ РЯДУ */
knock = -1;
break;
case 0xF2: /* SOUND — потребить 1 байт */
Kid.curr_seq++;
@@ -186,7 +195,7 @@ void kid_heal(void)
{
uint8_t p = gfx_get_draw_page();
if (kid_lvalid[p])
gfx_heal(kid_lx[p], kid_ly[p], kid_lw[p], kid_lh[p]);
gfx_heal(kid_lx[p], kid_ly[p] + POP_YOFF, kid_lw[p], kid_lh[p]); /* +YOFF: центрирование */
kid_lvalid[p] = 0;
}
@@ -229,8 +238,11 @@ void kid_draw(void)
top = obj_y - (int)h + 1 + KID_YOFF;
uint8_t dp = gfx_get_draw_page(); /* в какую страницу рисуем */
gfx_set_bank(GFX_BANK_SPRITE); /* видео-ОЗУ, без теневой копии */
gfx_blit_cols(bx, top, img, flip);
gfx_blit_cols(bx, top + POP_YOFF, img, flip); /* +YOFF: центрирование */
gfx_set_bank(GFX_BANK_NORMAL);
/* клип СВОЕГО выхода за поле (падение ниже поля / верхний борт) —
* узко, только по прямоугольнику Кида и только при выходе. */
pop_clip_sprite(bx, w, top + POP_YOFF, (int)h);
kid_lx[dp] = bx; kid_ly[dp] = top;
kid_lw[dp] = w; kid_lh[dp] = h; kid_lvalid[dp] = 1;
kid_fp_w = w; kid_fp_h = h; /* размер кадра для футпринта fore */