Опорные изображения
Модель
Материнская плата
Диаграмма
Краткое введение
Sony знала, что разработка железа для 3D может оказаться очень сложной. Однако их дебютная консоль сохранит свой дизайн простым и практичным… Хотя ради этого пришлось чем-то пожертвовать!
Процессор
В этом разделе рассматривается чип Sony CXD8530BQ, один из двух больших чипов, установленных в этой консоли. Сегодня это то, что мы бы назвали “Системой-на-Кристале” (System-on-Chip, SoC).
Истоки
Про основной процессор можно сказать типичное “он разработан кем-то, основан на чём-то и получен от кого-то”, но нельзя просто ограничиться историей в пару предложений. Так почему бы нам не начать с предыстории?
Немного истории
Начало 90-х годов ознаменовалось изменением судеб многих популярных процессоров. Некогда лидирующие 8-битные процессоры, такие как Z80 и 6502, уже давно не рассматривались, а знаменитый Motorola 68000, наряду с другими 16-битными разработками, которые пользовались успехом в конце 80-х годов, стали кандидатами на замену. Даже в мире ПК в это время Таненбаум в своем знаменитом споре с Торвальдсом только дал архитектуре x86 от Intel ещё пять лет до её ухода с домашнего рынка.
Сначала может показаться, что технологическое развитие на этом этапе зашло в тупик. Но на самом деле это была новая волна относительно неизвестных процессоров, пробивающих себе дорогу в массовые устройства. Многие из этих разработок были созданы в академических кругах и существовали для того, чтобы доказать определенные наборы конструкторских идей. Примерами новых процессоров этой эпохи являются:
- MIPS: принят Silicon Graphics Incorporated (графические рабочие станции).
- PowerPC: принят Apple (настольные системы для издательств).
- SPARC: создан Sun Microsystems (сервера и рабочие станции для бизнеса).
- ARM: создан Acorn (изначально был нацелен на потребительский рынок, а затем на КПК и сотовые телефоны).
- … и куча других “микроконтроллеров”, которым ещё только предстояло завершение разработки или принятие какой-либо индустрией, таких как Hitachi SH или NEC V810. К удивлению разработчиков, эти чипы были выбраны для Sega Saturn и Nintendo Virtual Boy соответственно.
Все эти процессоры имели нечто общее: они следовали принципам Reduced Instruction Set Computer (RISC), которые радикально изменили подход к проектированию и программированию этих чипов. Одно из правил RISC-процессоров гласило, что одна инструкция не может сочетать в себе операции с памятью и регистрами. Это позволило разработчикам аппаратного обеспечения упростить схему, выполняющую инструкции… а затем усовершенствовать её с помощью методов параллелизма.
MIPS и Sony
MIPS Computer Systems возникла из желания её основателей (Стэнфордского факультета) воплотить свои исследования в физический процессор, во что венчурные капиталисты Кремниевой Долины 80-х не очень хотели вкладываться [2]. Их дебютный процессор “MIPS R2000” считается первым коммерческим ЦП, реализовавшим модель RISC. Этот процессор хорошо себя зарекомендовал во многих рабочих станциях UNIX.
Однако только в 1987 процессоры MIPS стали предметом обсуждения после того, как их приняла (а затем и приобрела) компания Silicon Graphics Incorporated (SGI) для встраивания в своё оборудование. SGI была влиятельным новатором на рынке компьютерной графики, особенно в разработке аппаратно-ускоренных вершинных конвейеров, задача которых изначально выполнялась программно (в рамках центрального процессора). После приобретения SGI заняла лидирующие позиции как в сфере процессоров, так и в сфере графики.
До начала разработки PlayStation MIPS перешла на бизнес-модель на основе лицензирования интеллектуальной собственности, в которой их проекты ЦП продавались в виде лицензий, а лицензиаты могли свободно их менять и производить. Одним из их предложений был процессор R3000A, находящийся в их бюджетном каталоге. Следовательно, серия R3000A не была частью флагманской линейки (в отличие от R4000, которую позже выберут другие), но она была привлекательной инвестицией с точки зрения стоимости.
Возвращаясь к главной теме, Sony разработала свои аудио- и графические чипы собственными силами, но им все еще нужен был ведущий чип, который мог бы управлять этими двумя устройствами. Выбранный процессор должен был быть достаточно мощным, чтобы демонстрировать впечатляющие возможности чипов Sony, но при этом быть доступным, чтобы сохранить конкурентоспособную цену консоли.
LSI и заказы
В то же время компания LSI Logic (производитель полупроводников) была лицензиатом MIPS, который предоставлял бизнесу программу “сборки собственного процессора”. Эта услуга называлась CoreWare, и она позволяла клиентам создавать свои собственные процессоры, выбирая серию строительных блоков [3]. Библиотека CoreWare включала в себя блок “CW33300”. Это было процессорное ядро, основанное на LSI LR33300 - готовом чипе, который компания LSI также продавала.
Итак, к чему я всё это говорю? Оказывается, что LR33300 и CW33300 от LSI - бинарно-совместимые версии чипов линейки MIPS R3000A. Их архитектуры немного отличаются в некоторых областях, но интерфейс программирования (набор инструкций MIPS I) остаётся одинаковым.
В конечном итоге Sony поручила LSI создать свой процессор. Они выбрали CW33000, изменили некоторые биты и объединили его с другими блоками, чтобы сформировать чип, который можно найти на материнской плате PlayStation.
Предложение
Полученное ядро процессора работает на частоте 33.87 МГц и имеет следующие характеристики:
- Набор инструкций MIPS I: первая версия набора инструкций MIPS. Кроме всего прочего, длина слов составляет 32 бита, а набор включает в себя инструкции умножения и деления.
- 32 регистра общего назначения и 2 регистра умножения и деления: это также 32-битные регистры. Один регистр общего назначения всегда равен нулю (
R0
), что характерно для процессоров RISC. - 32-битная шина данных: в PS1 шина данных разделяется на две шины.
- Главная шина (32 бита) → Подключается к MDEC и GPU.
- Подшина (16/8 бит) → Соединяет остальные чипы и I/O. Эта шина присоединена с помощью блока Bus Interface Unit, который дает доступ к специальным портам GPU и SPU.
- 32-битная шина адреса: может быть адресовано до 4 ГБ физической памяти (т.е. ОЗУ, доступ к вводу-выводу через память и т.д.).
- 5-уровневый конвейер: позволяет выполнять до 5 инструкций одновременно (более подробную информацию можно найти в предыдущей статье).
- 4 КБ кэша инструкций: он также может быть “изолирован”, позволяя программе напрямую управлять кэшем инструкций.
- Как ни странно, кэша данных нет. 1 КБ памяти, обычно используемый для кэша данных, отображён на фиксированный адрес [4]. Эта область также называется Scratchpad (быстрая SRAM).
Чтобы сделать хоть что-нибудь полезное, Sony добавила 2 МБ оперативной памяти для общего использования. Любопытно, что они установили на материнской плате чипы Extended Data Out (EDO). Они немного более эффективны, чем обычная память DRAM, и обеспечивают меньшую задержку.
В обход CPU
Рано или поздно любая подсистема, будь то графическая, аудио или CD, потребует большие фрагменты данных на большой скорости. Однако ЦП не всегда может поспевать за спросом.
По этой причине контроллеры CD-ROM, MDEC, GPU, SPU и параллельного порта имеют прямой доступ к контроллеру DMA, когда это им необходимо. DMA берёт на себя управление главной шиной и осуществляет передачу данных. Таким образом мы получаем высокую скорость, которую невозможно достичь используя только процессор, хотя он всё ещё нужен для настройки передачи DMA.
Также стоит учесть, что как только DMA примется за работу, ЦП больше не сможет обратиться к главной шине. А значит, процессор будет находиться в ожидании, если только у него нет чего-нибудь, что можно сделать в Scratchpad!
Дополняя ядро
Как и другие процессоры, основанные на MIPS R3000, CW33000 поддерживал конфигурацию с 4 сопроцессорами. Sony добавила три чипа:
System Control Coprocessor
Обозначенный как “CP0”, System Control Coprocessor (Сопроцессор Управления Системой) является типичным блоком, находящимся в процессорах MIPS. В системах на основе R3000, подобных этой, CP0 управляет реализацией кэша. То есть он разрешает прямой доступ к кэшу данных (в форме “Scratchpad”) и кэшу инструкций (используя “изоляцию кэша”). Сопроцессор управления также отвечает за обработку прерываний, исключений и точек останова, полезных во время отладки.
Погодите, разве сопроцессоры не должны только расширять функционал ЦП? Почему CP0 так тесно связан с центральным процессором?
И действительно, ядра R3000 зависят от сопроцессора управления системой для использования многих компонентов, но “законно” ли так делать или нет сводится к интерпретации слова “сопроцессор”. Согласно MIPS, сопроцессор не обязан быть строго дополнением к ЦП, он также может командовать его окружением (кэш, прерывания и т.д.). То есть сопроцессор может быть неотъемлемой частью системы. Это всего лишь то, что нужно иметь в виду, когда речь идёт о системах MIPS.
Позже системы на основе R4000 встроили в этот блок Memory Management Unit (MMU, блок управления памятью) и Translation Lookaside Buffer (TLB, буфер ассоциативной трансляции), тем самым расширив его возможности и предоставив ему новые роли.
Geometry Transformation Engine
“CP2” или Geometry Transformation Engine (GTE, Движок Преобразования Геометрии) — это специальный математический процессор, который ускоряет векторные и матричные вычисления.
Хоть GTE и работает только с числами с фиксированной точкой, он всё ещё предоставляет полезные операции с 3D графикой, такие как:
- Произведение и сумма матриц или векторов, а также квадрат вектора.
- Перспективное преобразование (используется для 3D проекций).
- Тензорное произведение двух или трёх векторов (последнее используется для отсечения).
- Многие функции интерполяции, использующие различные параметры.
- Определение глубины и значения цвета от источника света (используется для операций с освещением и цветом).
- Среднее значение глубины/оси Z (Подозреваю, что это предназначено для “таблицы упорядочения”, подробнее об этом в разделе “Графика”).
Вам не нужно помнить всё это, чтобы понимать следующие главы этой статьи! Просто имейте в виду, что GTE позаботится о первых этапах графического конвейера, таких как 3D проекция, освещение и отсечение. Это поможет сгенерировать необходимые данные, которые будут переданы ГП для рендеринга.
Motion Decoder
Motion Decoder, также известный как “MDEC” или “Macroblock Decoder”, это ещё один процессор, живущий по соседству с центральным процессором. На этот раз он распаковывает “макроблоки” (Macroblock) в такой формат, который понимает ГП. Макроблоком называется структура данных, хранящая в себе картинку с кодировкой, аналогичной JPEG.
MDEC распаковывает изображения, составленные из блоков 8 на 8 пикселей с глубиной цвета 24 бит. Руководство по программированию Walker гласит, что MDEC может вычислить до 9000 макроблоков в секунду. Это позволяет достичь стриминга full-motion video (FMV, буквально “полностью подвижное видео”) в разрешении 320x240 пикселей в 30 кадрах в секунду.
DMA используется для передачи сжатых данных от CD-ROM в MDEC через ОЗУ. Этот же путь данные проделывают и в обратном направлении, правда на этот раз пунктом назначения является VRAM.
Хотя этот компонент и расположен внутри SoC и разделяет одну шину данных, он не является сопроцессором MIPS, так что ЦП и DMA обращаются к нему через размеченную память (в отличие от перехвата инструкций).
Для получения более подробной информации о блоке MDEC, я советую ознакомиться с ресурсами Sabin [5] и Czekański [6].
Ничего не пропустили?
Итак, у нас есть “CP0” и “CP2”, но где же “CP1”? Ну, это место зарезервировано под Floating Point Unit (FPU, математический сопроцессор) и, боюсь, Sony решили не добавлять его. Это не означает, что процессор не может выполнять вычисления с десятичными числами, это просто будет не так быстро (программная реализация FPU) или не так точно (вычисления с фиксированной точкой).
Игровая логика (включающая физику, обнаружение столкновений и т. д.) все еще может обойтись числами с фиксированной точкой. Формат с фиксированной точкой хранит десятичные числа с неизменным количеством знаков после запятой. Это подразумевает потерю точности после некоторых операций, но помните, что это игровая консоль, а не профессиональный авиа симулятор. Именно поэтому целесообразно пожертвовать точностью ради производительности.
Кстати, если вы хотите вспомнить, что такое “фиксированная точка”, “плавающая точка”, “десятичные числа” и “целые числа”, я рекомендую взглянуть на пост Габриэля Иванческу с кратким обзором этих понятий [7].
Изобилие задержек
Как мы уже видели ранее, процессор CW33300 реализует вычислительный конвейер, то есть процессор может поставить несколько инструкций в очередь и выполнить их параллельно на разных этапах. Это значительно повышает пропускную способность инструкций, но неправильное управление может привести к конфликтам конвейера и, следовательно, к вычислительным ошибкам.
Архитектура MIPS I подвержена следующим проблемам [8]:
- Конфликты управления: Инструкции могут выполниться тогда, когда не надо
- Конфликты данных: Инструкции могут работать с устаревшими данными до того, как они обновятся.
Следовательно, процессоры MIPS I демонстрируют следующее поведение:
- Всякая инструкция, следующая за опкодом типа “ветвление” или “прыжок”, выполняется в любом случае: Поэтому разработчикам приходилось вручную заполнять конвейер небольшими инструкциями (например,
посчитать 0 плюс 0
) после условного перехода или прыжка во избежание конфликтов. Эти заполнители также называются слотами задержки ветвления (branch delay slots).- Современные процессоры превратили это явление в преимущество - предсказание переходов. Добавив особую схему для определения конфликтов, ЦП сможет отбросить результат новых вычислений, если условие перехода/ветвления не было выполнено. А если условие удовлетворено, то процессор сэкономит немного времени.
- Инструкции для загрузки данных не останавливают конвейер до тех пор, пока не станут доступны требуемые данные: Второй этап конвейера (называемый
RD
или “Read and Decode”, “Чтение и Декодирование”) получает операторы [9], которые будут использованы при вычислениях на третьем этапе (АЛУ
). Четвёртый этап (MEM
, от “access MEMory”, “получить доступ к памяти”) ищет данные в памяти (например, основное ОЗУ, CD-привод и т.д.). И вот тут возникает проблема: к тому времени, как инструкцияload
получит данные извне, следующая инструкция уже получила операторы. Это значит, что инструкция, зависящая от значений после вызова предыдущей инструкцииload
, требует пустую инструкцию между ними, чтобы правильные операторы смогли загрузиться вовремя.
Как мы видим в примере, некоторые слоты задержки заполнены полезными инструкциями, которые выполняют вычисления, не подверженные конфликтам. Так что слоты задержки не всегда подразумевают пустую трату циклов.
После всего вышесказанного вы наверняка задаётесь вопросом о том, как процессор с такими недостатками мог вообще продаваться. Одна из основных идей RISC - это перенос бремени программирования процессора с разработчика на компилятор. MIPS в частности отдавал приоритет производству качественных компиляторов (в том числе ассемблеров) в дополнение к своим новым процессорам [10]. Таким образом, разработчики могли пользоваться языками высокого уровня (например, Си), в то время как инструментарий разбирался с конфликтами (меняя порядок инструкций, чтобы заполнить слоты, или в крайнем случае добавляя бессмысленные инструкции). Так что, хотя я не нахожу приятными процессоры, заполненные “пузырями”, мне кажется, что в MIPS очень умно решили эти проблемы.
Графика
Вкратце, большую часть графического конвейера берет на себя GTE. Он обрабатывает преобразование перспективы (которая позволяет создавать 3D-пространство на 2D-плоскости, используя ракурс камеры) и освещение. Затем обработанные данные передаются в проприетарный GPU Sony для рендеринга.
Организация контента
Система обладает 1 МБ VRAM, используемым для хранения буфера кадра, текстур и других ресурсов, которые могут потребоваться GPU для отрисовки сцены. Центральный процессор может заполнить эту область с помощью DMA.
Оперативная память типа VRAM является двухпортовой, как в Virtual Boy. VRAM использует две 16-битные шины, которые допускают одновременный доступ между ЦП, DMA, ГП и кодировщиком видео.
Однако в последующих ревизиях этой консоли Sony перешла на чипы SGRAM (вариант с одним портом, использующим одну 32-битную шину данных). Фу!… Ну, справедливости ради, оба вида чипов имеют свои плюсы и минусы. Одно можно сказать наверняка: из-за разницы в таймингах поздние игры (такие, как Jet Moto 3) будут показывать неправильную картинку на системах, использующих VRAM. Если вы хотите узнать поподробнее о таких вещах, как разные тайминги, в “Nocash PSX Specifications” от Martin Korth документированы многие подобные особенности [11].
Создание сцены
Если Вы читали статью о Sega Saturn, то я могу сказать, что дизайн этого GPU намного проще!
Итак, чтобы продемонстрировать, как рисуется сцена, я буду в основном использовать Spyro: Year of the Dragon от Insomniac в качестве примера. Имейте в виду, что внутреннее разрешение этой игры слишком мелкое (292 на 217 пикселей). Это не даёт мне чётко разобрать сцену на каждом этапе, поэтому я немного увеличил его для демонстрационных целей. Вот образец в оригинальном масштабе, если вам интересно.
Команды
Для начала, ЦП посылает геометрические данные (вершины) в ГП, заполнив его внутренний 64-байтовый FIFO-буфер командами (до трех штук). Эти команды могут запрашивать отрисовку чего-либо на GPU, изменять настройки или манипулировать видеопамятью.
По сути, команда отрисовки описывает, как и где рисовать примитив. ГП может рисовать индивидуальные линии, прямоугольники и треугольники - последние являются основным ингредиентом для композиции сложных 3D моделей.
После получения геометрии применяется отсечение (clipping), чтобы пропустить невидимые полигоны (в том числе и те, которые расположены за пределами обзора камеры).
Расположение примитива определяется координатной системой X/Y, указывающей на буфер кадра. GPU PS1 использует целочисленную модель координат, где каждая координата соответствует центру пикселя (под названием точка сэмплирования). Другими словами, тут нет дробных координат.
Подход к видимости
PS1, как и её конкуренты, не имеет какого-либо аппаратного решения проблемы видимости. Тем не менее GPU обрабатывает сортировку полигонов, предоставляя таблицу упорядочения: выделенную таблицу, в которой каждая запись индексируется с использованием значения глубины (также называемого “Z-значением”) и содержит адрес команды для GPU [13].
Процессор должен сначала вручную отсортировать полигоны, а затем сослаться на них в нужной записи таблицы. Наконец, CPU приказывает DMA отправить таблицу на GPU. Этот процесс позволит GPU рендерить геометрию в правильном порядке.
Для оказания помощи как ЦП, так и ГП в создании этой таблицы и прохода по ней также предоставляются различные функции DMA.
Растеризация
Как только графический процессор декодирует команды, наступает время преобразовать полученную геометрию (вершины) в пиксели. Это позволит системе произвести наложение текстур, эффектов и в конце концов вывести их на двумерную панель (ваш телевизор или монитор). Для этого GPU выделяет матрицу пикселей, используемую в качестве рабочей области, которая называется кадровым буфером. По сравнению с более сложной Sega Saturn, для GPU нужен только один кадровый буфер.
Растеризатор - это устройство, отвечающее за преобразование векторов в линии, треугольники или прямоугольники, а затем их в пиксели. Обработка сильно разнится в зависимости от запрошенного примитива [14]:
- Треугольники - самый сложный (и универсальный) тип, на который можно наложить текстуру и затенение.
- Линии проще всего рисовать, но естественно они не подходят для текстурированных поверхностей. Хотя они всё ещё могут быть затенены.
- Прямоугольники также быстрее в отрисовке, но могут уместить только спрайт размером до 256 x 256 пикселей (увеличение размера приведёт к дублированию рисунка спрайта). Тем более они не предоставляют аффинные преобразования (кроме отражения по осям X/Y), затенения или эффектов. Подозреваю, что это сделали для содействия в разработке 2D игр.
В случае треугольника, единственного текстурируемого полигона, растеризатор сделает следующее:
- Соберёт каждую вершину из трёх точек и вычислит грани. Они формируют треугольник.
- Проанализирует область треугольника, чтобы понять, какие пиксели кадрового буфера он занимает. Только секция треугольника, перекрывающая точки сэмплирования, превращается в пиксели.
Сгенерированные пиксели не сразу попадают в буфер кадра. Вместо этого они отправляются на следующие стадии конвейера для дальнейшей обработки, которую мы рассмотрим в следующих пунктах.
Шейдеры
Для применения световых эффектов над треугольниками или линиями графический процессор предоставляет два алгоритма:
- Плоское затенение: каждый примитив обладает одним постоянным уровнем освещённости.
- Затенение Гуро: Каждая вершина примитива имеет свой собственный уровень освещённости. Затем, яркость между каждой точкой автоматически интерполируется.
- Как вы можете себе представить, этот тип предлагает более реалистичные результаты, чем плоское затенение.
Выбирать между ними приходится потому что плоское затенение заполняет примерно в 2,5 раза больше полигонов в секунду, чем по Гуро. Поэтому важно учитывать то, какие полигоны нуждаются в более реалистичном затенении, а какие нет.
Текстуры
Треугольные поверхности ещё могут быть смешаны с текстурами (растровыми 2D изображениями), чтобы получить конечный результат.
Графический процессор выполняет обратное наложение текстур, которое заключается в прохождении по каждому растеризованному пикселю и поиске соответствующего ему пикселя на текстуре (под названием тексель). Тексели рассчитываются с использованием линейной интерполяции текстуры (находящейся в VRAM) для соответствия форме полигона. Процедура, используемая для интерполяции, называется аффинным наложением текстур. Эта техника работает только с двумерными координатами (значения X и Y), отбрасывая тем самым третью координату (Z или “глубину”), используемую для перспективы.
Так как текстуры редко совпадают по размерам с растеризуемым полигоном, может возникнуть алиасинг (неправильные результаты). Он проявляется нежелательными искажениями, такими как пропущенные или увеличенные тексели. Чтобы избежать алиасинг, сложные ГП применяют фильтрацию текстур для сглаживания (интерполяции) резких изменений цвета. В нашем случае ГП PS1 не реализует какой-либо фильтр, так что он обходится алгоритмом ближайшего соседа для исправления масштаба без сглаживания результата. Этот алгоритм очень быстрый (и дешёвый), но это также объясняет, почему текстурированные модели могут выглядеть, как будто сделаны из блоков.
Блок GPU также включает в себя следующие возможные эффекты (для треугольников):
- Полупрозрачность: Симулирует свет, проходящий через несколько текстур.
- Дизеринг: Смягчает резкие изменения цвета, придерживаясь одной и той же цветовой палитры.
Стоит отметить, что PS1 преуспела в этих эффектах!
Оставшиеся шаги
После завершения отрисовки, ГП записывает пиксели в область кадрового буфера в VRAM, которая потом используется кодировщиком видео и выводится на экран.
Дизайны
Давайте сделаем перерыв от всей этой теории. Вот несколько примеров игровых персонажей, разработанных с нуля для эры 3D. С ними можно взаимодействовать, поэтому я предлагаю вам их оценить!
Работа с VRAM
С доступным объемом VRAM (целый мегабайт) возможно разместить огромный буфер кадра размером 1024×512 пикселей с 16-битными цветами или практичный размером 960×512 пикселей с 24-битными цветами, позволяющий рисовать лучшие кадры, которые когда-либо показывала любая игра… Звучит впечатляюще, не правда ли? Что ж, тут возникают некоторые трудности, например:
- Эти размеры должны быть масштабированы в соответствии со стандартизированным разрешением (например, 480 NTSC, 576 PAL), чтобы видеокодер смог их отобразить на потребительских телевизорах.
- Как GPU сможет нарисовать что-нибудь достойное, если не осталось места для оставшихся материалов (например, текстур, таблиц цветов и так далее)?
- GPU в PS1 может рисовать только буферы кадра размером до 640×480 пикселей с 16-битными цветами.
Хорошо, давайте вместо этого возьмём буфер размером 640x480 с 16-битными цветами, что оставляет для материалов 424 КБ VRAM. Пока все хорошо. И опять же, такое разрешение будет неплохо выглядеть на мониторах с ЭЛТ, но на тех телевизорах, которые имелись у каждого в доме в 90-х годах, разница неощутима. Так если ли способ оптимизировать буфер кадра ещё лучше? Знакомьтесь, настраиваемые кадровые буферы.
По сути вместо того, чтобы тратить драгоценную VRAM на “неприемлемые” разрешения, графический процессор этой консоли позволяет уменьшить буфера кадра, чтобы фактически увеличить свободное место, доступное для других ресурсов. В “Gears Episode 2” [15] Halkun показывает способ, позволяющий разделить буфер с разрешением 640x480 на два по 320x480, а затем полагающийся на технику под названием page-flipping для отрисовки одновременно нескольких сцен.
Данная техника заключается в переключении расположения кадра для экрана между двумя доступными всякий раз, когда игра этого захочет, что позволяет игре рисовать одну сцену, пока на экране отображена другая. Это позволяет избежать мерцания и улучшить время загрузки (то, что игрок, безусловно, оценит!).
В целом, предложенная Халкуном компоновка потребляет всего 600 КБ VRAM. Остальная часть (424 КБ) может использоваться для хранения таблиц цветов и текстур. В сочетании с доступным кэшем текстур объемом в 2 КБ получается очень удобная и эффективная конфигурация.
Наконец, стоит упомянуть, что VRAM может быть заполнена с помощью нескольких цветовых глубин одновременно. Это означает, что программисты могут выделить 16-битные буферы рядом с 24-битными изображениями (используемыми, например, кадрами FMV). Это еще одна особенность, которая облегчает дальнейшую оптимизацию.
Секреты и ограничения
Хоть PS1 и имеет очень простую и удобную архитектуру, проблемы в любом случае будут возникать. Удивительно, что некоторые из них были решены весьма умными трюками!
Искажённые модели и текстуры
Известно, что процедуры, используемые для обработки геометрии и наложения текстур, содержат некоторые неточности.
Для начала, растеризатор работает только с целыми пикселями: В то время как координаты вершин заданы целыми числами, вычисляемые края треугольника могут занимать только долю пикселя. Однако растеризатор нарисует пиксель только если область треугольника покрывать точку сэмплирования пикселя, и он не будет запоминать занимаемую долю [16]. Это порождает некоторые проблемы:
- Внешние грани моделей делают внезапные скачки при малейшем движении.
- Треугольники внутри полигональной сетки (разделяя одни и те же вершины и рёбра) будут “бороться” за право отобразиться на одних и тех же пикселях. С таблицей сортировки ГП будет рисовать по принципу “последним пришёл - первым ушёл”, что может привести к мерцанию пересечений треугольников или появлению пересечений при небольших движениях.
Обычно это решается реализацией субпиксельного разрешения, с которым растеризатор следит за долями пикселей, занимаемыми областью каждого треугольника [17]. Следовательно, для смягчения резких краёв или резких изменений цвета можно применить методы антиалиасинга.
Переходим к таблице упорядочивания. Она переносит бремя отображения геометрии в правильном порядке на разработчика или программу. В некоторых случаях вычисления опираются на слишком много приближений ради повышения производительности. Это может привести к мерцанию или окклюзии поверхностей, которые должны быть отображены.
Более того, уменьшение разрешения буфера кадра может усилить все эти проблемы с алиасингом.
В конце концов, как вам известно, аффинные преобразования игнорируют глубину перспективы. Это может сбить с толку восприятие пользователя, когда камера находится близко к модели и расположена перпендикулярно зрителю [18]. Этот эффект также называют искажением текстур (texture warping). Поэтому для устранения искажения некоторые игры прибегают к тесселяции (разделение большого полигона на несколько маленьких), а другие просто заменили текстуры на сплошные цвета. В общем, GPU решает эту проблему путём применения коррекции перспективы, которая интерполирует текстуры с помощью значения глубины.
Противоречивые утверждения
Зайдя на различные технические каналы или форумы, вы обнаружите альтернативные объяснения об эффектах тряски/искажения на PS1. Некоторые из них совпадают с тем объяснением, которое я дам ниже, но другие могут доказывать обратное. Так что я бы хотел поделиться своим мнением о том, почему следующие заявления не соответствуют действительности:
Модели/текстуры трясутся из-за отсутствия FPU
FPU не определяет возможность компьютера работать с дробными числами. Как и любой другой компьютер без FPU, PS1 по-прежнему может выполнять арифметику с фиксированной точкой. Более того, с помощью программной эмуляции можно также вычислять и числа с плавающей точкой (хотя и не так быстро). Короче говоря, FPU - это просто ускорители, не путайте их с ALU (арифметико-логическое устройство, важная часть процессора, которая делает вычисления) или десятичными числами.
Модели/текстуры трясутся из-за использования целочисленных координат в ГП
Применение целочисленных координат является распространённым подходом к снижению стоимости вычислений на GPU. Проблема в неиспользовании субпиксельного разрешения, что приводит к заметным артефактам. В общем, можно было применить антиалиасинг для сглаживания резких изменений в цвете, если бы растеризатор хранил долю пикселя, занимаемую треугольником.
Текстуры искажаются из-за отсутствия MIP-текстурирования
Графические процессоры, которые реализуют обратное наложение текстур, как в нашем случае, подвержены ошибке измерения под названием “undersampling” (один пиксель наложен на несколько текселей). Это и создаёт алиасинг (неправильные результаты). Поведение заметно при отображении геометрии вдалеке от камеры. Для исправления этой проблемы современные устройства наложения текстур применяют “трилинейную фильтрацию”, которая смягчает тексели, использующие те же текстуры, но в разных масштабах (MIP-текстуры) и применяет интерполяцию между ними. То есть, MIP-текстурирование - это подход к решению алиасинга. Проблема в аффинном наложении текстур (не имеющем коррекции перспективы), которое интерполирует текстуры на трёхточечных поверхностях, не учитывая глубину. Отсюда и берётся эффект “искажения”.
Модели/текстуры мерцают из-за отсутствия Z-буферизации
ГП с Z-буфером решает проблему определения видимых поверхностей на аппаратном уровне. PS1 полагается на таблицу сортировки, а это значит, что разработчики берут ответственность за то, какая геометрия будет стоять перед какой. Короче говоря, любое мерцание треугольников на моделях вызвано процедурами сортировки (на уровне ПО), так что и решается эта проблема программно.
Предварительно отрисованная графика
Давайте для разнообразия обсудим какую-нибудь “положительную” особенность…
Если игра стремилась к более реалистичным сценам, чем мог обеспечить GPU, одним из доступных вариантов было сложить два треугольника и использовать Motion Decoder для рисования на них предварительно отрисованных роликов. FMV-видео может занимать много места, но к счастью, CD-ROM к такому был готов.
Некоторые игры полагались на него специально для создания фонов, и, честно говоря, на ЭЛТ-телевизоре они выглядели крайне убедительно. Очевидно, что современные эмуляторы с их возможностями масштабирования очень быстро докажут обратное.
Видеовыход
Первая ревизия консоли оказалась удивительно щедрой на количество видео сигналов со следующими портами:
- RFU DC: Его убрали довольно быстро, он предназначался для подключения к RF модулятору.
- RCA (“тюльпаны”): Предоставляет композитное видео.
- S-Video: Предоставляет яркость (Luma), объединённую с синхронизацией (Sync), и цветность (Chroma).
- AV Multi Out: Предоставляет все перечисленные выше сигналы, кроме RFU, плюс RGB и линию 5+ Вольт.
Последующие ревизии консоли убрали эти порты и в конце концов остался только “AV Multi Out”.
Звук
Фирменный Sound Processing Unit (SPU, Устройство Обработки Звука) от Sony отвечает за аудио. Этот чип поддерживает 24 канала с 16-битными ADPCM сэмплами (это более эффективная версия известного PCM-кодирования) и частотой дискретизации 44,1 кГц (качество Audio CD).
Этот чип также предоставляет следующие возможности:
- Модуляция высоты тона: Как следует из названия, игры могут автоматически изменять высоту своих сэмплов вместо того, чтобы хранить дополнительные. Это полезно для секвенирования музыки.
- Модуляция частоты: Голоса могут быть использованы для изменения частоты других голосов. Сравнимо с FM синтезом.
- Огибающая ADSR: Это набор свойств, доступных для амплитудной модуляции.
- Зацикливание: Указывает системе многократно воспроизвести фрагмент аудио.
- Цифровая реверберация: Имитирует воспроизведение сэмла в определенной атмосфере для погружения игрока в происходящее.
512 КБ DRAM (под названием “Sound RAM”) предоставляются в качестве аудио-буфера. Эта память доступна и процессору (только через DMA), и контроллеру CD. Однако игры могут сохранять сэмплы только в 508 КБ, остальная память зарезервирована SPU для обработки музыки с Audio CD. Доступная память сокращается еще сильнее, если активирована реверберация.
Контроллер CD также может посылать сэмплы напрямую на аудио микшер без прохождения аудио-буфера или вмешательства центрального процессора. Сэмплы также могут быть сжаты кодировкой “XA”, которую SPU может декодировать на лету.
Эра стриминга
Как и в случае Saturn, игры перестали полагаться на секвенсирование музыки или заданные формы волн, а благодаря огромному свободному пространству на CD-ROM дисках разработчики могут хранить продюсированные сэмплы целиком и передавать их в аудио чип.
I/O
Для аддонов доступны два порта ввода-вывода (Последовательный и Параллельный). Однако они были удалены в более поздних моделях консоли из-за непопулярности аддонов и того факта, что они потенциально могут быть использованы для взлома системы защиты от копирования.
Подсистема CD
Блок управления CD-приводом - это очень интересная область, его можно представить как отдельный компьютер, живущий внутри PlayStation.
Подсистема состоит из следующих компонентов:
- DSP (Цифровой сигнальный процессор): управляет мотором и лазером, и обрабатывает радиочастотный сигнал, поступающий от лазера.
- Sub-CPU (подпроцессор): центральный процессор, состоящий из микроконтроллера Motorola 68HC05, 512 Б ОЗУ и 16 КБ ПЗУ [19]. По сути Sub-CPU запускает свою программу, записанную в ПЗУ и управляет DSP. Программа Sub-CPU реализует меры защиты от копирования, которые применяются независимо от того, “хочет” того центральный процессор или нет.
- Контроллер CD: Это посредник между подсистемой CD и остальными частями консоли, получающий команды от главного ЦП (в порядке FIFO - “первым пришёл - первым ушёл”) и вызывающий прерывания после определённых событий. В качестве контроллера этот чип говорит с Sub-CPU и получает данные с CD от DSP. Кроме того, контроллер содержит устройство DMA, подключённое к SPU, что позволяет передавать ему аудио напрямую.
- 32 КБ SRAM, подключенные к контроллеру: Предположительно они выступают в роли буфера для данных, читаемых с диска.
Эта подсистема напоминает типичный CD привод, который был дома у каждого, за исключением некоторых изменений, сделанных Sony в программе Sub-CPU для выполнения антипиратских проверок.
Передние порты
Слоты для контроллеров и карт памяти электрически идентичны [20], поэтому адреса каждого из них известны заранее. К тому же во избежание проблем Sony изменила форму самих слотов.
Связь с этими устройствами осуществляется с помощью последовательного интерфейса. Команды, отправленные с консоли, будут доставлены в один из двух слотов (либо “карта памяти 0” и “контроллер 0”, либо “карта памяти 1” и “контроллер 1”). Затем оба аксессуара будут отвечать своими уникальными идентификаторами, что позволит консоли отныне фокусироваться на определенном типе устройства (карта памяти или контроллер).
Операционная система
Система поставлялась с ПЗУ на 512 КБ, в котором хранится “BIOS”. Эта программа выполняла множество задач, включая инициализацию, отображение пользовательской оболочки и, наконец, предоставление набора процедур на работы с системой ввода-вывода [21].
BIOS/Ядро
BIOS являлся критической зависимостью для игр, так как эта программа запускает их с CD-привода. Более того, BIOS служит “посредником” для взаимодействия с аппаратным обеспечением консоли. Это похоже на то, как IBM реализовала BIOS в своих ПК, что заставляло разработчиков использовать стандартную таблицу прерываний (содержавшую процедуры ввода-вывода) вместо платформозависимых портов ввода-вывода.
При этом, BIOS PS1 предоставляет такие процедуры, как:
- Команды для привода CD-ROM.
- Операции над файловой системой (из CD-ROM и карты памяти).
- Многопоточность.
- Функции стандартной библиотеки Си (управление строками, операции с памятью, и т.д.).
Поскольку доступ к ПЗУ BIOS очень медленный (оно подключено к 8-битной шине), API упаковывался в форме ядра и копировался в основное ОЗУ при загрузке. Таким образом, 64 КБ основного ОЗУ зарезервированы для этого ядра. Кстати, ядро также называется ОС PlayStation.
Процесс загрузки
Вектор сброса ЦП находится по адресу 0xBFC00000
, который указывает на ПЗУ с BIOS.
Подобно процессу загрузки Saturn, после подачи питания PS1 сделает следующее:
- Найдёт ПЗУ BIOS и выполнит процедуры инициализации оборудования.
- Загрузит ОС PlayStation.
- Покажет экран заставки.
- Если CD вставлен, контроллер CD-ROM проверит его подлинность:
- Подлинный → Контроллер позволит прочитать его содержимое.
- CPU будет искать ‘SYSTEM.CNF’ и продолжит выполнение оттуда.
- Не подлинный → Центральный процессор отобразит сообщение об ошибке.
- Подлинный → Контроллер позволит прочитать его содержимое.
- Если же CD не вставлен, процессор отобразит оболочку. Управление передаётся пользователю.
Оболочка представляет собой простой графический интерфейс, позволяющий пользователю копировать или удалять сохранения с карты памяти, а также проигрывать компакт-диски с аудио.
Игры
Так же, как и Sega Saturn и любая другая консоль, перешедшая на носитель CD, игры получили следующий набор новшеств: большое хранилище (640 МБ), хорошее качество звука и “не такая уж и медленная” скорость чтения благодаря 2x дисководам.
Если вам интересно, как работают компакт-диски (CD), я написал краткое объяснение в статье про Sega Saturn.
Экосистема разработки ПО
Официальный SDK предоставляет библиотеки C, которые связаны с процедурами BIOS для доступа к оборудованию. Если вам интересно, это главный фактор, который помог эмулировать PS1 на самых разных платформах.
Наряду с SDK, Sony также распространяла специализированное оборудование, например, DTL-H2000: двойная ISA карта, содержащая внутренние устройства и I/O от PS1 [22], а также дополнительную схему для отладки. Плата имеет доступ к жесткому диску хоста и может выполнять программы для PS1 без ограничений. Сопутствующее программное обеспечение требует ПК с установленной Windows 3.1 или 95.
Защита от пиратства и блокировка регионов
Как вам может быть известно, чтобы получить данные с диска, лазерный луч должен считать “ямки” и “бугорки” с его дорожки.
Обычные диски не на 100% плоские, и они часто имеют крошечные колебания в своих дорожках. Эти дефекты совершенно незаметны при считывании данных, так как лазеры могут автоматически калиброваться по мере считывания.
Именно на этом Sony основывала свою защиту от копирования: подпроцессор позволит прочитать только диски с оглавлениями (Table of Contents, TOC), выгравированными с использованием определенной частоты, неофициально известной как Wobble Groove, которая применяется только во время мастеринга и не может быть воспроизведена с помощью обычных приводов CD. TOC находится во внутренней части компакт-диска (область “Lead-In”) и сообщает как лазеру двигаться по диску [23]. Более того, операция выполняется много раз в качестве механизма отказоустойчивости.
В оглавление игр для PS1 встраивается одна из следующих последовательностей символов:
- SCEA → Sony Computer Entertainment of America.
- SCEE → Sony Computer Entertainment of Europe.
- SCEI → Sony Computer Entertainment of Japan.
Как вы можете себе представить, считыватель также применяет региональную блокировку, используя эту технику.
Поражение
С другой стороны, эта проверка осуществляется только при запуске, так что её можно обойти просто подменив диск сразу же после её прохождения… с риском повредить дисковод. Позднее некоторые игры взяли дело в свои руки и зачастую заново инициализировали дисковод во время игры, чтобы проверка была снова проведена. Это было сделано для предотвращения так называемого “swap trick” (трюк с подменой).
В качестве альтернативы в консоль можно было впаять крошечные платы, запрограммированные на имитацию нужного сигнала с компакт-диска. Эти платы известны как Модчипы и, хотя и вызывали сомнения с точки зрения закона, они имели огромную популярность.
Возмездие
Использование эмуляторов также рассматривалось как угроза для издателей. В результате некоторые игры выполняли свои собственные проверки (в основном контрольные суммы) для борьбы с любым видом несанкционированного использования или модификации.
Одна из таких проверок, про которую мне рассказали, состояла в преднамеренной повторной инициализации дисковода и чтении особых секторов, не проходящих проверку “wobble groove”. Если все таки удалось разблокировать привод, игра (все еще находящаяся в RAM) c радостью раскрыла бы этот антипиратский материал. Обратите внимание, что этот подход также может повлиять на модифицированные консоли, использующие подлинные игры.
Позднее компания Sony представила библиотеку под названием Libcrypt, которая усилила защиту от копирования с использованием двух подходов [24]:
- Со стороны аппаратного обеспечения в подканалах диска хранятся контрольные суммы секторов.
- Обычно подканалы CD-ROM хранят метаданные, в основном предназначенные для привода. Они недоступны пользователям, и типичные устройства для чтения компакт-дисков очень редко позволяют перезаписать их вручную.
- Со стороны программного обеспечения в различных местах кода игры встраивается набор процедур, которые получают значения контрольных сумм и смешивают их с другими. Это является попыткой обхода как эмуляторов, так и модчипов.