[Перевод] Nintendo DS: внутреннее устройство, принципы работы и взлом

image


Оригинальная Nintendo DS (Blue edition). Выпущена 21.11.2004 в Америке, 02.12.2004 в Японии и 11.03.2004 в Европе.

Краткое введение


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

CPU


Как и предыдущая портативная консоль Nintendo, эта система основана на большом чипе под названием CPU NTR. «NTR» — это сокращение от «Nitro», кодового имени оригинальной Nintendo DS.

В CPU NTR реализована интересная многопроцессорная архитектура с использованием двух разных процессоров ARM, эта структура была создана ещё до того, как ARM Holdings официально начала выпускать многопроцессорные системы. Поэтому их работу с учётом существовавшего тогда уровня технологий можно считать довольно нестандартной.
Хоть это и не первая параллельная система, анализируемая в моей серии статей, её структура сильно отличается от остальных. Например, здесь нет «экспериментальной» конфигурации master-slave, с которой дебютировала Saturn, или «сопроцессорной» структуры, использовавшейся в PS1 или N64. Nintendo DS содержит в себе два независимых компьютера, способных выполнять самостоятельные операции, каждый из которых имел выделенную шину. Такая созависимость предопределила общую производительность консоли.

Давайте взглянем на эти два процессора:

ARM7TDMI


923fuqmsy3wdnkkuhmoj-davkii.png


Структура и компоненты ARM7

Начнём с более знакомого нам, ARM7TDMI — это тот же самый процессор, который использовался в GameBoy Advance, но теперь работающий с частотой примерно 34 МГц (вдвое большей). Он по-прежнему содержит все свои возможности (в частности, Thumb).

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

ARM946E-S


eebb311c6ee626d213de27a72e5e17e1.png


Структура и компоненты ARM9

Это «главный» процессор Nintendo DS, работающий с частотой примерно 67 МГц. Если забыть о печальной судьбе серии ARM8, то можно сказать, что ARM946E-S стала «некстген»-версией ARM7. Это ядро, являющееся частью линейки ARM9, не только унаследовало все функции ARM7TDMI, но и добавило нечто новое:

  • ARMv5TE ISA: по сравнению с предыдущей версией v4, она имеет несколько новых инструкций и более быстрый умножитель.
    • Буква «E» в названии ядра означает Enhanced DSP, и это подразумевает, что многие из этих новых инструкций связаны с областями применения обработки сигналов.
  • 5-этапный конвейер: это прирост ещё одного показателя по сравнению с предыдущим конвейером из 3 этапов.
  • 12 КБ кэша L1: теперь ядро имеет кэш, в котором 8 КБ выделено под инструкции, а 4 КБ — под данные.
  • 48 КБ сильносвязанной памяти (Tightly-Coupled Memory), или TCM: она похожа на Scratchpad-память, однако в ней больший объём отдаётся инструкциям (32 КБ) в ущерб данным (16 КБ).


Nintendo также добавила к ядру следующие компоненты:

  • Блок делителя и вычисления квадратного корня для ускорения подобного типа операций (сам ARM9 неспособен выполнять такие вычисления).
  • Контроллер прямого доступа к памяти (Direct Memory Access, DMA): ускоряет передачу данных в память без зависимости от процессора. Благодаря использованию кэша процессор и DMA потенциально могут работать параллельно.
    • Кэш и DMA способны обеспечить большую производительность, но и создавать новые проблемы, например, проблему целостности данных. Поэтому программистам пришлось вручную поддерживать целостность памяти, например, очищая перед использованием DMA буфер записи.


Думаю, что учитывая наличие такого оборудования, легко понять, почему дети на самом деле любили эту консоль?

Взаимосвязь


Итак, мы рассказали о том, как два процессора работали по отдельности. Но чтобы работать как единое целое, им приходилось постоянно кооперироваться. Для этого оба процессора напрямую общались друг с другом при помощи специализированного блока FIFO; этот блок данных хранит две 64-байтных очереди (максимум 16 элементов) для двунаправленной коммуникации.

