Видеопроцессор Денди (PPU).

Видеопроцессор (PPU) ориентирован на генерацию картинки на выходе в одном из стандартов: для американской NES и японской Famicom – это NTSC; для российских Денди (и китайщины, продаваемой у нас) – это, как правило, PAL (в редких случаях SECAM – что не меняет формата размера картинки в сравнении с PAL). Далее рассматриваем именно вариант PAL.

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

Характеристики и возможности PPU:

  • Шина Адреса – 14 бит (адресное пространство 16k) + 256 байт отдельно адресуемой памяти спрайтов;
  • Шина Данных – 8 бит;
  • Количество цветовых оттенков всего – 64;
  • Одновременно на экране – до 25 (любые из 64), а именно: до 13-и для фона и до 12-и для спрайтов;
  • Количество спрайтов на экране – 64 (не более 8-и на линии);
  • Разрешение выводимой картинки (PAL/NTSC) – 256x240 / 256x224;
  • Частота регенерации (PAL/NTSC) – 50Гц/60Гц;

Для программиста (и CPU) – видеопроцессор это 8 регистров, адресуемые CPU по адресам $2000-$2007 (в архитектуре Денди) – они обеспечивают возможность полного управления видеопроцессором. Помимо этого, запись в память спрайтов PPU может осуществлять так же и контроллер DMA (понятно, что без непосредственного участия процессора). Иных способов общения с PPU нет!

Адресное пространство PPU распределяется следующим образом:

Адрес

Размер

Назначение

$0000-$0FFF

4k

CHR-ROM Знакогенератор 0 (На картридже)

$1000-$1FFF

4k

CHR-ROM Знакогенератор 1 (На картридже)

$2000-$23BF

$3C0 = 960 байт

VRAM Экранная страница 1 – Символы (В приставке)

$23C0-$23FF

$40 = 64 байта

VRAM Экранная страница 1 – Атрибуты (В приставке)

$2400-$26BF

$3C0 = 960 байт

VRAM Экранная страница 2 – Символы (В приставке)

$27C0-$27FF

$40 = 64 байта

VRAM Экранная страница 2 – Атрибуты (В приставке)

$2800-$2BBF

$3C0 = 960 байт

VRAM Экранная страница 3 – Символы (На картридже)

$2BC0-$2BFF

$40 = 64 байта

VRAM Экранная страница 3 – Атрибуты (На картридже)

$2C00-$2FBF

$3C0 = 960 байт

VRAM Экранная страница 4 – Символы (На картридже)

$2FC0-$2FFF

$40 = 64 байта

VRAM Экранная страница 4 – Атрибуты (На картридже)

$3000-$3EFF

$F00 = 3840 байт

VRAM Mirror of $2000-2EFF

$3F00-$3F0F

$10 = 16 байт

Палитра фона (в регистрах PPU)

$3F10-$3F1F

$10 = 16 байт

Палитра спрайтов (в регистрах PPU)

$3F20-$3FFF

$E0 = 224 байт

Не используются

Регистры видеопроцессора выполняют следующие функции:

Регистр (адресация по CPU)

Биты

Назначение

$2000 w/o

 

Управление видеопроцессором

7

Формирование запроса прерывания NMI при кадровом синхроимпульсе
(0 - запрещено; 1 - разрешено)

6

Не используется (должен быть 0)

5

Размер спрайтов (0 - 8x8; 1 - 8x16)

4

Выбор знакогенератора фона (0/1)

3

Выбор знакогенератора спрайтов (0/1)

2

Выбор режима инкремента адреса при обращении к видеопамяти
(0 – увеличение на единицу «горизонтальная запись»; 1 - увеличение на 32 «вертикальная запись»)

1,0

Адрес активной экранной страницы (00 – $2000; 01 – $2400; 10 – $2800; 11 - $2C00)

$2001 w/o

 

Управление видеопроцессором

7-5

Яркость экрана/интенсивность цвета в RGB (в Денди не используется)

4

0 – Спрайты не отображаются; 1 – Спрайты отображаются

3

0 – Фон не отображается; 1 – Фон отображается

2

0 – Спрайты невидны в крайнем левом столбце; 1- Все спрайты видны

1

0 – Рисунок фона невиден в крайнем левом столбце; 1- Весь фон виден

0

Тип дисплея: Color/Monochrome (в Денди не используется)

$2002 r/o

 

Состояние видеопроцессора. Чтение сбрасывает некоторые биты!

7

1 – PPU генерирует обратный кадровый импульс; 0 – PPU рисует картинку на экране. Сбрасывается при чтении.

6

Устанавливается в 1 после вывода спрайта с номером 0. Сбрасывается при чтении или при кадровом синхроимпульсе.

5

1 – На линии больше 8-и спрайтов; 0 - меньше

4

1 – Запись в видеопамять разрешена; 0 - запрещена

3-0

Не используются

$2003 w/o,

$2004 r/w

 

Операции с памятью спрайтов. В регистр $2003 записывается адрес в памяти спрайтов ($00-$FF). После чего с регистром $2004 производится операция чтения/записи. После каждой операции происходит автоинкремент адреса на единицу.

$2005 w/o(x2)

 

Аппаратный скроллинг фоновой картинки. В регистр последовательно записываются два байта. Первый – абсолютное значение вертикального скроллинга; второе – горизонтального (подробнее см. главу «Отражение экранных страниц».)

$2006 w/o(x2),

$2007 r/w

 

Операции с видеопамятью. Обеспечивают доступ к любой ячейке адресного пространства видеопроцессора. Регистр $2006 – адрес (2байта), сначала записывается старший. Регистр $2007 – операционный буфер (чтение/запись). После каждой операции происходит автоинкремент адреса на 1 или на 32 (см. регистр $2000- бит 2).

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

Пусть в VRAM с адреса $2000 содержится: $AA $BB $CC $DD.

При операциях с VRAM инкремент равен 1.

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

      LDA #$20
      STA $2006
      LDA #$00
      STA $2006        ; VRAM address now set at $2000
      LDA $2007        ; A=??     VRAM Buffer=$AA
      LDA $2007        ; A=$AA    VRAM Buffer=$BB
      LDA $2007        ; A=$BB    VRAM Buffer=$CC
      LDA #$20
      STA $2006
      LDA #$00
      STA $2006        ; VRAM address now set at $2000
      LDA $2007        ; A=$CC    VRAM Buffer=$AA
      LDA $2007        ; A=$AA    VRAM Buffer=$BB

При работе с палитрами буфер адреса не используется (т.к. они находятся специальных регистрах видеопроцессора). При записи в память не требуется лишнего цикла.

Таблицы 2 и 3.

Теперь подробнее:

CHR-ROM (Она же VROM) [8k] – Вспомним нашу модель картриджа (из предыдущей главы), в которой второе ПЗУ размером 8k подключалось к шинам PPU. Функционально оно называется CHR-ROM. В нем хранятся два знакогенератора (по 4k каждый). Знакогенератор содержит «иконки» (они же «тайлы», «спрайты», «значки»), размер каждой иконки 8x8 пикселей. На каждый пиксель выделяется 2 бита. В каждом знакогенераторе 256 таких иконок. Все что «умеет» видеопроцессор – это отображать содержимое знакогенераторов (и ничего более!)

VRAM [2k] Ровно столько в Денди оперативной видеопамяти. Далее под словом «видеопамять» - понимаем именно VRAM (не путать с адресным пространством PPU, которое включает, в том числе, и VRAM). В видеопамяти хранятся экранные страницы или иными словами – фоновая картинка (точнее: информация о том из каких иконок она состоит – область символов; два старших бита цвета иконки – область атрибутов). Каждая экранная страница занимает ровно 1k видеопамяти (960 байт – информация о номерах иконок из знакогенератора + 64 байта – информация о цвете групп иконок). В видеопамяти приставки (2k) умещается только две экранных страницы – в то время как архитектурно (для PPU) предусмотрено четыре экранных страницы. Подробнее об экранных страницах см. ниже в подразделе «Отражение экранных страниц».

