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

Комментарии 45

Спасибо за Торт!

Хорошая статья. Пишу свой эмулятор C64 и так же на плюсах. Есть желание после заняться мегадрайвом. Пара вопросов. При эмуляции учитывается количество затрачиваемых циклов процессора на выполнение команд? Как синхронизируется переферия сидящая на общей шине с процессором? Есть какое то архитектурное решение или просто все заинтересованные лица мониторят сколько циклов прошло? Я новичок в вопросах эмулятостроения поэтому интересен опыт других.

При эмуляции учитывается количество затрачиваемых циклов процессора на выполнение команд? 

Нет, команды выполняются всё время без ограничений, пока не наступит VBLANK-прерывание. По идее ничего плохого не произойдет, просто игра будет много времени проводить в функции наподобии WaitVBLANK.

Как синхронизируется переферия сидящая на общей шине с процессором? Есть какое то архитектурное решение или просто все заинтересованные лица мониторят сколько циклов прошло?

Всё работает в один поток - есть цикл, который делает эти вещи:

  1. poll_events - проверить события GUI, если видим что окно закрыли (нажали на крестик) то цикл прерывается и программа завершается.

  2. update_controller - насобирать информацию с периферии, то есть про нажатия кнопок с клавиатуры и геймпада, и поставить флаги про это в "контроллер". А он в свою очередь реализует интерфейс Device и потом будет отдавать информацию про нажатия когда BusDevice ему передаст команду на read/write.

  3. execute - постоянно исполнять инструкции пока верно условие или пока не получим информацию что мы прыгнули на VBLANK

  4. video_.update() - вычисляет пиксели на игровом экране

  5. render() - рисует весь GUI, в том числе игровой экран

Я новичок в вопросах эмулятостроения поэтому интересен опыт других.

Для меня это тоже первый эмулятор и я в другие эмуляторы не смотрел особо, пробовал позапускать, но с Linux они все как-то плохо дружат

Точность в соблюдении циклов может быть важна в некоторых играх, ну и, конечно, в демках, типа titan.

много поздних игр делают разные сложные визуальные эффекты перепрограммируя VDP чуть не на каждый scanline

используемая схема хороша с точки зрения простоты кода и его понимания, но для корректной эмуляции нужно реально считать циклы

Спасибо за интересную статью! В свое время занимался ремонтом данных приставок, всегда было интересно для чего был нужен z80, теперь узнал.

Вот это монументально, спасибо, отличная работа.
Несмотря на понимание, что тут происходит, не думаю, что когда нибудь найду время сделать нечто подобное.

По поводу BCD - Я так понимаю тяжелое наследие со славных времен микрокалькуляторов (для которых и делались первые процессоры).
Это когда вместо честного двоичного числа (шестнадцатеричного по 4 бита) записывается поразрядно десятичное. Из 16-ти значений 4-х бит используется только 10. Но зато ты точно знаешь, что каждые 4 бита можно прямо читать и отображать как число разряда.
Это сильно упрощает логику сегментных дисплеев. Соответственно хорошо, когда процессоры поддерживают операции над такими числами, можно делать более простые устройства на их основе.

Поддержка bcd до сих пор есть в x86_64.

Отличная работа! После работы над PPSSPP было интересно прикинуть, как там живут в параллельных мирах другие эмуляторы. Кстати, рад, что воспользовались ImHex, я дофига сил отдал, чтобы он стал более-менее стабильным.

Можно ещё все это дело развернуть на черничке... Статья топ

Молодец, хорошая статья! Попробуй продолжить проект и материала наберёшь ещё не на одну статью (например узнаешь о важности точной эмуляции генерации прерываний, а уверен в некоторых играх ещё и скорости работы dma).

Кроме плагина для гидры есть плагин для иды, который ещё и отладчик. Точность у него уровня gens, но тем не менее, как работают какие-нибудь игровые штуки, полотна, спрайты и т.п. понять можно будет в рантайме.

Чот сцыль не пашет.

Если что, именно загрузчики для гидры и иды я на базе твоего старого от 6й идки делал. Было это очень давно)

Я рад, что моя работа кому-то была полезна. В свою очередь, я напомню, что:

Большое спасибо за очень интересную статью. Можно сказать подарок! Работа проделана колоссальная!

