From d154cb452c7d40c77325d17875e28b782556b338 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Mon, 10 Aug 2026 23:02:48 +0300 Subject: [PATCH] =?UTF-8?q?NEXT=5FSESSION.md:=20=D1=82=D0=BE=D1=87=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B2=D1=85=D0=BE=D0=B4=D0=B0=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=80=D1=82=D0=B0=20=D1=81=20=D1=87=D0=B8?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D1=81=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Одним файлом: состояние репозитория (11 коммитов дня с хешами), состояние окружения (образ MAME на уровне 4; как пересобрать SDLPoP с -g без pkg-config — нужен -std=gnu99, иначе прячется strncasecmp; неприбранный диагностический fprintf DBGMIRROR), задача на завтра и открытые пункты. Задача на завтра — XOR/OR-блит через акселератор. Записано всё, что установлено замером: тень уровня 4 рисуется ДВУМЯ блитами одного спрайта Кида (seg008:1602, blitters_2_or + blitters_3_xor со сдвигом на пиксель), обе сущности идут из chtab=2 — различие только в блиттере. Механизм на Sprinter из accelerator_doc.txt: операцию задаёт опкод CPU между триггерами, цена «байт / 7 МГц», операция ортогональна направлению. Открытый вопрос честно помечен: акселератор XOR-ит ИНДЕКСЫ, а SDLPoP — RGB; как это ляжет на нашу перепакованную палитру, надо увидеть. Отдельным разделом — грабли дня, чтобы не повторять: не оценивать железо по своей же memory-заметке (ошибся с accel, поправил пользователь); lldb через FIFO ненадёжен, вместо него fprintf прямо в SDLPoP; make без hdd не обновляет образ MAME. Ссылка на файл добавлена в roomtest/CLAUDE.md, который грузится сам. Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/CLAUDE.md | 3 + applications/PoP/roomtest/NEXT_SESSION.md | 154 ++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 applications/PoP/roomtest/NEXT_SESSION.md diff --git a/applications/PoP/roomtest/CLAUDE.md b/applications/PoP/roomtest/CLAUDE.md index 45e63b3..8647ed2 100644 --- a/applications/PoP/roomtest/CLAUDE.md +++ b/applications/PoP/roomtest/CLAUDE.md @@ -13,6 +13,9 @@ иначе) перечислены в `../docs/impl_diff.md` — новое туда же записью, а не только комментарием в коде. +**НАЧИНАТЬ С `NEXT_SESSION.md`** — состояние окружения, задача на +ближайший заход и грабли последней сессии одним файлом. + **Что в работе сейчас — `TASKS_OPEN.md`** (доска задач: приоритеты, критерии готовности); сделанное с протоколами замеров — `TASKS_CLOSED.md`. Баги — `bug_list.md` (только ОТКРЫТЫЕ) и `bug_closed.md` (закрытые + разбор корней: diff --git a/applications/PoP/roomtest/NEXT_SESSION.md b/applications/PoP/roomtest/NEXT_SESSION.md new file mode 100644 index 0000000..795a757 --- /dev/null +++ b/applications/PoP/roomtest/NEXT_SESSION.md @@ -0,0 +1,154 @@ +# Точка входа для следующей сессии (записано 2026-08-10, поздний вечер) + +Файл для старта с чистого контекста: где всё стоит, что делать первым, какие +грабли уже собраны. Читать целиком — он короткий. Дальше по ссылкам: +`TASKS_OPEN.md` (доска), `bug_list.md` (открытые баги), `CLAUDE.md`. + +--- + +## 1. Состояние репозитория + +Всё закоммичено и запушено, `main` в синхроне с `origin/main`. +Последний коммит сессии — `8beb66a`. + +`tests-host`: 5 наборов, все проходят (`[geom] 3144`). +`make size-check`: чисто, роста нет. + +Коммиты за день, по порядку: + +| хеш | что | +|---|---| +| `8cac51d` | убраны три последних `/63 %4` в `pop_room.c` | +| `72797e1` | инвентаризация ВСЕХ делений по `.asm`, три убраны | +| `8175121` | `scr_x` таблицей на весь диапазон, включая отрицательные | +| `fc0ede9` | байтовая таблица `x/7` вместо словарной (−1152 Б, на такт быстрее) | +| `e261a35` | замер в MAME: A/B со сборкой до правок, делений в горячем пути 0 | +| `67a4c71` | `BUG-TORCH-CHOMP-2`: застывший чомпер накрывался пламенем | +| `1b2111f` | L4-MIRROR шаги 1-2: зеркало в атласе + постановка тайла | +| `844fa6d` | L4-MIRROR шаг 4: прыжок сквозь зеркало и рождение тени | +| `8f0362f` | L4-MIRROR шаги 3 и 5 + **левый клип колонок в libbgi** | +| `3913f1e` | fore-проход поверх отражения (ноги/голова вылезали из арки) | +| `8beb66a` | заведён `FORE-DUP` с разбором | + +## 2. Состояние окружения + +- **MAME запущена** с образом уровня 4 (`FIRST_LEVEL=4`, `PROF_BORDER=1`). + Пересобрать образ: `make PROF_FLAGS="-DPROF_BORDER=1 -DFIRST_LEVEL=4" hdd`, + после этого MAME **обязан** полный рестарт (memory + `mame_hdd_rebuild_restart`). Загрузка: `keyseq d:{ENTER}`, потом + `keyseq roomtest{ENTER}`, ждать ~18 с. +- **SDLPoP пересобран с отладочной информацией** (`-O0 -g3`). pkg-config на + машине НЕТ, собирать так: + ``` + cd applications/PoP/SDLPoP/src + SDLC="-I/opt/homebrew/include -I/opt/homebrew/include/SDL2 -D_THREAD_SAFE" + SDLL="-L/opt/homebrew/lib -lSDL2main -lSDL2 -Wl,-framework,Cocoa \ + -L/opt/homebrew/Cellar/sdl2_image/2.8.12_1/lib -lSDL2_image" + make -j8 CFLAGS="-std=gnu99 -D_DARWIN_C_SOURCE -O0 -g3 $SDLC" LIBS="$SDLL" + ``` + `-std=c99` НЕ работает (прячет `strncasecmp` на Darwin), нужен `gnu99`. +- **НЕ ПРИБРАНО:** в `SDLPoP/src/seg008.c` мой диагностический `fprintf` + с меткой `DBGMIRROR` в начале `add_objtable`. Убрать перед следующей + сборкой SDLPoP (или оставить — он гейтится по `obj_type == 1 || == 4`). + +## 3. ЗАДАЧА НА ЗАВТРА: XOR/OR-блит через акселератор + +Единственный открытый пункт `L4-MIRROR` — вид тени. + +**Что установлено (замером, не гипотезой).** Тень уровня 4 в оригинале +рисуется ДВУМЯ блитами одного и того же спрайта Кида (seg008:1602): + +```c +case 1: // shadow + add_midtable(obj_chtab, obj_id + 1, obj_xh, obj_xl, obj_y, blitters_2_or, 1); + add_midtable(obj_chtab, obj_id + 1, obj_xh, obj_xl + 1, obj_y, blitters_3_xor, 1); +``` + +OR на месте, XOR со сдвигом на пиксель вправо — XOR гасит совпавшее, остаются +края, отсюда «контурный» вид. Это ЗАМЫСЕЛ оригинала, не артефакт SDLPoP. + +Подтверждено печатью из живого SDLPoP (`DBGMIRROR`): и тень, и отражение идут +из `chtab=2` (собственные спрайты Кида), `swordbits=0`, обычными кадрами: + +``` +type=4 chtab=2 img=40 dir=0 clipL=137 clipT=3 charid=0 frame=41 <- отражение +type=1 chtab=2 img=41 dir=0 clipL=137 clipT=3 charid=1 frame=42 <- тень +``` + +Различие между ними — ТОЛЬКО блиттер. Наша тень сейчас рисуется обычной +прозрачной копией, то есть выглядит вторым Кидом. + +**Механизм на Sprinter** (`docs/part2/accelerator_doc.txt`, memory +`sprinter_accelerator` дополнена сегодня). Акселератор умеет блочные +AND/OR/XOR; операцию задаёт ОПКОД CPU между триггерами: + +```asm +LD A,(DE) ; триггер чтения: блок из спрайта -> память акселератора +XOR (HL) ; триггер операции: блок XOR с тем, что по адресу приёмника +LD (HL),A ; триггер записи: результат обратно +``` + +Цена — «число байт / 7 МГц», попиксельного цикла CPU НЕТ. **Операция +ортогональна направлению**: горизонтальный/вертикальный режим (`LD L,L` / +`LD A,A`) выбирается отдельно и на операцию не влияет — то есть с нашими +column-major спрайтами ([[accel_vertical_copy]]) это работает так же, как +копия. Мнемоника: `XOR (HL)` даёт `A = A ^ (HL)`; «xor (hl),a» на Z80 нет. + +### План + +1. **Эксперимент в MAME на маленьком тесте в `tests/`, НЕ сразу в PoP.** + Примитив трогает ассемблерное ядро libbgi, проверять его надо в изоляции. + Цель: убедиться, что связка read-триггер / `XOR` / запись даёт ожидаемый + блок в вертикальном режиме. +2. **libbgi: `_bgi_blit_cols_op_raw`** — клон `_bgi_blit_cols_raw` (asm), где + write-триггер `LD (DE),A` заменён парой «`XOR (dst)` + `LD (dst),A`». + Наружу — `gfx_blit_cols_part_op(...)` с параметром операции + (COPY / OR / XOR), чтобы одним примитивом закрыть оба блиттера тени. + Побочно закрывается давний пункт `2d-1` из `docs/TODO.md` + (`putimage` с `XOR/OR/AND_PUT` до сих пор на попиксельном пути). + После правки libbgi — `make size-check` ОБЯЗАТЕЛЕН. +3. **PoP:** тень двумя блитами, OR на месте + XOR со сдвигом `+1` по X. + Место — ветка слота соперника в `pop_char_draw` (`pop_cdraw.c`), где уже + стоит выбор атласа и клип тени по `CHARID_1_SHADOW`. +4. **Смотреть на палитру глазами.** Тут предсказать нельзя: акселератор + XOR-ит ИНДЕКСЫ, а SDLPoP делает XOR в 24-битном RGB (`blit_xor`, + seg009:3190). DOS-оригинал (режим 13h) тоже XOR-ил индексы, то есть мы + будем БЛИЖЕ к DOS, чем SDLPoP, но конкретные цвета контура определит + раскладка нашей палитры (атласы перепакованы `pop_pack_kid.py`). + Может выйти и лучше, и мусорнее — это надо увидеть. + +## 4. Остальное открытое + +- **`FORE-DUP`** (`bug_list.md`) — передний слой тайла рисуется дважды при + перекрытии объектов (Кид+отражение всегда, Кид+соперник — весь ближний + бой). Картинку не портит, тратит такты. В оригинале невозможно: там + `redraw_at_char` только ПОМЕЧАЕТ тайлы. **Сначала замерить, потом чинить** + — окно клипа вместо перебора тайлов в своё время дало 3.2×. +- **`TORCH-ANIM-RIGHT`** (`bug_list.md`) — под запечённым пламенем могут + застыть не только челюсти чомпера, но и пики/меч/зелье справа от факела. + На уровнях 1-4 такого соседства нет. +- **`DIED-ON-BUTTON`** — не портирован `died_on_button` (seg007:776). +- Долгие: `BUG-SPIKE-1`, `BUG-CHOMP-JUMP-1` (оба низкий приоритет), + `L3-PASS`, `L3-COLOR`, `L1-SPEED`, `TUNE-1`. +- **Не проверено в MAME** из вчерашнего: отражение с fore-проходом и клип + тени слева (собрано и залито, но живьём не смотрели). + +## 5. Грабли, собранные сегодня + +- **Не оценивать железо по своей же memory-заметке.** Я заявил, что accel + умеет только копирование и XOR потребует ~25 % кадра на CPU — неверно, + поправил пользователь. Заметка описывала копирование, я принял её + неполноту за свойство железа. +- **lldb через FIFO — плохая идея.** Повторяющиеся `-o` при + `breakpoint command add` записываются НЕПОЛНЫМИ (берётся последний), а + оставшийся от неудачной попытки `script print(... lldb.frame ...)` уронил + lldb прямо в обработчике точки останова. Три прыжка пользователя ушли + впустую. **Работает надёжно:** добавить `fprintf(stderr, ...)` прямо в + SDLPoP, пересобрать (он собирается за секунды) и читать stdout. В дереве + уже есть такие метки (`DBG kidobj`). +- **`make` без `hdd` не обновляет образ MAME**, а `FIRST_LEVEL` живёт в + `roomtest.c` — при смене нужен `touch roomtest.c`. Я дважды сказал + «образ пересобран», когда он не был. +- Диапазон `obj_x` = **−416..695** (посчитан из `kid_data.bin`: `dx` кадров + Кида −5..+10, стража −2..+10, плюс `render_dx ∈ {−140,0,+140}`). + Пригодится всякий раз, когда нужна таблица по экранной X.