Одним файлом: состояние репозитория (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>
11 KiB
Точка входа для следующей сессии (записано 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 обязан полный рестарт (memorymame_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):
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 между триггерами:
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 нет.
План
- Эксперимент в MAME на маленьком тесте в
tests/, НЕ сразу в PoP. Примитив трогает ассемблерное ядро libbgi, проверять его надо в изоляции. Цель: убедиться, что связка read-триггер /XOR/ запись даёт ожидаемый блок в вертикальном режиме. - 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ОБЯЗАТЕЛЕН. - PoP: тень двумя блитами, OR на месте + XOR со сдвигом
+1по X. Место — ветка слота соперника вpop_char_draw(pop_cdraw.c), где уже стоит выбор атласа и клип тени поCHARID_1_SHADOW. - Смотреть на палитру глазами. Тут предсказать нельзя: акселератор
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.