Спасибо! Z80 если что это сердце ZX Spectrum, который не приставка, а вполне себе персональный компьютер с интерпретатором бейсика, а также отдельно загружаемыми программами на ассемблере. Даже дизассемблер на нем грузил. Памяти правда на нем, насколько помню, было 32-48K...

Памяти в нем было 48K плюс 16K ROM.

Есть еще ZX Spectrum 128, в котором можно было переключением банков по 16К суммарно иметь 128K RAM, а позже появились клоны с объемом памяти вплоть до нескольких мегабайт.

Превосходная работа, спасибо!

Помимо невероятной крутости статьи и проделанной работы не могу не подметить, что приятно смотреть на современный C++ с человеческим лицом

И хорошо и не очень одновременно...

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

Просьба не воспринимать ни на чей счёт! Каждый пишет так, как ему удобнее или как он может изложить. И это не плохо!

По статье было бы желательно добавить ссылки для ознакомления: где какая информация бралась, с чего лучше всего начинать изучать информацию, ссылки на эмуляторы готовые (желательно самые простые), возможно на литературу (если она есть, а она есть на русском языке даже для изучения, ниже напишу), ну и желательно документацию - где её можно найти.

По статье, ссылок не мало, но в основном на свои ресурсы. А вот на сторонние - можно сказать мало (ну и ссылки все разбросаны по статье, с одной стороны хорошо, а с другой не очень). Информации много и не очень...

Получается что посмотреть что сделано можно, но посмотреть как это делалось - нельзя...

Вот и получается довольно двоякое мнение о статье. )))

P.S. Про книгу-то я и забыл...

Королёв А.Г., Игровые приставки, изд. ДМК, Москва, 2002.

ссылки на эмуляторы готовые (желательно самые простые)

Готовые эмуляторы в основном сами те еще раритеты годов написания этак 1995-2005 (золотой век эмуляторов давно прошел). Год назад переписывался с Sega-энтузиастом, его отзыв на то как обстоят дела с ретрохакингом:

Самое обидное в SMD-ретрохакинге — что с FOSS там очень плохо.

Gens, включая форк с выводом кишок — несвободный.
Когда-то была Kega Fusion, она просто говнище.
GPGX открытый, но несвободный, там от предыдущего автора осталась non-commercial-лицензия, и код такой из 90-х, трудно куда-то это встраивать, чтобы через год отребейзить и нифига не развалилось. Но это лучшее, что есть.
BizHawk тоже позволяет смотреть на кишки, в качестве smd core там тоже форк GPGX, но его пишут .NETеры какие-то волшебные, он без Windows не работает.

Если хочется сами игоры конструировать, то вообще все принятые сообществом ромхак-инструменты — это win-specific говнище без исходников.

ну и желательно документацию - где её можно найти.

Пробовал читать "официальную документацию Sega" (на segaretro есть), она жуткая, намного удобнее и понятнее читать неофициальные сайты - segaretro, plutiedev, rasterscroll.

Информацию про то как писать всякие штуки на C++ (в т.ч. то что использовалось для симулятора) я иногда публикую в своем канале https://t.me/cxx95 (в теле статьи о нем не упоминал, чтобы не навязывать рекламу).

Есть же BlastEm. Мультиформенный, опенсорсный, лицензия GPLv3.

Еще есть Exodus, который пусть и Windows-only, но тоже опенсорсный, MIT, и с потрясающими возможности для отладки игр.

Причем у обоих cycle accuracy из преимуществ.

Когда я слышу слово "сущность", у меня начинается когнитивный диссонанс, я не понимаю, что хотел сказать автор. Просто слово паразит, причём активный. Ну есть классы, структуры, есть объекты классов и структур. Какое определение у "сущности", в сущности?

Достаточно вспомнить, как оно будет на ангельском и сразу всё встанет на свои места. И да, это не наш, не русский метод. Но и эти языки погроммирования не мы, не русские, изобрели. Увы.

PS: Entity.

Спасибо. Просто часто встречаю применение этого термина везде и всюду. И в вэбе, и в бд, а теперь в священном Си++. И от того, что им называют всё подряд, смысл подистерся.