0c6eda8aa7a40f856fe393bca8fdbd61.png


Схема блока FIFO

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

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

Основная память


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

8834dc9e2b6397f47c753abfcd6d0372.png


Модель ОЗУ консоли

  • 32 КБ WRAM (рабочей ОЗУ, Work RAM), работающей с 32-битной шиной: использовалась для хранения быстрых данных, общих для ARM7 и ARM9.
    • Помните, что одновременно к одному адресу имел доступ только один процессор.
  • 64 КБ WRAM c 32-битной шиной: тоже для быстрых данных, но доступ к ним имел только ARM7, как и в GBA.
  • 4 МБ PSRAM с 16-битной шиной: более медленный тип памяти, доступный процессору и управляемый блоком интерфейса памяти.
    • Pseudo SRAM (псевдо-SRAM), или PSRAM — это разновидность DRAM, которая выполняет обновление внутри чипа. Следовательно, она ведёт себя как SRAM (более быстрая, но и более дорогая альтернатива DRAM). Такая схема напоминает мне о 1T‑SRAM консоли Gamecube.


Обратная совместимость


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

Но для использования в DS «внутреннего» GBA в консоль был встроен набор программных процедур, переключающих консоль в режим AGB Compatibility Mode. При этом они фактически останавливают ARM9, отключают большинство «особого» оборудования, выполняют переадресацию шин, делают ARM7 главным процессором и снижают его частоту до 16,78 МГц. Далее ARM7 начинает загружать исходный AGB BIOS, запускающий картридж GamePak (точно так же, как сам GameBoy Advance). Тем не менее, этот режим всё равно демонстрирует некоторые особенности, отсутствующие в оригинальной консоли, например, отображение игры в чёрной рамке (в следующем разделе мы увидим, что в новой консоли разрешение экрана стало выше). Кроме того, поскольку DS имеет два экрана, пользователи могут выбирать, какой из них будет использоваться для отображения игры GBA.

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

Секреты и ограничения


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

Неиспользованная мощь


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

Начнём с ARM9, этот процессор работает вдвое быстрее, чем ARM7, но большинство (если не все) операций ввода-вывода зависят от ARM7, поэтому ARM9 уязвим к простаиваниям в ожидании ответа ARM7. Мало того, внешняя шина ARM9 работает с половинной скоростью, поэтому возникает несколько «бутылочных горлышек».

К тому же шина основной памяти имеет ширину всего 16 бит. Следовательно, каждый раз, когда процессору нужно получить из памяти слово (шириной 32 бита), интерфейс приостанавливает процессор (ожидание может достигать до трёх циклов), пока не будет воссоздано полное слово. Сильнее всего это влияет на скорость, когда доступ к памяти не последовательный, из-за чего простаивание происходит при каждой операции доступа. Эта проблема также возникает при получении инструкций (к сожалению, в те времена ARM не поддерживал последовательное получение опкодов), что, к моему разочарованию, также влияет на код Thumb (потому что каждая операция получения 16 бит выполняется как 32-битный блок). С другой стороны, этот недостаток можно компенсировать благодаря полному использованию кэша и TCM.

В конечном итоге это означает, что в наихудшем случае «потрясающая» скорость ARM9 в 66 МГц практически снижается всего лишь примерно до 8 МГц. Так происходит, если программа ужасно использует кэш/TCM.

Вопрос о выборе оборудования


Когда я читал о процессоре GameBoy Advance, меня очень удивил потенциал ARM7: процессор не только выполнял предназначенные ему задачи, но и мог помогать с другими, например, с обеспечением секвенирования звука или созданием графики в псевдо-3D.

