Grafikler Picture Processing Unit (PPU) adı verilen özel bir çip tarafından üretilir. Bu, NES'e kimlik kazandıran çiplerden biridir. Başka bir şekilde ifade etmek gerekirse, herkes nalburdan 6502 CPU alabilir, o halde NES'in örneğin bir Apple 2 veya Commodore 64'ten ne farkı var? NES'i diğer makinelerden ayıran şey CPU'yu çevreleyen çiplerdir: PPU ve APU. Bunlar sırasıyla NES'in benzersiz grafik ve ses özelliklerini oluşturur.
Bununla birlikte PPU, sprites ve backgrounds adı verilen 2D grafikleri işleyerek sonucu video sinyaline aktarır.
İçeriğin düzenlenmesi
Ekranda bir şey oluşturmak için PPU'nun hangi grafikleri çizeceğini, ekranda nereye yerleştireceğini ve nasıl çizeceğini (yani hangi paleti kullanacağını) bilmesi gerekir.
Bu soruları yanıtlamak için PPU, aşağıdaki veri türlerini arayan farklı bir bellek haritası ile önceden programlanmış olarak gelir:
- Grafik verileri, Character Memory adı verilen ve 2B çizimleri (tiles adı verilen) Pattern table adlı bir veri yapısında düzenlenmiş olarak saklayan özel bir çip içeren oyun kartuşundan alınır. Character Memory, oyunun değişmez bir grafik setiyle birlikte gelmesine veya CPU'nun müdahale etmesi gerekmesine bağlı olarak sırasıyla 'Salt Okunur Bellek' (ROM) veya 'Rastgele Erişimli Bellek' (RAM) şeklinde gerçekleşir.
- PPU, her biri 4 KB'lık iki grup halinde düzenlenmiş 8 KB'a kadar Character Memory adresler.
- PPU'ya grafiklerin 'nerede' ve 'nasıl' çizileceğini söyleyen meta veriler başka alanlarda bulunur:
- Anakarta ayrı bir 2 KB SRAM yerleştirilmiştir ve bu kez grafikle ilgili verilere ayrılmıştır. Nintendo bu alanı Video RAM (VRAM) olarak adlandırır ve Nametables adı verilen iki veri yapısını depolar.
- PPU, Object Attribute Memory'yi (OAM) saklamak için 256 B DRAM yerleştirir.
- Son olarak PPU, renk paletlerini tanımlamak için 4 B bellek de barındırıyor.
Yeni terminoloji konusunda endişelenmeyin, bu veri yapılarının anlamı aşağıdaki paragraflarda adım adım ele alınmaktadır.
Kare Oluşturulması
Çağdaşlarında olduğu gibi, bu çip de CRT ekran davranışı için tasarlanmıştır. Böyle bir kare tamponu yoktur: PPU, CRT'nin ışınıyla adım adım işleyerek görüntüyü anında oluşturur.
PPU, 256x240 piksel sabit boyutunda çerçeveler çizer. Ne yazık ki, dünya genelinde analog video standartlarındaki farklılıklar nedeniyle, görüntü, cihazın görüntülendiği bölgeye (NTSC veya PAL) bağlı olarak görünüm açısından farklılık gösterecektir. Özetle, NTSC televizyonlar aşırı taramaya uyum sağlamak için üst ve alt kenarları kırpacaktır (yalnızca ~224 tarama çizgisi görünür), bu nedenle bu kenarlar geliştiriciler tarafından oyunda öğelerin nereye yerleştirileceğine karar verirken 'tehlikeli bölgeler' olarak kabul edilir. Öte yandan, PAL televizyonlar kenarları kırpmaz, ancak daha uzun sinyali doldurmak için ekstra siyah çubuklar gösterir (PAL 288 tarama çizgisi kullanır).
Sahne arkasında, PPU'nun çıkardığı çerçeve iki farklı katmandan oluşur. Gösterim amacıyla, bunun nasıl çalıştığını göstermek için Super Mario Bros.'u kullanalım:
Kareler

Birden fazla karonun birbirine sıkıştırıldığı iki desen tablosu.