Ну, для себя я сделал вывод, что это новояз для обозначения "объект". Ну в парадигме ООП или даже xHDL.

Удивительные люди, которые ставят минус, но объяснить не могут. Это минусы от злости, что я прав? Ну честно кого я не спрашивал в живую что это за термин, они начинали сразу объясняться без этого термина. Подозреваю, что есть какие-то курсы, где есть чувак, вбросивший этот термин без объяснения. Филолог обыкновенус, звучит красиво и загадочно, да и пойдет. Так что ли? Просто если есть уже объяснение объекта и класса, то введение нового термина подразумевает какое-то его отличие от предыдущих. Как программист Си, привык к однозначным определениям. Википедия говорит, что сущность - это любой класс, который в будущем подразумевает сохранение в бд. Я думаю не надо плодить сущности товарищи филологи, либо дайте ссылку на нормальное определение.

Сущность — это калька с entity. По моим наблюдениям, оно употребляется в значении слова «понятие» из логики, с той поправкой, что понятиями оперирует логическое мышление человека, а вот эти самые «сущности» — концепция, совместимая и с описанием алгоритмов для машины, и с мышлением человека.

Когда человек логически мыслит в отношении чего то, ему для этого нужен понятийный аппарат, где понятия строго определены, имеют отношения род‑вид и вот это всё.

Так и тут — мы делаем некий софт, вырабатываем набор сущностей, их описание и взаимосвязи — то есть, в некотором смысле, «понятийный аппарат», которым будет «мыслить» машина, и далее уже описываем, как эти сущности должны между собой взаимодействовать.

Спасибо. Просто часто встречаю применение этого термина везде и всюду. И в вэбе, и в бд, а теперь в священном Си++. И от того, что им называют всё подряд, смысл подистерся.

Это нормально, т.к. это обобщение над классами, объектами, таблицами и прочими строительными блоками, из которых строится софт.

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

Не совсем так же. Там про "в том числе и в БД", имея в виду связи между объектами как часть сущности. Сущность действительно, как уже сказал VBDUnit, попытка обезличить (абстрагироваться от типа и других свойств) абсолютно любой автономный объект и его связи для описания фабулы. Уточнения подъезжают лишь тогда, когда в них появляется необходимость через уточняющий запрос.

PS Я думаю, что тут просто немного разниться смысл слова.

An entity is something that exists as itself. It does not need to be of material existence. In particular, abstractions and legal fictions are usually regarded as entities. In general, there is also no presumption that an entity is animate, or present.

Сущность (др.-греч.; лат. essentia, substantia) — смысл данной вещи, то, что она есть сама по себе, в отличие от всех других вещей и в отличие от изменчивых (под влиянием тех или иных обстоятельств) состояний вещи.

У нас нет уточнения "не обязательно существует физически", а для некоторых "вещь" это явно что-то физически существующее, хотя слово может применяться (и применяется) и к абстрактным вещам.

Когда я только начинал свой путь в C++, мне бы прям очень зашёл термин "сущность", который, как я понимаю, чаще всего применяется, когда не делается различий между классом или его объектом. Потому что я часто не обращал внимание о чем конкретно идёт речь. Но читая литературу тех лет, когда я начинал изучать си (2002 г), во мне выработалась четкая привычка отличать класс от объекта. В вики ещё пишут, что сущности уникальны, к примеру, каждая содержит свой уникальный id, как необходимый минимум различий. Поэтому и привязка идёт к БД. Когда начал изучать вэб, на одном из собесов меня попросили создать несколько сущностей. Конкретно там под этим подразумевалось "таблиц" БД. Это тоже был некорректный вопрос, т.к. он либо имел ввиду таблицы, либо добавить несколько "читателей" в таблицу. Как по мне, в случае данной статьи, уместнее было бы указать "класс". А сущность как абстрактная надстройка имеет свойства в виде разговорных терминов - сила, количество лет, и т.д. Когда пишут int size, то речь уже об классе и его свойстве. Я сделал вывод, что в контексте данной статьи "добавить сущность" - сделать описание класса для работы с памятью, в контексте БД, согласно Вики, добавить несколько записей в таблицу, но некоторые могут иметь ввиду создать таблицу. Оставил этот комментарий для себя в будущем.