В процессе вывода ARM7 в коммерческую продажу ARM Holdings объединила усилия с DEC для создания высокомощной версии чипов ARM. Для этого DEC использовала структуру передачи данных своего процессора Alpha, и смешала её со структурой передачи данных ARM. В результате получилась новая серия процессоров, названная StrongARM, оказавшаяся на удивление быстрой. Ценой избавления от некоторых возможностей (Thumb и отладки) DEC смогла пересечь мегагерцовый порог и достичь скоростей до 233 МГц. Когда обычный пользователь собирался покупать новый PC на процессоре ARM (допустим, RiscPC), то он мог выбрать или машину со старым ARM710 на 40 МГц, или машину с StrongARM, работающим примерно на 582% быстрее. Влияние StrongARM было настолько фундаментальным, что ARM Holdings позаимствовала часть возможностей StrongARM для создания своей новой линейки процессоров, начиная с ARM9. Дальнейшее развитие истории нам известно.

Но вот в чём заключается мой вопрос: учитывая новые технологии в мире ARM, почему Nintendo в конечном итоге выбрала ужасно медленный ARM9 в сочетании с ещё более медленным ARM7, а не быстрый ARM9 (или даже StrongARM)? В то время другие компании как раз начали использовать StrongARM, например, Apple в своей линейке КПК Newton.

Я не хочу критиковать выбор Nintendo, но считаю, что этот вопрос нужно было обязательно задать, учитывая огромные объёмы зарождавшихся тогда технологий. Думаю, их выбор был вызван стремлением экономии заряда аккумулятора и снижения затрат на производство (благодаря использованию тех же процессоров, которые устанавливались в GBA).

Графика


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

Давайте начнём с физических характеристик: Nintendo DS содержит два ЖК-экрана, каждый из которых имеет размер 256×192 пикселя, то есть примерно на 20% больше пикселей, чем у GBA. Они могут отображать 262 144 цвета (18 бит) и обновляться с частотой примерно 60 Гц.

Архитектура


Графическая подсистема способна отрисовывать 2D и 3D-объекты. Первые состоят из двухмерной геометрии, заполняемой битовыми картами размером 8×8 пикселей (называемых тайлами), а последние отрисовывают трёхмерные объекты (четырёхугольники и прямоугольники) при помощи вершин.

Углубившись в изучение внутреннего чипа, управляющего этими экранами, мы заметим, что у консоли есть раздельное оборудование для 2D и 3D-геометрии. 2D-данные обрабатываются знакомым нам движком PPU (который теперь просто называется 2D engine), а 3D-данные обрабатываются совершенно новой подсистемой. Стоит заметить, что хоть это и не первая консоль, в которой появилась 3D-графика, она стала первой, в которой применяется собственная структура для рендеринга 3D-графики.

9df82a0a05db773440249a6fa7563cd0.png


Схема разных графических блоков

Эти движки должны быть привязаны к одному из экранов, и для 2D-игр это не проблема, потому что для каждого экрана есть свой 2D-движок. Однако для тех игр, которые хотят продемонстрировать современные технологии, есть только один 3D-движок. Следовательно, 3D-функции одновременно доступны только на одном из экранов. А как насчёт объединения 2D и 3D-объектов? Это возможно; позвольте мне объяснить каждый из движков по отдельности, чтобы мы могли обсудить это позже.

Построение кадра с 2D-графикой


Перед изучением каждого этапа рекомендую прочитать в предыдущей статье о PPU консоли GBA, потому что здесь я упомяну только те изменения, которые позволяют создавать 2D-игры «следующего поколения». Кроме того, поскольку существует два движка, один называется Main, а второй — Sub. Это не обязательно означает, к какому экрану подключен каждый из них. С другой стороны, Main содержит немного больше функций, чем Sub.

Чтобы объяснить на примере, на этот раз я позаимствую графику из New Super Mario Bros.

Тайлы


c0c7780e7a9cf612bb4a8ba303b94ab8.png


Некоторые из тайлов, находящихся во VRAM. Для демонстрации используется стандартная палитра