Палитры фона и спрайтов [16 + 16 байт] – PPU может отображать 64 цвета (каждому номеру строго определенный цвет - см. рисунок 2). Соответствие цветов формату RGB см. приложение 2.

Рисунок 2.

PPU содержит в себе регистры палитр (адресуются через адресное пространство PPU). Предусмотрено две палитры – палитра фона ($3F00-$3F0F) и палитра спрайтов ($3F10-$3F1F). При помощи палитры происходит выбор любых 16-ти цветов из 64-х возможных для текущего отображения на экране (в ячейку палитры заносится номер цвета (00h-3Fh) - см. рисунок 2).

Слои. Общий принцип формирования изображения.

PPU, работающий в системе PAL, формирует картинку с разрешением 256x240. PPU формирует изображение из четырех слоев путем их последовательного наложения (каждый следующий слой «заслоняет» предыдущий, если не является прозрачным в данной точке):

Задний план – холст, окрашенный цветом из палитры фона с индексом 0 (цвет любой - см. рисунок 2).

Слой спрайтов с битом приоритета = 0 (подробнее см. в разделе «Спрайты. Контроллер DMA.»)

Фоновый рисунок – картинка, составленная из иконок знакогенератора (как из мозаики 32x30). Фоновый рисунок хранится в экранной странице (VRAM). В области символов - 960 байт (32x30) должны быть записаны номера иконок знакогенератора фона (см. регистр $2000 - бит 4). На экране отображается содержимое активной экранной страницы (см. регистр $2000 - бит 1,0). Экранная страница содержит только информацию о фоновом рисунке. Знакогенератор содержит иконки с двумя младшими битами цвета для каждого пикселя иконки. Два старших бита цвета – общие для всей иконки, берутся из области атрибутов экранной страницы. Полученное четырехбитное число определяет номер цвета в палитре фона. Таким образом, каждая иконка (без смены палитры) может иметь до четырех вариантов раскраски. Т.е. при помощи двух бит из области атрибутов экранной страницы – палитра фактически разбивается на 4 части (по 4 цвета в каждой), номер части определяется битами области атрибутов, номер цвета (внутри части) – битами пикселя в знакогенераторе.

Слой спрайтов с битом приоритета = 1 (подробнее см. в разделе «Спрайты. Контроллер DMA.»)

Далее рассмотрим двоичные форматы перечисленных структур.

Знакогенератор.

В знакогенераторе отводится по 16 байт на каждую иконку (16x256=4096). Первые 8 байт определяют построчно младший бит цвета иконки. Следующие 8 бит – старший (см. рисунок). Пиксель иконки, со значением обеих бит равными нулю – считается прозрачным (вне зависимости от старших бит из области атрибутов).

Символ в                       

знакогенераторе                

---------------                

%00010000 = $10 --¬            

%00000000 = $00   ¦             

%01000100 = $44   ¦            

%00000000 = $00   +-- Бит 0    

%11111110 = $FE   ¦            

%00000000 = $00   ¦            

%10000010 = $82   ¦            

%00000000 = $00 ---            

%00000000 = $00 --¬

%00101000 = $28   ¦

%01000100 = $44   ¦

%10000010 = $82   +-- Бит 1

%00000000 = $00   ¦

%10000010 = $82   ¦

%10000010 = $82   ¦

%00000000 = $00 ---

Результат

расшифровки

-----------

 ...1....  . – 00 (прозрачный)

 ..2.2...  1 - 01

 .3...3..  2 - 10

 2.....2.  3 - 11

 1111111.

 2.....2.

 3.....3.

 ........

Область символов экранной страницы.