Классы, структуры и экземпляры классов — это инструменты языка программирования. В каких-то языках таких фич, например, и нет вовсе.

Сущность же — это из понятийного аппарата человека, в отрыве от фич ЯП и абстрагируясь от специфики ЯП.

Я не понимаю, какие проблемы могут быть с восприятием термина «сущность»? Проблемы с абстрактным мышлением? Определенно, это не слово паразит. Это гипероним для множества более узко-специализированных понятий.

Сущность же — это из понятийного аппарата человека, в отрыве от фич ЯП и абстрагируясь от специфики ЯП.

Ммм, то-то я смотрю, что в англоязычных документах так любят плодить эти сущности... Особенно при описании протоколов. Многие вещи про USB и Ethernet можно описать проще и понятнее, но 100500 сущностей не просто так там появились, просто следует запомнить.

Прочитал статью как блокбастер о воскрешении 16-битной приставки! Особенно понравились подробности про VDP и подводные камни с DMA. Кстати, как насчёт поддержки 6-кнопочного геймпада? В некоторых играх он кардинально менял геймплей!

6-кнопочный сейчас поддержал в коммите, там просто муторная система для поддержки обратной совместимости с 3-кнопочным - описание на plutiedev

Проверил на игре Ultimate Mortal Kombat 3 (1996) - на скриншоте нажатие кнопки Z которая делает high kick

Автор спасибо. Когда эмуль PS4 будет готов?

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

Получается, есть и другой подход - оставлять эмулятор простым и быстрым, но взамен патчить сами игры, исправлять их баги перед запуском.

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

основную боль разработчикам доставляет то, что оригинальное железо игнорирует многочисленные некорректные действия кода игр

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

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

Нет аппаратных багов. Есть последствия упрощённой адресации и блокировка цикла шины при обращении к региону, для которого сигнал подтверждения /DTACK, необходимый для арбитража шины, не формируется. Я делал внешний формирователь и всё работало как обычно. Области, где этого сигнала нет, относятся к EXT разъёму, т.е. MegaCD и стгнал формировать должен подключенный аддон. Маленькая область относится к аддону 32х. И это всё абсолютно не должно волновать эмулятор.

т.к. контрольная сумма игры неизвестна и не применяются исправления

Заголовок ROMа в общем и контрольная сумма в частности это рекомендация от SEGA а не правило. У приставки нет встроенной ОС, которая бы следила за заголовком. Так что для неё это потеря 256 байт данных. Эмуляторы, которые проверяют контрольную сумму на самом деле не соответствуют действительности. ROM будет работать с любой информацией в заголовке.

Необходимые условия для запуска игры следующие:

  1. Корректная таблица векторов, причём важны только вектор сброса и вектора аппаратных прерываний (только 3 из 7, 1 обязательный на VBlank и 2 опциональных на HBlank и ExtInt);

  2. 4 буквы 'SEGA' по адресу 0x100 для TMSS, которая проверяет их наличие перед запуском. Это предмет копирайта и защиты от несанкционированного запуска кода. Систему ввели не сразу, поэтому этот пункт актуален только для официальных моделей приставок с некоторой версии платы (уже не помню, VA4 или VA5 для MD1). Т.е. ранние версии и пиратские клоны это игнорируют. И эмуляторам тоже следует, ибо код TMSS это объект копирайта.

Я писал про эмуляторы других консолей, конкретно PS2.

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

Это признак плохого программирования эмулятора. Является результатом того, что либо его пишет чистый программер, который далёк от железа и понимания как оно работает, либо/в том числе из-за отсутствия полной документации на железо и особенно errata, т.е. приходится реализовывать black box поведенческим методом. Посмотрите на эмуляторы денди и сеги от команды Эмураши, они на основе декапа. Они работают так как оригинальное железо. На 100%. Проблема лишь в производительности эмуляции на таком уровне, но если это загнать в ФПГА, то получится абсолютный клон.

PS CRC как ID использовался ещё для денди файлов *.nes, потому что некоторые игры используют кастомные мапперы, а некоторые мапперы имеют несколько версий, по разному себя ведущих, например ММС3 имеет версии A, B и C (прямо на маркировке чипа).

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

Есть эмулятор no$gba, где для такого случая экран удваивается.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации