Где на картридже NES хранятся все эти графические данные?
Я успешно эмулировал (слегка чередующееся) ядро 6502 для Nintendo Entertainment System, и теперь я немного застрял в эмуляции PPU.
В различных документах отмечается, что PPU имеет 0x4000 (16KB) байтов доступной памяти. Только 2 КБ из этого - внутренняя RAM, в то время как остальное находится на картридже (или что-то в этом роде) Чего я не понимаю, так это того, что PPU использует таблицы шаблонов, таблицы имен, таблицы атрибутов, фоновую палитру и палитру спрайтов (от макушки головы). Где хранятся все эти вещи? Я знаю, что банк памяти CHR имеет размер 8 КБ, поэтому даже если в ПЗУ имеется несколько банков графической памяти, как ППУ узнает, в каком банке какую из этих таблиц / палитр найти? А в некоторых играх даже нет памяти CHR, и все хранится в памяти PRG. Как я могу выяснить, где хранится все графическое изображение для целей эмуляции?
РЕДАКТИРОВАТЬ: я добавил свое собственное объяснение в качестве ответа, так как теперь у меня гораздо больше опыта во внутренней работе NES.
2 ответа
С тех пор, как я задал этот вопрос, я узнал массу нового о PPU NES, поэтому я сам отвечу на этот вопрос.
Для начала, карта памяти PPU выглядит следующим образом:
$0000 - $0FFF Pattern table 0
$1000 - $1FFF Pattern table 1
$2000 - $23BF Nametable 0
$23C0 - $23FF Attribute table 0
$2400 - $27BF Nametable 1
$27C0 - $27FF Attribute table 1
$2800 - $2BBF Nametable 2
$2BC0 - $2BFF Attribute table 2
$2C00 - $2FBF Nametable 3
$2FC0 - $2FFF Attribute table 3
$3000 - $3EFF [0x2000 - 0x2EFF] mirror
$3F00 - $3F09 Background palette
$3F10 - $3F19 Sprite palette
$3F20 - $3FFF Palette mirror
Кроме этого, есть область байтов $FF (256), называемая OAM, и область байтов $20 (32), называемая Secondary OAM.
Как они написаны?
Таблицы шаблонов используются для хранения графических данных NES в шаблонах, т.е. все, что хранится здесь, показывает форму используемых спрайтов. Обычно они хранятся в ПЗУ CHR на картридже, но программист игры может также записать их в память PPU. Как это происходит, будет объяснено ниже.
Кроме таблиц шаблонов, все, кроме OAM и Secondary OAM, записывается программистом игры в память PPU. Это происходит с использованием регистров $2006 и $ 2007. Как?
Всякий раз, когда программист хочет записать определенный адрес в памяти PPU, он может сделать это, сохранив (sta, stx, sty и, возможно, другие инструкции) адрес, к которому он хочет получить доступ, записав $2006 дважды через ЦП, как он делает в обычной сборке. Примером может быть:
LDA #$20
STA $2006
LDA #$00
STA $2006
Пользователь сначала записывает старший байт адреса, а затем младший. Теперь внутренняя 15-битная защелка PPU (не уверена, является ли слово latch правильным) хранит адрес PPU $2000. Всякий раз, когда программист хочет написать по этому адресу (который в данном случае является начальным адресом первой именной таблицы), он обычно может сделать это, записав значение, которое он хочет сохранить в этой области памяти, по адресу $ 2007. При записи по этому адресу записанное значение будет помещено в адрес в 15-битной защелке, а защелка будет увеличена либо на 1, либо на 32 (определяется битом 2 значения в адресе $2000). Вот в основном как все просто.
Конечно, не все так просто. Адреса $2000 - $2007 называются Регистрами отображения памяти PPU, и они называются так, потому что они находятся в памяти процессора. Они расположены там, потому что ЦП и ППУ не могут напрямую обращаться к памяти друг друга, поэтому ЦП должен найти какой-то шлюз для памяти ППУ, и эти адреса таковы. В этих регистрах есть много странных исключений и причуд, и все они объяснены здесь.
Помимо них, есть все еще упомянутые выше OAM и Secondary OAM, но это совсем другое, и их следует объяснить полностью, прочитав действительно жизнеспособные источники, а не быстрое объяснение.
Лучше прочитать его из упомянутого источника ( опять же, здесь), чтобы получить полное понимание, но это всего лишь краткое объяснение для тех, кто был любопытен и действительно имеет базовое понимание такого рода вещей.
Игровой картридж содержит интегральную схему, которая может содержать множество микросхем ПЗУ. Они будут доступны через провода вдоль соединительной кромки. Помимо возможности горячей замены, они работают так же, как микросхема ПЗУ или ОЗУ, которая постоянно находится в компьютере. Доступ к нему можно получить, отправив на него правильные сигналы, обычно опосредованные микросхемой контроллера шины и тактовым импульсом. Адрес (в двоичном виде) представляется его адресным проводникам, а затем через определенное количество тактовых импульсов он выдает нужные данные по своим информационным проводам, которые затем передаются по шине на процессор или контроллер dma.
Физические местоположения будут в некоторой степени диктоваться аппаратными средствами (у многих микросхем памяти были части ОЗУ и ПЗУ, которые могли быть отображены в один и тот же диапазон). Но это в значительной степени под контролем программы. Рассчитайте значение указателя, затем используйте его. Довольно просто в сборке.