Последовательно хранятся номера иконок из знакогенератора фона (величина смещения иконки от начала знакогенератора деленная на 16). Экран заполняется иконками построчно (32x30=960 иконок на экране).

Область атрибутов экранной страницы.

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

$2000

$2001

$2002

$2003

$2020

$2021

$2022

$2023

$2040

$2041

$2042

$2043

$2060

$2061

$2062

$2063

Табличка выше иллюстрирует фрагмент VRAM, адреса из области символов Экранной страницы 1 («левый верхний угол экрана») – изображены ячейки с адресами начала первых четырех строк экрана. Цветом показаны группы иконок, имеющие одинаковый атрибут (два старших бита индекса цвета в палитре фона).

Байт области атрибутов (для указанного выше фрагмента: «левый верхний угол» - по адресу $23C0) содержит атрибуты четырех смежных групп:

7

6

5

4

3

2

1

0

Цветом указано соответствие битов байта атрибутов группам иконок экранной страницы.

Весь экран построчно разбивается на группы (8 строк и 8 столбцов) – последняя строка неполная. Соответственно за каждую группу отвечает один байт атрибутов.

Палитры.

На самом деле не из 16-ти цветов палитры происходит выбор цвета. Происходит это потому, что и здесь имеет место явление «отражения» (mirroring) – на этот раз применительно к цветам палитры. Происходит это так. Как отмечалось выше, пиксель иконки знакогенератора, оба бита которого нулевые, вне зависимости от атрибута, считается прозрачным. Из этого следует, что в палитре фона есть 3 ячейки, содержимое которых нас не интересует (цвет то и так прозрачный по условию). Это ячейки с адресами $3F04, $3F08 и $3F0C. В ячейке $3F00 (как упоминалось выше) хранится номер цвета холста, и именно он виден  сквозь «прозрачные» пиксели. Так вот – архитектура PPU Денди предусматривает отражение «лишних» ячеек палитры ($3F04, $3F08 и $3F0C) в ячейку цвета холста ($3F00).

С палитрой спрайтов таже история – у спрайтов (подробнее о спрайтах в следующем разделе) нет «своего» холста, и поэтому ячейки палитры спрайтов, на которые приходятся прозрачные цвета ($3F10, $3F14, $3F18 и $3F1C), также отражаются на ячейку $3F00.

Спрайты. Контроллер DMA.

Со спрайтами все очень просто. В качестве спрайтов выступают все теже иконки знакогенератора (определенного, «как знакогенератор спрайтов» - см. регистр $2000 - бит 3). Внутри PPU есть отдельно адресуемая (от основного адресного пространства PPU – 16k) память спрайтов, размером 256 байт. Эта память хранит «записи» о 64 спрайтах, размер каждой записи 4 байта. Располагаются записи последовательно от младших адресов.

Формат записи следующий:

Байт записи

Биты

Назначение

0

 

Абсолютная координата верхнего левого угла спрайта по вертикали

1

 

Номер иконки из знакогенератора

2

 

Атрибуты спрайта

7

Отражение спрайта относительно вертикальной оси. 0 – Обычный; 1 - Зеркальный

6

Отражение спрайта относительно горизонтальной оси. 0 – Обычный; 1 - Зеркальный

5

Приоритет спрайта. 1 – Спрайт перед фоном; 0 – Спрайт за фоном

4-2

Не используются

1,0

Два старших бита цвета (аналог атрибута цвета для фона)

3

 

Координата верхнего левого угла спрайта по горизонтали

Таблица 4.

Спрайты нумеруются начиная с нуля. После вывода нулевого спрайта (а он может быть в любом месте экрана) устанавливается бит 6 регистра $2002 PPU. Запись/чтение в/из память/и спрайтов производится при помощи регистров $2003 (адрес) и $2004 (данные). При каждой операции адрес автоинкрементируется на 1.

