PoP roomtest: непрозрачные нижние грани + edge-триггер бампа + 2 колонки шва
Три фикса, найденные разбором в MAME. 1. Просвечивание Кида сквозь торец кнопки (подъём/спуск у кромки). draw_tile_bottom (seg008:570) рисует нижнюю грань блиттером blitters_0_no_transp: пиксель индекса 0 заливается ЧЁРНЫМ, а не пропускается. У граней кнопок (env 96/149) и нижних кадров loose (73/74) последняя строка целиком нулевая — наш упаковщик переводил 0 в 0xFF для ВСЕХ спрайтов, и она становилась дырой, сквозь которую был виден Kid за тайлом (на запечённом фоне не видно — там и так чёрное). pop_pack_bg.py: NO_TRANSP_ENV_IDS пакуется с сохранением индекса 0 как ЦВЕТА (0x50 = чёрный в палитре env). Ноль тактов в рантайме. 2. Разворот в проёме опущенной решётки выкидывал Кида на другую её сторону. check_bumped проверял столкновение УРОВНЕМ («край зашёл за грань»), поэтому разворот на месте внутри тайла-стены менял, какую грань мы меряем, и это читалось как новое столкновение → Kid.x = char_dx_forward(d) швырял его сквозь решётку. Оригинал (check_collisions + get_row_collision_data, seg004:0004) считает флаги перекрытия от ГАБАРИТА персонажа, БЕЗ направления, и зовёт bumped() только на переходе 0 -> 1 (вправо смотрит на 0x0F, влево на 0xF0). Порт этого edge-триггера: флаги от габарита + память прошлого кадра по колонке, сброс при смене комнаты (в оригинале это несовпадение prev_coll_room/curr_row_coll_room). Проверено: теперь разворот даёт уход в комнату 8 (leave_room, взгляд влево, char_x_left<=54) — то есть туда, где Kid физически и стоит. 3. Снимок шва расширен до ДВУХ колонок с каждой стороны (lcol_fg[6]/ rcol_fg[6]: col9+col8 и col0+col1). Kid, стоящий В шве (curr_col=-1), смотрит вперёд на колонку -2, где раньше была мнимая стена (get_tile -> TILE_WALL). Оригинал резолвит любую колонку через find_room_of_tile (seg006:005D). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -143,9 +143,22 @@ def collect_used():
|
||||
|
||||
|
||||
# ---- 2. Загрузка спрайта в 8bpp-блоб ---------------------------------
|
||||
def load_indexed(chtab, id):
|
||||
# Спрайты chtab_6, которые оригинал рисует БЕЗ прозрачности
|
||||
# (blitters_0_no_transp): нижние грани тайлов (draw_tile_bottom, seg008:570) и
|
||||
# нижние кадры loose (draw_loose, seg008:600). У 96/149 (грани кнопок) и 73/74
|
||||
# (кадры loose) ПОСЛЕДНЯЯ строка — пиксель 0; в оригинале она заливается ЧЁРНЫМ
|
||||
# поверх того, что сзади, а у нас 0 -> 0xFF делал её прозрачной, и сквозь неё
|
||||
# просвечивал Kid (спуск/подъём у кромки кнопки). 43/36 полностью непрозрачны —
|
||||
# для них флаг ничего не меняет, оставлены для полноты списка.
|
||||
NO_TRANSP_ENV_IDS = {36, 43, 73, 74, 96, 149}
|
||||
|
||||
|
||||
def load_indexed(chtab, id, opaque=False):
|
||||
"""PNG (mode P, 16 цветов) -> (w, h, bytes 8bpp). Каскад VDUNGEON->VPALACE.
|
||||
Пиксель 0 -> 0xFF (прозрач); i -> base+i (env 0x50 / wall 0x60)."""
|
||||
Пиксель 0 -> 0xFF (прозрач); i -> base+i (env 0x50 / wall 0x60).
|
||||
|
||||
opaque=True — пиксель 0 остаётся ЦВЕТОМ (base+0 = чёрный), а не ключом
|
||||
прозрачности: порт blitters_0_no_transp (см. NO_TRANSP_ENV_IDS)."""
|
||||
base_res = 360 if chtab == R.CHTAB_WALL else 200
|
||||
pal_base = 0x60 if chtab == R.CHTAB_WALL else 0x50
|
||||
fname = f"res{base_res + id}.png"
|
||||
@@ -161,7 +174,10 @@ def load_indexed(chtab, id):
|
||||
if im.mode != "P":
|
||||
die(f"{fname}: mode {im.mode}, ожидался P (16-цветный)")
|
||||
src = im.tobytes()
|
||||
out = bytes((0xFF if v == 0 else pal_base + v) for v in src)
|
||||
if opaque:
|
||||
out = bytes((pal_base + v) for v in src)
|
||||
else:
|
||||
out = bytes((0xFF if v == 0 else pal_base + v) for v in src)
|
||||
return im.width, im.height, out
|
||||
|
||||
|
||||
@@ -330,7 +346,7 @@ def main():
|
||||
# ENV фон -> страницы по id>>SHIFT
|
||||
pages = {}
|
||||
for id in env_bg:
|
||||
w, h, pix = load_indexed(R.CHTAB_ENV, id)
|
||||
w, h, pix = load_indexed(R.CHTAB_ENV, id, id in NO_TRANSP_ENV_IDS)
|
||||
pages.setdefault(id >> ENV_SHIFT, {})[id & ENV_MASK] = (w, h, pix)
|
||||
max_pg = max(pages) if pages else -1
|
||||
env_page_names = []
|
||||
|
||||
Reference in New Issue
Block a user