Опорные изображения
Модели
Материнская плата
Диаграмма
Краткое введение
Внутренний дизайн Game Boy Advance довольно впечатляющий для портативной консоли, которая работает от двух АА батареек.
В этой консоли по-прежнему будет использоваться фирменный графический процессор Nintendo. Кроме того, в ней будет представлен относительно новый процессор от британской компании, который будет набирать популярность в ближайшие годы.
Процессор
Большинство компонентов объединены в единый модуль под названием CPU AGB. Модуль содержит два совершенно разных процессора:
- Sharp SM83, работающий на частоте 8,4 или 4,2 МГц: Да это же тот самый процессор, что использовался в Game Boy! Он позволяет запускать игры для Game Boy (DMG) и Game Boy Color (CGB). Вот моя предыдущая статья, если вы хотите узнать больше об этих консолях.
- ARM7TDMI работает на частоте 16,78 МГц: Это новый процессор, на котором мы сосредоточимся. Именно он запускает игры Game Boy Advance.
Надо отметить, что оба процессора никогда не работают одновременно и никаким сопроцессингом не занимаются. Единственная причина включать очень старый Sharp - это обратная совместимость.
Тем не менее, прежде чем я расскажу про чип ARM, я считаю, что целесообразно начать с истории за этим брендом CPU.
Кембриджское чудо
История о происхождении процессора ARM и его последующем пути к славе захватывает дух. Здесь мы увидим сочетание государственных инвестиций, экспоненциального роста, злополучных решений и партнерств на большом расстоянии.
Расцвет Acorn Computers
Конец 70-х для жителей Соединённого Королевства выдался неспокойным. Интервенционистская экономика, когда-то построенная в соответствии с послевоенными идеалами, достигла своего курса, и вскоре маятник покачнулся в сторону реформ свободного рынка. Посреди этого шторма, венчурный бизнес из Кембриджа, такой как Acorn Computers, вместе с Sinclair и подобными, продавал компьютерные наборы для лабораторий и энтузиастов. Подобно американским и японским предприятиям, компьютеры Acorn опирались на процессор 6502 и проприетарный диалект BASIC.
Входя в 80-е годы, интересы министерств в рамках нового британского правительства привели к созданию проекта по повышению компьютерной грамотности в школах [2]. Благодаря предстоящему домашнему компьютеру “Proton” от Acorn компания получила контракт на создание доступного компьютера, который соответствует видению правительства. Результатом стал BBC Micro (по прозвищу “Beeb”), которым удалось добиться значительных успехов среди школ, учителей и студентов. Внутрь Micro Acorn добавила авангардный интерфейс ‘Tube’, который позволяет расширить компьютер с помощью второго процессора. Это проложит путь к следующей большой инвестиции Acorn.
В ходе разработки своего следующего продукта, на этот раз нацеленного на компании, Acorn не нашла подходящего процессора на замену 6502. Давление на создание инноваций против японской и американской конкуренции, в сочетании с неудачным планированием, привели Acorn к плачевному финансовому состоянию. Таким образом, перед новым подразделением в Acorn была поставлена задача создать хороший центральный процессор. Чтобы обойти недавние ограничения, Acorn команда, отвечавшая за центральный процессор, основала свою архитектуру на учениях исследовательской работы под названием Дело о компьютере с сокращённым набором инструкций (англ. Reduced Instruction Set Computer) [3] и его прототипе, процессоре RISC [4]. Наконец, в 1985 году Acorn начали поставку процессора ARM1 в качестве модуля Tube для BBC Micro, но его позиционировали только для научно-исследовательских и опытно-конструкторских работ. Так было до тех пор, пока в 1987 не представили свой первый компьютер Acorn Archimedes, после этого чипы ARM (на тот момент уже ARM2) заняли главную роль.
Новая авантюра с процессором
Во время коммерциализации Acorn Archimedes, Apple была поражена энергоэффективными процессорами Acorn, но американская компания до сих пор не была убеждена в том, что последний ARM3 Acorn подходит для нового небольшого проекта Apple: Newton. Однако, вместо того, чтобы уйти (в конце концов, Акорн был конкурентом), оба обсудили возможность эволюции ARM3 для соответствия требованиям Apple [5], а именно гибкая тактовая частота, интегрированный MMU и полная 32-битная адресация.
Это сотрудничество в скором времени превратилось в партнерство, где Acorn, Apple и VLSI (производитель микросхем ARM) создали новую компанию, ориентированную исключительно на разработку процессоров ARM. Apple предоставила инвестиции (приобретая 43% продукта), Acorn поделился своим персоналом, а VLSI позаботился о производстве. В 1990 году появилась на свет Advanced RISC Machines (ARM) Ltd с Robin Saxby в качестве исполнительного председателя.
Годы спустя Apple наконец-то начала продажу Newton MessagePad на базе ARM610, одного из следующих поколений чипов ARM, выполнявшего требования Apple. Между тем, Acorn также выпустил RiscPC с использованием новых процессоров.
Теперь, когда Acorn и Apple удерживались на компьютерном/портативном рынке, ARM разработала радикальную бизнес-модель. Избегая производство, видение Saxby заключалось в лицензировании интеллектуальной собственности ARM в форме схем центрального процессора и его набора инструкций [6]. Это дало ARM клиентов за пределами компьютерной сферы, такие как Texas Instruments [7], которые позднее свяжут компанию с формирующимся мобильным рынком (кульминацией станет Nokia 6110) и телевизионными приставками. В последующие годы технологии ARM будут поставляться в миллиардах мобильных устройств [8].
Партнёрство с Nintendo
Тем временем в Японии, благодаря анализу Game Boy, мы узнали, что стратегия Nintendo в области аппаратного обеспечения портативных систем поощряет модель Систем на кристалле (СНК, англ. SoC). Это позволило компании спрятать доступную готовую технологию и объединить ее с собственными разработками. При этом новая консоль может быть уникальной и конкурентоспособной.
К счастью, лицензионная модель ARM подходила именно для этих нужд. Обе компании вели переговоры с 1994 (за год до выпуска Virtual Boy), хотя многие годы они ни к чему не приводили [9]. Причина была проста: японцы видели проблему в плотности кода для ARM и необходимости в 32 проводах для данных (чего процессору Virtual Boy удалось избежать). Тем не менее новый разработчик процессоров ARM - Dave Jaggar - быстро дал ответ в виде ARM7TDMI. Новый процессор был ориентирован на максимальной производительности с ограничениями по питанию и запоминающим устройствам. Это был поворотный момент для ARM, так как их новый продукт не только угодил Nintendo, но ещё привлёк внимание Texas Instruments, Nokia и остальных конкурентов на рынке сотовых телефонов.
Неудивительно, что когда Nintendo начала работу над преемником Game Boy Color, в качестве процессора был выбран именно ARM7TDMI.
ARM7TDMI
Давай погрузимся в то, что предлагает этот чип.
Командуем процессором
Для начала, ARM7TDMI реализует набор инструкций ARMv4, наследника ARMv3. Это значит:
- Строение на основе RISC: Как было сказано выше, процессоры ARM создавались под влиянием работы из университета Беркли под названием “Дело о компьютере с сокращённым набором инструкций” [10]. Её исследования очерчивали набор требований для масштабируемой конструкции процессора и защищает использование архитектуры load-store, фиксированного размера инструкций и большого регистрового файла. Многие из них не были реализованы на рынке центральных процессоров того времени (т.е. Intel 8086, MOS 6502, Zilog Z80 и Motorola 68000), но при этом они повлияли на конструкцию новых линеек процессоров в 80-е и 90-х годах.
- Условное исполнение (англ. Conditional execution): Характерная черта архитектуры набора инструкций ARM. По сути, почти каждая инструкция включает в себя условие, которое определяет, должны ли они выполниться. Как правило, другие процессоры следуют процессу «сравнить и перейти» (также называемым «ветвлением») для контроля над тем, какие команды будут исполнены ЦП. Напротив, программисты ARM могут вставить условие в саму команду. Это возможно из-за первых четырех бит кодов операций ARM, зарезервированных для условия (например,
равенство
,неравенство
и так далее). В общем и целом это уменьшает сложность кода ARM, поскольку условное исполнение обеспечивает более чистое строение процедур, в отличие от ветвления и разделения на подпрограммы. Кроме того, оно служит обходным путём для конфликтов управления (control hazards) (подробнее об этом будет рассказано далее). - Инструкции для 32-битного и 64-битного умножения: Дополнение из ARM v4. Кроме того, 64-битные операции выводят результат в два регистра.
Кристалл
А теперь, зная, как разработчики разговаривают с чипом, давайте посмотрим, что находится на кристалле.
Ядро
В плане схемы ARM7TDMI является урезанной версией ARM710 с интересными дополнениями. Ядро включает в себя [11] [12]:
- Шестнадцать 32-разрядных регистров общего назначения: Хотя это большой скачок по сравнению с семью 8-битными регистрами SM83/Game Boy, это нарушение принципов RISC, требующих тридцать два регистра размером в 32 бита. Так сделано потому, что ARM предпочитает поддерживать маленький размер кремниевого чипа [13].
- 32-битная шина данных и АЛУ: Позволяет перемещать и управлять 32-разрядными значениями без траты дополнительных циклов.
- Чистая 32-битная адресация: Эта часть была одним из требований Apple. Первые три процессора ARM использовали 26-разрядные адреса памяти для повышения производительности (счётчик команд и регистр статуса вместе могли поместиться в одном 32-битном слове) взамен адресуемости памяти (можно получить доступ только к 64 МБ памяти). В последующей серии ARM6 (с архитектурой набора инструкций ARMv3) реализована 32-битная логика адресации, но сохранён режим обратной совместимости для старого кода. А затем ARM7TDMI (ориентированны на мобильные устройства) избавился от 26-битного режима и оставил логику только для 32-битных адресов (тем самым уменьшил требуемое количество кремния).
- Отсутствие Блока управления памятью (англ. MMU): Начиная с ARM1, ARM предоставляла готовый MMU. Сначала как сопроцессор ‘MEMC’, а затем встроенный в ARM610. А сейчас, похоже, ARM7TDMI остаётся единственным в своей серии без такого блока, потенциально из-за отсутствия интереса (ранние мобильные устройства не требовали сложной виртуальной памяти).
- Отсутствие кеша: Очередное сокращение затрат на этот чип, так как предыдущие чипы ARM имели небольшой кеш.
Наконец, всё это может работать от 3-вольтового блока питания [14]. Это очевидный шаг в сторону мобильных вычислений, так как предыдущие ядра требовали блока питания на 5 Вольт.
Конвейер
Начиная с первой версии ARM обладал трёх этапным конвейером для выполнения кода. Другими словами, выполнение инструкций разбито на три шага или этапа. Процессор выбирает, декодирует и выполняет до трех инструкций параллельно. Это позоволяет использовать ресурсы процессора по максимуму (что снижает простой процессора), при этом так же увеличивает количество выполняемых за еденицу времени инструкций.
Как и два очень похожих современника, процессоры ARM подвержены конфликтам данных (data hazards). Тем не менее ни программист, ни компилятор их не заметят, так как в данном случае процессор автоматически приостановит конвейер всякий раз, когда это необходимо.
Также присутствуют и конфликты управления (control hazards), но ARM решил эту проблему эффективным методом условного аннулирования (conditional annulment): Всякий раз, когда на втором этапе (Decode
, декодирование) появляется команда условного перехода, центральный процессор будет вычислять её условие [15]. В зависимости от результата, если должен произойти переход, процессор автоматически аннулирует последующую инструкцию (превращая её в пустую команду). Если сравнивать с подходом MIPS, то это звучит затратно, ведь компилятор MIPS мог вставлять не только пустышки, но и полезные инструкции. Поэтому, кроме условных переходов, ARM также предоставляет условное исполнение. Оно делает конвейер процессора его преимуществом, так как ARM может декодировать инструкции и вычислять встроенные в них условия в пределах одного этапа. В таком случае пустые инструкции не вставлялись. Вот поэтому в программировании под ARM условное исполнение предпочтительнее условного перехода [16].
Выжимание производительности
Один из недостатков архитектуры load-store привёл к разрежённости кода для ARM. Такие конкуренты, как x86, могут выполнять те же задачи, используя меньшее количество кода, требующего меньше пространства. Следовательно, когда в Nintendo посмотрели на последнюю разработку ARM - ARM7, они остались недовольны. Размер инструкций ARM означал, что железо гипотетических устройств, заточенное под 16-битные шины и ограниченную постоянную и оперативную память - всё ради экономии стоимости и энергии - станет для процессора бутылочным горлышком и ограничит его эффективность. К счастью, Dave Jaggar только что закончил работу над ARM7 и не собирался сдаваться. Во время своей поездки после встречи Nintendo он придумал решение: Набор инструкций Thumb [17].
Thumb — это подмножество набора инструкций ARM, инструкции которых кодируются в 16-битные слова (в отличие от 32-бит) [18]. Будучи 16-битными, инструкции Thumb требуют половину от ширины шины и занимают вдвое меньше памяти.
Главный компромисс заключается в том, что Thumb не предлагает условное исполнение, полагаясь на использование ветвей. К тому же, его коды операций с данными использовали только формат с двумя адресами, а не с тремя, и он имел доступ только к нижней половине регистрового файла (то есть, доступно только восемь регистров общего назначения). В общем, так как инструкции Thumb предлагают только функциональное подмножество инструкций ARM, разработчикам может потребоваться больше инструкций для достижения схожего результата.
На практике Thumb занимает 70% места ARM кода. На 16-битной памяти Thumb работает быстрее, чем ARM. При нужде ARM и Thumb инструкции можно смешивать в одной программе (т. н. interworking), так что разработчик может выбирать когда и где использовать каждый режим.
Расширения
ARM7TDMI является, по своей сути, ARMv3-совместимым ядром с расширениями. Это отражено в его имени (TDMI), которое значит:
- T → Thumb: Включение набора инструкций Thumb.
- D → Debug Extensions: обеспечивает отладку через JTAG.
- M → Улучшенный множитель (Enhanced Multiplier): Предыдущим ядрам ARM требовалось несколько тактов для вычисления полного 32-битного умножения, а данное усовершенствование сокращает этот процесс до нескольких тактов.
- I → EmbeddedICE macrocell: Включает аппаратные точки останова, точки наблюдения и позволяет останавливать систему во время отладки. Это облегчает разработку программ для данного процессора.
Всё это сделало ARM7TDMI привлекательным решением для мобильных и встроенных устройств.
Расположение памяти
В частности, включение Thumb оказало сильное влияние на окончательный дизайн этой консоли. Nintendo смешивала 16-битные и 32-битные шины между различными модулями, чтобы снизить затраты, и в то же время предоставляла программистам необходимые ресурсы для оптимизации кода.
Память, используемая в Game Boy Advance, распределена по следующим местам (в порядке от самой быстрой к самой медленной) [19]:
- IWRAM (Internal WRAM) → 32-бит с 32 КБ: Используется для хранения инструкций ARM.
- VRAM (Video RAM) → 16-бит с 96 КБ: Хотя этот блок предназначен для графических данных (об этом в следующем разделе этой статьи), он всё равно находится в области памяти процессора, поэтому программисты могут хранить другие данные, если IWRAM недостаточно.
- EWRAM (External WRAM) → 16-бит с 256 КБ: отдельный чип рядом с CPU AGB. Оптимален для хранения инструкций только в формате Thumb и данных небольшими фрагментами. С другой стороны доступ к этому чипу может быть до шести раз медленнее, чем к IWRAM.
- Game PAK ROM → 16-бит переменного размера: отсюда читается ROM картриджа. Хотя он может обеспечивать одну из самых медленных скоростей, он также зеркалируется в карте памяти для управления различными скоростями доступа. Кроме этого, Nintendo добавили Prefetch Buffer (буфер предварительной выборки), который взаимодействует с картриджем для уменьшения чрезмерных задержек. Этот компонент независимо кэширует непрерывные адреса, когда CPU не обращается к картриджу, он может вмещать до восьми 16-битных слов.
- Однако на практике процессор редко позволяет буферу выполнять свою работу. Поскольку по умолчанию он будет продолжать получать инструкции из картриджа для продолжения выполнения [20] (вот почему IWRAM и EWRAM так важны).
- Game PAK RAM → 8-бит переменного размера: здесь происходит доступ к оперативной памяти картриджа (SRAM или Flash Memory).
- Это строго 8-битная шина (процессор видит ‘мусор’ в незадействованных битах), по этой причине Nintendo заявляют, что с ней можно работать только через их библиотеки.
Хотя эту консоль позиционировали как 32-битную систему, с большей частью памяти можно общаться только через 16-битную шину, а значит игры в основном используют набор инструкций Thumb, чтобы не тратить два цикла на один запрос инструкций. Только в очень исключительных обстоятельствах (например, при необходимости использовать инструкции, отсутствующие в Thumb, храня их в IWRAM) программисты смогут воспользоваться набором инструкций ARM.
Становление Game Boy Color
Кроме включения компонентов GBC (Sharp SM83, оригинальный BIOS, режимы аудио и видео, совместимый слот для картриджей и так далее), для обеспечения обратной совместимости нужны еще две функции.
Со стороны оборудования консоль полагается на переключатели для определения, какой картридж вставлен: Game Boy или Game Boy Color. Детектор формы в слоте для картриджей по сути определяет тип картриджа и позволяет процессору читать его состояние. Предполагается, что некий компонент CPU AGB читает это значение и автоматически выключает ненужное в режиме GBC оборудование.
Со стороны программного обеспечения существует специальный 16-битный регистр REG_DISPCNT
, который может изменять многие свойства дисплея, но один из его битов вводит консоль в “режим GBC” [21]. Сначала мне было очень трудно понять, когда именно GBA пытается обновить это регистр. К счастью, нашлись разработчики прояснить ситуацию:
Думаю, вот что происходит во время загрузки GBC: она проверяет переключатель (считывается по адресу REG_WAITCNT 0x4000204), делает переход (очень быстрый, сложно заметить), потом окончательно переключатеся в режим GBC (BIOS пишет в REG_DISPCNT 0x4000000), останавливая ARM7.
Остается недостающий кусочек пазла: что если убрать часть корпуса на картридже GBC, чтобы переключатель больше не нажимался, а потом сделать программное переключение в режим GBC? Может помочь режим мультизагрузки. Не уверен, требуется ли нажатие переключателя, чтобы шина картриджа GBC работала корректно, или она работает само собой. Я склонен считать, что переключатель все таки необходим, но это всего лишь догадка.
– Dan Weiss (он же Dwedit, текущий разработчик PocketNES и Goomba Color)
Графика
Прежде чем мы начнем, вы узнаете, что система представляет собой смесь между SNES и Game Boy, графическим ядром по-прежнему является хорошо известный 2D движок под названием PPU. Поэтому, я рекомендую прочитать эти статьи, прежде чем продолжить, так как я буду рассматривать множество ранее разъясненных понятий.
По сравнению с прошлыми приставками серии Game Boy, у нас появился цветной LCD дисплей, который может показывать до 32 768 цветов (15-бит). Его разрешение 240 x 160 пикселей, а частота обновления примерно 60Гц.
Организация контента
Графика распределяется по следующим областям памяти:
- 96 КБ 16-битной VRAM (Video RAM): 64 КБ для хранения фонов и 32 КБ для хранения спрайтов.
- 1 КБ 32-битной OAM (Object Attribute Memory): хранит до 128 спрайтовых записей (не изображения, только индексы и атрибуты). Шина оптимизирована для быстрой отрисовки.
- 1 КБ 16-битной PAL RAM (Palette RAM): хранит две палитры, одна для фонов, а другая для спрайтов. В каждой палитре 256 записей 15-битных цветов, цвет
0
значит прозрачность.
Построение кадра
Если вы читали прошлые статьи, GBA будет казаться вам знакомой, хотя дополнительная функциональность может вас удивить, и не надо забывать, что консоль работает от двух пальчиковых батареек.
Я одолжу графику из Sonic Advance 3 от Sega, чтобы проиллюстрировать, как составляется кадр.
Тайлы
Тайлы GBA - это растровые изображения размером строго 8x8 пикселей, они могут использовать 16 цветов (4 bpp) или 256 цветов (8 bpp). Плитки размером 4 bpp занимают 32 байта, а 8 bpp - 64 байта.
Тайлы можно хранить где угодно в VRAM, однако, для PPU их нужно группировать в charblocks: блоки по 16 КБ. Каждый блок резервирует определенный тип слоев (фон или спрайты). Это может привести к перекрытиям, что, как следствие, позволяет блоками иметь общие тайлы.
Из-за размера блока символов в одном блоке можно хранить до 256 плиток 8 bpp или 512 плиток 4 bpp. Допускается до шести таких блоков, что в сумме требует 96 КБ памяти: точное количество VRAM этой консоли.
Для фонов можно использовать только четыре, а два можно применить для спрайтов.
Фоны
Этот конкретный слой сдвигается по горизонтали на определенных сканлайнах для имитации эффектов воды.
Фоновый слой в этой системе значительно улучшился со времен Game Boy Color. Она наконец-то включает в себя некоторые функции, найденные в Super Nintendo (помните аффинное преобразование?)
PPU теперь умеет рисовать до четырех фоновых слоев. Возможности каждого из них зависят от выбранного режима работы [22]:
- Режим 0: четыре статических слоя.
- Режим 1: доступно всего три слоя, но один из них аффинный (может вращаться и масштабироваться).
- Режим 2: два аффинных слоя.
Размеры каждого слоя могут быть до 512x512 пикселей. Если слой аффинный, он может быть размером до 1024x1024 пикселей.
Совокупность данных, которая задает фоновый слой, называют Tile Map. Чтобы реализовать ее в понятном для PPU виде, программисты используют screenblocks, структуру, задающую части фонового слоя (32x32 тайлов). Screenblock занимает всего 2 КБ, но для построения всего слоя их требуется несколько штук. Программисты вольны размещать их где угодно внутри фонового блока, а значит не все тайлы хранят графику!
Спрайты
Спрайт может быть размером до 64x64 пикселей, но из-за маленького экрана, он будет занимать большую его часть.
Если этого недостаточно, PPU теперь умеет применять к спрайтам аффинные преобразования!
Спрайтовые записи занимают 32 бита, их значения можно разделить на две группы:
- Атрибуты: x/y - положение, h/v - отражение, размер, форма (квадрат или прямоугольник), тип спрайта (аффинный или простой) и положение первого тайла.
- Аффинные данные: Используются только если спрайт аффинный. Они задают масштабирование и вращение.
Результат
Как обычно, PPU объеденяет все слои автоматически, но это еще не все! Система может наложить на эти слои несколько эффектов:
- Mosaic: делает тайлы более пиксельными.
- Alpha blending: комбинирует цвета двух наложенных слоев, что дает эффекты прозрачности.
- Windowing: разделяет экран на два разных окна, в каждом может быть своя собственная графика и эффекты, внешнюю зону обоих окон также можно отрисовывать тайлами.
С другой стороны, для обновления кадра есть несколько опций на выбор:
- Распоряжатся ЦП: у процессора теперь полный доступ к VRAM в любое вермя. Однако изменение некоторых данных посреди када может привести к нежелательным артефактам, так что ждать VBlank/HBlank промежутков (традиционный подход) остаестя самой безопасной тактикой в больинстве случаев.
- Использовать DMA контроллер: DMA обеспечивает в ~10 раз более быструю передачу данных, его можно отправить в обработку во время VBlank и HBlank. Консоль предоставляет 4 канала DMA (два зарезервированы под звук, один для критических операций, другой - общего назначения). При этом контроллер остановит процессор на время операции (хотя он едва заметит это!).
Кроме тайлов
Мы можем захотеть составить фон с которым тайловый движок не справится. Современные консоли решили это, внедрив архитектуру с буфером кадра, но это невозможно при очень маленькой емкости памяти… Что же, у GBA как раз есть 96 КБ видеопамяти, чего достаточно для растрового изображения размером с наш LCD экран.
Хорошей новостью является то, что PPU фактически реализовал эту функциональность, включив три дополнительных режима, которые называются bitmap modes [23]:
- Режим 3: Выделяет один полноцветный (16 bpp, 32 768 цветов) кадр.
- Режим 4: Предоставляет два кадра с половиной цветов (8 bpp, 256 цветов) каждый.
- Режим 5: Два полностью цветных кадра с половиной размера каждого (160x128 пикселей).
Причина наличия двух растровых изображений заключается в возможности перелистывания страниц: Рисование поверх отображаемого растрового изображения может привести к появлению некоторых странных артефактов во время процесса. Если вместо этого манипулировать другим, то ни один из глюков не будет показан пользователю. Как только вторая растровая карта будет готова, PPU можно обновить, чтобы указать на вторую, эффективно поменяв отображаемый кадр местами.
Растровый режим позволил процессору рисовать рудиментарную 3D графику.
Объекты переднего плана это спрайты (отдельный слой).
Растровая картинка с примитивами.
Обратите внимание, экран не показывает существенных узоры тайловых движков.
В целом звучит как передовая фишка, однако большинство игр продолжало пользоваться тайловым движком. Почему? Потому, что на практике, растры сьедают очень много ресурсов ЦП.
Видите ли, когда применяется тайловый движок, процессор делегирует большинство вычислений графическому чипу. А вот система фреймбуфферов от PPU ограничена только отображением сегмента памяти на единственном фоновом слое, что значит больше нет индивидуальных аффинных транформаций, наложений или эффектов если процессор сам их не просчитает. Фреймбуффер также занимает 80 КБ памяти, так что только 16 КБ (половина) доступны для хранения спрайтовых тайлов.
Вот почему эти режимы применяются в исключетельных случаях, таких как проигрывание видео (Game Boy Advance Video полностью на это полагалось) или отрисовка 3D геометрии через ЦП. В любом случае результаты были мягко говоря впечатляющими.
Звук
В GBA используется двухканальный проигрыватель сэмплов, который работает в связке со звуковай системой Game Boy.
Функционал
Вот разбор каждого звукового компонента на примере Sonic Advance 2:
PCM
Новая звуковая система теперь умеет проигрывать PCM сэмплы, она предоставляет два канала под названием Direct Sound, куда приходят сэмплы через очередь FIFO (реализована в виде 16-битного буфера).
Сэмплы 8-битные и со знаком (кодируются в значениях от -128 до 127). Частота дискретизации по умолчанию 32 кГц, хотя это зависит от игры: так как бо́льшая частота означает больший размер и большее количество циклов процессора, не каждая игра выделяет одинаковое количество ресурсов аудиочипу.
DMA необходим во избежание лишней траты циклов ЦП. Таймеры также доступны для синхронизации с очередью.
PSG
Хотя подсистема от Game Boy не делится ресурсами ЦП, доступ к своему PSG она дает. В целях обратной совместимости используется тот же подход, что и в оригинальном Game Boy. Ранее я уже писал эту статью, в которой подробно рассказывается о каждом канале в отдельности.
Большинство игры GBA используют его для аккомпанемента или эффектов. Более поздние оптимизировали музыку под PCM, а PSG оставили незадействованным.
Комбинирование
Наконец, все автоматически микшируется и выводится через динамик/разъем наушников.
Несмотря на то, что в GBA только два канала PCM, некоторые игры волшебным образом проигрывают более двух сэмплов одновременно. Как такое возможно? Хотя на бумаге наличие только двух каналов может показаться немного слабым, основной процессор может использовать часть своих циклов для обеспечения секвенирования и микширования звука [24] (это должно дать вам представление о мощности ARM7!). Более того, в разделе “Операционная система” вы узнаете, что в ROM BIOS-а входит аудиосеквенсор!
Лучшее из обоих миров
Некоторые игры развили концепцию дуальности PCM-PSG еще дальше и “сменяли” ведущий чип в зависимости от контекста.
В этой игре (Mother 3) игрок может войти в две разные комнаты, одна относительно нормальная, а другая в ностальгическом сеттинге. В зависимости от того, в какой комнате находится персонаж, одна и та же самая музыка будет звучать современно или восьмибитно.
Операционная система
Вектор сброса ARM7 находится по адресу 0x00000000
, который указывает на 16 КБ ПЗУ BIOS. Это означает, что Game Boy Advance сначала загружается из BIOS, который, в свою очередь, показывает знаменитую заставку, а затем решает, загружать игру или нет.
ПЗУ BIOS также хранит программные процедуры, которые игры могут вызывать для упрощения определенных операций и уменьшения размера картриджа [25]. К ним относятся:
- Арифметические функции: Процедуры для вычисления деления, квадратного корня и арктангенса.
- Вычисление аффинной матрицы: Получая значение “приближения” и угол, вычисляет аффинную матрицу, которая будет передана в PPU для масштабирования/поворачивания фона или спрайта.
- Есть две функции, одна для спрайтов, другая для фонов. Их параметры немного отличаются, но идея одна и та же.
- Функции разжатия данных: Реализует алгоритмы распаковки, такие как кодирование длин серий (run-length encoding, RLE), LZ77 и алгоритм Хаффмана. Он также обеспечивает распаковку битов и дельта декодирование.
- Копирование памяти: Две функции, которые перемещают память. Первая копирует 32-байтовые блоки, используя специализированный опкод для этого типа передачи (
LDMIA
для загрузки иSDMIA
для хранения) только один раз. Вторая копирует 2-байтовые или 4-байтовые блоки, используя повторяющиеся опкодыLDRH/STRH
илиLDMIA/STMIA
, соответственно. Таким образом, вторая функция является более гибкой, но не такой быстрой. - Звук: Реализует полноценный MIDI-секвенсор! Он включает в себя множество функций для управления им.
- Интерфейс питания: процедуры для сброса, очистки большей части оперативной памяти, остановки процессора до наступления определенного события (V-blank или пользовательского) или перехода в “режим низкого энергопотребления”.
- Мультизагрузка (Multi-boot): Загружает программу на другой GBA и запускает ее. Более подробную информацию можно найти в разделе “Игры”.
BIOS подключен через 32-битную шину и реализован с использованием комбинации инструкций Arm и Thumb, хотя последняя является наиболее заметной.
Также помните, что все это будет работать только на ARM7. Другими словами, эти операции не имеют никакого аппаратного ускорения. Таким образом, Nintendo обеспечила всю эту функциональность с помощью программного обеспечения.
Игры
Игры распространяются на новом проприетарном формате картриджей, он также называется Game Pak, но имеет меньший размер.
Программы для GBA чаще всего написаны на языке C с критичными по времени выполнения секциями на языке ассемблера (ARM и Thumb), чтобы сэкономить циклы. Nintendo предоставила SDK с библиотеками и компиляторами.
Программирование для GBA имело много общих методологий с Super Nintendo, но также унаследовало все преимущества разработки игр в начале 2000-х годов: стандартизированные языки высокого уровня, надёжные компиляторы, более быстрые RISC-процессоры, не проприетарные решения для разработки, сравнительно лучшая документация и… Доступ к Интернету!
Доступ к данным картриджа
Хотя ARM7 имеет 32-битную адресную шину, к картриджу подключено только 24 адресных линии.
Это значит, что в теории можно адресовать только 16 МБ данных с картриджа без использования маппера. Однако карта памяти гласит, что можно адресовать до 32 МБ ПЗУ картриджа. Как такое возможно? Дело в том, что Gamepak использует 25-битные адреса (что объясняет 32 мегабайтный блок), но младший бит адреса всегда равен нулю. Таким образом, только 24 бита имеют значение. Вот так работает адресация Game Pak.
Означает ли это, что данные, расположенные по нечетным адресам (с 1
в наименьшем значащем бите), будут недоступны? Нет, потому что шина данных 16-битная: При каждой передаче CPU/DMA получает расположенный байт плюс следующий, что позволяет читать как четные, так и нечетные адреса. Как видите, это еще одно произведение инженерной мысли, в котором полностью используются возможности аппаратного обеспечения при одновременном снижении затрат.
Любопытно, что 26-битные процессоры ARM также пользовались такой техникой. Они имели 24-битный программный счётчик, так как биты должны были быть кратным 8 (т.е. “выравненными по слову”), чтобы последние два бита 26-битного адреса всегда равнялись нулю. Однако так как эти процессоры считывают по 32 бита (первый байт и три последующих), можно получить доступ ко всему 26-битному адресному пространству.
Пространство оперативной памяти картриджа
Для хранения сохранений Game Pak-и могут включать [27]:
- SRAM: Нуждается в батарейке для сохранения своего содержимого и может иметь размер до 64 КБ (хотя коммерческие игры не превышали 32 КБ). Доступ к нему осуществляется через карту пространства памяти GBA.
- Flash ROM: аналогично SRAM без необходимости использования батареи, размер может достигать 128 КБ.
- EEPROM: Они требуют последовательного подключения и теоретически могут иметь любой размер (часто встречается до 8 КБ).
Аксессуары
Прежний разъём Game Boy Link обеспечивает возможность многопользовательской игры или получения дополнительного контента. Хотя, по какой-то причине они убрали ИК датчик (наверное, он был недостаточно надёжным для передачи больших объёмов).
Кроме того, в BIOS GBA встроена специальная функция, известная как Multi-boot: другая консоль (GBA либо GameCube) может отправить работающую игру в EWRAM получателя, а затем последний может загрузиться с неё (вместо Game Pak).
Борьба с пиратством и хоумбрю
В целом, использование проприетарных картриджей было большим препятствием по сравнению с постоянной игрой в кошки-мышки, с которой приходилось бороться другим производителям консолей при использовании CD-ROM.
Для борьбы с подделками картриджей (несанкционированными копиями) в BIOS GBA были встроены те же проверки загрузки, что и в оригинальном Game Boy.
Флеш-картриджи
По мере того как твердотельные накопители становились все более доступными, на рынке появился новый тип картриджей. Флэш-картриджи выглядели как обычные Game Pak-и, но имели дополнительную перезаписываемую память или слот для карт памяти. Это позволяет пользователям играть с ROM-файлов в консоли. Концепция на самом деле не нова, разработчики издревле использовали подобные инструменты для тестирования своих игр на реальной консоли (а производители предоставляли аппаратное обеспечение для этого).
Более ранние решения включали прошиваемую флэш память на технологии NOR (до 32 МБ) и некоторые SRAM с питанием от батареи. Для загрузки двоичных файлов на картридж в комплекте поставлялся кабель Link-to-USB, который использовался с GBA и ПК под управлением Windows XP. С помощью фирменной программы для прошивки и драйверов компьютер загружал в GBA программу multi-boot, которая, в свою очередь, использовалась для передачи бинарного файла игры с ПК на Flashcart (вставленный в GBA). В целом, весь процесс загрузки игры считался слишком медленным. Более поздние флэш-карты (например, “EZ-Flash”) предлагали больший объем памяти и возможность прошивки картриджа без использования GBA в качестве промежуточного устройства [29]. Последние полагались на съемные накопители (SD, MiniSD, MicroSD или любые другие).
Коммерческая доступность этих карт оказалась серой правовой зоной: Nintendo осуждала их использование из-за возможности пиратства, в то время как некоторые пользователи защищали, что это единственный способ запуска Homebrew (программ, созданных вне игровых студий и, следовательно, без одобрения Nintendo). Аргумент Nintendo был подкреплен тем, что такие прошивальщики, как EZ-Writer, помогали пользователям патчить игровые ПЗУ, чтобы они могли без проблем запускаться в картриджах EZ-Flash. После юридических попыток Nintendo эти картриджи были запрещены в некоторых странах (например, в Великобритании). Тем не менее они сохранялись повсеместно.
Вот и всё, ребята
Жаль, что у нее нет подсветки!