Tek bir karo.
Başlangıç olarak PPU, sprite ve arka plan üretmek için temel bir bileşen olarak tiles kullanır.
NES karoları temel 8x8 piksel haritaları olarak tanımlar, bunlar Karakter belleğinde (oyun kartuşunda bulunur) saklanır ve Patern Tablosu adı verilen büyük bir veri yapısında düzenlenir. Her karo 16 B kaplar ve bir Desen tablosu 256 karo barındırır . PPU 8 KB'a kadar Karakter belleğini adreslediğinden, en fazla iki Desen tablosuna erişebilir.
Bir karonun içindeki piksellerin her biri, bir paletteki dört renkten birine referans veren 2 bitlik bir değer kullanılarak kodlanır. Programcılar sekiz adede kadar palet tanımlayabilirler (dördü arka plan için ve diğeri sprite'lar için). Her palette referans verilen renkler, bu konsolun üretebileceği tüm renkleri temsil eden 64 renkten oluşan bir 'ana palete' işaret eder. Paletler dört renkten oluşur, ancak bir renk transparent için ayrılmıştır.
Ekranda bir şey çizmeye başlamak için, oyunlar Karakter belleğindeki karolara referanslar içeren bir dizi tabloyu doldurur. Her tablo çerçevenin bir katmanından (sprite veya arka plan) sorumludur. Daha sonra, PPU bu tablolardan okur ve CRT tabancası tarafından ışınlanacak tarama çizgilerini oluşturur.
Şimdi her bir katmanın/tablonun nasıl çalıştığını ve işlevsellik açısından nasıl farklılık gösterdiğini açıklayacağım.
Arka Plan Katmanı

Seçilen alanın işaretlendiği tahsis edilmiş arka plan haritası.
Arka plan katmanı, statik kutucuklar içeren 512x480 piksellik bir haritadır . Görüntülenebilir çerçevenin çok daha küçük olduğunu hatırlayabilirsiniz, bu nedenle katmanın hangi kısmının görüntülenmek üzere seçileceğine oyun karar verir. Oyunlar ayrıca oyun sırasında görüntülenebilir alanı hareket ettirebilir; kaydırma efekti bu şekilde gerçekleştirilir.
Bellekten tasarruf etmek için, dört karodan oluşan gruplar blok adı verilen 16x16 piksel haritalar halinde birleştirilir ve bu haritalar içinde tüm karolar bir renk paletini paylaşır.
Nametables (VRAM'de saklanır) arka plan katmanında hangi karoların görüntüleneceğini belirtir. PPU, her biri katmanın bir çeyreğine karşılık gelen dört adet 1024 baytlık Nametable arar. Ancak, yalnızca 2 KB VRAM kullanılabilir! Sonuç olarak, kartuştan ek donanım olmadan yalnızca iki Nametable depolanabilir. Gerçi kalan ikisinin hala bir yerde ele alınması gerekir: çoğu oyun kalan ikisini ilk ikisinin olduğu yere yönlendirir (buna mirroring denir).
Bu mimari ilk başta kusurlu görünse de, basit genişleyebilirlik sağlarken maliyetleri düşük tutmak için tasarlanmıştır: oyunlar daha geniş bir arka plana ihtiyaç duyarsa, kartuşa ekstra VRAM dahil edilebilir.
Her İsim Tablosunun son baytları, her bloğa hangi renk paletinin atanacağını belirten 64 baytlık bir Öznitelik tablosu depolar .
Sprite Katmanı
![]()
Render edilmiş sprite katmanı.
Sprite'lar ekran etrafında hareket edebilen kutucuklardır. Ayrıca birbirleriyle örtüşebilir veya arka planın arkasında görünebilirler. Görüntülenebilir grafiğe öncelik değerine göre karar verilecektir (geleneksel grafik tasarım yazılımındaki 'katmanlar' ile aynı kavramdır).
Object Attribute Memory (OAM) tablosu hangi karoların sprite olarak kullanılacağını belirtir . Karo indeksine ek olarak, her giriş bir (x,y) konumu ve birden fazla nitelik (renk paleti, bir öncelik ve çevirme bayrakları) içerir. Bu tablo PPU yongasında bulunan 256 baytlık bir DRAM'de saklanır.
OAM tablosu CPU tarafından doldurulabilir. Ancak, bu pratikte oldukça yavaş olabilir (ve doğru zamanda yapılmazsa çerçeveyi bozma riski taşır), sonuç olarak PPU, tabloyu WRAM'den almak için programlanabilen (PPU'nun kayıtlarını değiştirerek) Direct Memory Access veya 'DMA' adı verilen küçük bir bileşen içerir. DMA ile, bir sonraki kare çizildiğinde tablonun yükleneceği garanti edilir, ancak aktarım sırasında CPU'nun durdurulacağını unutmayın!
PPU, tarama çizgisi başına sekiz sprite ve kare başına 64 sprite ile sınırlıdır. 'OAM order rotation' adı verilen ve oyunun OAM'deki girişlerin sırasını manuel olarak değiştirdiği bir teknik sayesinde tarama çizgisi sınırı aşılabilir. Bu, PPU'nun her karede farklı bir sprite seti oluşturmasını sağlar ve CRT ışınının hızı, kullanıcıyı izin verilenden daha fazla sprite görmesi için kandırır. Ancak ekranda titriyor gibi de görüneceklerdir.
Arka plan ayrımı

Farklı kaydırma değerleri tanımlanmış iki bölümü vurgulayan işlenmiş arka plan katmanı. Mario hareket ettikçe sadece ikinci kısım kayar.
Devam etmeden önce, size henüz söylemediğim bir şey var. Super Mario Bros oynarsanız, Mario hareket ettiğinde sahnenin aksamadan ilerlediğini fark edeceksiniz. Ancak, her iki bölüm de aynı arka plan katmanının parçası olmasına rağmen üst alanın (istatistiklerin olduğu yer) sabit kaldığını da gözlemleyeceksiniz! Peki, burada ne oluyor? Oyun, karenin ortasında kaydırma değerlerini değiştirerek yeryüzünü ve istatistikleri (arka planın sabit bir bölümünde yer alan) aynı anda gösteriyor. NES bu özelliği yerel olarak sağlamaz, ancak oyun PPU'nun durumunu gözlemleyerek zamanlamaları çıkarır (durum kaydı aracılığıyla gösterilir).
Bunu başarmak için oyunlar Sprite 0 Hit adı verilen bir teknik uygular. Super Mario Bros, PPU'ya madeni paranın arkasında sahte bir sprite oluşturmasını söyler, bu kare içinde çizilen ilk sprite olur. PPU bunu ışınladıktan sonra, durum kaydını ilk sprite'ın (diğer adıyla 'sprite 0') çizildiğini belirten bir bayrakla günceller. Bu arada oyun, sprite 0 durumunun işaretlenip işaretlenmediğini (diğer bir deyişle 'isabet') sürekli olarak kare ortasında kontrol eder, eğer bu olursa, oyun Mario'nun bulunduğu yere kaydırmak için arka plan tablosunun kaydırma özelliğini güncellemeye devam eder.
Genel olarak, 'Sprite 0 Hit' çok hassas bir prosedürdür, çünkü zamanlamaları karıştırmak kolaydır (sprite 0'ın bayrağı yoklandıktan sonra temizlenmez, bu da 'yinelenen' pozitiflere yol açar ). Ayrıca, bu rutin süresiz olarak tekrarlandığından, yürütülmesi oldukça pahalı (CPU döngüleri açısından) olabilir. İşin iyi tarafı, daha sonraki haritacılar bu işlevi, örneğin Super Mario Bros 3'ün görsel yeteneklerini önemli ölçüde geliştiren rastgele bir tarama çizgisine (çok daha verimli bir teknik) her vurulduğunda tetiklenen otomatik kesintiler kullanarak devraldılar.
Sonuç
Kare tamamlandığında, bir sonrakine geçme zamanı gelmiş demektir!
Ancak CPU, PPU tarafından kullanılmakta olan herhangi bir tabloyu değiştiremez, aksi takdirde ekranda artefaktlar görünebilir. Böylece, tüm tarama satırları tamamlandığında, PPU CPU'da Vertical Blank (V-Blank) kesmesini tetikler . Bu, oyuna o anda görüntülenen resmi yırtmadan tabloları güncellemeye başlayabileceğini bildirir. O anda CRT'nin ışını ekranın görünür alanının altına, aşırı taramaya (veya alt kenarlık alanına) işaret eder.
V-Blank penceresinin dışında yalnızca bir avuç PPU kaydı güncellenebilir, bu da arka plan katmanını kare ortasında kaydırma yeteneğini açıklar.
Sırlar ve sınırlamalar
Tam kareyi saklamak için bellek tahsis edilmiş bir kare arabelleği sisteminin tercih edilebileceğini düşünüyorsanız: RAM maliyetleri çok yüksekti ve konsolun amacı uygun fiyatlı olmaktı. Şimdi size bu tasarımın neden çok verimli ve esnek olduğunu göstereyim.
Multi-Scrolling

Super Mario Bros. 2. Dikey kaydırma için isim tablosu kurulumu (yatay yansıtma).

Super Mario Bros. 3. Mario koşabilir ve uçabilir, bu yüzden PPU'nun çapraz kaydırma yapması gerekir. Sağ kenarın yanlış renk paletini gösterdiğine dikkat edin! Sol kenara bir maske uygulanmıştır.
Bazı oyunlar ana karakterin dikey olarak hareket etmesini gerektirir - bu nedenle isim tablosu yatay yansıtma ile kurulacaktır. Diğer oyunlar karakterlerinin sola ve sağa hareket etmesine ihtiyaç duyar ve bu nedenle bunun yerine dikey yansıtma kullanır.
Her iki yansıtma türü de PPU'nun kullanıcı fark etmeden arka plan döşemelerini güncellemesine izin verecektir: yeni döşemeler uzaktan işlenirken kaydırmak için bolca alan vardır.
Peki ya karakter çapraz hareket etmek isterse? PPU herhangi bir yönde kaydırma yapabilir, ancak ekstra VRAM olmadan kenarlar aynı renk paletini paylaşmaya zorlanır (karoların bloklar halinde gruplandığını unutmayın).
Bu yüzden Super Mario Bros. 3 gibi bazı oyunlar Mario hareket ederken ekranın sağ kenarında garip grafikler gösterir (oyun dikey kaydırma için ayarlanmıştır) . Kartuş başına donanım maliyetini en aza indirmeleri gerekmiş olabilir (çünkü bu oyunda zaten güçlü bir eşleyici yüklü).
İlginç bir düzeltme olarak: PPU, geliştiricilerin karoların üzerine dikey bir maske uygulamasına izin vererek hatalı alanın bir kısmını etkili bir şekilde gizledi.
Karo Değiştirme

Kullanıcıya gösterilen son görüntü.
Super Mario Bros. 3'ün bir başka özelliği de görüntüleyebildiği grafik miktarıdır.
Bu oyun, kesinlikle izin verilenden daha fazla arka plan taşı görüntüler. Peki bunu nasıl yapıyor? Ekran oluşturulurken farklı zamanlarda iki ekran görüntüsü alırsak, son karenin aslında iki farklı kareden oluştuğunu görebiliriz.
Bu, MMC3 eşleyicisinin bir başka sihirbazlığıdır ve sadece Program ROM'unda fazladan alana erişmek için kullanılmaz, aynı zamanda iki farklı Karakter yongasını bağlayarak Karakter ROM alanını da genişletir. PPU'nun ekranın hangi bölümünü talep ettiğini kontrol ederek, eşleyici bir çipe veya diğerine yönlendirecek - böylece ekranda başlangıçta desteklenenden daha fazla benzersiz kutucuğa izin verecektir .
Meraklı davranışlar
Araştırmam boyunca, PPU'nun olağandışı davranışlarını açıklayan birçok ilginç makaleye rastladım, bu yüzden bazılarından burada bahsetmeyi düşündüm:
- Daha sonra yayın için NTSC/PAL sinyallerine kodlanan RGB renkleri üreten Master System'in VDP'sinin aksine, NES'in PPU'su hepsini bir kerede yapar . Bu nedenle, PPU ana paletinin renkleri ile standart RGB renk alanı (mevcut teknoloji tarafından yaygın olarak benimsenmiştir) arasında bire bir bağlantı yoktur. Bu, yorumlama için bir miktar alan bırakır ve sonuç olarak, çeşitli emülatörler farklı bir palet gösterecektir.
- RGB paletleri arasındaki tutarsızlıklar en çok Tim Worthington'ın NES'e RGB sinyal çıkışı ekleyen DIY kitinde belirgindir, çünkü önceden tanımlanmış üç palet arasında seçim yapan bir anahtar da uygulamaktadır .
- Ana palet, NTSC TV sinyalini bozan bir 'lanetli' renk (
$0D) içerir . Bazı TV'ler bu rengi gösterecek sinyali boşluk sinyali ile karıştırır, bu nedenle titreme meydana gelebilir. - PPU, Nesne Öznitelik Belleğini (OAM) depolamak için DRAM'e güvenir. Şimdi, DRAM'in veri kaybını önlemek için sürekli olarak yenilenmesi gerekir (SRAM'in aksine) ve PPU, kareyi oluşturmadığında DRAM'i yenilemeyecektir . Bu durum dikey karartma sırasında ortaya çıkar. Bu nedenle, V-boşluk sırasında meydana gelen yenilemesiz dönem tablonun bir kısmını bozacağından, OAM'nin dikey boşluk dışında güncellenmemesi tavsiye edilir.
- PAL sistemleri için PPU varyantı bundan etkilenmez, çünkü V-Blank sırasında yenilenir (PAL sistemlerinde daha uzun sürer).




