Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
Выкладываю исходники своего порта эмулятора NES FCE Ultra под STM32H743 (отладочная плата NUCLEO-H743).
Особенности:
1) Для сборки используется Keil ARM MDK 5.16a с установленным софт-паком STM32H7xx_DFP 2.1.0. Такая конфигурация работает даже под Win32 WinXP
2) Периферия соединяется к GPIO как давал на картинках выше.
3) Используется Sony Ericsson K800i LCD (контроллер Toshiba) в портретном режиме. Можно использовать другой LCD, переписав функции LCD_Init(), LCD_Position() и заменить команду Display RAM Write. Времянки FMC изменить на свои (учесть клок FMC =200 MHz). GPIO Speed попробовать повысить (у меня капризный LCD - ему крышу срывает, когда ставишь больше, чем GPIO_SPEED_FREQ_LOW).
4) Кнопки управления при нажатии выдают логический "0" (на GPIO включены PULL-UP). Состояние кнопок опрашивается примерно 60 раз в секунду. Опрос висит в обработчике прерывания SysTick.
5) Для вывода звука используется внутренние DAC & Output Buffer. Можно подключить наушники 16..32 Ом + РЕЗИСТОР от 470 Ом (резистор обязателен, чтобы не угробить порт!). Я использую УНЧ на MC34119D.
6) В силу специфики фрагментированной памяти RAM STM32H743, использую своё распределение памяти. Секции описаны в файле для линковщика scatter.sct (Кейловский дефолтный сетап памяти не используется и выключен!).
7) ROM игры линкуется вместе с эмулятором. Использую ассемблерную директиву INCBIN. Это позволяет избежать лишней конвертации BIN to H (для инклуда) и снизить нагрузку на компилятор. В файле ROM.S исправить название игры на своё, а в папку ROMs закинуть игру.
8) Эмулятор не использует функции для работы с кучей (heap) и требует минимум памяти под стек (stack).
9) Синхронизация эмулятора по звуку. Длина аудио-буфера подобрана так, чтобы вызывать прерывание примерно 60 раз в секунду (NTSC). Возможность работы в режиме PAL: имеется и очень просто.
10) Стейт эмулятора (для сохранения/восстановления) расположен в UNINIT регионе. Это даёт возможность восстанавливаться даже после горячего сброса STM32H743 !
11) Floating Point Hardware выключен (Not Used). Связано это с типом "long double", который различается на разных платформах. Если его включить в режим "двойная точность", то APU DMC будет проигрываться мгновенно (из-за неверных рассчётов).
Готовая прошивка: obj\nes.hex + ИСХОДНИКИ:
Это сообщение отредактировал Gospodin_Riba - Jul 13 2018, 04:21 PM
Задолбался портировать, потому что на C++ написан с применением ООП. А это "привет, куча, сколько ты жрёшь памяти? ..." и всё в таком духе. Много пришлось оптимизировать. Обэтом позже когда до конца отшлифую.
За основу брал референс-код эмулятора Handy 0.95. Сорцы ниже:
Это сообщение отредактировал Gospodin_Riba - Jul 13 2018, 04:25 PM
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
Так как нативное разрешение Atari Lynx всего 160 x 102 пиксела, то на дисплее 320x240 это будет всего кадр-четвертушка.
Дисплей, который я использую, поддерживает аппаратное растяжение. Без фильтрации.
Поэтому было решено портировать фильтр, который был заточен на пиксель-арт графику. Из всех кандидатов (SaI, Eagle, HQ2x) выбор пал на SaI. Потому что менее ресурсоёмкий и почти как HQ2x (который ресурсоемкий и требует много памяти для вспомогательных таблиц). И лучше, чем Eagle (потому что Орёл пропускает пикселы).
Что вышло, на фоте ниже. Слева - аппаратное растяжение без фильтрации. Справа- фильтрация 2xSAI. Пришлось рисовать с помощью DMA, иначе CPU не выдерживает 60 фреймов/с.
Картинку тыкнуть мышью для увеличения - будут лучше заметны пиксели слева .
Сорец под STM32H743 выложу, как закончу над ним работать.
Это сообщение отредактировал Gospodin_Riba - Jul 13 2018, 04:32 PM
Присоединённое изображение (Нажмите для увеличения)
--------------------
По всем вопросам пишите на почту: repstosw2018 [собака] gmail [точка] com Энтузиазм заканчивается, когда начинается Кризис. Рождается Капитализм :)
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
Доделал эмулятор для H743. Расходы памяти (вместе с ROM-ом игры 128КБ):
CODE
Program Size: Code=70084 RO-data=132824 RW-data=459236 ZI-data=436476
Сделал 4 варианта видео-режима (LCD_MODE.H):
CODE
#define MODE_X1 0 /* Режим 160x102 Четверть экрана */ #define MODE_X2_NEAREST 1 /* Режим 320x204 Аппаратное растяжение */ #define MODE_X2_SAI 2 /* Режим 320x204 Фильтр 2xSaI */ #define MODE_X2_LQ 3 /* Режим 320x204 Фильтр 2xLQ */
#define LCD_MODE MODE_X2_SAI
Фильтры взял с других эмуляторов, развернул их на 90 градусов и адаптировал под свои нужды.
Поставил SaI2x, так как мне он больше всего нравится.
Сделал ещё HQ2x, но из сорцов решил его убрать, так как звук херится, когда на кадре много мелких деталей(этот фильтр ресурсоемкий).
Файлы игр (и загрузчик) лежат в папке ROMs. В файле CartROM.S в INCBIN добавить нужную игру и откомпилировать. Пример: ROMs\Zendocon.lnx
В компиляторе глобально задефайнены: NDEBUG,DINGUX,ANSI_GCC,SDL_PATCH
Собирается с ключом --force_new_nothrow , иначе C++ ООП не заработает.
В scatter.sct объявленырегионы-секции для объектов. Кейловский дефолтный сетап не используется.
Для сохранения и восстановления пришлось написать враппер для файловых функций, имитирующих открытие-закрытие-чтение-запись файлов: pseudoFile.cpp , pseudoFile.h
Кнопки упрвления:
1) U, D, L, R, B, A, Start, X, Y 2) Select - сохранить стейт 3) U+D - восстановить стейт
Стейт сохраняется даже после сброса CPU.
Сорцы + готовая прошивка(obj\atari.hex) + несколько игр: (Keil ARM MDK v5)
Это сообщение отредактировал Gospodin_Riba - Jul 16 2018, 12:50 PM
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
Выкладываю исходники своего порта под STM32H743 (отладочная плата Nucleo-H743).
1) Управление:
U D L R Select Start A B (A и B поменял местами: удар- слева, прыжок- справа).
X - Сохранить стейт Y - Восстановить стейт.
Стейт выживает даже после сброса CPU.
2) Две опции отображения видео:
Режим 160x144 - по центру экрана. Режим 320x240 Фильтр 2xSaI - на весь экран.
Растянутый фильтром кадр в 2 раза имеет разрешение 320x288 и не влезает в 240 строк используемого LCD. Поэтому было принято решение пропускать каждую 6-ю строку выходного буфера: итого из 288 строк получается ровно 240. При этом качество картинки остаётся на должном уровне.
Конфигурация в файлк LCD_MODE.H:
CODE
#define LCD_CONTROLLER LCD_CONTROLLER_RENESAS
#define MODE_X1 0 /* Режим 160x144 */ #define MODE_X2_SAI 1 /* Режим 320x240 Фильтр 2xSaI */
#define LCD_MODE MODE_X2_SAI
3) Две опции выбора контроллера LCD. Дисплей от тел. SE K800i.
4) Поддержка ROM-ов от GameBoy B/W (*.gb) и GameBoy Color (*.gbc).
В папку ROMs - кидаем игры. В файле ROM.S пишим имя файла игры (пример: INCBIN ROMs\Tank.gb). Затем билдим и прошиваем.
5) Эмулятор не использует кучу(HEAP) и использует минимум стека(STACK).
6) Есть возможность адаптации рендерера на 8-битный режим (для экономии памяти).
7) Для отображения растянутого фильтром кадра используется MASTER DMA (MDMA) вместо "обычного" DMA. Это позволило отказаться от свопинга байтов на каждый пиксел. MDMA умеет передавать байты с разным порядком.
8) Есть ограничение на размер игр(ROM-ов). Игры размером 2 МБ, 4 МБ не смогут пойти физически из-за ограниченного объёма Flash-памяти у STM32H743.
9) За основу взят эмулятор - Cingb. Звук приделан от другого эмулятора - GNUBoy. Так уж исторически сложилось (Cingb - это первый в моей жизни портированный эмулятор!)
Исходники + прошивка с игрой(obj\*.hex) + несколько игр:
Это сообщение отредактировал Gospodin_Riba - Jul 21 2018, 11:54 AM
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
На этот раз решил испытать пришедшие новые дисплеи от K800i с контроллером Renesas(Hitachi). Они оказались более помехзащищёнными, но качество картинки немного огорчило - на дисплее видны вертикальные полосы (особенно заметны, когда LCD залит одним цветом).
Присоединённое изображение (Нажмите для увеличения)
--------------------
По всем вопросам пишите на почту: repstosw2018 [собака] gmail [точка] com Энтузиазм заканчивается, когда начинается Кризис. Рождается Капитализм :)
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
Работу фильтра в эмуляторе поясняет рисунок. Вкратце: исходный катр Геймбоя 160x144 увеличиваем в 2 раза : 320x288. Чтобы влезло на дисплей, надо пропускать каждую 6-ю строку(с выходного буфера фильтра! не с исходного!) Тогда из 288 строк выйдет ровно 240 и всё круто!
Присоединённое изображение (Нажмите для увеличения)
--------------------
По всем вопросам пишите на почту: repstosw2018 [собака] gmail [точка] com Энтузиазм заканчивается, когда начинается Кризис. Рождается Капитализм :)