1 puan yazan GN⁺ 2024-07-15 | 1 yorum | WhatsApp'ta paylaş
  • 2001 yapımı RTS Emperor: Battle for Dune, modern Windows’ta çalıştırma, kurulum ve çevrim içi oynama açısından sorunluydu; EmperorLauncher ise onu yeniden oynanabilir hale getiren bir yama
  • Temel iyileştirmeler yüksek çözünürlük desteği, 60 FPS sınırı, doğrudan IP ile çevrim içi çok oyunculu mod, eşli senaryo modu ve bozuk kurulum sürecini atlatma üzerine odaklanıyor
  • Uygulama; Emperor.exe yerine geçen bir başlatıcı, Game.exe hedefli DLL enjeksiyonu, Microsoft Detours ile fonksiyon yamalama, Direct3D 7 render hook’ları, winsock yakalama ve basit bir WOL sunucusundan oluşuyor
  • Çevrim içi oyun, mevcut P2P/rastgele port/NAT punching yapısını tek bir istemci→sunucu bağlantısı üzerinden tünelleyerek yalnızca sunucu host’unun ağ ayarlarıyla uğraşmasını yeterli hale getiriyor
  • Orijinal CD dosyalarını kopyalama, .cab çıkarma, resmi v1.09 yamasını uygulama, WOLAPI.DLL için COM kaydı atlatma ve Win32 başlatıcı UI’ını bir araya getirerek kurulumdan çalıştırmaya kadar tüm süreci yönetiyor

Emperor: Battle for Dune’un takıldığı noktalar

  • Emperor: Battle for Dune, 2001’de Westwood Studios tarafından yapılan bir gerçek zamanlı strateji oyunu ve Dune 2000in devamı
  • Modern sistemlerde oyunu oynamayı engelleyen çeşitli sorunlar hâlâ var
    • Modern ekranlara uygun yüksek çözünürlükte çalışmıyor
    • Çok oyunculu modda oyun simülasyon hızı sınırlandırılmadığı için aşırı hızlanıyor
    • Westwood Online(WOL) artık çalışmadığından LAN dışı çok oyunculu oyun zorlaşıyor
    • Eşli senaryo çevrim içi özel bir özellik olduğu için LAN’da kullanılamıyor
    • Diskte yer alan kurulum programı bozuk
    • Modern PC’lerdeki yüksek kare hızlarında çeşitli görsel efektler bozuluyor
  • EmperorLauncher bu sorunları çözmeye yönelik bir yama; indirme dosyası ve kaynak kodu açık

Emperor.exe’nin değiştirilmesi ve Game.exe’nin ilklendirilmesi

  • Oyunun Emperor.exe dosyası gerçek oyun çalıştırılabilir dosyası değil, Game.exeyi açan ince bir wrapper
  • Game.exe doğrudan çalıştırıldığında hiçbir şey olmadığı için, Emperor.exenin yaptığı ilklendirme sürecinin analiz edilip alternatif başlatıcıda yeniden üretilmesi gerekti
  • Analizde IDA kullanıldı
    • IDA, çalıştırılabilir dosyayı disassemble edebilir ve bazı kodları C biçiminde decompile edebilir
    • Tip bilgisi ve struct bilgisinin kaybolduğu bir binary içinde fonksiyon çağrılarını ve Windows API kullanımını izlemek gerekir
  • Emperor.exe, Game.exeyi başlatmadan önce mutex ve anonim file mapping handle’ları oluşturuyor, Emperor.datten okuduğu veriyi işledikten sonra mapping’e kopyalıyor
  • Ebeveyn süreç, CreateProcessA ile elde ettiği alt sürecin main thread ID’sine Windows mesajı göndererek file mapping handle değerini iletiyor
    • Özel mesaj ID’si olarak 0xBEEF kullanılıyor
    • File mapping verisi "UIDATA,3DDATA,MAPS" şeklinde üç string’di ve oyunun asset yükleme koduna iletiliyordu
  • Şifre çözme kodunu doğrudan yeniden uygulamak yerine, Game.exe yerine bir dump aracı konup aktarılan veri diske kaydedildi; ardından başlatıcıda aynı sekans yürütüldü

