Доски приведены в соответствие с кодом; bug_list/bug_closed → BUGS_OPEN/BUGS_CLOSED
Доска отставала от кода на три задачи — планировать по ней было нельзя. Сверка проведена грепом по исходникам, а не по записям: - L4-MIRROR ЗАКРЫТА: шаги 1-5 сделаны и проверены пользователем в MAME (зеркало в атласе, постановка тайла, отражение, прыжок сквозь зеркало с рождением тени, левый клип тени). Протокол с разбором решений — в архиве; - L3-CHOMP и L3-SKEL закрыты ещё 2026-08-08/07 (коммитыdc0bd47,4d4323f,db4106a,1461ed5), на доске значились как предстоящие; - тайлсет palace (шаг 2 levels_plan) в коде есть целиком — pop_bg_load(type), pal_*.atl, дворцовый wall_pattern, решётки 25-29 и в tile_table, и в коллизии (tile_is_floor совпадает с seg006:0628); - в GUARD-PHYS остаток пересобран по факту: check_chomped_guard сделан, скелет в check_guard_fallout сделан, ветки ТЕНИ нет — она уехала в L5-SHADOW. Приёмки: по решению пользователя уровни 1-4 приняты SMOKE-тестами, полные обходы всех комнат делаются по готовности ВСЕХ уровней — L3-PASS/L4-PASS как отдельные задачи отменены, вместо них политика приёмок в архиве. Новая цель — уровень 5. Инвентарь res2005.bin: НИ ОДНОГО нового тайла, всё портировано на уровнях 1-4. Единственная новая механика — спецсобытие «тень крадёт зелье» (комната 24): заведена задача L5-SHADOW с портом по SDLPoP (check_shadow / do_init_shad / do_auto_moves + shad_drink_move / autocontrol_shadow_level5 + ветка тени в check_guard_fallout), включая готовые константы и то, что у нас уже есть под это. Заведён MIRROR-FG-STALE (низкий): place_mirror пишет тайл в данные уровня, но не в снимок room_fg, по которому работает коллизия — если зеркало поставлено, пока игрок В комнате 4, оно невидимо для коллизии (тень не родится). В обычном прохождении недостижимо: дверь выхода в другой комнате. Записан точный сценарий воспроизведения читом ROOMNAV и фикс на несколько строк. Правило «в _OPEN только незакрытое» теперь выполняется буквально: - bug_list.md → BUGS_OPEN.md, bug_closed.md → BUGS_CLOSED.md (ссылки обновлены во всех документах и в комментарии pop_trob.c); - из TASKS_OPEN убраны блоки закрытых задач (L3-CHOMP, L3-SKEL, L3-PASS, L4-MIRROR, DRAW-CHAR), справка по связности комнат уехала в архив; - из BUGS_OPEN убраны 8 строк таблицы закрытых багов, закрытый T-2 (уехал в BUGS_CLOSED) и раздел «уровень 3 — неначатые задачи» (обе записи закрыты); сводная таблица пересобрана по реально открытым записям. Все внутренние ссылки проверены скриптом: битых якорей 0. make size-check OK (65 программ), tests-host 5/5. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,173 +1,114 @@
|
||||
# Точка входа для следующей сессии (записано 2026-08-10, поздний вечер)
|
||||
# Точка входа для следующей сессии (обновлено 2026-08-11)
|
||||
|
||||
Файл для старта с чистого контекста: где всё стоит, что делать первым, какие
|
||||
грабли уже собраны. Читать целиком — он короткий. Дальше по ссылкам:
|
||||
`TASKS_OPEN.md` (доска), `bug_list.md` (открытые баги), `CLAUDE.md`.
|
||||
`TASKS_OPEN.md` (доска), `BUGS_OPEN.md` (открытые баги), `CLAUDE.md`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Состояние репозитория
|
||||
## 1. СЛЕДУЮЩАЯ ЗАДАЧА: [L5-SHADOW](TASKS_OPEN.md#l5-shadow) — уровень 5
|
||||
|
||||
Всё закоммичено и запушено, `main` в синхроне с `origin/main`.
|
||||
Последний коммит сессии — `8beb66a`.
|
||||
Уровни 1-4 приняты **smoke-тестами**; полные обходы всех комнат делаются по
|
||||
готовности ВСЕХ уровней ([политика приёмок](TASKS_CLOSED.md#pass-policy),
|
||||
решение пользователя 2026-08-11) — отдельных `L3-PASS`/`L4-PASS` больше нет.
|
||||
|
||||
`tests-host`: 5 наборов, все проходят (`[geom] 3144`).
|
||||
`make size-check`: чисто, роста нет.
|
||||
Уровень 5 **не приносит ни одного нового тайла** (инвентарь `res2005.bin`
|
||||
сверен: всё уже есть с уровней 1-4). Вся работа — одно спецсобытие: тень
|
||||
появляется в комнате 24, ждёт открытия двери, идёт к зелью, **выпивает его**
|
||||
и уходит за левый край; боя нет. Писать: `do_auto_moves` + таблица
|
||||
`shad_drink_move`, `do_init_shad`, ветку `check_shadow` для уровня 5,
|
||||
`autocontrol_shadow_level5`, плюс ветку ТЕНИ в `check_guard_fallout`.
|
||||
Всё расписано по SDLPoP прямо в задаче, включая готовые константы.
|
||||
|
||||
Коммиты за день, по порядку:
|
||||
Опора: механизм «спецсобытие порождает персонажа в слоте соперника» уже
|
||||
отработан на скелете (`pop_check_skel`), а сама тень как `charid_1_shadow`
|
||||
заведена на уровне 4.
|
||||
|
||||
## 2. Состояние репозитория
|
||||
|
||||
Всё закоммичено, `main` чист. `tests-host`: 5 наборов проходят
|
||||
(`[char] 65`, `[geom] 3144`, `[grab] 53`, `[phys] 1723`, `[wall] 1`).
|
||||
`make size-check`: OK (65 программ, роста нет).
|
||||
|
||||
Коммиты 2026-08-11:
|
||||
|
||||
| хеш | что |
|
||||
|---|---|
|
||||
| `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` с разбором |
|
||||
| `a823e7e` | libbgi: блочные AND/OR/XOR акселератора (строками и колонками) |
|
||||
| `860468f` | libbgi: NOT_PUT тоже через акселератор + `docs/shadow_render.md` |
|
||||
| `c0075c7` | NEXT_SESSION: op-блиты сделаны, вид тени отложен |
|
||||
|
||||
## 2. Состояние окружения
|
||||
Накануне (2026-08-10) закрыт `L4-MIRROR`: шаги 1-5 + фикс fore-прохода над
|
||||
отражением; протокол — [`TASKS_CLOSED.md`](TASKS_CLOSED.md#l4-mirror).
|
||||
|
||||
- **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. Состояние окружения
|
||||
|
||||
## 3. XOR/OR-блит через акселератор — СДЕЛАНО 2026-08-11, тень ОТЛОЖЕНА
|
||||
- **MAME запущена с мостом**, но на её HDD сейчас лежат ТЕСТЫ libbgi
|
||||
(`accop.exe`, `bgiimg.exe`), а не roomtest. Под roomtest пересобрать
|
||||
образ: `make hdd` (или `make PROF_FLAGS="-DFIRST_LEVEL=5" hdd` — при смене
|
||||
`FIRST_LEVEL` нужен `touch roomtest.c`, иначе не переедет), после чего
|
||||
MAME **обязана** пройти полный рестарт (memory `mame_hdd_rebuild_restart`).
|
||||
- **Остановка MAME — `mame/v306/bridge_cmd.sh 'cmd exit'`**, НЕ `kill`
|
||||
(правило пользователя). `pkill -f` бывает не срабатывает, и остаются ДВА
|
||||
инстанса, оба отвечающих на файловый IPC — тогда скриншоты приходят от
|
||||
чужой машины. Проверять `pgrep -f mame.arm` после остановки.
|
||||
- Прогон без MCP-инструментов: `bridge_cmd.sh 'cont'` → sleep ~45 с (бут
|
||||
DSS) → `bridge_cmd.sh 'keyseq d:{ENTER}'` → `keyseq <имя>{ENTER}` →
|
||||
`snap /tmp/mame_snap/x.png`. **Имя .exe на образе — не длиннее 8 символов
|
||||
(FAT 8.3) и БЕЗ подчёркивания** (`keyseq` не умеет `_`).
|
||||
- **SDLPoP собран с отладочной информацией** (`-O0 -g3`); pkg-config на
|
||||
машине нет, команда сборки — в истории этого файла (`git log -p`).
|
||||
- **НЕ ПРИБРАНО:** в `SDLPoP/src/seg008.c` диагностический `fprintf` с меткой
|
||||
`DBGMIRROR` в начале `add_objtable` (гейтится по `obj_type == 1 || == 4`).
|
||||
|
||||
**Библиотечная часть закрыта.** В libbgi поднят полный набор блочных
|
||||
операций акселератора — AND/OR/XOR/NOT, строками и колонками:
|
||||
`gfx_blit_op` / `gfx_blit_part_op`, `gfx_blit_cols_op` /
|
||||
`gfx_blit_cols_part_wx_op` (клип-окно и флип — как у копирующих близнецов);
|
||||
опкод операции патчится SMC, одна функция на все операции. `putimage`
|
||||
лишился попиксельного пути целиком (закрыт пункт 2d-1 `docs/TODO.md`).
|
||||
Регресс — `tests/accop`, 10/10 PASS в MAME, побайтно; `tests/bgi_img`
|
||||
получил две байтовые самопроверки. Механика и три ловушки — memory
|
||||
`accel_block_ops`.
|
||||
## 4. Что сделано в libbgi и чем это полезно дальше
|
||||
|
||||
**Вид тени (два блиттера OR+XOR) отложен решением пользователя** до того,
|
||||
как будут сделаны все уровни: пока тень рисуется обычной копией из атласов
|
||||
Кида. Причина не в примитивах — XOR несовместим с нашей прозрачностью
|
||||
`#FF`, а операция читает ОЗУ-копию экрана, из-за чего два прохода
|
||||
оригинала вырождаются в один XOR. Всё выясненное, замеры и четыре
|
||||
варианта — [`../docs/shadow_render.md`](../docs/shadow_render.md). Ключ к
|
||||
выбору варианта — список кадров, которыми тень реально пользуется
|
||||
(ожидание: бег, длинный прыжок из зеркала, питьё зелья, боёвка).
|
||||
Блочные операции акселератора — полный набор AND/OR/XOR/NOT, строками и
|
||||
колонками: `gfx_blit_op` / `gfx_blit_part_op`, `gfx_blit_cols_op` /
|
||||
`gfx_blit_cols_part_wx_op` (клип-окно и флип — как у копирующих близнецов),
|
||||
опкод патчится SMC. `putimage` лишился попиксельного пути целиком (закрыт
|
||||
пункт 2d-1 `docs/TODO.md`). Регресс — `tests/accop` (10/10 PASS в MAME,
|
||||
побайтно). Механика и три ловушки — memory `accel_block_ops`; главные:
|
||||
операция читает ОЗУ-КОПИЮ экрана (не VRAM), а прозрачность `#FF` совместима
|
||||
с AND/OR, но не с XOR.
|
||||
|
||||
Ниже — исходная постановка задачи, оставлена как справка.
|
||||
**Вид тени (OR+XOR) отложен** до готовности всех уровней — разбор, замеры и
|
||||
варианты в [`../docs/shadow_render.md`](../docs/shadow_render.md).
|
||||
|
||||
**Что установлено (замером, не гипотезой).** Тень уровня 4 в оригинале
|
||||
рисуется ДВУМЯ блитами одного и того же спрайта Кида (seg008:1602):
|
||||
## 5. Остальное открытое
|
||||
|
||||
```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).
|
||||
- **[FORE-DUP](BUGS_OPEN.md#fore-dup)** — передний слой тайла рисуется дважды
|
||||
при перекрытии объектов (Кид+отражение всегда, Кид+соперник — весь ближний
|
||||
бой). Картинку не портит, тратит такты. **Сначала замерить, потом
|
||||
чинить** — окно клипа в своё время дало 3.2×.
|
||||
- **[MIRROR-FG-STALE](BUGS_OPEN.md#mirror-fg-stale)** — зеркало, поставленное
|
||||
пока игрок В комнате 4, не попадает в снимок `room_fg` и потому невидимо
|
||||
для коллизии. В обычном прохождении недостижимо; фикс на несколько строк,
|
||||
делать вместе со следующей правкой `pop_trob.c`.
|
||||
- **[DIED-ON-BUTTON](BUGS_OPEN.md#died-on-button)** — `died_on_button`
|
||||
(seg007:776) не портирован.
|
||||
- **TORCH-ANIM-RIGHT** — под запечённым пламенем могут застыть пики/меч/зелье
|
||||
справа от факела; на уровнях 1-4 такого соседства нет.
|
||||
- **[GUARD-PHYS](TASKS_OPEN.md#guard-phys)** — остаток: ветка тени в
|
||||
`check_guard_fallout` (уходит в L5-SHADOW) и живая проверка стража,
|
||||
нажимающего напольную кнопку.
|
||||
- Долгие: `BUG-SPIKE-1`, `BUG-CHOMP-JUMP-1` (оба низкий приоритет),
|
||||
`L3-PASS`, `L3-COLOR`, `L1-SPEED`, `TUNE-1`.
|
||||
- **Не проверено в MAME** из вчерашнего: отражение с fore-проходом и клип
|
||||
тени слева (собрано и залито, но живьём не смотрели).
|
||||
`L3-COLOR`, `L1-SPEED` (игра на ~39 % быстрее оригинала), `TUNE-1`.
|
||||
|
||||
## 5. Грабли, собранные сегодня
|
||||
## 6. Грабли, собранные 2026-08-10/11
|
||||
|
||||
- **Не оценивать железо по своей же memory-заметке.** Я заявил, что accel
|
||||
- **Не оценивать железо по своей же memory-заметке.** Заявил, что accel
|
||||
умеет только копирование и XOR потребует ~25 % кадра на CPU — неверно,
|
||||
поправил пользователь. Заметка описывала копирование, я принял её
|
||||
неполноту за свойство железа.
|
||||
неполноту за свойство железа. Проверять по драйверу MAME
|
||||
(`mame/sources/MAME/src/mame/sinclair/sprinter.cpp`) и `docs/new/06-accel.md`.
|
||||
- **lldb через FIFO — плохая идея.** Повторяющиеся `-o` при
|
||||
`breakpoint command add` записываются НЕПОЛНЫМИ (берётся последний), а
|
||||
оставшийся от неудачной попытки `script print(... lldb.frame ...)` уронил
|
||||
lldb прямо в обработчике точки останова. Три прыжка пользователя ушли
|
||||
впустую. **Работает надёжно:** добавить `fprintf(stderr, ...)` прямо в
|
||||
SDLPoP, пересобрать (он собирается за секунды) и читать stdout. В дереве
|
||||
уже есть такие метки (`DBG kidobj`).
|
||||
`breakpoint command add` записываются НЕПОЛНЫМИ. **Работает надёжно:**
|
||||
`fprintf(stderr, ...)` прямо в SDLPoP, пересборка (секунды) и чтение stdout.
|
||||
- **`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.
|
||||
`roomtest.c` — при смене нужен `touch roomtest.c`.
|
||||
- **Доска отставала от кода на три задачи** (`L3-CHOMP`, `L3-SKEL`, шаги 3/5
|
||||
`L4-MIRROR` значились несделанными). Перед планированием — сверять
|
||||
`TASKS_OPEN.md` с кодом грепом, а не верить записи.
|
||||
- Диапазон `obj_x` = **−416..695** (посчитан из `kid_data.bin`). Пригодится
|
||||
всякий раз, когда нужна таблица по экранной X.
|
||||
|
||||
Reference in New Issue
Block a user