Files
Sprinter-SDCC/applications/PoP/roomtest/NEXT_SESSION.md
T
snark13 d154cb452c NEXT_SESSION.md: точка входа для старта с чистого контекста
Одним файлом: состояние репозитория (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 <noreply@anthropic.com>
2026-08-10 23:02:48 +03:00

155 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Точка входа для следующей сессии (записано 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.