DLL enjeksiyonu ve fonksiyon yamalama yöntemi

  • Yamayı uygulamak için Game.exe sürecinin içinde kullanıcı kodu çalıştırmak gerekiyordu; bunun için CreateRemoteThread + LoadLibrary yöntemi kullanıldı
  • Enjeksiyon adımları şu sırayla ilerliyor
    • Hedef süreç belleğinde VirtualAllocEx ile buffer ayırmak
    • DLL yolu string’ini WriteProcessMemory ile kopyalamak
    • LoadLibrary adresini ve DLL yolu buffer’ını CreateRemoteThreade vererek DLL’i hedef süreçte yüklemek
    • DLL’in DllMaini çalışınca yama kodunun devreye girmesi
  • Süreç suspended durumda başlatılıp ardından DLL enjekte edilerek main çalışmadan önce kod çalıştırma garanti altına alındı
  • Mevcut fonksiyonların değiştirilmesinde Microsoft Detours kullanıldı
    • Detours, orijinal fonksiyonun başlangıç talimatlarını jump talimatıyla değiştirerek çağrıyı alternatif fonksiyona yönlendiriyor
    • Üzerine yazılan orijinal talimatlar ayrı bir belleğe kopyalanıyor; ardından orijinal fonksiyonun kalan konumuna jump eden bir wrapper oluşturularak orijinal fonksiyon çağrısı da mümkün kılınıyor
  • Fonksiyon kod sayfaları güvenlik nedeniyle yazılabilir olmadığından VirtualProtect ile izinlerin değiştirilmesi ve değişiklikten sonra FlushInstructionCache çağrılması gerekiyor

Debug loglarının geri getirilmesi

  • Binary içinde debug loguna benzeyen çağrılar vardı; ancak gerçek hedef fonksiyon yalnızca ret içeren boş bir fonksiyondu
  • Release build’de birden çok boş fonksiyonun aynı kodda birleştirilmiş olduğu, bunlardan birinin de debug logger olduğu anlaşılıyor
  • Başta ilk argümanı string pointer olarak yorumlayıp yazdırılabilir ASCII karakteri olup olmadığını kontrol eden bir sezgisel yöntem kullanıldı
    • Hatalı pointer erişimleri Windows’un SEH exception mekanizmasıyla yakalanıp yok sayıldı
    • Bu yöntem bir ölçüde çalıştı ancak false positive ve false negative sonuçlar kaldı
  • Daha sonra IDA’nın yama özelliği ve Python script’iyle log çağrı noktaları ayrı bir boş fonksiyona taşındı
    • Bazıları sezgisel yöntemle, bazıları string sabitini push edip çağırma pattern’iyle bulundu
    • Kalan yüzlerce çağrı noktası elle yorum satırıyla işaretlendi
  • Geri getirilen loglar WOL çok oyunculu hata ayıklamasında yardımcı oldu
    • SC_MESSAGE_YOUR_DETAILS işlenirken çıkan "MyId == INVALID_ID" assert logu sayesinde, Wireshark dump’ında GAMEOPT komutunun yanlışlıkla tüm oyunculara gönderildiği doğrulandı

Direct3D 7 grafik yaması

  • Emperor, Direct3D 7 tabanlı bir oyun ve modern Windows’un Direct3D 7 desteği eksiksiz değil
  • Yüksek çözünürlük sorunu, Direct3D 7 wrapper katmanındaki 2048 maksimum texture boyutu sınırıyla ilişkiliydi; UCyborg’un LegacyD3DResolutionHack kodundan yararlanılarak çözüldü
  • Oyun 4:3 oranı dışındaki ekranları düzgün işleyemiyor
    • Render işlemi gerçekleşiyor ama UI aşırı büyütülmüş gibi bozuluyor
    • Oyun içi mouse render offset’i de ekran merkezine olan mesafeye göre kayıyor
  • Çözüm 4:3 letterboxing
    • Oyun pencere modunda çalıştırıldığında rastgele çözünürlük kullanmak mümkün
    • Pencere kenarlığı stili kaldırılıyor ve oyun penceresi tam ekran siyah pencerenin üzerine yeniden parent ediliyor
    • Çoklu monitörde veya pencere modunda kenar kaydırmanın bozulmaması için mouse capture ekleniyor
  • Kare hızı sınırı, IDirect3DDevice7::EndScene yamalanarak 60 FPS’e ayarlanıyor
    • EndScene her karenin sonunda bir kez çağrıldığı için gecikmeyi hesaplayıp thread’i sleep ettirmek için uygun
    • EndScene pointer’ı doğrudan export edilmediğinden, DirectDrawCreateEx ve IDirect3D7::CreateDevice çağrıları sırayla hook’lanarak vtable’dan fonksiyon pointer’ı alınıyor