Теперь мы знаем, как в целом работает система тайлов, но как конкретно управляются тайлы на этой консоли? Доступно 656 КБ VRAM, и эта область разделена на разные банки: четыре по 128 КБ, один по 64 КБ, один по 32 КБ и три по 16 КБ. Программисты могут заполнять банки графикой и указывать движку, где находятся требуемые данные. Оба движка могут считывать любые из этих банков, но не могут получать доступ к нескольким одновременно.

Тем не менее, существуют определённые ограничения на распределение данных. Например, ARM7 может получать доступ только к двум банкам по 128 КБ. В то же время, эти два банка не могут хранить спрайты, а доступ к последнему банку на 16 КБ имеет только движок Sub. Есть и другие ограничения, но принцип понятен.

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

Типы фонов


Со времён Super Nintendo блок PPU обеспечивал всё большую гибкость при построении слоёв фонов. 14 лет спустя мы получили чип, способный читать тайлы и применять множество аффинных преобразований; более того, слой в конечном итоге может создаваться из буфера кадра.

Прежде чем мы приступим к обсуждению различных режимов, в котором может работать 2D-движок для генерации фонов, позвольте показать этот список с типами фонов, генерируемых движком:

  • Группа символьных типов: эти типы фонов соответствуют традиционной системе тайлов, кадр рендерится заполнением его тайлами.
    • Фон Static или Text: обычный фон. До 512×512 пикселя, 256 цветов и 16 палитр. Он содержит все стандартные эффекты (отзеркаливание по горизонтали/вертикали, скроллинг по горизонтали/вертикали, мозаика, альфа-смешение), плюс дополнительный эффект «затемнения». Может использоваться до 1024 тайлов.
    • Фон Affine: фон с аффинными преобразованиями. Однако он не позволяет отзеркаливать по горизонтали/вертикали и способен получать только 256 тайлов (четверть от максимального числа). Этот слой имеет размер 1024×1024.
    • Фон Affine Extended: такой же, как affine, но поддерживает полное количество тайлов и отзеркаливание по горизонтали/вертикали.
  • Группа битовых типов: вместо обработки тайлов движок воспринимает VRAM как буфер кадра. Все режимы наследуют эффекты, доступные из символьного аффинного фона.
    • 256 colours Extended: использует буфер кадра размером 512×512 пикселя.
    • Direct colour Extended: похож на предыдущий, но в нём буфер кадра поддерживает до 32 768 цветов (15 бит).
    • Large screen: съедает всю область 128 КБ VRAM для рендеринга большого буфера размером 1024×512 пикселя.


Эти режимы нельзя выбирать произвольно, консоль предоставляет набор режимов фонов с различными сочетаниями.

Режимы фонов


f3855f31472fd06323eb2c3bf2317c63.png


Layer 0

2c138bbc1523a0daef1f0312a5291b73.png


Layer 2

6c9b1d892c1cca7e9fa1c8a3edd214ab.png


Layer 3
Используемые аффинные слои. Layer 0 преобразуется в реальном времени для имитации движения облаков

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

  • Mode 0: 4 статических слоя.
  • Mode 1: 3 статических слоя + 1 аффинный слой.
  • Mode 2: 2 статических слоя + 2 аффинных слоя.
  • Mode 3: 3 статических слоя + 1 расширенный аффинный слой.
  • Mode 4: 2 статических слоя + 1 аффинный слой + 1 расширенный аффинный слой.
  • Mode 5: 2 статических слоя + 2 расширенных аффинных слоя.
    • Это самый часто используемый режим, потому что он невероятно гибок.
  • Mode 6: 1 статический слой, отрисовываемый 3D-движком + 1 large screen.
    • Так как место есть только для одного буфера кадра, этот режим доступен только для Main.


Спрайты


12b7ac952309f96ae4c09e04b184cff1.png


Отрендеренный слой спрайтов

Спрайты, или «объекты» наследуют все функциональные возможности из PPU консоли GBA, но имеют два важных дополнения.

