Commander Keen’in Uyarlamalı Karo Yenilemesi (Adaptive Tile Refresh)
(fabiensanglard.net)- Adaptive Tile Refresh (ATR), Commander Keen 1~3’ün EGA’nın yavaş tam ekran yenilemesinden kaçınmak için ekranın tamamını değil, yalnızca değişen karoları yeniden çizecek şekilde geliştirdiği bir kaydırma tekniğidir
- EGA mode
Dh, 320x200 16 renkli ekranı 4 düzleme (C0~C3) ayırarak saklar; 32KiB’lik tüm ekran her karede ISA veri yoluna yazıldığında yaklaşık 5fps ile sınırlı kalır ve 60Hz yenileme zorlaşır - ATR, sanal ekran içindeki dikey ve yatay hareketi
CRTC_START,OFFSET,PELyazmaçlarıyla işler; kenara ulaşıldığında jolt ile ekran referansını geri alır ve yalnızca gerekli karoları VRAM üzerine yazar - jolt maliyeti yeniden çizilecek karo sayısına bağlıdır; Commander Keen 1 örneğinde 250 karodan yalnızca 40 karo değişmiş, yani tüm ekranın sadece %16’sı yeniden çizilmiştir; çok sayıda tekrar eden karo içeren harita tasarımı performansı belirler
- Commander Keen 4~6’da ATR yerine, 64KiB VRAM aperture’ının wraparound davranışından yararlanarak sürekli panning yapıp yalnızca yeni ortaya çıkan kenar şeritlerini çizme yöntemine geçildi; bazı Super VGA kartlarında başlatılmamış belleğe girilmesi nedeniyle uyumluluk sorunları oluştu
EGA’da karşılaşılan bant genişliği sınırı
- Commander Keen, EGA (Enhanced Graphic Adapter) takılı PC’lerde en iyi şekilde çalışıyordu; grafik programlama, yapılandırma yazmaçları ve VRAM’e eşlenen 64KiB bellek penceresi üzerinden yapılıyordu
- EGA, dahili verileri 4 düzlemde,
C0,C1,C2,C3içinde saklarC0, her 4 bitlik piksel değerinin en düşük anlamlı bitini (LSB) saklarC3, en yüksek anlamlı biti (MSB) saklar- Her düzlem 200 satırdan ve satır başına 40 bayttan oluşur
- 4 bankalı yapı, CRT ekranına yetişecek bant genişliğini sağlamak için tasarlanmıştı ve CRTC 4 baytı paralel okur
- Commander Keen’in kullandığı EGA mode
Dh, 320x200 çözünürlük ve 16 renk sunar- mode
10hgibi, 64 renk değeri arasından mürekkebi yeniden yapılandıran yöntemi kullanmaz - mode
Dhiçinde de varsayılan 16 renk içindeki palet renkleri değiştirilebilir; bu, Commander Keen’in basit fade in/out efektlerinde kullanılır
- mode
Adaptive Tile Refresh’in kaçındığı tam ekran yeniden çizimi
- ATR’nin çözdüğü temel darboğaz bant genişliğidir
- 320x200 pikselin 4 bitlik değerlerini, yani yaklaşık 32KiB veriyi her karede yazmak ISA veri yolu için fazla büyük bir yüktür
- Tüm ekranı her seferinde yenileyen basit bir döngü yaklaşık saniyede 5 kare seviyesinde kalır
- EGA’da 4 banka aynı anda yazmanın bir yolu da vardır; ancak ekran temizleme veya Wolfenstein 3D’deki sütun kopyalama için yardımcı olsa da Commander Keen’in kaydırma sorununa uygun değildir
Yazmaçlarla yapılan akıcı kaydırma
- ATR önce VRAM içinde ekrandan daha büyük bir sanal ekran oluşturur ve CRTC’nin okumaya nereden başlayacağını belirleyen
CRTC_STARTdeğerini değiştirerek görüntüleme alanını hareket ettirir - Dikey kaydırma görece basittir
- Görünen ekranın üstüne ve altına 16’şar satır eklendiğinde düzlem başına
40 x 232 = 9,280bayt kullanılır - Ekranı bir satır yukarı hareket ettirirken
CRTC_START40 bayt artırılır - Bir satır aşağı hareket ettirirken
CRTC_START40 bayt azaltılır
- Görünen ekranın üstüne ve altına 16’şar satır eklendiğinde düzlem başına
- Yatay kaydırma
OFFSETyazmacı ilePELyazmacını birlikte kullanırOFFSET2 olarak ayarlandığında satırlar arasına 16 bayt dolgu eklenir ve sanal ekranın solunda ve sağında 16’şar piksel boşluk oluşurCRTC_START1 artırıldığında düzlem yapısı nedeniyle ekran 8 piksellik adımlarla hareket eder; bu fazla kabadırHorizontal Pel Panning, yaniPELyazmacı,CRTC_STARTsonrasında en fazla 7 biti atlatıp piksel düzeyinde yatay kaydırmayı mümkün kılar
- Gerçek sağ-sol hareket, koordinatın 8’e bölünmüş değeriyle
CRTC_STARTayarlanıp koordinatın kalanıyla (% 8)PELayarlanarak yapılır
jolt ve karo düzeyinde kısmi yenileme
- Sanal ekranın kenarına ulaşıldığında ATR, sanal ekranı tekrar merkeze hizalamak için jolt uygular
- Tüm ekranı yeniden çizmek yaklaşık 200ms sürüp 5fps’ye düşürdüğü için jolt, tam yeniden çizim yerine yalnızca değişen karoların üzerine yazacak şekilde çalışır
- Commander Keen seviyeleri 16x16 karolardan oluşur
- Sanatçı karoları çizdiğinde derleme sistemi her karoya benzersiz bir ID verir
- Seviye tasarımcısı, 2D editörde karo ID’lerini yerleştirerek haritayı oluşturur
- Motor, sanal ekranda hangi karo ID’lerinin bulunduğunu izler
- jolt anında mevcut sanal ekran durumu ile tekrar merkeze hizalanmış hedef durumun karo ID’leri karşılaştırılır
- Aynı karo atlanır
- Yalnızca farklı karolar VRAM üzerine yazılır
- jolt verimliliği yeniden çizilecek karo sayısıyla ters orantılı olduğundan, oyun tasarımcısının tilemap’i çok sayıda tekrar eden karo içerecek şekilde kurması gerekiyordu
- Commander Keen 1 örneğinde, sağa doğru akıcı hareket sırasında sanal ekran sona erip 16 piksel sola jolt oluştuğunda 250 karodan yalnızca 40 karo değişir
- Yeniden çizilen oran tüm ekranın %16’sıdır
- Arka planın üzerine sprite katmanı çizilir
- Motor, sprite’ların üzerine yazdığı dirty karo koordinatlarının listesini tutar
- Her yeni karede dirty listeyi dolaşarak arka plan karolarını geri yükler, ardından sprite’ları yeniden çizer
Çift arabellek ve ikinci üçlemenin drifting tekniği
- Görsel artefaktlardan kaçınmak için tüm sistem iki framebuffer ile çoğaltılır
- CRTC biri okurken diğerine VRAM’in başka bir konumunda yazılabilir
- Her arabellek
(320 + 32) * (200 + 32) * 4 / 8 = 40,832bayt kullanır - Çift arabelleğin tamamı
40,832 * 2 = 81,664bayttır ve IBM’in özgün EGA kartındaki 64KiB’yi aşar
- VileR’e göre 64KiB ile donatılan tek kart özgün IBM EGA kartıydı; 1986~1987 civarında çıkan EGA klonlarının çoğunda 256K vardı ve Commander Keen’in çıkış zamanında 256K’dan düşük EGA kartı neredeyse yoktu
- Commander Keen 1~3’te ATR’nin gerektirdiği tekrar desenleri ekranda belirgindir, ancak Commander Keen 4~6’da aynı özellik göze çarpmaz
- İkinci Keen üçlemesi,
CRTC_START64KiB bloğunun sonuna ulaştığında tekrar bloğun başına dönen wraparound davranışından yararlanır- Ekranı sürekli panning yapar ve yalnızca yeni görünen kenar karo satırlarını çizer
- jolt ortadan kalktıkça benzer renkte tekrar alanları oluşturma ihtiyacı azalır
- Bu yöntem yeni bir özellik eklemekten çok jolt’u ortadan kaldıran bir iyileştirmeye yakındır
- İki çift arabellek öğesi VRAM alanında aynı hızla drift ettiği için birbirleriyle çakışmaz
- Çoğu durumda iyi çalışır
- Bazı Super VGA kartlarında sorun çıkar
- Standarttan farklı uygulamalara ve daha büyük belleğe sahip kartlarda, sondan başa wraparound yapmak yerine gerçekten var olan ama başlatılmamış belleğe girilebiliyordu
- Carmack, standart dışı birçok karta ayrı ayrı uyum sağlamak yerine, ekranın sonuna ulaşıldığında hitch’i göze alıp tüm ekranı yukarı kopyalayan kolay çözümü seçti
- Bu drifting tekniği, karoları ve sprite’ları VRAM’de tutup hızlı VRAM-to-VRAM kopyalama kullanma yöntemini engellemiş olabilir; ancak her karede çizilecek miktar çok az olduğundan büyük bir sorun olmamış olabilir
1 yorum
Hacker News yorumları
Commander Keen 4~6’daki kaydırmanın akıcılığına PC’de yıllarca hiçbir oyun yaklaşamadı; oyunlar 256 renkli grafiklere geçtikten sonra bile durum böyleydi.
John Carmack’ın olağanüstü teknik çalışması ve Adrian Carmack’ın 16 renk paletli sanatı sayesinde id, 1990’larda bir süre PC’de en iyi görünen platform oyunlarını yapmış sayılır.
Adrian Carmack, daha ünlü Carmack’ın akrabası değil ama bana göre 16 renk paletinin gizli ustası.
Grafik ve oynanıştaki ilerleme hızı gerçekten inanılmazdı.
İlk oyundaki değişim: https://en.wikipedia.org/wiki/Commander_Keen_in_Invasion_of_...
Son oyuna kadarki değişim: https://en.wikipedia.org/wiki/Commander_Keen_in_Goodbye,_Gal...
O zamanlar çocukken bizzat oynamıştım; işlerin bu kadar hızlı gerçekleştiğini unutmuşum.
Commander Keen’i küçümsemek istemem ama PoP’un görselleri ve oyun mekaniği, dönemin standartlarına göre benzersizdi diye düşünüyorum.
Yaklaşık 7 yaşındayken ilk oynadığımda büyülü bir izlenim bırakmıştı; bugün de en sevdiğim platform oyunu olduğu için biraz önyargılıyım tabii.
Elbette PoP’ta hiç kaydırma yok; orası Commander Keen’in kara büyüsü.
“Bellek yavaş, o yüzden sadece değişenleri yeniden çizelim” fikri bugün neredeyse bariz sayılır.
Yine de 4~6. bölümlerdeki optimizasyonlar ilginç. 1~3. bölümlerde tamponun wrap etmeyeceği varsayımı yüzünden tüm işi yapmışlar; gerçekte wrap edince o işin boşa çıkması da ilginç.
Windows 98’de DirectX 5 ile tile tabanlı bir oyun yapmıştım; başta bu yazıda anlatılana benzer bir yöntem uygulamıştım.
Ekran kaymıyordu ama çok sayıda tile’ı yeniden çizmek gerekebildiği için durum biraz daha basitti.
Sonunda o kodun tamamını söküp attım; çünkü RIVA TnT kartta tam ekranı çizmenin maliyetini profillediğimde geçen süre o kadar küçüktü ki ölçülemiyordu bile.
PC geliştirmede EGA dönemini kaçırdığıma seviniyorum. O dönemde olsaydım muhtemelen hiçbir şeyi tamamlayamazdım.
Çarpma yerine bit kaydırmayla optimizasyon yapmak, kritik kodu assembly ile yazmak, işlemciler geliştikçe tek seferde 16 bit ya da 32 bit yazmak gibi şeylerdi.
Elimde az kaynak olduğundan yerel kütüphanedeki kitaplardan ve txt dosyalarıyla dolu disketlerden sürekli öğrenirdim.
Çok genç ve deneyimsiz olduğum için tamamladığım bir şey olmadı ama akıcı dikey kaydırma yapmıştım, yatay kaydırmayı da neredeyse çalıştırmıştım; ayrıca dönen bir 3D küp için çift tamponlama da uygulamıştım. Derinlik tamponlama, matematik ve satır bazlı poligon çizimi de buna dahildi.
Sonra DirectX çıkınca makineyle temas noktası kayboldu; dönen 3D küp de fazla kolaylaştığı için eğlencesi kalmadı.
Veri yolu 8 bitten 16/32 bite genişliyor, grafik kartları posted writes destekleyerek CPU’nun daha az beklemesini sağlıyor, CPU da hızlandıkça hızlı sistemler 640x480x256 ekranı saniyede 300 kareden fazla yazabiliyordu.
Bu durumda muhtemelen önbelleğe alınmış sistem belleği tamponu ve DMA kopyası vardı ya da çizimi blitter üstlenmiş olabilir. Ama Windows 98 döneminde bile düşük maliyetli 3D kartların bazıları CPU erişiminde çok yavaştı; eski ISA veri yolu kartlarından ancak biraz daha iyi düzeydeydiler.
Ekran çözünürlüğü çok yükseldiği için bugün bazı açılardan yeniden biraz tersine dönmüş durumda. 4K tam ekranı saniyede 60 kare yeniden çizebilseniz bile buna verimli demek zor.
Oyunlar genelde hâlâ her şeyi yeniden çiziyor ama masaüstü bileştiriciler, yeniden çizilen alanı azaltmak için katmanları donanım düzlemlerine dinamik olarak atamak gibi epey optimizasyon yapıyor.
Aynı dönemde başka bir oyun şirketinde çalışıyordum; ikinci yaklaşımla aynı kaydırma tekniğini kendim bulmuştum.
Bunun o kadar şaşırtıcı bir şey olduğunu düşünmüyorum. O sırada aynı problemi çözmeye çalışıyor olsaydınız muhtemelen benzer bir sonuca varırdınız.
PC speaker üzerinden örneklenmiş ses çalmak için kendi PWM ses sürücümü de yapmıştım; sanırım başkaları da hep bunu yapıyordu.
Hepimiz konsola geçmeden önce PC yeterince sevilmedi. Hornet’in 8088 MPH gibi demolarını görünce hâlâ heyecanlanıyorum.
Eğlenceli bir oyunun olmazsa olmazı değil ama Keen’in özellikle 10MHz altı gibi düşük donanımda gösterdiği akıcılık o dönem göz açıcıydı.
Binlerce yıl boyunca bilinmeden kalmış sayısız harika icat olmuş olmalı.
Ben de LinkedIn’den 10 yıl önce benzer bir şeyi “icat” etmiştim ama başarılı biçimde ticarileştiremedim. Çoğu icadın geniş kitlelerce bilinmediğini düşünüyorum.
Bu yüzden birçok startup iki kişiyle başlar: bir uzman ve bir iş insanı.
Dolayısıyla yanlış değil. Bu icat kendi başına özel olmayan bir şey olabilir; ama yenilik, fayda ve başarılı ticarileştirmenin birleşmesiyle özel hâle geldi.
Mükemmel kitap Masters of Doom, Keen’in Mario tarzı, yani yatay kaydırmalı bir oyun olduğunu anlatır
id, Mario’yu PC’ye portlama seçeneği olarak bu teknolojiyi Nintendo’ya önermişti; ancak Nintendo reddetti ve böylece Keen doğdu
PC oyunları için dev bir sıçramaydı ve yeni bir PC oyunları çağını başlattı
Yine de hâlâ tam anlayamadığım şey şu: NES ile PC teknolojisi arasında ne bu kadar farklıydı da Nintendo yatay kaydırmayı PC’den birkaç yıl önce gerçekleştirebildi?
EGA grafik modunda çizgi, daire, tek tek pikseller gibi istediğiniz herhangi bir şeyi çizebilirsiniz; zaten bu şekilde kullanılmak üzere tasarlanmıştı
Ama kaydırma bedava değildir. Belleği doğrudan kopyalamanız gerekir ve bağlantı verilen yazının gösterdiği gibi kaba kuvvetle yaparsanız ISA veri yolu bant genişliği sınırı yüzünden saniyede ancak yaklaşık 5 kare alırsınız
NES ve diğer 8/16 bit oyun konsolları keyfî şeyler çizmek için tasarlanmamıştı. Tile render etmek için tasarlanmıştı
Arka plan tile ızgarasını tanımlayıp kaydırma ofseti vermeniz yeterlidir. Sprite’lar da benzer çalışır ama bağımsız hareket edebilir. Bunların hepsi saniyede 60 kare olarak bedavaya gelir
Dezavantajı, keyfî şeyleri kolayca render edememenizdir. Örneğin bir yere tek bir piksel boyamak isterseniz epey ağır bir dolambaçlı yol gerekir
Bu, Nintendo’nun IBM’den önce “çözdüğü” bir sorun olmaktan çok; IBM’in genel amaçlı bilgisayarlar ve statik grafikler için genel amaçlı bir grafik sistemi yapıp her piksel üzerinde ince ayarlı kontrol sunmasıydı. Bir EGA karta bakarsanız içinde bolca silikon bulunan epey büyük bir cihazdır
Nintendo ise tile’ları itip kaydırmaya yönelik çok daha basit bir özel amaçlı grafik sistemi yapmıştı
Nintendo kabul etmeyince yeni asset’ler yaptılar ve bu daha sonra Keen’e dönüştü
Portun videosu burada: https://youtu.be/1YWD6Y9FUuw
NES tarafı için https://www.nesdev.org/wiki/PPU iyi bir başlangıç noktası gibi görünüyor
Asıl zorluk “yatay kaydırmanın nasıl yapılacağını bulmak” değil; yatay kaydırmalı bir oyun motorunu tamamen farklı bir sistemin bellek alanı ve bant genişliği kısıtları içinde iyi görünecek şekilde uyarlamak
Katmanları olan sprite tabanlı oyunlar yapıldığı için 2D’yi “hızlandırma” biçimi oldukça mantıklıydı
Lex Fridman’ın John Carmack röportajında her oyunun başlıca yeniliklerinin hepsi üzerinden geçiliyor
Gerçekten ilginç bir bölüm; vaktiniz varsa şiddetle tavsiye ederim. Yaklaşık 5 saat sürüyor
Onun diğer iki röportajını da öneririm
Todd Howard: https://www.youtube.com/watch?v=H9AAnV59ddE
Guido van Rossum: https://www.youtube.com/watch?v=-DVyjdw4t9I
Commander Keen Goodbye Galaxy’deki neredeyse tüm gizli unsurları bildiğime inandığım günleri hâlâ hatırlıyorum
Okul arkadaşlarım, okuldan sonra okul bilgisayarlarında oynadıkları bölümlerdeki sırları bana sorarlardı
fabiensanglard.net’i görünce hemen tavsiye ediyorum
Teknik olarak derinliği olan başka klasik oyun blogları bilen varsa paylaşmasını isterim
https://nicole.express/ ve https://sudden-desu.net/ de sevdiğim yerler
Framebuffer başlangıcını scanline bazında ayarlayınca dikey kaydırmanın nasıl çalıştığını anladım, ama yatay kaydırmanın framebuffer’ı ciddi biçimde bükmeden nasıl mümkün olduğu başta net değildi
Biraz daha düşününce bunun silindirin yan yüzeyine resim çizmeye benzediğini fark ettim. Görüntünün sol kenarını nereye çizerseniz çizin, silindiri döndürüp CRTC_START ve PEL yazmaçlarını ayarlayarak görüntünün tamamını net biçimde görmenin her zaman bir yolu var
“Ekranın kenarına ulaşıldığında, basit bir çözüm olarak takılmayı göze alıp tüm ekranı yukarı kopyalıyorlardı” kısmı da ilginç
Keen’i başlatırken genelde “VGA compatibility mode enabled” gibi bir mesaj çıktığını hatırlıyorum; bunun ne anlama geldiğini hep merak etmiştim
Commander Keen gerçekten sevimli küçük bir oyundu
Yeniden çalıştırmanın bir yolunu bulmam gerek
Ama bunu nasıl çalıştırmak en iyisi olur? “Yetişkin” olduktan sonra yaklaşık 20 yıldır Windows kullanmıyorum; Debian’da nasıl oynayabilirim?
O dönemde bilgisayarlar konsollardan yaklaşık 10 kat pahalıydı; genelde bunun nedeni de yetişkinlerin, çocuğun ne yapması gerektiği konusunda güçlü fikirleri olmasıydı
NES ve Genesis oyunlarıyla karşılaştırınca ruhu eksik. O zamanlar sevmiştim ama yakın zamanda DosBox’ta tekrar oynayınca kesinlikle aynı seviyede olmadığını hissettim
Birkaç yıl önce ikinci yöntemi uygulamıştım; sadece ön kenarı çizmek bile çok yavaştı
Ancak C ile yazmıştım ve assembly programlamayı doğru dürüst öğrenmiş değilim
https://github.com/geon/kate/blob/master/src/platform/dos/eg...