Как стать автором
Обновить

Эмулятор NES в каждый проект [0x03]

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров1.9K
Bomberman
Bomberman

Вот уже как неделю я отдыхаю от проекта. За время разработки от последней статьи мне удалось реализовать управление джойстиком и теперь за Марио можно было играть. Так как ошибок в коде больше не наблюдалось, я приступил к следующей игре. Нужна была игра, которая делает скролл экрана и я думал, что bomberman подойдет, но как оказалось позже, он не делает скролл, хотя может я пока не дошел до этого места.

Первое чему я удивился, так это то, что джойстик не работал в меню игры bomberman. В моём эмуляторе джойстик читался один раз и больше к нему код не обращался. Я уж было подумал, что опять сложный и интересный баг нашел, и решил исследовать, что передается в джойстике в готовом эмуляторе и почему он не дает больше читать клавиши от джойстика в моем эмуляторе.

Оказалось два варианта из-за чего не работал джойстик, это не было реализовано кнопки SELECT, а второе, что не было реализовано вертикальная синхронизация.

Объясню про синхронизацию. В Марио, игра шла без проблем и я не видел проблем, но оказывается, что если даже ничего не рисуется на экран, когда в PPU_CTRL мы ставим не VBLANK, то этот таймер этого рисования всё равно отрабатывает, но без рисования. Когда я поместил в код обновление PPU_STATUS как 0x80, то джойстик заработал. Конечно, чтобы понять всё это, я сделал просмотр, где в текущий момент выполняются команды, и заметил, что он останавливается на одном из двух циклов, где читает PPU_STATUS. Я открыл документацию по NESdev, но она не открывалась, я начал в последнее время наблюдать, что сайт почти никогда не работает. Не долго думая, я обратился к гигачату, к нейросети, которая тоже всё знает про NES. Смог понять как это работает.

Следующий баг был, когда уровень не загружался. Игра останавливалась на картинке "STAGE 1". Я чуть-чуть поисследовал, не понял, и оставил проблему на несколько дней. Пока я занимался другими делами, я настраивал себя, чтобы вот возьмусь за задачку и буду исследовать ассемблерный код на предмет неточностей.

И вот, спустя четыре дня, я собрался с силами, и обратился к реверсу Bomberman. Я ничего такого не заметил, а смотрел я NMI рендеринг. Впрочем, я заметил, что перестает вообще срабатывать NMI рисования уровня. Исследовав этот вопрос, и найдя опять же по отладочному PC, что работа застревает на одном и том же куске кода в рендере Bomberman, я решил посмотреть на чем подвисает и так я понял, что там реализована логика SPRITE_HIT_0. Я почитал документацию, и узнал, что это возникает, когда первый спрайт из DMA сравнивается со всеми остальными. Но вроде даже с фоном сравнивается. Тогда я обратился к нейросети и спросил сколько длиться scanline, и узнал, что 53 микросекунды. Я сделал таймер для scanline, который увеличивал переменную на один каждый раз, а когда увеличивал, то проверялась коллизия, если спрайт пересекает другие спрайты, то ставил в PPU_STATUS бит 0x40. И уровень заработал. Как можно видеть, уровень работает, но не правильно работает скролл, и не исчезают кирпичики. В этом мне дальше надо было разобраться.

В это мне помогла ссылка https://www.nesdev.org/wiki/PPU_scrolling, в описании которой, я удостоверился, как надо правильно делать. Спустя 4 часа, я сделал это наконец, но всё работает не идеально. Сначала, я добавил чтобы перемещалось по квадратам, всё получилось. Потом добавил плавное смещение по данным, которые поступают в PPU_SCROLL. То-есть, когда по квадратам рисовал, то PPU_SCROLL делил на 8, так как размер тайла занимает 8 пикселей. Потом улучшил код и теперь вот как выглядит.

На видео видно, что происходят какие-то скачки в изображении, в реальности этого не было видно. Насчет скролла, я думал, что сначала задается скролл, а потом записываются данные в PPU, таким образом я сделал массив, который хранит в себе значения скроллов, когда они записываются в PPU_ADDR. Как оказалось, это работает не так. Думаю, что в последующие дни я посмотрю где и как игра работает со скроллом и реши эту проблему.

Ещё не взрываются стены, если за ними пустое пространство, этот баг тоже надо найти, но думаю, что я этим всем займусь уже в следующие дни, а пока надо отдыхать от этого и читать книги.

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
+2
Комментарии1

Публикации

Истории

Ближайшие события

25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань
20 – 22 июня
Летняя айти-тусовка Summer Merge
Ульяновская область