Routerman & Ultra
Привет, Рутермен! Слушай, наткнулась тут на один старый глюк NES – спрайт мигает каждые 32 миллисекунды, похоже, ЦП и PPU борются за общий шину памяти. Думаю, это какая-то тонкая гонка времени. Хочешь проследим за потоком данных и выясним, откуда на самом деле эта странность берется?
Да, этот мерцание – типичный конфликт шины. Процессор и графический чип буквально "перекидываются" из-за той самой 16-битной шины, а 32-миллисекундный интервал как раз совпадает с периодом вертикальной прорисовки. Давай проследим путь: данные спрайтов хранятся в OAM, но графический чип при отрисовке берёт данные из таблиц имен, в то время как процессор пытается записать в эти же таблицы. Аппаратный арбитр передает управление тому, чей запрос активен, но в данном случае синхронизация сбивается. Если сопоставим запросы шины с линиями развертки графического чипа, увидим повторяющийся перехлёст каждые 32 миллисекунды. Начни с проверки количества циклов в начале каждого периода вертикальной прорисовки, затем проследи за операциями записи процессора в видеопамять в течение этого интервала. Это покажет, является ли сбой результатом невидимой гонки или просто смещением по времени логики шины. Готова погрузиться в схему работы с циклами?
Отлично порешано, Рутерман. Давай захватим счетчик циклов, подключим логгер шины и построим график записи во времени. Я выровняю строки развертки и посмотрю, где возникают скачки. Если это гонка, подкрутим задержку процессора, чтобы её убрать. Если это сдвиг по времени – попробуем изменить фазу тактового сигнала ПУ. Пора копаться в данных. Я готова, когда ты.
Отлично. Сейчас запущу счетчик циклов, включу логгер шины и сделаю первый снимок временной шкалы. Скажи, как увидишь скачок, чтобы мы поняли – это чистый конфликт шины или просто фазовый сдвиг. Поиграем с задержкой, посмотрим, исчезнет ли мерцание – если данные покажут тонкий сбой синхронизации, углубимся в анализ. Давай посмотрим на график.
Привет, Роутермен. Сделала снимок. Пик идеально совпадает с границей V-blank, интервал – ровно 32 миллисекунды. Похоже на чистый конфликт по шине – графический процессор тянет то же самое 16-битное слово, которое процессор пытается записать. Я добавлю небольшую задержку в цикл записи процессора и пересниму. Если мерцание исчезнет, подтвердится, что это гонка за ресурсами. Если нет – придется подстроить фазу графического процессора. Давай внесем правку и посмотрим, что покажет анализ.
Отлично, всё совпало с V‑blank слотом. Добавим небольшую задержку при записи в ЦП – это даст шине немного передышки. Если мерцание исчезнет – значит, мы попали в классическую гонку за ресурсами. Если нет – придётся смотреть на выравнивание цикла сканирования в ПУ. Сообщи мне, что будет в следующей записи. Посмотрим, может, шине просто нужно вежливое "подожди" перед тем, как снова тянуть одно и то же слово.
Забавно, микро-задержка – это классический приём "подожди". Если мерцание пропадёт, значит, мы поймали чистый гонки по шине. Если нет, то придётся синхронизировать фазу построения кадров PPU. Напиши мне, как получишь следующий кадр.
Поехали. Микрозадержка должна быть в районе нескольких наносекунд – хватит, чтобы контроллер видео успел прочитать данные до записи процессора. Если мерцание исчезнет – считаем, что это была гонка. Если останется – сдвинем фазу тактового сигнала контроллера видео на одну строку и снова залогируем. Посмотрим, что получится на новом графике.
Поняла, добавляю буфер в 200 наносекунд. Следи за логами — если мерцание пропадет, значит, мы поймали проблему с конфликтом. Если останется, подвинем тактовый сигнал ППУ на одну строку и попробуем перезахватим. Давай посмотрим обновненный график.