Çevrim içi çok oyunculu mod ve WOL alternatifi

  • Hedef, lobi veya hosting altyapısı olmadan port forwarding ve IP girişiyle bağlanan doğrudan IP çok oyunculu mod idi
  • LAN modu çalışıyor ancak sunucuyu UDP broadcast ile bulduğu için internet üzerinden oynamaya uygun değil
    • LAN menüsünde manuel IP giriş özelliği yok
    • Başta IP belirtmek için LAN sohbetini yamalama yöntemi denendi; ancak eşli senaryonun WOL’a özel olduğu anlaşılınca bundan vazgeçildi
  • WOL’u canlandırmak için iki şey gerekiyordu
    • Oyunun nereye bağlanacağını ve hangi oyunu başlatacağını bilebilmesini sağlayan sahte bir WOL master server
    • Oyun paketlerinin doğrudan IP bağlantısı üzerinde çalışmasını sağlayan bir proxy
  • Mevcut WOL yapısında master server ile birlikte bir “mangler” sunucusu vardı; mangler’ın NAT punching koordinasyonu rolü üstlendiği düşünülüyor
    • Orijinal mangler sunucusu ortadan kalkmıştı ve oyun bu yanıtı beklerken takılıyordu
    • Yamayla mangler çağrısı kaldırıldı
  • Emperor, P2P ağ modelini kullanıyor; her oyuncu çifti için çift yönlü bağlantı açıyor ve rastgele port seçiyor
    • Tüm istemcilerin açık port kabul etmesini gerektiren bu yapı modern internet ortamına uygun değil
  • Çözüm, winsock fonksiyonlarını yakalayıp tüm bağlantıları tek bir istemci→sunucu bağlantısı üzerinden tünellemek
    • İstemcinin sunucuya veya başka istemcilere göndermek istediği mesaj yakalanıyor, bir header ile sarılıyor ve tek bağlantı üzerinden gönderiliyor
    • Sunucu tarafındaki thread mesajı alıp hedefe dağıtıyor
    • Oyun hâlâ P2P gibi çalıştığına inanıyor; gerçekte ise yalnızca sunucu host’unun ağ ayarlarını halletmesi yeterli oluyor
  • Bu yapı sayesinde eşli senaryo oyunu başlatılabildi ve katılım sağlanabildi

Basit WOL sunucusu uygulaması

  • WOL master server, IRC sunucusuna yakın bir yapıdaydı
  • xwis.net üzerinde hayranlar tarafından işletiliyor gibi görünen bir sunucu vardı ve yazım sırasında oyunun orijinal DNS kaydı servserv.westwood.com üzerinde de erişim yetkisi varmış gibi görünüyordu
    • Emperor xwis üzerinde olduğu gibi düzgün çalışmasa da lobi oluşturma ve katılma için referans oldu
  • Açık WOL sunucusu uygulaması olan pvpgn-server’ın handle_wol.cpp dosyası da kaynak olarak kullanıldı
  • Kendi sunucusunu yazma nedeni, dış sunucuların sürekli ayakta kalacağının garantisi olmamasıydı
    • Amaç rakip bir topluluk işletmek değil, çok oyunculu oyunu çalıştırmak için gereken minimum işlevleri sunmak
  • WOL, standart IRC ile özel davranışların karışımı
    • Oyun lobisi özel bir kanal
    • Lobi bilgisi IRC topic’i kullanıyor
    • Lobi sohbeti PRIVMSG yerine PAGE kullanıyor
    • Oyun ayarlarının senkronizasyonu ASCII olmayan içerik taşıyan GAMEINFO mesajıyla yapılıyor
  • Temel WOL sunucusu uygulaması trial and error ile tamamlandı; normal akıştan sapıldığında sağlam değil ama çalışıyor