Во-первых, OAM (область, в которой хранятся записи спрайтов) теперь имеет размер 2 КБ, что позволяет отображать на экране до 128 спрайтов на кадр. Следовательно, каждому из движков выделяется по 1 КБ.

Во-вторых, OAM теперь может ссылаться на битовые карты из VRAM, а не только использовать тайлы и палитры. Это ещё одно отличие от системы тайлинга. На самом деле, оба спрайтовых «режима» могут сосуществовать в одном кадре, потому что эта опция задаётся для каждого отдельного спрайта.

Результат


c344f140ee2a534831eda32feea94355.png


Все слои объединены… чего-то не хватает?

Так как каждый слой рендерится на лету, на последнем этапе всё объединяется и отправляется на выбранный экран. Это почти то же самое, что происходит в предыдущих консолях с PPU, но значит ли это, что работа закончена?

Ещё нет! Main всё ещё должен получить слой из ещё одного движка, самого мощного из них.

3D-ускоритель


Если вы играли в Nintendo DS, то знаете, что эта консоль способна отображать определённое количество 3D-графики. В отличие от графики некоторых игр для GBA, она не обрабатывается процессором. CPU-NTR содержит два компонента, составляющих 3D-движок. Довольно любопытно, что использованная Nintendo структура напоминает мне о RCP компании SGI.

Если вы вернётесь к разделу «Режимы фонов», то заметите, что каждый режим имеет по крайней мере один статический фон, потому что этот слой можно заполнить графикой, созданной 3D-движком. Единственная тонкость заключается в том, что это может делать только Main, и это одна из причин, по которой Mode 6 доступен только движку Main.

Движок геометрии


ab098cf1c2b89ff2b24eef103b90c4b6.png


Архитектура движка геометрии

Если вы читали какие-нибудь из статей о консолях четвёртого или пятого поколений, то можете задаться вопросом:, а где же SIMD-процессор? Это правильный вопрос, потому что ARM9 не особо хорошо справляется с векторными операциями и я не думаю, что для этого достаточно отдельного делителя. Именно поэтому Nintendo встроила в консоль компонент под названием Geometry Engine, занимающийся преобразованием вершин, проецированием, освещением, усечением, отсечением и сортировкой полигонов. Последняя функция необходима для правильного использования функций прозрачности.

Этот движок имеет строгие ограничения, в частности, на количество полигонов, которое он может обработать: доступны дополнительные 248 КБ ОЗУ, используемые для хранения обработанной геометрии; эта величина позволяет хранить до 2048 треугольников или 1706 четырёхугольников, хотя этот предел снижается из-за использования полос полигонов (а не отдельных полигонов). Чтобы получить представление о значении этого числа, рекомендую изучить разделы «interactive models» из предыдущих статей: вы увидите, что это ограничение довольно серьёзное, но не забывайте, что и разрешение у этой консоли гораздо меньше, что немного компенсирует проблему.

Как бы то ни было, этот движок управляется при помощи Command FIFO, заполняемого данными из процессора или DMA. FIFO хранит 256 элементов, однако дополнен ещё одним буфером под названием PIPE, который хранит ещё четыре команды (что в сумме даёт 260).

Движок рендеринга


ee37c928fc188cd48b58d802cbfb3a4e.png


Архитектура движка рендеринга

Это растеризатор, отвечающий за генерацию пикселей и наложение текстур. Для последней операции он использует коррекцию перспективы и затенение по Гуро. Более того, устройство обеспечивает такие современные функции, как Z-буферизацию, альфа-смешение, стенсил-тесты, туман и сглаживание.

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

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

Результат


8fbe52227455d50984d14ccfd781bf17.png


О, вот это уже неплохо

Вместо записи результатов обратно в буфер кадра для отображения движок рендеринга выполняет запись в блок под названием Colour Buffer, хранящий до 48 растровых строк. Каждая растровая строка получается 2D-движком для заполнения слоя BG0 в порядке FIFO.

