361c9d9f78
Спецсобытие уровня 8 (SDLPoP seg003:0545/0ABA, seg002:07EB): когда дверь уровня открыта, а Кид остаётся в комнате 16, через 150 кадров приходит мышь, пробегает справа налево по верхнему ряду, наступает на кнопку (0,7) — решётка (0,3) открывается — и убегает. Ассетов не потребовалось: кадры 186..188 идут по таблице Кида, их спрайты (images 130..132) уже лежат в kid16.atl, отрисовка подхватывает мышь сама. - guards.c: pop_check_mouse, autocontrol_mouse, ветки мыши в autocontrol_opponent / play_guard / check_can_guard_see_kid; - pop_leveldoor_open стал word, как в оригинале (в него же считается задержка — байт переполнился бы через 255 кадров); - leave_guard больше не записывает тень и мышь в данные уровня (seg002:02F5); - полосы HP у мыши нет (seg000:1159); - tests-host/t_mouse: 17 проверок, единственный набор с guards.c. Разгрузка резидента (куча в huge упала до 879 Б): pop_start_level, find_start_level_door, чит-навигация по комнатам и лейбл номера уехали в roomtest_cold.c (--bank 8, n_banks = 8). _CODE 25653 -> 24825, куча -> 1707 Б; кадровый путь не тронут. Проверено: tests-host 6/6, make size-check OK, живьём в MAME (мышь появилась, нажала кнопку, решётка поехала вверх, мышь ушла). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
153 lines
12 KiB
Markdown
153 lines
12 KiB
Markdown
# Точка входа для следующей сессии (обновлено 2026-08-12, вечер)
|
||
|
||
Файл для старта с чистого контекста: где всё стоит, что делать первым, какие
|
||
грабли уже собраны. Читать целиком — он короткий. Дальше по ссылкам:
|
||
`TASKS_OPEN.md` (доска), `BUGS_OPEN.md` (открытые баги), `CLAUDE.md`.
|
||
|
||
---
|
||
|
||
## 1. СЛЕДУЮЩАЯ ЗАДАЧА: smoke-прогон уровня 8
|
||
|
||
Зелья приняты пользователем (уровень 2 — «−HP», уровень 7 — перо), уровень 7
|
||
считается прошедшим smoke. Спецсобытие уровня 8 —
|
||
[L8-MOUSE](TASKS_CLOSED.md#l8-mouse) — **закрыто 2026-08-12**: мышь
|
||
портирована, покрыта хост-набором `t_mouse` (17 проверок) и проверена живьём в
|
||
MAME (появилась, нажала кнопку (0,7) комнаты 16, решётка (0,3) поехала вверх,
|
||
ушла и погасла). Новых тайлов уровень 8 не приносит вовсе.
|
||
|
||
Осталось пройти сам уровень: он длинный, с возвратом через два чомпера
|
||
комнаты 4, и стражи там сильнее прежних — комната 5 держит **skill 7**
|
||
(максимум из встречавшихся), комнаты 12/22/24 — skill 2/3/3.
|
||
|
||
Правило появления мыши (сверено с оригиналом, детали в
|
||
[TASKS_CLOSED](TASKS_CLOSED.md#l8-mouse)): счётчик — сам `leveldoor_open`,
|
||
растёт только пока Кид в комнате 16, срабатывание ровно на 150, **второго
|
||
раза нет**; сбрасывает только рестарт уровня. Тупика это не создаёт — низом
|
||
через провал есть путь к двери уровня ценой 1 HP.
|
||
|
||
Резидент разгружен ([MEM-COLD1](TASKS_CLOSED.md#mem-cold1)): холодная половина
|
||
главного цикла уехала в **банк 8** (`roomtest_cold.c`), куча 879 → **1707 Б**.
|
||
Следующие кандидаты — [MEM-COLD2](TASKS_OPEN.md#mem-cold2).
|
||
|
||
Ощущенческий хвост прежний — [GRAB-KBD-TIMING](BUGS_OPEN.md#grab-kbd-timing),
|
||
разбирается после готовности всех уровней (решение пользователя).
|
||
|
||
## 2. Состояние репозитория
|
||
|
||
Всё закоммичено, `main` чист. `tests-host`: **6 наборов** проходят
|
||
(`[char] 65`, `[geom] 3144`, `[grab] 55`, `[mouse] 17`, `[phys] 1727`,
|
||
`[wall] 1`). `make size-check`: OK (65 программ, роста нет).
|
||
|
||
Коммиты 2026-08-12:
|
||
|
||
| хеш | что |
|
||
|---|---|
|
||
| `b5951c9` | зацеп за кромку нижнего ряда: `do_fall` пускает ряд до 3 + `check_grab` в midair |
|
||
| `d7d18ae` | зелье медленного падения (перо) + цвет пузырьков по типу зелья |
|
||
|
||
Раньше (2026-08-11, вечер): `abe4a83` уровень 5, `740cc6d` арка у ворот,
|
||
`e4ef489` L6-SHADOW, `9ecea17` уровень 6 → 7.
|
||
|
||
Уровни 1-6 проходятся.
|
||
|
||
## 3. Состояние окружения
|
||
|
||
- **MAME запущена с мостом**, на HDD — roomtest, собранный с
|
||
`-DFIRST_LEVEL=8`. **ПРАВИЛО ПОЛЬЗОВАТЕЛЯ: перед сборкой образа —
|
||
`make clean`, потом `make`, потом `make hdd`** (memory
|
||
`mame_build_clean_rule`). Без этого `make hdd` кладёт на диск ПРОШЛУЮ
|
||
сборку: `FIRST_LEVEL` живёт внутри `roomtest.c`, и без изменения исходника
|
||
make считает `.exe` актуальным — 2026-08-12 на этом уехал уровень 1 вместо
|
||
8, заметил пользователь. После пересборки образа MAME **обязана** пройти
|
||
полный рестарт (memory `mame_hdd_rebuild_restart`).
|
||
- Адреса состояния сместились после MEM-COLD1: брать из
|
||
`.sprinter-cc-roomtest/roomtest.map` заново (`cur_room` 0xA33D,
|
||
`pop_leveldoor_open` 0xA34C, `Kid` 0xA3B1, `Guard` 0xA759 — на сборку
|
||
2026-08-12). Мост: `setmem ADDR HEXBYTES` (не `write`), `mem ADDR N`.
|
||
- **Остановка MAME — `mame/v306/bridge_cmd.sh 'cmd exit'`**, НЕ `kill`
|
||
(правило пользователя). `pkill -f` бывает не срабатывает, и остаются ДВА
|
||
инстанса, оба отвечающих на файловый IPC — тогда скриншоты приходят от
|
||
чужой машины. Проверять `pgrep -f mame.arm` после остановки.
|
||
- Прогон без MCP-инструментов: запустить `run_bridge.sh` → **sleep 6** →
|
||
`bridge_cmd.sh 'cont'` → **sleep 8** → `keyseq d:{ENTER}` →
|
||
`keyseq roomtest{ENTER}` → `snap <путь>.png`. Тайминги — правило
|
||
пользователя, длиннее ставить не надо. **Имя .exe на образе — не длиннее
|
||
8 символов (FAT 8.3) и БЕЗ подчёркивания** (`keyseq` не умеет `_`).
|
||
- **Вести игру из моста — по обратной связи из памяти, а не по скриншотам**:
|
||
`mem 0xA46A 10` = `pop_char_t` Кида, `mem 0xA3F7 1` = номер комнаты (адреса
|
||
из `.sprinter-cc-roomtest/roomtest.map`+`.sym`). Полный рецепт (удержания,
|
||
чит-навигация, тайминги нажатий) — memory `mame_mcp_bridge`.
|
||
- **MCP-инструменты `mame-z80` не поднимались**: сервер падал на
|
||
`ModuleNotFoundError: mcp.server.fastmcp` — вышел `mcp` 2.0, где FastMCP
|
||
переехал. В `~/.claude.json` зафиксировано `--with "mcp<2"`; подхватится
|
||
при следующем СТАРТЕ сессии Claude (внутри текущей — нет).
|
||
- **SDLPoP собран с отладочной информацией** (`-O0 -g3`); pkg-config на
|
||
машине нет, команда сборки — в истории этого файла (`git log -p`).
|
||
- **НЕ ПРИБРАНО:** в `SDLPoP/src/seg008.c` диагностический `fprintf` с меткой
|
||
`DBGMIRROR` в начале `add_objtable` (гейтится по `obj_type == 1 || == 4`).
|
||
|
||
## 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,
|
||
побайтно). Механика и три ловушки — memory `accel_block_ops`; главные:
|
||
операция читает ОЗУ-КОПИЮ экрана (не VRAM), а прозрачность `#FF` совместима
|
||
с AND/OR, но не с XOR.
|
||
|
||
**Вид тени (OR+XOR) отложен** до готовности всех уровней — разбор, замеры и
|
||
варианты в [`../docs/shadow_render.md`](../docs/shadow_render.md).
|
||
|
||
## 5. Остальное открытое
|
||
|
||
- **[FORE-DUP](BUGS_OPEN.md#fore-dup)** — передний слой тайла рисуется дважды
|
||
при перекрытии объектов (Кид+отражение всегда, Кид+соперник — весь ближний
|
||
бой). Картинку не портит, тратит такты. **Сначала замерить, потом
|
||
чинить** — окно клипа в своё время дало 3.2×.
|
||
- **[DIED-ON-BUTTON](BUGS_OPEN.md#died-on-button)** — `died_on_button`
|
||
(seg007:776) не портирован.
|
||
- **TORCH-ANIM-RIGHT** — под запечённым пламенем могут застыть пики/меч/зелье
|
||
справа от факела; на уровнях 1-4 такого соседства нет.
|
||
- **GUARD-PHYS ЗАКРЫТ** 2026-08-11: нажатие напольной кнопки НЕ-Кидом
|
||
проверено живьём на уровне 6 (тень встаёт на `closer` и роняет решётку).
|
||
- **[GATE-FORE-KID](BUGS_OPEN.md#gate-fore-kid)** — Кид в проёме ворот виден
|
||
поверх решётки; портирован только шовный случай.
|
||
- Долгие: `BUG-SPIKE-1`, `BUG-CHOMP-JUMP-1` (оба низкий приоритет),
|
||
`L3-COLOR`, `L1-SPEED` (игра на ~39 % быстрее оригинала), `TUNE-1`.
|
||
|
||
## 6. Грабли, собранные 2026-08-12
|
||
|
||
- **Тест, который «проходит» и на сломанном коде, ничего не стоит.** Первая
|
||
версия регресса на спуск-зацеп засчитывала ЛЮБОЙ вис — а Кид на первых
|
||
кадрах падения цепляется обратно за ту же верхнюю кромку. Признак цели
|
||
обязан быть позиционным. Проверять новый регресс откатом фикса — обязательно.
|
||
- **`action == 3` (midair) — это не только падение**: кадры спуска `seq_68`
|
||
тоже идут с ним. Ждать «начала падения» по одному `action` нельзя.
|
||
- **Клавиши, зажатые из моста, переживают точечный `release`**: плагин
|
||
переустанавливает удержания каждый кадр, и после серии `hold` осталось 6
|
||
незакрытых входов — у пользователя «Кид ходит как с зажатым Shift».
|
||
Заканчивать работу с вводом только `pause` + `cont` (release_all).
|
||
- **Чит-навигация `+`/`−` теряет нажатия и роняет Кида** из комнат без пола:
|
||
уровень 7 из комнаты 17 всегда сваливается в 1, и кольцо `−` до комнаты 14
|
||
не доходит никогда. Ходить циклом с проверкой номера комнаты.
|
||
|
||
## Грабли 2026-08-10/11
|
||
|
||
- **Не оценивать железо по своей же 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` записываются НЕПОЛНЫМИ. **Работает надёжно:**
|
||
`fprintf(stderr, ...)` прямо в SDLPoP, пересборка (секунды) и чтение stdout.
|
||
- **`make` без `hdd` не обновляет образ MAME**, а `FIRST_LEVEL` живёт в
|
||
`roomtest.c` — при смене нужен `touch roomtest.c`.
|
||
- **Доска отставала от кода на три задачи** (`L3-CHOMP`, `L3-SKEL`, шаги 3/5
|
||
`L4-MIRROR` значились несделанными). Перед планированием — сверять
|
||
`TASKS_OPEN.md` с кодом грепом, а не верить записи.
|
||
- Диапазон `obj_x` = **−416..695** (посчитан из `kid_data.bin`). Пригодится
|
||
всякий раз, когда нужна таблица по экранной X.
|