Kurulum programı ve v1.09 yamasının uygulanması

  • Orijinal kurulum programı bozuk olduğu için kullanıcının CD içeriğini hard diske kopyalayıp alternatif setup’ı üzerine yazdığı bir çözüm gerekiyordu
  • EmperorLauncher, orijinal CD’den dosyaları kopyalayan ve .cab dosyalarını çıkaran bir kurulum işlevi içeriyor
    • .cab, zip’e benzer bir arşiv formatı ve Windows’ta çıkarma için bir arayüz bulunuyor
  • Son resmi yama olan v1.09un uygulanması daha zordu
    • EM109EN.EXEyi 7zip ile basitçe çıkarıp en yeni binary’leri alma yöntemi işe yaramıyor
    • Windows resource içinde çalıştırılabilir dosya header’ı görünen büyük bir resource bulundu
    • Bu resource’un ilk 4 baytı dosya boyutu, sonrası ise gerçek dosyaydı
  • EM109EN.EXE, gömülü DLL’i geçici dosyaya çıkarıp yükledikten sonra DLL içindeki RTPatch32@12 fonksiyonunu çalıştırıyor
    • RTPatch, binary diff yama aracıydı
    • myRTP aracı referans alınarak gömülü DLL doğrudan yüklendi ve çalıştırıldı
  • DLL, argüman olarak aldığı kurulum yolunu değil registry’den okuduğu yolu kullandığı için, beklenen registry key sahte olarak oluşturulup yama uygulandı

Westwood Online Shared Internet Components işlemi

  • Orijinal kurulumda Emperor’ın kendisinden ayrı olarak Westwood Online Shared Internet Components bulunuyor
  • Bu bileşen yoksa WOL çalışmıyor; ana dosya WOLAPI.DLL
  • WOLAPI.DLL bir COM class library ve Emperor, DLL içindeki COM nesnelerini CoCreateClass ile oluşturuyor
  • Tipik COM kaydı, HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID altında CLSID ve DLL yolunu sistem genelinde kaydeder
    • Bu yöntem yönetici yetkisi gerektirir
    • Oyun sürecinin kapsamını aşarak tüm sistemi etkiler
  • Yamayla registry redirect ve OaEnablePerUserTLibRegistration kullanılarak kullanıcı bazlı kayıt yöntemiyle çözüldü
    • Yalnızca tek bir süreç için class library kaydetmenin bir yolu bulunamadı
    • DllGetClassObjectu doğrudan kullanma denemesi işe yaramadı

Başlatıcı UI’ı ve nihai sonuç

  • Son aşama, IP girişi ve temel ayar değişiklikleri için basit bir başlatıcı UI’ıydı
  • UI raw Win32 controls ile yazıldı
    • Statik ve basit bir UI için yeterliydi, ancak doğrudan Win32 UI yapmak zorlu bir deneyimdi
  • EmperorLauncher sonuçta modern sistemlerde çalıştırma, yüksek çözünürlük, 60 FPS sınırı, doğrudan IP çok oyunculu mod, eşli senaryo, kurulum ve yama uygulamayı kapsayan bir araç haline geldi