3D-рендеринг начинается до 2D-рендеринга, что позволяет последнему при необходимости применять преобразования к новому слою. Main также позволяет захватывать 2D, 3D или сгенерированный комбинированный кадр, смешивать его с ещё одним кадром во VRAM и записывать результат обратно во VRAM, которую затем можно отобразить.

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

Сравнение известных игр


Одни из первых игр, выпущенных для этой консоли, пытались походить на игры с другой консоли (а именно Nintendo 64). Поэтому я бы хотел вкратце объяснить, почему игроки могли видеть значительные различия между двумя версиями:

Первый пример


23555efbcce4a7aed7e59eb115485a2b.png


Super Mario 64 (1996 год), отрендерен с разрешением 320×240 пикселей

dbf2b51c23f8df1ded63ab0c07b4027d.png


Super Mario 64 DS (2004 год), отрендерен в разрешении 256×192 пикселя

Второй пример


063c7a52384c94ebc7a711e5dc54f3c3.png


Mario Kart 64 (1996 год), отрендерен в разрешении 320×240 пикселей

4e97e60ef8890eba02a06be28f4ceb27.png


Mario Kart DS (2005 год), отрендерен в разрешении 256×192 пикселя

Давайте объясним происходящее в кадре на основании того, что говорят люди на форумах:

  • Текстуры NDS выглядят более угловатыми → движок рендеринга не применяет никаких фильтров, поэтому текстуры интерполируются по принципу «ближайший сосед».
  • Текстуры NDS выглядят насыщеннее → движок рендеринга не ограничен 4 килобайтами TMEM, ему доступно до 512 КБ VRAM (наряду с механизмами сжатия), поэтому можно загрузить больше данных.
  • Модели на NDS имеют пикселизированные края → модели на NDS рендерятся с более низким разрешением, чем на N64.
  • Вдалеке текстуры NDS выглядят искажёнными → движок рендеринга не использует координаты с плавающей запятой и субпиксельной точности. Свой вклад в искажения вносят и низкое разрешение с отсутствием mip-mapping.


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

Модели


Я дополнил wee model viewer алгоритмом «ближайший сосед», что позволяет визуализировать модели Nintendo DS на GPU. В оригинале статьи модели можно покрутить мышью.

New Super Mario Bros (2004 год), 636 треугольников


jhy3cnx_fingssmrikloqg15oj4.png


Модель

2rrkckm7we6dwlnecr0hxr9i74c.png


С текстурами

Nintendogs (2005 год), 750 треугольников


m-tccs-olunmxgmbjm0fygiqfzk.png


Модель

modyr604cwsyq6ceuaztjwtefro.png


С текстурами

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

Звук


Большинство улучшений звука касалось в совершенствовании каналов PCM, которые имелись у GBA. Как мы видели ранее, игры GBA отдавали приоритет программному секвенированию в ущерб PSG, и результат был довольно впечатляющим.
Last Window: The Secret of Cape West (2010 год). Демонстрация вывода микшированного стерео

Поэтому в новой аудиосистеме присутствует 16 каналов PCM, что позволяет передать задачи микширования оборудованию. PCM-сэмплы могут быть 8-битными (в стиле GBA), 16-битными (оптимальное разрешение) или ACPCM (сжатый вид). Как бы то ни было, микшер создаёт 32-килогерцовый стереосигнал, который можно воспроизводить через динамики (теперь стерео) или наушники. Также микшер может записывать полученные стереоданные во WRAM, что позволяет субпроцессору (ARM7) накладывать эффекты (например, реверберацию).

Мы ничего не забыли? Забыли — поскольку консоль может запускать игры GBA, у неё должно быть нечто, напоминающее PSG (реализованное программно или аппаратно). Выясняется, что последние 6 каналов могут стать PSG (любой из них синтезирует или импульс, или волну произвольной формы, а два из них создают импульс или шум).

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

Интерактивное сравнение


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

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

Некоторые проблемы


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