Существует более быстрый способ записи в память спрайтов – запись через контроллер DMA. Контроллер DMA занимает в адресном пространстве CPU один адрес - $4014. При записи в этот порт числа $XX, контроллер DMA отправляет в память спрайтов содержимое 256-ти ячеек памяти, начиная с адреса = $XX x $100. (Например: при записи в регистр контроллера DMA $02 – в память спрайтов отправится содержимое ячеек $0200-$02FF). В программах рекомендуется использовать именно этот способ записи – как наиболее быстрый (около 100мкс.)

Отражение экранных страниц.

Как уже упоминалось выше – в Денди установлено 2k VRAM (сразу еще раз ругнемся на разработчиков – пожалели еще одну микросхему ОЗУ). Да именно пожалели, если посмотреть на карту адресного пространства PPU (см. выше) – то можно видеть, что реально видеопроцессор может работать с четырьмя страницами VRAM. Оно так и бывает, если на картридже установлены недостающие 2k VRAM – уймись программист или раскошелься пользователь, если разработчик решил сэкономить!

Но вернемся к архитектуре – какие возможности добавляют нам лишние 2k VRAM?

Рассмотрим все по порядку …

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

3
$2800

4
$2C00

1
$2000

2
$2400

В регистр $2005 последовательно записываются два значения - абсолютное вертикальное и горизонтальное смещение (соответственно) относительно текущей активной страницы. Например, активная страница 1 ($2000) – горизонтальное смещение ноль, а вертикальное $E0 (240) – как результат, на экране видно содержимое страницы 3. Варьируя значение вертикального смещения, можно получить фон, состоящий из части страниц 1 и 3 (их стыковку). Если «закрутить» эту операцию в цикл – то можно получить эффект «скроллинга» фоновой картинки. Аналогично происходит горизонтальный скроллинг (прокрутка).

Программы, не использующие функцию скроллинга, должны записывать в регистр $2005 два нуля при каждой обработке прерывания VBlank, иначе изображение будет смещенным!

Но есть один нюанс – в Денди нет памяти подо все четыре страницы. Как и в прочих случаях, тут тоже имеет место «отражение» - и на этот раз экранных страниц (друг на друга). Вид отражения определяет архитектура используемого картриджа. Существует 2 вида отражения – горизонтальное (1=2 и 3=4) и вертикальное (1=3 и 2=4). То есть содержимое  указанных страниц идентично (т.е. зеркалируется).

3

4

1

2

Горизонтальное отражение экранных страниц

3

4

1

2

Вертикальное отражение экранных страниц

Если в картридже установлены недостающие 2k VRAM – то содержимое всех четырех страниц может быть различным.

3

4

1

2

Вне зависимости от способа отражения (или при наличии всех четырех страниц) – скроллинг возможен в любом направлении (в том числе и по диагонали).

Аппаратная реализация выбора способа отражения экранных страниц следующая. Старшая линия физической микросхемы VRAM в приставке (A10) выведена исключительно на разъем картриджа VRAM A10 (см. приложение 4 и Приложение 5), таким образом, управлять данной линией может либо маппер (например, MMC3) – либо данная линия жестко «закольцована» в картридже на одну из адресных линий PPU (А10 или А11), тем самым и определяя вид зеркалирования экранных страниц. Лучше понять суть описанного поможет следующая (уже знакомая) иллюстрация.

3
$2800

A11

A10

1

0

4
$2C00

A11

A10

1

1

1
$2000

A11

A10

0

0

2
$2400

A11

A10

0

1

Горизонтальное отражение – источником сигнала VRAM A10 является линия A11 (состояние линии А10 не определяет адрес в микросхеме VRAM);

Вертикальное отражение - источником сигнала VRAM A10 является линия A10 (состояние линии А11 не определяет адрес в микросхеме VRAM);

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

Введение
Глава 1
Глава 2
Глава 3
Глава 4
Глава 5
Приложение 1
Приложение 2
Приложение 3
Приложение 4
Приложение 5
Приложение 6