Как пишется эмуляция

Эмуля́ция (англ. emulation) в вычислительной технике — комплекс программных, аппаратных средств или их сочетание, предназначенное для копирования (или эмулирования) функций одной вычислительной системы (гостя) на другой, отличной от первой, вычислительной системе (хосте) таким образом, чтобы эмулированное поведение как можно ближе соответствовало поведению оригинальной системы (гостя). Целью является максимально точное воспроизведение поведения в отличие от разных форм компьютерного моделирования, в которых имитируется поведение некоторой абстрактной модели. Например, моделирование урагана или химической реакции не является эмуляцией.

Все значения слова «эмуляция»

  • Если эмуляция прошла успешно, можно приступать к записи диска.

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

  • В данном контексте эмуляция – это имитация с целью сравняться или превзойти.

  • (все предложения)
  • виртуальная память
  • графический интерфейс пользователя
  • протокол передачи данных
  • компьютер общего назначения
  • архитектура процессора
  • (ещё синонимы…)

Русский[править]

Морфологические и синтаксические свойства[править]

падеж ед. ч. мн. ч.
Им. эмуля́ция эмуля́ции
Р. эмуля́ции эмуля́ций
Д. эмуля́ции эмуля́циям
В. эмуля́цию эмуля́ции
Тв. эмуля́цией
эмуля́циею
эмуля́циями
Пр. эмуля́ции эмуля́циях

э·муля́ци·я

Существительное, неодушевлённое, женский род, 1-е склонение (тип склонения 7a по классификации А. А. Зализняка).

Корень: -эмул-; суффикс: -яциj; окончание: .

Произношение[править]

  • МФА: [ɛmʊˈlʲat͡sɨɪ̯ə]

Семантические свойства[править]

Значение[править]

  1. книжн. желание превзойти в чём-либо друг друга, соперничество ◆ Отсутствует пример употребления (см. рекомендации).
  2. прогр. имитация функционирования одного устройства посредством другого устройства или устройств вычислительной машины, при которой имитирующее устройство воспринимает те же данные, выполняет ту же программу и достигает того же результата, что и имитируемое ◆ При работе виртуальной машины эмулируются лишь действия, связанные с вводом-выводом, в то время как простые «вычислительные» команды программ выполняются прямо на процессоре, то есть без многократной потери быстродействия, присущей обычной эмуляции. «Вычислительная инфраструктура для прикладных задач ― будущее и настоящее» // «Геоинформатика», 30 июня 2004 г. [НКРЯ]

Синонимы[править]

  1. соперничество, конкуренция

Антонимы[править]

Гиперонимы[править]

Гипонимы[править]

Родственные слова[править]

Ближайшее родство
  • существительные: эмулятор
  • глаголы: эмулировать, эмулироваться

Этимология[править]

Происходит от англ. emulation «соревнование; состязание; соперничество», далее от ??

Фразеологизмы и устойчивые сочетания[править]

Перевод[править]

Список переводов

Библиография[править]

эмуляция

эмуляция

эмул’яция, -и

Русский орфографический словарь. / Российская академия наук. Ин-т рус. яз. им. В. В. Виноградова. — М.: «Азбуковник».
.
1999.

Синонимы:

Смотреть что такое «эмуляция» в других словарях:

  • Эмуляция — имитация работы одной системы средствами другой без потери функциональных возможностей и искажений результатов. Эмуляция выполняется программными и/или аппаратными средствами. См. также: Исполнение программ Финансовый словарь Финам …   Финансовый словарь

  • эмуляция — Имитация функционирования одного устройства посредством другого устройства или устройств вычислительной машины, при которой имитирующее устройство воспринимает те же данные, выполняет ту же программу и достигает того же результата, что и… …   Справочник технического переводчика

  • ЭМУЛЯЦИЯ — [англ. emulation соревнование, соперничество] соперничество, конкуренция, желание перещеголять кого л. Словарь иностранных слов. Комлев Н.Г., 2006 …   Словарь иностранных слов русского языка

  • эмуляция — сущ., кол во синонимов: 3 • конкуренция (8) • подражание (25) • соперничество (21) …   Словарь синонимов

  • эмуляция — и, ж. émulation f. См. Эмюляция …   Исторический словарь галлицизмов русского языка

  • Эмуляция — DOSBox эмулирует работу DOS …   Википедия

  • эмуляция — emuliacija statusas T sritis automatika atitikmenys: angl. emulation vok. Emulation, f rus. эмуляция, f pranc. émulation, f …   Automatikos terminų žodynas

  • Эмуляция — 53. Эмуляция Emulation Имитация функционирования одного устройства посредством другого устройства или устройств вычислительной машины, при которой имитирующее устройство воспринимает те же данные, выполняет ту же программу и достигает того же… …   Словарь-справочник терминов нормативно-технической документации

  • эмуляция LAN — Технология, обеспечивающая возможность прозрачного подключения к сети ATM рабочих станций локальных сетей, использующих традиционные протоколы доступа. Для этого в процедуре подключения используется эмуляция всех основных функций подуровня MAC… …   Справочник технического переводчика

  • эмуляция ЛВС — Набор протоколов, разработанных ATM Forum, которые позволяют эмулировать в сети ATM услуги, обеспечиваемые традиционными ЛВС. Эмуляция ЛВС требуется из за того, что сети ATM ориентированы на организацию соединений и, следовательно, могут… …   Справочник технического переводчика

  • эмуляция ТфОП/ЦСИС — Определяет возможности и интерфейсы служб КТСОП/ЦСИС, используя адаптацию к инфраструктуре IP. Примечание Не все возможности и интерфейсы служб должны быть представлены для обеспечения эмуляции. (МСЭ T Y.2271) [http://www.iks… …   Справочник технического переводчика

Написание слова

Эмуляция — в слове после «ц» пишется буква «и», так как по правилам русского языка предусмотрено написание в словах после «ц» буквы «и», кроме окончаний слов (птицы, овцы) и в суффиксе «ын» (сестрицын, куницын).

Примеры употребления

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

Нашли ошибку? Выделите фрагмент текста и нажмите одновременно «левый Ctrl»+«Enter».

Здравствуйте!

Не так давно на Хабре появилась статья о создании эмулятора chip-8, благодаря которой удалось хотя бы поверхностно понять, как пишутся эмуляторы. После реализации своего эмулятора появилось желание пойти дальше. Выбор пал на оригинальный Gameboy. Как оказалось, выбор был идеальным для ситуации, когда хочется реализовать что-то более серьезное, а опыт разработки эмуляторов практически отсутствует.

С точки зрения эмуляции Gameboy относительно прост, но даже он требует изучения достаточно большого объема информации. По этой причине разработке эмулятора Gameboy будет посвящено несколько статей. Конечным итогом будет эмулятор с неплохой совместимостью, поддержкой практически всех функций оригинала, в том числе звука, который нередко отсутствует в других эмуляторах. В качестве бонуса наш эмулятор будет проходить практически все тестовые ROM’ы, но об этом позже.

Данные статьи не будут содержать исчерпывающего описания реализации эмулятора. Это слишком объемно, да и весь интерес от реализации пропадает. До конкретного кода будет доходить лишь в редких случаях. Перед собой я ставил задачу дать в большей степени теоретическое описание с небольшими намеками на реализацию, что, в идеале, должно позволить вам без особых затруднений написать свой эмулятор и в тоже время чувствовать, что вы написали его самостоятельно. Где надо я буду ссылаться на собственную реализацию – при необходимости вы сможете найти нужный код без того, чтобы продираться через тонны строк кода.

В данной статье мы познакомимся с Gameboy и начнем с эмуляции его процессора и памяти.

Пишем эмулятор Gameboy, часть 1
Пишем эмулятор Gameboy, часть 2
Пишем эмулятор Gameboy, часть 3

Оглавление

Введение
Архитектура
Процессор
Прерывания
Память
Заключение

Введение


Gameboy – портативная консоль Nintendo, выпуск которой начался в 1989 году. Речь пойдет именно об оригинальном черно-белом Gameboy. Стоит заметить, что в различных документах, которыми мы будем руководствоваться, используется кодовое название Gameboy – DMG(Dot Matrix Game). Далее я буду использовать именно его.

Перед тем как приступить, необходимо ознакомиться с техническими характеристиками DMG:

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

Для DMG существует замечательный документ под названием Gameboy CPU Manual. Он включает в себя несколько известных документов от именитых разработчиков и содержит практически всю необходимую нам информацию. Естественно это не все, но на данном этапе этого более чем достаточно.

Сразу предупреждаю, что в документах будут ошибки, даже в официальных. В течение данного цикла статей я постараюсь упомянуть все недочеты различных документов какие смог найти (вспомнить). Так же постараюсь восполнить многие пробелы. Суть в том, что для DMG не существует исчерпывающего описания. Доступные материалы дают лишь поверхностное представление о работе многих узлов консоли. Если программист не в курсе таких «подводных камней», то разработка эмулятора станет намного сложнее, чем она могла бы быть. DMG достаточно прост, когда на руках достоверная и подробная информация. И проблема в том, что многие важные детали можно почерпнуть только из исходного кода других эмуляторов, что, тем не менее, не делает нашу задачу проще. Код известных эмуляторов или излишне сложен (Gambatte), или представляет собой жуткое нагромождение, кхм, низкокачественного кода (Visual Boy Advance – смотреть без слез на его код невозможно).

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

Архитектура

Начнем с архитектуры будущего эмулятора. Для эмуляции DMG нам придется реализовать множество модулей, которые практически независимы друг от друга. В подобных условиях было бы глупо идти напролом, складывая все в одну кучу (что нередко наблюдается в других эмуляторах. Привет VBA). Более элегантным решением является реализация отдельных частей DMG как отдельных классов, эмулирующих свои части железа.

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

Итак, приступим.

Процессор

DMG содержит 8-битный процессор Sharp LR35902, работающий на частоте 4194304 Гц (не стоит удивляться такой точности – это число понадобится нам в будущем). Можно считать его упрощенной версией процессора Zilog Z80, который, в свою очередь, основан на Intel 8080. По сравнению с Z80 отсутствуют некоторые регистры и наборы инструкций.

Процессор содержит восемь 8-битных регистров A, B, C, D, E, F, H, L и два 16-битных регистра специального назначения — PC и SP. Некоторые инструкции позволяют объединять 8-битные регистры и использовать их как 16-битные регистры, а именно AF, BC, DE, HL. Например, регистр BC представляет собой «склеенные» регистры B и C, где регистр C исполняет роль младшего байта, а B – старшего.
Регистры A, B, C, D, E, H, L являются регистрами общего назначения. Регистр A так же является и аккумулятором. Регистр F содержит флаги процессора и напрямую недоступен. Ниже приведена схема регистра. Биты от 0 до 3 не используются.

Назначение флагов:

  • Zero Flag (Z) – флаг установлен (бит равен 1), если результат последней математической операции равен нулю или два операнда оказались равными при сравнении.
  • Substract Flag (N) – флаг установлен, если последней операцией было вычитание.
  • Half Carry Flag (H) – флаг установлен, если в результате последней математической операции произошел перенос из младшего полу-байта.
  • Carry Flag (С) – флаг установлен, если в результате последней математической операции произошел перенос.

Регистр PC (program counter), как несложно догадаться, является счетчиком инструкций и содержит адрес следующей инструкции.

Регистр SP (stack pointer), соответственно, является указателем на вершину стека. Для тех, кто не в курсе, стек это область памяти, в которую записываются значения переменных, адреса возврата и прочее. SP содержит адрес вершины стека – стек растет вниз, от старших адресов к младшим. Для него всегда существует как минимум две операции. PUSH позволяет вставить некое значение – сначала регистр SP уменьшается, а затем происходит вставка нового значения. POP позволяет извлечь значение – сначала по адресу SP значение извлекается из памяти, а затем SP увеличивается.

Так же процессор содержит так называемый IME (interrupt master enable) – флаг, который разрешает обработку прерываний. Принимает, соответственно, два значения – запретить (0) и разрешить (1).

С теорией все, можно приступать к реализации. Поскольку нам придется работать как с 8-битными регистрами, так и с их 16-битными парами, то целесообразно реализовать механизм, который позволяет иметь одновременный доступ и к тем, и к тем без необходимости использовать битовые операции. Для этого объявим следующий тип:

union WordRegister
{
	struct
	{
		BYTE L;
		BYTE H;
	} bytes;
	WORD word;
}; 

Регистры процессора будем хранить как пары, а к отдельным частям будем иметь доступ благодаря объединению WordRegister. Поле «word» даст доступ ко всему 16-битному регистру. Поле «bytes» дает доступ к отдельным регистрам в паре. Единственное, регистры А и F стоит хранить отдельно. Регистр А является аккумулятором, а значит используется очень часто. Похожая ситуация с регистром F – флаги процессора приходится устанавливать довольно часто.

Теперь приступим к реализации собственно процессора – за это будет отвечать класс Cookieboy::CPU. Чтение и исполнение инструкций будет реализовано по обычной схеме – чтение опкода из памяти, а затем декодирование и исполнение посредством конструкции switch:

BYTE opcode = MMC.Read(PC);
PC++;

switch (opcode)
{
case 0x00:
    break;
}

Все опкоды имеют длину 1 байт, но некоторые инструкции используют так называемый префикс – первым байтом идет префикс набора инструкций (для нас единственный префикс это 0xCB), вторым байтом идет собственно опкод из этого набора. Реализация элементарная – как только мы наткнулись на 0xCB, то читаем еще один байт и декодируем его вложенным switch.

Данный код помещается в функцию void Step(), которая за один вызов исполняет одну инструкцию процессора и производит другие необходимые операции.

Естественно для чтения и записи в память нам понадобится другой класс – Cookieboy::Memory, объект которого можно видеть выше под именем «MMC». На данном этапе достаточно заглушки с основными методами:

class Memory
{
public:
	void Write(WORD addr, BYTE value);
	BYTE Read(WORD addr);
};

Процессор DMG имеет достаточно большое число инструкций, список которых можно найти в Gameboy CPU Manual. Там же указано, какие флаги процессора необходимо устанавливать и сколько тактов занимает исполнение каждой инструкции. ОЧЕНЬ внимательно читайте описание флагов – неправильно реализованная установка флагов нередко приводит к неработоспособности игр, а отладка превращается в пытку. Но спешу немного успокоить – существует тестовые ROM’ы для флагов процессора, но до исполнения ROM’ов нам еще далеко.

К слову о тактах. Если chip-8 был достаточно прост, и его эмуляция не требовала учета длительности исполнения инструкций, то c DMG дело обстоит иначе. Компоненты консоли работают не абы как, а синхронизированы с помощью генератора тактовой частоты. Для нас это означает то, что нам необходимо синхронизировать работу всех компонентов нашего эмулятора с процессором.

Решить эту проблему достаточно просто. Процессор является центральным звеном нашего эмулятора. Исполнив инструкцию, мы передаем другим компонентам затраченное процессором время в тактах для синхронизации всех компонентов между собой. Для этого я используют макрос SYNC_WITH_CPU(clockDelta), в который и передается затраченное процессором время на исполнение инструкции. Он уже вызывает функции синхронизации остальных компонентов эмулятора. Решение проблемы синхронизации можно было бы легко вынести за пределы класса процессора, если бы не одно но.

Компоненты консоли работают одновременно, никто не ждет, пока процессор закончит исполнение инструкции, как это делаем мы. Некоторые инструкции требует длительного времени на исполнение и в процессе происходит чтение и запись данных в память. Процессор, как можно догадаться, тратит определенное время на чтение/запись в память (4 такта). Это приводит к тому, что в процессе исполнения содержимое памяти может измениться, что, естественно, неплохо было бы тоже эмулировать.

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

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

А теперь немного отвлечемся, чтобы прояснить ситуацию с тактами. В различной документации наблюдается путаница. Некоторые документы пишут такие числа, что, например, NOP имеет длительность 4 такта, другие – 1 такт (так, например, написано в официальной документации Nintendo). Для понимания причины стоит немного отвлечься на теорию.

Любая инструкция процессора имеет определенную длительность, которую назовем машинный цикл. За один машинный цикл процессор может произвести одно действие от и до, как например чтение опкода, его декодирование и исполнение команды; чтение или запись значения в памяти. В свою очередь, машинный цикл состоит из машинных тактов, поскольку за один машинный цикл процессор может совершить несколько операций. И вот мы приходим к нашему процессору. Если мы говорим, что NOP длится 4 такта, то мы говорим о машинных тактах. Если мы говорим об 1 такте для NOP, то мы говорим о машинных циклах. Процессор DMG именно так и работает – его машинный цикл длится 4 машинных такта и многие инструкции имеют длительность ровно 4 такта или 1 машинный цикл – процессор DMG способен прочитать опкод из памяти, декодировать его и исполнить инструкцию всего за 4 машинных такта.

Здесь и далее я буду использовать более привычные машинные такты. Именно они соответствуют одному периоду тактового генератора, а значит, являются минимальной и неделимой единицей времени для нашего эмулятора. Таким образом, операция NOP будет длиться 4 такта.

На данном этапе уже можно полностью реализовать эмуляцию всех команд процессора. Отдельно стоит упомянуть некоторые из них:

  • HALT имеет достаточно интересное поведение, которое описано в CPU Manual (2.7.3. Low-Power Mode). Решение в лоб приведет к тому, что тест инструкции HALT не будет пройден. Здесь нужно быть внимательным как в реализации самой инструкции, так и в реализации обработчика прерываний (об этом далее). Реализация инструкции такова, что она не приостанавливает исполнение и приводит к упомянутому багу только в том случае, если IME равен нулю и в данный момент нет прерываний, которые необходимо обработать (об этом так же далее) – именно последний момент опущен в большинстве документов. В противном случае бага нет, и исполнение приостанавливается. Естественно, тактовый генератор и все остальные компоненты продолжают свою работу, а значит надо продолжать вызывать функции синхронизации, давая в качестве аргумента 4 такта (нет смысла считать в этом режиме по одному такту). Как будто процессор исполняет NOP.
  • В POP AF стоит учесть тот факт, что в регистре F есть неиспользуемые биты. Для этого необходимо обнулить младшие 4 бита регистра F после того, как его содержимое будет извлечено из стека.
  • Инструкции RLCA, RLA, RRCA, RRA всегда обнуляют флаг Z в регистре F.

Помимо этих недочетов есть и другие. CPU Manual содержит неполное описание длительности инструкций. Как можно догадаться, инструкции условных переходов должны иметь разную длительность в зависимости от того, произошел переход или нет. Можно было бы воспользоваться тестовыми ROM’ми, но они неправильно работают сами по себе из-за этих инструкций, поэтому выводят неизвестную ошибку даже не начав тестирование. Вот таблица этих инструкций с указанием их длительности:

Так же для инструкций RST n (опкоды 0xC7, 0xCF, 0xD7, 0xDF, 0xE7, 0xEF, 0xF7, 0xFF) указана неправильная длительность. Правильное значение равно 16 тактам.

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

Прерывания

Прерывание – это событие, которое приостанавливает исполнение текущих инструкций процессора и передает управление обработчику прерывания. DMG работает именно по такому принципу.

В ходе синхронизации мы вызываем методы синхронизации других компонентов эмулятора, которые могут запросить прерывание. В DMG это осуществляется следующим образом. Существует два регистра (где они находятся будет рассмотрено далее) – IF (interrupt flags) и IE (interrupt enable). Их биты имеют определенное назначение, которое идентично в обоих регистрах:

Биты регистра IF показывают, какие прерывания были запрошены. Если бит установлен, то прерывание запрошено.

Биты регистра IE разрешают обработку прерываний. Если бит установлен в единицу и соответствующее прерывание было запрошено, то оно будет обработано. Если нет, то прерывание обработано не будет.

Как видно, идентичное назначение битов очень кстати и позволяет с помощью логической операции И узнать, какие прерывания следует обработать.

Одна важная деталь состоит в том, что прерывание выводит процессор из состояния останова, произошедшее в результате исполнения HALT или STOP. И здесь очень важен алгоритм, по которому проверяются регистры прерываний. Алгоритм таков:

  1. Проверяем, есть ли вообще прерывания, которые стоит обработать. Делается это с помощью операции логического И между регистрами IE и IF. Дополнительно стоит произвести операцию логического И с результатом и числом 0x1F для удаления возможного мусора, поскольку старшие три бита не используются в обоих регистрах.
  2. Если таких прерываний нет, то выходим из функции. Если же они есть, то именно сейчас мы должны вывести процессор из состояния останова.
  3. Теперь мы приступаем к обработке прерываний. Для этого мы проверяем, не запрещает ли флаг IME их обработку. Если нет, то:
    1. обнуляем IME;
    2. загружаем регистр PC в стек;
    3. вызываем обработчик прерывания путем установки регистра PC равному адресу обработчика в памяти;
    4. обнуляем бит регистра IF соответственно обработанному прерыванию.

Прерывания обрабатываются по одному за раз и в строго определенном порядке. Вся информация о приоритетах и адресах обработчиков указана в CPU Manual.

Важная деталь. Опять же, кому-то уже могла прийти в голову мысль – обработка прерывания очень похожа на вызов процедуры, а значит должна занимать какое-то время. Это действительно так и занимает она 20 тактов. По какой-то причине этот момент опущен в документах, описывающих DMG.

Теперь приступаем к реализации. Прерываниями у нас будет заниматься класс Cookieboy::Interrupts. В него мы помещаем регистры IE и IF и объявляем функции для доступа к этим регистрам (они понадобятся нам позже), а так же функцию, которая позволяет запросить определенное прерывание (нам же не хочется каждый раз манипулировать битами, чтобы запросить какое-то прерывание). Так же нам понадобится функция, которая будет проверять, какие прерывания стоит обработать. Помещаем вызов этой функции в конце функции Step процессора и дополнительно синхронизируем компоненты.

Немного про запрос прерываний. Он осуществляется установкой в регистре IF соответствующих битов. Перед установкой проверка регистра IE не требуется. Даже если биты в нем запрещают конкретное прерывание, мы все равно устанавливается биты в IF регистре для этого прерывания.

Если вы смотрели исходный код моей реализации Cookieboy::Interrupts, то могли заметить, что я возвращаю значение регистров IE и IF после того, как установлю в единицу все неиспользуемые в них биты (операция ИЛИ со значением 0xE0). Делаю я это не просто так. Многие регистры в I/O ports (об этом чуть ниже) используют не все биты, другие ограничивают доступ на чтение к некоторым битам или ко всему регистру сразу. Это так же необходимо учитывать – для этого неиспользуемые и запрещенные для чтения биты стоит установить в 1 перед возвращением.

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

Память

Заранее определимся с одним термином – банк памяти. Под этим понимается область памяти строго определенного размера. Существует два вида банков – ROM банки, имеющие длину 0x4000 байт, и RAM банки, имеющие длину 0x2000 (стоит сразу привыкнуть к 16-ричной системе счисления, так будет проще и мне, и вам). Зачем это нужно? Процессор DMG способен работать с 16-битным адресами, а значит адресное пространство ограничено 0x10000 байтам. Из них только 0x8000 байт отведено на образ игры. В большинстве случаев этого недостаточно и в ход вступают банки памяти.

Обращаясь по адресам 0x4000-0x7FFF, без банков памяти мы бы попали именно по этому адресу в образе игры. С помощью банков памяти мы можем установить так, чтобы образ был поделен на банки, а по адресу 0x4000-0x7FFF был отображен выбранный банк. Таким образом, в один момент в этой области находится второй банк, в другой – десятый. Как мы захотим, в общем. Таким образом, мы приходим к виртуальным и физическим адресам. 0x4000-0x7FFF – это виртуальные адреса, которые не обязаны совпадать с физическими. Физический адрес – это настоящий адрес, по которому происходит доступ к ячейкам памяти.

Все это необходимо для того, чтобы наш DMG мог работать с образами игры, которые намного превышают не только 0x8000 байт, но и все адресное пространство. На словах это все может показаться слишком сложным, но в ходе реализации будет понятно, что это предельно элементарные вещи, которые проще и быстрее реализовать, чем объяснить.

Все тоже самое относится и к оперативной памяти. Банки позволяют расширить ее объем, поместив микросхемы в картридж. Кроме того, так можно реализовать полноценную систему сохранений, используя встроенный в картридж аккумулятор для питания оперативной памяти.

Задача перевода виртуального адреса в физический лежит на MBC-контроллере, который находится внутри картриджа. Все операции чтения и записи в области ROM’а проходят через него. Так же сюда перенаправляются операции, связанные с внешней оперативной памятью.

Естественно мы не может изменить содержимое ROM. Операции записи используются как управляющие команды для MBC. В CPU Manual можно прочитать, какие адреса, за какие функции отвечают. Таким образом, записав по определенному адресу число 9, мы говорим, что хотим выбрать банк 9. После этого мы можем читать его содержимое, обращаясь по адресам 0x4000-0x7FFF.

На рисунке ниже представлена простейшая схема работы MBC. Здесь область 0x0000-0x3FFF всегда перенаправляется в банк 0, как в некоторых реальных контроллерах, а вот область 0x4000-0x7FFF перенаправляется в текущий банк.

Рассмотрим схему адресного пространства DMG:

Подробнее о каждой секции:

  • ROM bank 0. Switchable ROM bank. Данные области мы уже рассмотрели.
  • Video RAM. Подробнее будет рассмотрена при реализации графики.
  • Internal RAM 1. Оперативная память внутри DMG.
  • Echo of Internal RAM 1. Здесь дублируется содержимое Internal RAM 1.
  • OAM. Здесь хранится описание спрайтов.
  • I/O ports. Здесь мы получаем доступ к регистрам других компонентов DMG.
  • Internal RAM 2. Оперативная память внутри DMG.
  • Interrupt enable register. В этом регистре хранятся флаги, которые разрешают обработку определенных прерываний. Это тот самый регистр IE, о котором мы уже говорили.

Поскольку архитектура эмулятора предполагает, что каждый компонент DMG будет иметь свой класс, то класс Cookieboy::Memory, эмулирующий память, будет содержать лишь следующие области памяти – ROM банки, internal RAM 1, Echo of internal RAM 1, Switchable RAM bank, internal RAM 2. При обращении ко всем другим областям будут вызываться методы доступа соответствующих классов.

Начнем с операций чтения и записи в памяти. Все предельно просто – смотрим на адрес и перенаправляем операции в соответствующие области памяти. Я сделал следующим образом. Как можно заметить, многие области памяти хорошо выравнены, что позволяет реализовать все с помощью switch и логических операций. Вот как это выглядит:

switch (addr & 0xF000)
{
case 0x8000:
case 0x9000:
	//осуществляем операции с видеопамятью
	break;
}

И никаких громоздких условных конструкций. Пока можно оставить лишь заготовку, поскольку некоторые области памяти будут находиться в других классах (например, видеопамять), которые мы еще не реализовали. Можно лишь реализовать то, что действительно есть в Cookieboy::Memory. Здесь стоит обратить внимание на банки ROM’а и Switchable RAM bank.

Если картридж, с которого был снят ROM, содержал MBC-контроллер, то в этих областях памяти нам надо реализовать логику этих контроллеров. Для этого можно поступить очень просто – доступ к этим областям перенаправляется в классы, которые реализуют соответствующие MBC-контроллеры, а они уже сами пусть решают, куда, как и что. Рассмотрим два примера – MBC 2 и MMM01. Первый – как пример, который позволит вам реализовать остальное. MMM01 – довольно странный MBC. По нему практически нет документации, а его реализация довольно сильно отличается от других MBC. Не повредит восполнить этот пробел в деле эмуляции DMG.

Для начала обзаведемся базовым классом MBC. Выглядеть он будет следующим образом:

const int ROMBankSize = 0x4000;
const int RAMBankSize = 0x2000;

class MBC
{
public:
	virtual void Write(WORD addr, BYTE value) = 0;
	virtual BYTE Read(WORD addr) = 0;
	
	virtual bool SaveRAM(const char *path, DWORD RAMSize);

	virtual bool LoadRAM(const char *path, DWORD RAMSize);

protected:
	MBC(BYTE *ROM, DWORD ROMSize, BYTE *RAMBanks, DWORD RAMSize) : ROM(ROM), ROMSize(ROMSize), RAMBanks(RAMBanks), RAMSize(RAMSize) {}

	BYTE *ROM;
	BYTE *RAMBanks;

	DWORD ROMOffset;
	DWORD RAMOffset;

	DWORD ROMSize;
	DWORD RAMSize;
};

Как видно, сначала идут функции записи и чтения – именно они будут вызываться из нашего Cookieboy::Memory. Далее идут функции сохранения и загрузки RAM. Тут мы сразу готовим почву для будущей эмуляции памяти в картридже, которая запитана от аккумулятора для сохранения ее содержимого после выключения консоли. Их реализацию я опущу – это всего лишь сохранение и чтение массива RAMBanks из файла, не более. Затем предельно очевидный конструктор и несколько полей:

  • ROM. Здесь у нас находится весь образ игры.
  • RAMBanks. Здесь находится оперативная память картриджа.
  • RAMOffset и ROMOffset. Это смещения, которые указывают на текущий банк памяти.
  • ROMSize и RAMSize, думаю, не требуют пояснений. Значения хранятся в банках памяти, а не в байтах.

С базовым классом покончено, теперь приступим к реализации класса, который эмулирует MBC2. Сразу посмотрим на код, а затем уже разберемся, как работает этот контроллер:

class MBC2 : public MBC
{
public:
	MBC2(BYTE *ROM, DWORD ROMSize, BYTE *RAMBanks, DWORD RAMSize) : MBC(ROM, ROMSize, RAMBanks, RAMSize)
	{
		ROMOffset = ROMBankSize;
		RAMOffset = 0;
	}

	virtual void Write(WORD addr, BYTE value)
	{
		switch (addr & 0xF000)
		{
		//ROM bank switching
		case 0x2000:
		case 0x3000:
			ROMOffset = value & 0xF;
			ROMOffset %= ROMSize;

			if (ROMOffset == 0)
			{
				ROMOffset = 1;
			}

			ROMOffset *= ROMBankSize;
			break;

		//RAM bank 0
		case 0xA000:
		case 0xB000:
			RAMBanks[addr - 0xA000] = value & 0xF;
			break;
		}
	}

	virtual BYTE Read(WORD addr)
	{
		switch (addr & 0xF000)
		{
		//ROM bank 0
		case 0x0000:
		case 0x1000:
		case 0x2000:
		case 0x3000:
			return ROM[addr];

		//ROM bank 1
		case 0x4000:
		case 0x5000:
		case 0x6000:
		case 0x7000:
			return ROM[ROMOffset + (addr - 0x4000)];

		//RAM bank 0
		case 0xA000:
		case 0xB000:
			return RAMBanks[addr - 0xA000] & 0xF;
		}

		return 0xFF;
	}
};

С функцией чтения все просто. ROMOffset используется как смещение для обращения к текущему банку ROM. С оперативной памятью есть одна деталь. MBC2 имеет 512 4-битовых блоков RAM. Мы, естественно, выделяем все 512 байт, просто операции записи и чтения обрезают значения до 4 младших бит.

Теперь функция записи. Именно здесь эмулируется логика MBC. MBC2 поддерживает только смену банков ROM. Меняются они с помощью записи номера банка длиной 4 бита в область адресов 0x2000-0x3FFF. Нулевой банк выбрать нельзя, т.к. он и так находится в 0x0000-0x3FFF. Здесь же стоит проверять выход за границы ROM. Некоторые игры по неопределенной причине пытаются выбрать банк, которого не существует. Это, естественно, приводит к ошибке. С проверкой игра работает, как ни в чем не бывало. Одной из таких игр является WordZap. Может это последствия неточной эмуляции (на идеальную эмуляцию DMG я, естественно, не претендую), но в любом случае проверка не повредит.

Да, 0xFF возвращается не случайно – на DMG данное значение возвращается в случае, когда содержимое не определено.

Наконец, рассмотрим MMM01. Я не уверен в правильности своего кода, поскольку описание этого контроллера было найдено на форуме, а само оно написано неизвестно кем. Код:

class MBC_MMM01 : public MBC
{
public:
	enum MMM01ModesEnum
	{
		MMM01MODE_ROMONLY = 0,
		MMM01MODE_BANKING = 1
	};

	MBC_MMM01(BYTE *ROM, DWORD ROMSize, BYTE *RAMBanks, DWORD RAMSize) : MBC(ROM, ROMSize, RAMBanks, RAMSize)
	{
		ROMOffset = ROMBankSize;
		RAMOffset = 0;
		RAMEnabled = false;
		Mode = MMM01MODE_ROMONLY;
		ROMBase = 0x0;
	}

	virtual void Write(WORD addr, BYTE value)
	{
		switch (addr & 0xF000)
		{
		//Modes switching
		case 0x0000:
		case 0x1000:
			if (Mode == MMM01MODE_ROMONLY)
			{
				Mode = MMM01MODE_BANKING;
			}
			else
			{
				RAMEnabled = (value & 0x0F) == 0x0A;
			}
			break;

		//ROM bank switching
		case 0x2000:
		case 0x3000:
			if (Mode == MMM01MODE_ROMONLY)
			{
				ROMBase = value & 0x3F;
				ROMBase %= ROMSize - 2;
				ROMBase *= ROMBankSize;
			}
			else
			{
				if (value + ROMBase / ROMBankSize > ROMSize - 3)
				{
					value = (ROMSize - 3 - ROMBase / ROMBankSize) & 0xFF;
				}

				ROMOffset = value * ROMBankSize;
			}
			break;

		//RAM bank switching in banking mode
		case 0x4000:
		case 0x5000:
			if (Mode == MMM01MODE_BANKING)
			{
				value %= RAMSize;
				RAMOffset = value * RAMBankSize;
			}
			break;
		//Switchable RAM bank
		case 0xA000:
		case 0xB000:
			if (RAMEnabled)
			{
				RAMBanks[RAMOffset + (addr - 0xA000)] = value;
			}
			break;
		}
	}

	virtual BYTE Read(WORD addr)
	{
		if (Mode == MMM01MODE_ROMONLY)
		{
			switch (addr & 0xF000)
			{
			//ROM bank 0
			case 0x0000:
			case 0x1000:
			case 0x2000:
			case 0x3000:
			//ROM bank 1
			case 0x4000:
			case 0x5000:
			case 0x6000:
			case 0x7000:
				return ROM[addr];

			//Switchable RAM bank
			case 0xA000:
			case 0xB000:
				if (RAMEnabled)
				{
					return RAMBanks[RAMOffset + (addr - 0xA000)];
				}
			}
		}
		else
		{
			switch (addr & 0xF000)
			{
			//ROM bank 0
			case 0x0000:
			case 0x1000:
			case 0x2000:
			case 0x3000:
				return ROM[ROMBankSize * 2 + ROMBase + addr];

			//ROM bank 1
			case 0x4000:
			case 0x5000:
			case 0x6000:
			case 0x7000:
				return ROM[ROMBankSize * 2 + ROMBase + ROMOffset + (addr - 0x4000)];

			//Switchable RAM bank
			case 0xA000:
			case 0xB000:
				if (RAMEnabled)
				{
					return RAMBanks[RAMOffset + (addr - 0xA000)];
				}
			}
		}

		return 0xFF;
	}

private:
	bool RAMEnabled;
	MMM01ModesEnum Mode;	
	DWORD ROMBase;
};

Как видите, кода много. Не буду объяснять каждую строчку – после предыдущего примера я надеюсь, что вам не составит труда понять, что и зачем делается. Скажу лишь, что MMM01 вроде бы используется всего в 2 играх, поэтому не случайно он есть далеко не во всех эмуляторах.

Возвращаясь к эмуляции памяти, стоит немного прояснить область памяти под названием I/O ports. Т.к. DMG состоит из различных компонентов, то неплохо бы иметь возможность как-то влиять на их работу и даже контролировать. Для этого в области памяти I/O ports мы имеем доступ к регистрам всех остальных компонентов DMG: контроллер экрана, звук, таймеры, управление и т.д. Естественно, все эти регистры в нашем эмуляторе будут находиться в соответствующих классах, а значит Cookieboy::Memory будет лишь перенаправлять все операции в них. Список и назначение всех регистров можно найти в CPU Manual. Так же я буду рассматривать их при необходимости. Кстати, один из них мы уже рассмотрели – IF. Этот регистр доступен именно в этой области памяти, поэтому необходимо перенаправить операции чтения и записи в класс Cookieboy::Interrupts. Мы уже можем это сделать, т.к. обеспокоились об этом заранее при рассмотрении прерываний.

Настало время еще одной важной функции – загрузки ROM из файла. Перед реализацией загрузки образа в память самое время упомянуть, что же происходит при включении DMG.

Сначала идет исполнение Bootstrap ROM’а, который хранится внутри DMG. Его содержимое можно найти в исходном коде класса Cookieboy::Memory. Он не делает ничего особенного, кроме проверки содержимого картриджа и отображения лого Nintendo. Он имеет длину 256 байт, исполнение начинается с 0 – т.е. после включения регистр PC процессора равен нулю. Его исполнение заканчивается командой, которая осуществляется запись по адресу 0xFF50. По этому адресу находится скрытый регистр, который указывает, откуда в данный момент поступают команды для процессора – из Bootstrap ROM’а или картриджа. Как ни странно, описания этого регистра нет практически нигде. Более того, нет даже упоминаний о нем.

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

Замечу, что при включении оперативная память DMG и картриджа содержит случайные числа. Это незначительная деталь, поэтому обычно эмуляторы заполняют эти области нулями. Как поступать – решать вам. Скорее всего, лучше или хуже от этого игры работать не станут. Учтите, речь только об оперативной памяти. Заполнение случайными значениями других областей приведет к некорректной работе эмулятора.

Конечно, не хотелось бы каждый раз запускать этот образ. Для этого можно сделать следующее. Регистр PC должен быть равен 0x100 – именно по этому адресу находится первая команда в образах игр. Далее, все регистры процессора и область памяти I/O ports необходимо проинициализировать значениями, которые оставляет после себя Bootstrap ROM – эти значения можно найти в CPU Manual. Не все игры настолько хорошо написаны, чтобы устанавливать все необходимые значения самостоятельно, некоторые могут полагаться на значения, которые установлены после выполнения Bootstrap ROM. Для этого все компоненты содержат функцию EmulateBIOS, посредством которой устанавливаются все необходимые значения.

И так, приступим к загрузке обараза. Весь файл образа читается в массив, а из заголовочной части образа читаются метаданные образа. Самое важное это узнать тип картриджа (тип MBC-контроллера) и размер внешней оперативной памяти внутри картриджа. Адреса указаны в CPU Manual. Так же стоит реализовать те проверки, которые делает Bootstrap ROM. С помощью них можно легко узнать, действительно ли файл является образом для DMG. Первая проверка – лого Nintendo. Каждый ROM содержит логотип Nintendo, который и отображается при выполнении Bootstrap ROM. Он должен иметь строго определенное значение. Какое – указано в CPU Manual. Так же можно проверить контрольную сумму заголовка образа. Для этого можно воспользоваться следующим кодом:

BYTE Complement = 0;
for (int i = 0x134; i <= 0x14C; i++)
{
	Complement = Complement - ROM[i] - 1; 
}
if (Complement != ROM[0x14D])
{
	//проверка не пройдена 
}

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

Касательно оперативной памяти картриджа, то неплохо всегда иметь под рукой как минимум один банк памяти, даже если образ «говорит», что она не используется. Некоторые игры выдают себя за картриджи без MBС, но, тем не менее, могут иметь простенький чип лишь для оперативной памяти.

Все, с памятью покончено.

Заключение

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

Значение слова «ЭМУЛЯЦИЯ» найдено в 25 источниках

ЭМУЛЯЦИЯ

эмуляция
сущ., кол-во синонимов: 3
• конкуренция (8)
• подражание (25)
• соперничество (21)
Словарь синонимов ASIS.В.Н. Тришин.2013.
.
Синонимы:
конкуренция, подражание, соперничество

Эмуляция (Emulation) — имитация функционирования одного устройства посредством другого устройства или устройств вычислительной машины, при которой имитирующее устройство воспринимает те же данные, выполняет ту же программу и достигает того же результата, что и имитируемое.

[ГОСТ 15971-90. Системы обработки информации. Термины и определения]

[ГОСТ 33707-2016. (ISO/IEC 2382:2015) Информационные технологии (ИТ). Словарь]

[ГОСТ Р 58362-2019. Магистральный трубопроводный транспорт нефти и нефтепродуктов. Автоматизация и телемеханизация технологического оборудования. Основные положения, термины и определения (с Поправкой)]

Эмуляция – автоматическое составление машинной программы для ЭВМ другой архитектуры по исходной программе, созданной на языке программирования посредством кросс-системы.

[Основные термины программного обеспечения. (Электронный ресурс). Режим доступа: http:// studopedia.su›9_74588_osnovnie-termini /, свободный.]

1) Орфографическая запись слова: эмуляция
2) Ударение в слове: эмул`яция
3) Деление слова на слоги (перенос слова): эмуляция
4) Фонетическая транскрипция слова эмуляция : [мл’`аа]
5) Характеристика всех звуков:
э э — гласный, безударный
м [м] — согласный, твердый, звонкий, непарный, сонорный
у у — гласный, безударный
л [л’] — согласный, мягкий, звонкий, непарный, сонорный
я [`а] — гласный, ударный
ц ц — согласный, твердый, глухой, непарный
и ы — гласный, безударный
я й[а] — гласный, безударный


8 букв, 4 звук

Эмуляция

Эмуляция — имитация работы одной системы средствами другой без потери функциональных возможностей и искажений результатов. Эмуляция выполняется программными и/или аппаратными средствами.

См. также: Исполнение программ

Финансовый словарь Финам.

Синонимы:

конкуренция, подражание, соперничество

ЭМУЛЯЦИЯ

[англ. emulation — соревнование, соперничество] — соперничество, конкуренция, желание перещеголять кого-л.

Словарь иностранных слов.- Комлев Н.Г.,2006.

Синонимы:

конкуренция, подражание, соперничество

1. Имитация функционирования одного устройства посредством другого устройства или устройств вычислительной машины, при которой имитирующее устройство воспринимает те же данные, выполняет ту же программу и достигает того же результата, что и имитируемое Употребляется в документе:
ГОСТ 15971-90 Системы обработки информации. Термины и определения
Телекоммуникационный словарь.2013.
Синонимы:
конкуренция, подражание, соперничество

Ударение в слове: эмул`яция
Ударение падает на букву: я
Безударные гласные в слове: эмул`яция

ЭМУЛЯЦИЯ и, ж. émulation f. См. Эмюляция.

Синонимы:

конкуренция, подражание, соперничество

эмуля́ция, -и
Синонимы:

конкуренция, подражание, соперничество

эмул’яция, -и

Синонимы:

конкуренция, подражание, соперничество

emulation вчт.

Синонимы:

конкуренция, подражание, соперничество

emulation

Синонимы:

конкуренция, подражание, соперничество

Начальная форма — Эмуляция, единственное число, женский род, именительный падеж, неодушевленное

(программного или аппаратного средства программными или аппаратными средствами) emulation вчт.

Тэмцэл, өрсөлдөөн, уралдаан, тэмцээн

Мул Миля Луи Имя Эмуляция Уля Цум

Эмуляция DOS на эмуляторе DOSBox

Эмуляция компьютера стандарта MSX на эмуляторе MESS

Эмуляция компьютера стандарта MSX на эмуляторе MESS

Эмуля́ция (англ. emulation) в вычислительной технике — комплекс программных, аппаратных средств или их сочетание, предназначенное для копирования (или эмулирования) функций одной вычислительной системы (гостя) на другую, отличную от первой, вычислительную систему (хост) таким образом, чтобы эмулированное поведение как можно ближе соответствовало поведению оригинальной системы (гостя). Целью является максимально точное воспроизведение поведения в отличие от разных форм компьютерного моделирования, в которых имитируется поведение некоторой абстрактной модели. Например, моделирование урагана или химической реакции не является эмуляцией.

Эмуляция в вычислительной технике

Эмуляция связана с возможностью компьютерной программы в одном устройстве эмулировать (имитировать) другую программу или устройство. Например, многие принтеры разработаны таким образом, чтобы эмулировать принтеры HP Laserjet, так как для данных принтеров существует большое количество программного обеспечения. Если принтер, не произведенный HP, эмулирует принтер HP, тогда любая программа, разработанная для принтеров HP, сможет работать и с принтером другого производителя, получая при этом идентичную печать.

Аппаратная эмуляция представлена эмуляторами, выполненными в виде отдельного устройства. Например, DOS-совместимые карты расширения наподобие Centris 610 и Performa 630, устанавливавшиеся в некоторые Macintosh для обеспечения возможности запуска DOS-программ с ПК. Другим примером являются аппаратные эмуляторы на основе ППВМ.

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

Электронное архивирование

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

Эмуляция адресует аппаратное и программное окружение оригинального цифрового устройства и воссоздаёт его на современной машине[2]. Эмуляция позволяет пользователю получить доступ к любому типу прикладного программного обеспечения или операционных систем на современной платформе, причем программное обеспечение выполняется так же, как и в оригинальном окружении[3]. Джеффри Ротенберг (Jeffery Rothenberg), один из первых сторонников применения эмуляции для электронного архивирования, считает, что «идеальным было бы единое расширяемое долговременное решение, которые могло бы быть разработанным раз и навсегда и применялось бы единообразно, автоматически и синхронно (например, каждый цикл обновления) ко всем типам документов и носителей»[4]. Далее он замечает, что это решение должно применяться не только к устаревшим системам, но и быть легко переносимым на пока неизвестные будущие системы[5]. На практике в случае, если выпускается новая версия приложения с целью обеспечения совместимости и миграции всех входящих в него компонентов, необходимо для этого приложения создать эмулятор, обеспечивающий доступ ко всем упомянутым компонентам.

Достоинства

  • Эмуляция сохраняет вид, поведение и ощущение от оригинальных систем, что не менее важно, чем данные сами по себе[3].
  • Несмотря на высокую изначальную стоимость создания эмулятора, со временем эмуляторы могут становиться более финансово выгодным решением[6].
  • Сокращает трудозатраты, так как вместо долгой и постоянно продолжающейся работы по миграции данных для каждого цифрового объекта при внесении библиотек приложений и операционных систем прошлого и настоящего в эмулятор для работы со всеми документами можно использовать одинаковые технологии[3].
  • Многие эмуляторы разработаны и доступны под лицензией GNU General Public License как открытое программное обеспечение, что расширяет масштабы сотрудничества[2].
  • Эмуляция позволяет использовать программное обеспечение, эксклюзивное для одной платформы, на другой платформе. Например, игры, эксклюзивные для PlayStation 2, теоретически могут быть эмулированы на ПК или Xbox 360. Это особенно полезно, когда оригинальная система труднодоступна для обретения или несовместима с современным оборудованием (например, старые игровые приставки может быть технически невозможно подключить к современным телевизорам).

Препятствия

  • Интеллектуальная собственность. Многие технологические компании, чтобы занять свою нишу на рынке, применяют при разработке своих продуктов нестандартизированные функции, постоянно внедряя улучшения, чтобы продукт оставался конкурентоспособным. Хоть это и приносит пользу, насыщая рынок технологичными продуктами и увеличивая рыночную долю продукта, это создаёт существенные проблемы пользователям, занимающимся архивированием, ввиду отсутствия всей необходимой документации, так как аппаратное и программное обеспечение проприетарно по своей сути[7].
  • Законы об авторских правах до сих пор не регламентируют защиту документации и спецификаций проприетарного оборудования и программ, встроенных в эмулятор[8].
  • Эмуляция часто используется в пиратских целях, поскольку эмуляторы освобождают пользователя от необходимости покупать оригинальное устройство, например игровую консоль, и крайне редко содержат какие-либо средства противодействия использованию нелегальных копий. Это приводит к весомой неопределенности правового положения эмуляции и к тому, что в программное обеспечение закладываются средства, препятствующие его работе в случае их запуска на эмуляторе. В компьютерных играх пользователь иногда может продолжить игру, но на последующих уровнях игра может становиться невозможной, что воспринимается либо как небрежность программиста, либо как просто чрезмерная сложность[9][10]. Такая защита способствует созданию более точных эмуляторов, которые бы не вызывали срабатывание программной защиты, которая зачастую не очевидна.

Медиаискусство

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

Эмуляция часто используется в медиаискусстве как средство сохранения цифровой информации, которая бы впоследствии воспроизводилась без изменений, независимо от оборудования, подверженного старению и устареванию. Парадокс заключается в том, что эмуляция и эмуляторы должны быть созданы, чтобы работать на машинах будущего[11].

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

Разные виды эмуляции широко используются при разработке и проектировании новых систем. Эмуляция упрощает разработку, давая возможность определить, исследовать и устранить недостатки проекта до его физического воплощения[12]. Особенно эмуляция полезна при разработке многоядерных систем, в которых конфликты параллельной обработки часто достаточно сложно определить и диагностировать без применения виртуальной управляемой аппаратуры, доступной при эмуляции[13]. Также эмуляция позволяет приступить к разработке программного обеспечения до фактического изготовления аппаратной части[14], таким образом проверяя заложенные в неё особенности.

Виды эмуляции

В большинстве существующих эмуляторов воспроизводится только аппаратное обеспечение. Таким образом, если требуется операционная система, хранящаяся в ПЗУ, или другое программное обеспечение, его следует получить дополнительно (впрочем, оно тоже может быть эмулировано). В дальнейшем и операционная система, и программное обеспечение будут интерпретированы эмулятором таким же образом, как и на изначальном оборудовании. Кроме интерпретатора эмулированных двоичных машинных кодов также должно эмулироваться и некоторое другое оборудование (например, вводные и выводные устройства). Например, если запись в определенную область памяти должна выводить что-то на экран, такое поведение также должно быть эмулировано.

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

Наоборот, некоторые другие устройства имели очень ограниченный прямой доступ к оборудованию. В подобных случаях может быть достаточно простого слоя совместимости. Системные запросы эмулируемой программы транслируются в системные запросы хоста, то есть в системах FreeBSD, NetBSD и OpenBSD для запуска Linux-приложений с закрытым кодом используется слой совместимости с Linux. Например, графический процессор Nintendo 64 был полностью программируемым, и большинство разработчиков игр использовало заложенные заводские программы, которые были самодостаточными и обменивались информацией с игрой через буфер FIFO. Поэтому многие эмуляторы вообще не эмулируют графический процессор, интерпретируя вместо этого команды центрального процессора так же как и оригинальная программа.

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

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

Структурный состав эмулятора

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

  • модуль эмуляции или симуляции CPU (в данном случае термины практически равнозначны);
  • модуль эмуляции подсистемы памяти;
  • модули эмуляции различных устройств ввода-вывода.

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

Подсистема памяти

При эмуляции вполне возможно отобразить всю подсистему памяти в виде простого массива, каждый элемент которого имеет размер эмулированного слова. Однако этот подход обречен на неудачу, потому что в этом случае никакой логический адрес памяти не будет совпадать с физической памятью. Наиболее ярко это проявляется в случае, когда оригинальное оборудование обладает продвинутым управлением памятью (в этом случае в модуле подсистемы памяти должна быть реализована логика MMU либо как отдельный модуль, либо как часть виртуального CPU).

Однако даже если эмулируемое устройство не содержит MMU, существуют и другие факторы, нарушающие эквивалентность логической и физической памяти: многие (если не все) архитектуры обладают отображаемыми в ОЗУ портами ввода-вывода; даже те, которые ими не обладают, имеют блоки памяти, отображаемые в ПЗУ. Это значит, что представление памяти в виде массива не должно применяться, если требуется эмулировать ПЗУ. Функции типа переключения банков или сегментной адресации также могут усложнить эмуляцию памяти.

В результате большинство эмуляторов имеет по меньшей мере две процедуры — для чтения из памяти и для записи в память, — которые ответственны за доступ к правильной области правильного объекта.

Для эмуляции систем с ограниченной адресацией, где адреса памяти с 0 по (размер ПЗУ) — 1 доступны только для чтения, а все остальные принадлежат ОЗУ, что-то подобное следующему является вполне типичным.

void WriteMemory(word Address, word Value) {
    word RealAddress;
    RealAddress = Address + BaseRegister;
    if ((RealAddress < LimitRegister) &&
        (RealAddress > ROMSIZE)) {
        Memory[RealAddress] = Value;
    } else {
        RaiseInterrupt(INT_SEGFAULT);
    }
}
word ReadMemory(word Address) {
    word RealAddress;
    RealAddress=Address+BaseRegister;
    if (RealAddress < LimitRegister) {
        return Memory[RealAddress];
    } else {
        RaiseInterrupt(INT_SEGFAULT);
        return NULL;
    }
}

Центральный процессор

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

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

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

void Execute(void) {
    if (Interrupt != INT_NONE) {
        SuperUser = TRUE;
        WriteMemory(++StackPointer, ProgramCounter);
        ProgramCounter = InterruptPointer;
    }
    switch (ReadMemory(ProgramCounter++)) {
        /*
         * Handling of every valid instruction
         * goes here...
         */
        default:
        Interrupt = INT_ILLEGAL;
    }
}

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

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

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

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

Чтобы обойти эти проблемы применяют разнообразные приемы, включая известную «компиляцию на лету». Компилятор ожидает, пока поток управления процессором не перейдет в область, содержащую нетранслированный код. Только тогда («на лету») происходит трансляция блока кода в код, который может быть выполнен. Обработанный код помещается в кэш кода, при этом оригинальный код не подвергается изменению. В таком случае даже блоки данных подвергнутся бессмысленной трансляции компилятором, единственным эффектом чего будет увеличение времени работы транслятора.

В некоторых случаях, например при запуске старых игр, высокая скорость эмуляции может быть нежелательной, так как игры создавались без оглядки на производительность компьютеров будущего. В игре, разработанной для ПК с CPU 30 MHz, игроку может отводиться 300 игровых секунд на игровой уровень, в случае запуска той же игры на ПК с CPU 300 MHz игроку эти 300 игровых секунд будут соответствовать 30 реальным секундам. Другие программы, например некоторые программы для DOS, вообще не смогут запуститься на быстром компьютере. Практически, если эмулируется система, являвшаяся «чёрным ящиком», изменения в ядре которого не ожидались, программы могут зависеть от некоторых специфических параметров оборудования (например, частоты CPU). Таким образом, для правильной эмуляции подобных приложений требуется очень точное управление скоростью эмуляции.

Ввод и вывод

Как уже было отмечено, системные шины эмулируются редко. Каждое устройство ввода-вывода рассматривается отдельно, потому как в эмуляторе отсутствует реализация какого-либо универсального интерфейса. Так как каждое устройство ввода-вывода может быть идеально подогнано к параметрам эмулированного устройства, это даёт выигрыш в производительности. Однако решения на основе стандартизованных, унифицированных API всё же могут составить конкуренцию упрощённым моделям в случае их грамотной, искусной реализации. Дополнительным преимуществом будет «автоматически» получаемая служба плагинов, через которую с эмулятором смогут работать сторонние виртуальные устройства. В унифицированных API ввода-вывода необязательно повторять полную структуру шины: её схемотехника ограничена несколькими электронными компонентами, таким образом, в программной реализации необязательно наличие системы разрешения конфликтов параллельных вычислений.

Даже в эмуляторах, рассматривающих отдельно каждое устройство, как правило присутствует следующая виртуальная инфраструктура:

  • управление прерываниями посредством процедуры, которая устанавливает флаги, считываемые эмулятором CPU, когда объявлено прерывание, что позволяет виртуальному CPU «опрашивать прерывания»;
  • запись и чтение физической памяти посредством двух процедур, подобных обслуживающим логическую память (однако в отличие от последнего, первые часто могут быть заменены простыми ссылками на массив памяти).

Эмуляция и симуляция

Слово «эмулятор» было придумано в IBM[15] при разработке серии продуктов NPL (IBM System/360), используя «новую комбинацию программы, микрокода и оборудования»[16]. Они обнаружили, что для исполнения программ, написанных для старых машин IBM, использование аппаратного Микрокода намного выгоднее по производительности, нежели программная симуляция. Ранее, в 1957 году, IBM поставляла программный интерпретатор для возможности запуска программ для более старого компьютера IBM 704 на компьютерах IBM 709 и IBM 7090[17]. В 1964 году инженеры IBM придумали слово «эмуляция» для описания концепции первого применения микрокода для ускорения процесса симуляции.

В последнее время употребление этого термина стало общеупотребительными в контексте программного обеспечения. До 1980-х годов слово «эмуляция» относилось исключительно к аппаратной реализации с применением микрокода, тогда как для программной эмуляции использовался термин «симуляция»[18]. Например, компьютер, специально разработанный для выполнения программ, написанный для другой архитектуры, являлся эмулятором. С другой стороны симулятором могла бы называться программа для ПК, с помощью которой можно было бы симулировать старые игры для Atari. Хотя пуристы продолжают указывать на это терминологическое различие, в настоящее время эмуляцией обычно принято называть полную имитацию машины, выполняющей двоичный код, тогда как симуляция в основном относится к компьютерному моделированию, работающему над абстрактной моделью. Компьютерное моделирование используется практически в любой научной и инженерной деятельности, не исключая также информатику, которая находит многие применения для работы с абстрактной моделью, например, моделирование сетей связи.

Моделирование логических схем

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

Функциональное моделирование

Функциональное моделирование — использование компьютерной программы для моделирования выполнения другой компьютерной программы, написанной на языке ассемблера или в исходных кодах, а не в виде двоичного машинного кода. С помощью функционального моделирования программист может выпускать и анализировать работу выбранного участка кода для обнаружения ошибок (багов), не прибегая к получению двоичного кода. Этим оно отличается от выполнения бинарного кода, что является эмуляцией.

Первое применение функционального моделирования осуществлено компанией Autonetics около 1960 года для тестирования программ на языке ассемблера, которые впоследствии должны были выполняться на военной машине D-17B. Это позволило писать, выполнять и тестировать полетное программное обеспечение до физического изготовления вычислительного оборудования D-17B. Эта же компания позднее применяла функциональное моделирование для тестирования полетного программного обеспечения, которое должно было выполняться на машине D-37C.

Эмуляция игровой приставки

Эмулятор игровой приставки — это программа, которая позволяет на персональном компьютере или игровой приставке эмулировать другую приставку. Чаще всего их используют для запуска старых игр на ПК или более современных приставках. Также эмуляторы используют для создания любительского перевода игр, модификаций игр, а также для разработки такого пользовательского контента как демоверсии и новые игры для старых систем. В распространении этого вида эмуляции большую роль сыграл интернет, так как большая часть (если не все) эмуляторов не доступна в точках розничных продаж. Некоторые из эмуляторов, выпущенные в последние два десятилетия: Dolphin, ZSNES, MAME, DeSmuME, ePSXe, Gens, VisualBoyAdvance, Jnes и Nestopia.

Эмуляция терминала

Эмулятор терминала — это программа для современного ПК или другого устройства, позволяющая получить интерактивный доступ к операционной системе мейнфрейма или другой системе хоста, например HP-UX или OpenVMS. Уже длительное время терминалы наподобие IBM 3270 и VT100 не производятся. Вместо этого используется программа, запускаемая на современной операционной системе, которая имитирует «глупый» терминал и способна отображать графические и текстовые элементы приложения хоста, отправлять клавиатурный ввод и обрабатывать команды через соответствующий протокол терминала. Некоторые из таких эмуляторов включают приложения для Attachmate Reflection, IBM Personal Communications, AlphaVM virtual machine от EmuVM, Stromasys CHARON-VAX/AXP и Micro Focus Rumba.

См. также

  • Список эмуляторов игровых консолей
  • Компьютерное моделирование
  • Некоторые виды эмуляторов:
    • Эмулятор игровой приставки
    • Эмулятор сервера
    • Эмулятор терминала
    • Эмулятор оптических дисководов
  • Двоичная трансляция
  • Внутрисхемный эмулятор:
    • JTAG
  • QEMU
  • Виртуальная машина

Примечания

  1. What is emulation? Koninklijke Bibliotheek. Дата обращения: 11 декабря 2012. Архивировано из оригинала 7 июня 2011 года.
  2. 1 2 van der Hoeven, Jeffrey, Bram Lohman, and Remco Verdegem. Emulation for Digital Preservation in Practice: The Results. The International Journal of Digital Curation 2.2 (2007): 123—132.
  3. 1 2 3 Muira, Gregory. Pushing the Boundaries of Traditional Heritage Policy: maintaining long-term access to multimedia content. IFLA Journal 33 (2007): 323—326.
  4. Rothenberg, Jeffrey. «Criteria for an Ideal Solution.» Avoiding Technological Quicksand: Finding a Viable Technical Foundation for Digital Preservation. Council on Library and Information Resources (1998). Дата обращения: 8 марта 2008. Архивировано из оригинала 20 февраля 2008 года.
  5. Rothenberg, Jeffrey. The Emulation Solution. Avoiding Technological Quicksand: Finding a Viable Technical Foundation for Digital Preservation. Washington, DC: Council on Library and Information Resources, 1998. Council on Library and Information Resources. 2008. 28 Mar. 2008 http://www.clir.org/pubs/reports/rothenberg/contents.html
  6. Granger, Stewart. Digital Preservation & Emulation: from theory to practice. Proc. of the ichim01 Meeting, vol. 2, 3 −7 Sept. 2001. Milano, Italy. Toronto: Archives and Museum Informatics, University of Toronto, 2001. 28 Mar. 2008 http://www.leeds.ac.uk/cedars/pubconf/papers/ichim01SG.html Архивная копия от 31 января 2009 на Wayback Machine
  7. Granger, Stewart. Emulation as a Digital Preservation Strategy. D-Lib Magazine 6.19 (2000). 29 Mar 2008 http://www.dlib.org/dlib/october00/granger/10granger.html
  8. Rothenberg, Jeffrey. The Emulation Solution. Avoiding Technological Quicksand: Finding a Viable Technical Foundation for Digital Preservation. Washington, DC: Council on Library and Information Resources, 1998. Council on Library and Information Resources. 2008. 28 Mar. 2008
  9. Pokémon Black and White — The Cutting Room Floor. Дата обращения: 25 мая 2013. Архивировано из оригинала 6 июня 2013 года.
  10. Mega Man Star Force — The Cutting Room Floor. Дата обращения: 25 мая 2013. Архивировано из оригинала 12 мая 2013 года.
  11. Echoes of Art: Emulation as preservation strategy. Дата обращения: 11 декабря 2007. Архивировано из оригинала 27 октября 2007 года.
  12. Peter Magnusson. Full System Simulation: Software Development’s Missing Link (2004). Дата обращения: 25 мая 2013. Архивировано 25 мая 2013 года.
  13. Debugging and Full System Simulation. Дата обращения: 25 мая 2013. Архивировано из оригинала 8 октября 2008 года.
  14. Vania Joloboff. Full System Simulation of Embedded Systems (2009). Дата обращения: 25 мая 2013. Архивировано из оригинала 9 февраля 2014 года.
  15. Pugh, Emerson W. Building IBM: Shaping an Industry and Its Technology (англ.). — MIT, 1995. — P. 274. — ISBN 0-262-16147-8.
  16. Pugh, Emerson W.; et al. IBM’s 360 and Early 370 Systems (неопр.). — MIT, 1991. — ISBN 0-262-16123-0. pages 160—161
  17. «7090 Data Processing System» — «Compatibility feature for IBM 704 programs» subsection
  18. S. G. Tucker, Emulation of Large Systems. Communications of the ACM (CACM) Vol. 8, No. 12, Dec. 1965, pp. 753—761

Литература

  • А. Аганичев, Д. Панфилов, М. Плавич, О. Полянский. Программно-аппаратный комплекс для отладки МП систем на основе микроконтроллеров семейства MC68HC11 фирмы MOTOROLA
  • Шагурин И., Бродин В., Калинин Л., Толстов Ю., Петров С., Исенин И., Эйдельман С., Ванюлин В. Средства проектирования и отладки систем управления на базе МК фирмы Motorola.

Ссылки

  • Как написать эмулятор компьютера
  • How to write a computer Emulator


Эта страница в последний раз была отредактирована 17 февраля 2023 в 08:10.

Как только страница обновилась в Википедии она обновляется в Вики 2.
Обычно почти сразу, изредка в течении часа.

Понравилась статья? Поделить с друзьями:
  • Как пишется эмульсия на латыни
  • Как пишется эмульсия или имульсия
  • Как пишется электронный адрес сайта
  • Как пишется эмульгатор
  • Как пишется электронное письмо на английском