В первом примере слышно (особенно на последних 10 секундах), что сложно конкурировать с возможностями, которые предоставлял компонент S-SMP консоли SNES.

Ввод-вывод


Если вкратце, то ввод-вывод целиком обрабатывается ARM7. На самом деле, с этим CPU практически ничего не происходит, кроме передачи данных, что сильно расстраивает.

Доступ к картриджам и памяти


В консоли есть интерфейс внешней памяти, соединяющий три конечные точки: Slot-1 (куда подключаются картриджи Nintendo DS), Slot-2 (куда подключаются картриджи и аксессуары GBA) и 4 МБ PSRAM (основная память). К этому интерфейсу могут получать доступ оба CPU, но он содержит регистры, которые можно изменять для повышения приоритета одного CPU над другим на случай выполнения двух одновременных запросов по одной шине.

4849d702c7ef768fc89519d0bd5ee27b.png


Модель внешней памяти с указанием ширины шины данных

Важный аспект: карты DS не привязаны к памяти, поэтому для считывания данных игры любым процессором содержимое необходимо сначала скопировать ОЗУ. Это выполняется отправкой блокам картриджей 8-битных команд, ссылающихся на 32-битные адреса. После них данные можно получить вручную, доставая их из 32-битного регистра или через DMA. Шина данных имеет ширину 8 бит, но может достигать скоростей до 5,96 МБ/с (по утверждениям Nintendo).

К используемому для сохранений «backup»-чипу (например EEPROM, FLASH или FRAM) доступ осуществляется через шину SPI (последовательную), которая использует собственный набор команд и подключена к 24-битной адресной шине.

Картридж Slot-2 привязан к памяти исходным расположением контактов, однако в режиме DS адреса смещены для адаптации к оборудованию, предоставляющему расширенную функциональность (дополнительное ОЗУ, вибрация и т.д.). Как и у GBA, шина ROM имеет ширину 16 бит, а шина RAM — ширину 8 бит.

Периферия


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

Любопытная особенность этого сенсорного экрана заключается в том, что кроме распознавания позиций X/Y, он также может возвращать диагональную позицию (используемую для вычисления «значения давления», представляющее собой область, к которой прикладывается давление). К сожалению, об этом никогда не говорилось в официальном SDK, поэтому, насколько я знаю, ни в одной игре не использовалась эта незадокументированная особенность (кроме самодельных homebrew-игр).

Многие говорили, что в «Hotel Dusk: Room 215» эта функция использовалась в одной из головоломок, где игрок должен был одновременно коснуться экрана двумя пальцами. Однако это не так: после экспериментов с отладчиком no$gba выяснилось, что в головоломке не используются данные о давлении. Вместо него она проверяет, изменились ли сильно значения x/y. Игра интерпретирует этот эффект так, как будто игрок нажал на экран двумя пальцами.

Головоломка

d461d27424d329cd216ba43d07150c36.png


Hotel Dusk: Room 215 (2007 год) с вышеупомянутой головоломкой с распределительным щитом. Чтобы спасти девушку, игрок должен одновременно свайпнуть по экрану двумя пальцами, чтобы включить свет

Неудача

398e559bd9e77ffae79f1a4170e40cda.png


Но если сделать это неправильно…

Наконец, в том же стеке находятся часы реального времени, или RTC.

Беспроводная сеть


Также консоль содержит контроллер беспроводной сети, работающий в полосе частот 2,4 ГГц и обеспечивающий инновационные возможности:

  • Игра по Интернету: позволяет любой игре подключаться к LAN-сети по стандартному соединению Wi-Fi.
  • Многокартная игра: до 16 консолей обмениваются друг с другом данными по проприетарному протоколу.
  • Однокартная игра: игра может загрузить программу на другую DS, в которую не вставлена карта с игрой.


Операционная система


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

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

Точка входа


На определённом этапе ARM7 и ARM9 потребуется инициализировать оборудование и для этого NTR-CPU содержит два отдельных неболь

© Habrahabr.ru