1 yorum

 
GN⁺ 2024-07-15
Hacker News yorumları
  • Bu oyunun gerçek zamanlı strateji türü genelinde epey büyük bir anlamı var. Gerçek zamanlı strateji denince genelde köylülerin kaynak topladığı ve bunun korunduğu bir yapı akla gelir; Dune RTS bu kalıba yakın bir ilk örnekti.
    Ancak bu yapının böyle olmasının nedeni biraz da orijinal roman. Öyle olmasaydı tür bambaşka bir yola gidebilirdi. Örneğin üssün kendi kaynakları çıkarılıyor, rakip de binaları rahatsız ederek baskı kuruyor olabilirdi; harita hâkimiyetinin ödülü de kaynak erişimi dışında başka bir biçimde olabilirdi.

    • Tam olarak söylersek bu yazı Dune 2 hakkında değil, Emperor: Battle for Dune hakkında.
    • Başkasının da belirttiği gibi, bu muhtemelen aklınızdaki Dune 2’nin devam oyunu.
      Dune 1 de temeli atmıştı. Başta daha çok point-and-click maceraya yakın, ama ilerledikçe kaynak yönetimi ve madencilik, birlik üretimi, savaş ve terraforming içeren bir oyuna dönüşüyor.
      Son bölümlerde ne yapacağımı bir türlü çıkaramamıştım. Hedef sanki gezegeni yeniden yeşile çevirmekti; ama yeşillik olunca spice çıkmıyordu. Buna rağmen İmparator sürekli daha fazla spice teslimatı istiyor, kotayı tutturamazsanız oyun bitiyordu.
      Çocukken oynadığım için doğru dürüst anlamamış olma ihtimalim de yüksek. Yeniden okumam gerekir, ama bugünün ölçütleriyle ya pek iyi eskimemiştir ya da sonuna kadar oynamak epey zaman alacaktır.
      Düzenleme: Dune 1 ve 2’nin aynı yıl çıktığını bilmiyordum. Öyleyse Dune 2’nin geliştirmesi zaten sürüyordu ya da motoru ve oyunu 1 yıl içinde yapmışlar demektir. Bugün indie ve araçlar hızlanmış olsa bile hayal etmesi zor.
    • The Settlers’ı (https://en.wikipedia.org/wiki/The_Settlers_(1993_video_game)) hep ilk gerçek zamanlı strateji oyunu olarak düşünmüştüm.
      Haziran 1993’te çıktığı için Dune’dan birkaç ay geç, ama iki oyun aynı anda geliştirme aşamasındaysa, birden fazla “mucit”in aynı fikre ulaşması örneği de olabilir. The Settlers’ın Populous (https://en.wikipedia.org/wiki/Populous_(video_game)) gibi “tanrı oyunları”ndan etkilendiği söyleniyor. Oyuncunun araziyi değiştirmek gibi tanrısal güçleri var, ama birimleri doğrudan kontrol etmiyor.
    • Dawn of War, klasik cevher madenciliği paradigmasından çıkan gerçek zamanlı stratejiler için iyi bir örnek.
    • Belki de sonunda zaten o yöne giderdi. Tarih, “köylüler kaynak tabanı, hükümdar stratejisttir” kalıbına epey yaslanıyor.
      Bunun sadece Dune’a özgü değil, tarihin geneli için bir ölçüde böyle olduğunu düşünüyorum.
  • Güzel yazı ve harika bir iş. Yaklaşık 10 yıl önce benzer bir şey yapmıştım; hedef Tiberian Sun idi ve ağ kodunu yamalıyordum.
    Başkasının koduna böyle dalmak, bir tür ortak bağ kuruyormuş hissi veriyor. Korkunç olan, modemle oyun için tamamen ayrı bir stack olduğunu keşfetmemdi. TCP/IP’yi doğrudan modem üzerinden göndermemişlerdi.
    Birileri aylar boyunca framing, senkronizasyon, hata işleme, bağlantı koparsa yeniden ararken ne yapılacağı gibi özel kodlar yazmış olmalı. Ama oyun ilk çıktığı sıralarda bu kod zaten neredeyse işe yaramaz hâle gelmişti.

    • Bence bunun başka bir nedeni vardı. Amaç çevirmeli internete bağlanmak değil, başka bir modemi doğrudan aramak olmalıydı.
      Kendim hiç kullanmadım ama eski oyunlarda böyle seçenekler çoktu.
  • Güzel. Yazıda şu bölüm dikkatimi çekti:
    “Westwood Online (WOL) artık çalışmıyor, bu yüzden LAN dışında çok oyunculu oynanamıyor”
    Çocukken Command & Conquer’ı severdim ve istemci tarafında Westwood Online hakkında biraz bilgim var.
    Yanlış hatırlamıyorsam WOL kapandıktan sonra XWIS.net çok destek verdi. Yazarın oradaki küçük geliştirici topluluğuyla iletişime geçmesi iyi olabilir. Gerçi artık gerçekten yok olmaya yüz tutmuş bir hava da olabilir.
    XWIS ekibinin yaptığı işler EA tarafından da tanınmıştı ve C&C Renegade’in WOL desteğini sürdürmeye epey yardımcı olmuştu diye hatırlıyorum.
    Ayrıca FreeRA projesi de var; Steam ve benzeri yerlerde çıkan son C&C yeniden yayımlarının doğrudan atası sayılır. Onlar da WOL’u canlandırma konusunda yardımcı olabilir.
    WOL, kendi kütüphanesini içeri itme yöntemiyle çalıştığı için, WOL stack’ini yeniden tersine mühendislik yapmaktansa kütüphaneyi değiştirmek çok daha kolay olabilir.
    Düzenleme: Yazıyı okumaya devam edince WOL bileşenlerini de düzelttiğini gördüm. Daha da iyi.

  • Harika bir yazı. Yazar o kadar eğlenceli ve zeki biri gibi görünüyor ki onunla gece dışarı çıkıp bir şeyler içmek isterdim.
    Sevimli açılır açıklamaları gerçekten çok sevdim ve kullanışlı da buldum. Yazıyı okurken bir tür seçimli macera RPG oynuyormuş gibi hissettim; epey yeni bir deneyimdi.
    Ayrıca “CS:GO ancak 2023’te emekli oldu” kısmıyla ilgili olarak, CS:GO’nun CS2 olarak yeniden markalandığını sanıyordum; yanlış mı biliyorum?

    • CS2 bazıları tarafından CS:GO’ya göre bir gerileme olarak görülüyor. Ben de öyle düşünüyorum.
      Turnuva PC’lerinde bile CS2’de düzgün saniye başına kare hızının korunamadığını duydum. Aynı donanım CS:GO’da harika çalışmasına rağmen böyleymiş. Üst düzey PC’lerde de benzer sonuçlar paylaşan çok sayıda kullanıcı raporu var.
      Valve, CS2’nin CS:GO’nun devamı gibi görünmesini istedi; ama daha iyi bir oyun yapıp doğal biçimde onun yerini almasını sağlamadı, oyuncu kitlesini değişime zorladı. CS:GO harika bir oyun olduğu için ben ve başkaları bir süre daha buruk kalacağız.
    • CS2, CS:GO ile aynı uygulama ID’si altında yayımlandı, ama yeni motorla tamamen yeniden yapılmış bir oyun. Bir yeniden markalama değil.
    • CS2, eski Source 1 tabanlı CS:GO’dan farklı olarak Source 2 motorunda DX11 veya Vulkan renderer kullanıyor.
  • Modern reklam dolu, kazanmak için ödeme gerektiren seri üretim oyunların eski klasiklere yenilmesi fikri gerçekten eğlenceli.
    Tek bir hacker yardım etse bile kitle böyle çöp oyunları kovabilir. Kalıcı medyada geçmişin iyi şeyleri, bugünün vasat şeylerini eninde sonunda yeniyor gibi görünüyor.

  • Harika bir yazı ve harika bir emek. Belki bizim CnCNet tarafındaki çalışmalarla bir şekilde entegre edilebilir. CnCNet’e gelip birlikte konuşsa güzel olur.

  • “Üzerinde 28.8 BPS modem var” ha.
    Aktif matris tabii. Milyonlarca psikedelik renk.

    • RISC mimarisi her şeyi değiştirecek.
  • Çok ilginç ve derinlikli bir yazı. Böyle terk edilmiş oyunları tersine mühendislik yapıp yamalamanın nasıl yapılacağına dair paylaşılan ayrıntı ve bilgi miktarı gerçekten hoşuma gitti.
    Bu oyunu mahalledeki ikinci el dükkânında görmüştüm ama sadece Dune II RTS oynadığım için bırakıp gelmiştim. Artık kesin alacağım.

    • Wine’da çalışıp çalışmayacağını merak ediyorum.
  • Bununla ilgili olarak Steam’de modern bir Dune gerçek zamanlı strateji oyunu var.
    https://store.steampowered.com/app/1605220/Dune_Spice_Wars/

    • Buna gerçek zamanlı strateji demek biraz zor. 4X oyununa daha yakın; ilerleyiş hızı yavaş ve savaş da o kadar önemli değil.
    • Başkalarının Spice Wars’un 4X olduğunu söylemesinden bağımsız olarak, gerçek anlamda modern Dune gerçek zamanlı stratejisine en çok yaklaşan oyun Homeworld: Deserts of Kharak idi.
  • “UI tasarımı benim tutkumdur” ha.
    Gerçekten güzel. Böyle yazıları özlüyorum. Birçok açıdan Steve Yegge blog yazılarını hatırlatıyor.