Monday, October 12, 2026

MAME360'a Save State ve Favoriler Eklemek

Xbox 360'ta bir süredir MAME72 Release 11 kullanıyorum. Emulator gayet güzel ama bir eksiği vardı: save state.

Bir oyunda ilerlerken yandıktan veya konsolu kapattıktan sonra aynı noktadan devam etmek istiyordum. Arcade sistemlerde bu olmadığından emülatörlerde save state'le yapılıyor malum. Fakat bunun için yeni bir serializer yazmak, RAM'i elle dosyaya dökmek veya MAME'in kendi sisteminden bağımsız yeni bir state formatı oluşturmak istemedim.

İlk bakmak istediğim şey şuydu:

MAME 0.72'nin kendi save-state sistemi kaynak kodunda hâlâ duruyor mu?

Hedef ortam Xbox 360 homebrew, Visual Studio 2010 SP1 ve Xbox 360 XDK idi. Başından beri kapsamı mümkün olduğunca küçük tutmak istedim. Büyük bir frontend değişikliği, yeni bir state menüsü veya slot seçme ekranıyla başlamanın anlamı yoktu. Önce tek bir state slotunun gerçekten çalıştığını görmek yeterliydi.


Başlangıç noktası

Temel aldığım proje mLoaDs/MAME360 deposuydu:

https://github.com/mLoaDs/MAME360

Temel commit:

63a21cfce35d42333885031cf2fe221808c44016

Çalışma dalı:

savestate-slot0-prototype

Hedef ortam:

Xbox 360 Homebrew
Visual Studio 2010 SP1
Xbox 360 XDK
MAME 0.72 / Release 11

MAME zaten save-state sistemine sahipmiş

Kaynak kodu incelendiğinde güzel haber ortaya çıktı: MAME72'nin save/load altyapısı zaten projede duruyordu.

Yani sistemi sıfırdan yazmaya gerek yoktu.

  • state.c ve state.h: kayıtlı alanların serileştirilmesi.
  • state_save_register_*: cihazların ve sürücülerin durumlarını kayıt sistemine eklemesi.
  • cpuexec.c: save/load zamanlama ve yürütme.
  • cpu_loadsave_schedule_file(): kayıt veya yükleme isteğinin zamanlanması.
  • handle_save() / handle_load(): CPU context'lerini de dikkate alan mevcut işlem.
  • FILETYPE_STATE: state dosyalarının mevcut MAME dosya katmanı üzerinden açılması.

Dolayısıyla Xbox 360 portunda asıl eksik olan şey, bu sistemi gamepad üzerinden kullanabilmekti.

Masaüstü MAME'deki F7 / Shift+F7 ve klavyeden slot seçme akışının Xbox 360 kontrolcüsünde kullanılabilir bir karşılığı yoktu.

İlk prototip için iki basit kombinasyon belirledim:

LB + RB + Y = Save State
LB + RB + X = Load State

Şimdilik yalnızca slot 0 var.


State dosyalarının yapısı

Çalışan ROM'un kısa adı otomatik alınıyor ve state dosyası şu yapıda saklanıyor:

GAME:\sta\<romname>\0.sta

Örneğin benim oynadığım Shinobi bootleg setinde:

GAME:\sta\shinobl\0.sta

Burada shinobl kodun içine sabit yazılmış değil. Hangi oyun çalışıyorsa onun ROM kısa adı kullanılıyor.

Dolayısıyla mekanizma yalnızca Shinobi'ye özel değil.

Ancak ortak save/load mekanizmasının bütün oyunlardan çağrılabilmesi, bütün MAME sürücülerinin save state'i eksiksiz desteklediği anlamına gelmiyor. İlgili driver'ın ve kullandığı cihazların gerekli state alanlarını doğru biçimde kaydetmiş olması gerekiyor.


Gamepad tarafı

İlk sürüm yalnızca tek kontrolcü portunu okuyordu. İkinci sürümde dört Xbox 360 gamepad portu da destekleniyor.

Tuşlara basılı tutulduğunda işlemin her frame tekrar tekrar tetiklenmemesi için edge detection eklendi.

Ayrıca X ve Y aynı anda basılırsa hiçbir save/load işlemi yapılmıyor.

Save/load işlemi doğrudan kontrolcü sorgusunun içinde gerçekleştirilmiyor. Gamepad kodu yalnızca isteği oluşturuyor ve gerçek işlem MAME'in zaten var olan zamanlayıcısına aktarılıyor.

Böylece:

  • Yeni serializer yazılmadı.
  • Yeni state dosyası formatı oluşturulmadı.
  • MAME'in mevcut save-state sistemi kullanılmaya devam edildi.

Dosya sistemi tarafındaki düzenlemeler

Xbox dosya katmanında da birkaç düzenleme gerekti.

Dizin oluşturma kodundaki işaretsiz sayı karşılaştırması düzeltildi ve state dosyaları için ayrı bir kök tanımlandı:

GAME:\sta

State okuma ve yazma tarafındaki hata kontrolleri de güçlendirildi.

  • Bellek ayırma hataları
  • Kısa okuma veya yazma
  • Dosya boyutu
  • State başlığı
  • Sürüm kontrolü
  • ROM adı
  • Kayıt imzası
  • Ses açık/kapalı uyumu

State yazmalarında gerçek yazma sonucu ve FlushFileBuffers sonucu da kontrol ediliyor.


Debug log

Release derlemesinde de hata ayıklamayı kolaylaştırmak için:

GAME:\debug.log

dosyasına bilgi yazılıyor.

[SAVESTATE] Save requested: shinobl slot 0
[SAVESTATE] Save OK
[SAVESTATE] Load requested: shinobl slot 0
[SAVESTATE] Load OK
[SAVESTATE] Failed: <neden>

Eski XDK ile derleme macerası

Burada klasik eski SDK problemleri de çıktı.

İlk derleme denemelerinde eski Xbox 360 XDK araç zincirinde:

Illegal System DLL Relocation

hatasıyla karşılaştım.

Derleme betiklerini kendi Windows oturumumda çalıştırarak ilerledim.

Bir sonraki sorun kullanılan XDK içerisinde:

INVALID_FILE_ATTRIBUTES

sabitinin tanımlı olmamasıydı.

Kod:

(DWORD)-1

karşılaştırmasını kullanacak şekilde düzeltildi.

Başka bir denemede build başarısız görünüyordu fakat aslında XEX düzgün şekilde üretilmişti. Başarısız olan bölüm build sonrası otomatik deployment işlemiydi:

xbecopy: Could not connect to Xbox 360 'unused'

Yerel yardımcı projede otomatik deployment kapatıldı.

Böylece iki ayrı konu birbirinden ayrılmış oldu:

XEX başarıyla derlendi mi?

Xbox'a otomatik olarak gönderilebildi mi?

İlk Xbox denemem

İlk sürümü Xbox 360'a attığımda emülatör açılıyordu fakat save/load kombinasyonlarına bastığımda ekranda hiçbir şey görünmüyordu.

Bu yüzden ilk anda çalışmadığını düşündüm.

O sırada dosya sistemini veya debug.log dosyasını kontrol etmemiştim.

İkinci sürümde mevcut MAME ekran mesajlarını kullanarak görünür geri bildirim ekledim.

Oyun açıldığında:

SS2 ready

mesajı çıkıyor.

Save veya load işleminden sonra da başarı veya hata mesajı gösteriliyor.

Oyun listesindeki sürüm işareti ise:

SS2+Fav

Bu sürümü gerçek Xbox 360 üzerinde denedim ve save/load düzgün şekilde çalıştı.

Daha sonra sürümü kullanmaya devam edip sorunsuz çalıştığını gördükten sonra normal GitHub release olarak yayınladım.

Burada bütün MAME oyunlarını veya mümkün olan bütün kontrolcü kombinasyonlarını gerçek Xbox üzerinde kapsamlı biçimde test ettiğimi iddia etmiyorum.


Favoriler

Save state çalıştıktan sonra oyun listesindeki başka bir eksik de gözüme battı: favoriler.

ROM sayısı arttıkça sürekli aynı oyunları aramak pek kullanışlı değil.

Bunun üzerine aynı süreç içinde basit bir favoriler sistemi de ekledim.

Y = Favoriye ekle / favoriden çıkar
X = Tüm oyunlar / favoriler filtresi

Favori oyunların yanında:

[*]

işareti görünüyor.

Liste şu dosyada tutuluyor:

GAME:\favorites.txt

Oyun kimliği olarak ekranda görünen uzun açıklama yerine ROM'un kısa adı kullanılıyor.

Favori dosyası doğrudan eski dosyanın üzerine körlemesine yazılmıyor. Önce geçici bir dosyaya yazılıyor; işlem başarılı olursa asıl dosya değiştiriliyor.

Yazma işlemi başarısız olursa bellekteki favori listesi de değiştirilmeden bırakılıyor.

Boş favori listesi, son favorinin kaldırılması ve tekrarlanan tuş olayları gibi durumlar da ele alındı.

Ayrıca bunun için yeni bir skin paketine ihtiyaç yok.

Favori işlevinin bilgisayar tarafındaki testleri geçti. Daha sonra genel olarak sürümün sorunsuz çalıştığını gördüm fakat favorilerin konsol yeniden başlatıldıktan sonraki kalıcılığına ilişkin ayrıca ayrıntılı bir test raporu hazırlamadım.


Bilgisayar tarafındaki testler

Gerçek MAME kaynak fonksiyonları kullanılarak çeşitli testler yapıldı.

  • Kayıtlı alanlar, CPU tag'leri ve callback'lerle save/load turu.
  • Orijinal MAME72 serializer'ıyla bayt seviyesinde dosya uyumu.
  • Bozuk veya uyumsuz state dosyalarının reddedilmesi.
  • Bellek ve dosya işlemi hataları.
  • Dört kontrolcü desteği.
  • Tuşlara basılı tutma durumu.
  • Kontrolcünün bağlantısının kesilmesi.
  • Eşzamanlı save/load istekleri.
  • Dizin oluşturma hataları.
  • Yazma ve flush hataları.
  • Favorilerin yeniden okunması.
  • Boş favori filtresi.
  • Aynı görünen oyun isimleri.
  • Yazma hatasında favori listesinin korunması.
  • Patch'in temiz kaynak koduna uygulanıp geri alınabilmesi.

Dosya sistemi ve XUI çağrılarının bazıları bilgisayar testlerinde adaptörlerle taklit edildi.

Dolayısıyla bu testler gerçek Xbox 360 üzerinde oynama testinin yerine geçmiyor.


Değişen emülatör dosyaları

mame_0.72/src/ altında değişen temel dosyalar:

cpuexec.c
osdepend.h
state.c
state.h
xbox/xbox_JoystickMouse.c
xbox/xbox_FileIO.cpp
xbox/xbox_Miscelaneous.c
xbox/RomList.cpp
xbox/RomList.h

Bunların dışında depoya test betikleri, teknik derleme notları ve README açıklamaları da eklendi.


Shinobi'nin ses problemi

Bu süreçte ayrıca MAME360'ta Shinobi oynarken duyduğum ses problemi üzerine de biraz araştırma yaptım.

Bazı efektlerde çatırdama veya patlama duyuyorum. Müzik ise oldukça düşük seviyede geliyor.

Mixer ayarlarıyla oynadım fakat sorun düzelmedi.

Problem save-state değişikliklerinden önce de vardı, yani yeni eklenen state sistemiyle bağlantılı değil.

İlk araştırmada orijinal shinobi setinden hareket edilerek uPD7759 tarafına bakıldı.

Daha sonra oynadığım sürümün aslında bootleg olduğunu fark ettim.

MAME72 ağacındaki:

shinobl

sürücüsü:

YM2151 + 7751/DAC

kullanıyor.

Dolayısıyla ilk ses donanımı varsayımı düzeltildi.

Araştırmada bootleg Shinobi'nin bazı efektlerinin, özellikle zıplama sesinin orijinal sürümden farklı olabildiğini belirten eski kullanıcı mesajlarına rastladım.

FinalBurn geçmişinde de Shinobi için DAC DC offset kaynaklı patlama/tıklama seslerini gideren bir düzeltme bulunuyor.

Ancak bunun benim duyduğum sorunun kesin nedeni olduğunu doğrulamadım.

Bu projeye herhangi bir ses düzeltmesi eklenmedi.

Yeni sürüm bana biraz daha az parazitli gelmiş olsa da ses üretim kodunda değişiklik yapılmadığı için bunu bir düzeltme kanıtı olarak görmüyorum.

Bendeki orijinal Shinobi seti de birkaç .bin dosyasının eksik olduğunu söylediği için henüz açılmıyor. Eksik dosyaları ayrıca ayrıntılı incelemedim.

Araştırmada baktığım kaynaklar:


GitHub ve yayın

mLoaDs'ın MAME360 deposunu kendi hesabıma fork ettim.

Benim depo:

https://github.com/kadirdogan/MAME360

Kod değişiklikleri ve testler commit edilip push edildi.

Şu anda GitHub tarafında emülatör kaynakları ve teknik notlar bulunuyor.

Derlenen XEX:

mame-ss2-favorites.xex

XEX ile birlikte SHA-256 doğrulama dosyası da GitHub Releases'a yüklendi ve yayınlanan dosyanın hash'i yerel XEX ile karşılaştırıldı.

İlk yayın pre-release olarak açıldı.

Xbox üzerinde test edip sorunsuz çalıştığını gördükten sonra normal release'e çevirdim ve şu anda Latest olarak işaretli.

İlk prototipten kalan tag adı ise:

ss2-prototype-1

Bilinen sınırlar

  • Şimdilik yalnızca slot 0 var.
  • State doğruluğu ilgili driver ve cihazların state kayıtlarının yeterliliğine bağlı.
  • State yazması atomik değil; başarısız bir yazma eski slotu bozabilir.
  • Save/load kombinasyonlarındaki X/Y tuşları normal oyun girdisine de ulaşabilir.
  • Farklı MAME360 derlemeleri arasında state uyumluluğu garanti edilmiyor.
  • Shinobi ses problemi çözülmüş değil.
  • Release yalnızca XEX ve checksum içeriyor; mevcut MAME360 media/config/ROM kurulumu gerekiyor.

Sonuç

Benim esas istediğim şey artık çalışıyor.

Xbox 360'ta MAME oynarken:

LB + RB + Y

ile kaldığım yeri kaydedebiliyorum.

Daha sonra:

LB + RB + X

ile aynı noktaya geri dönebiliyorum.

İşin güzel tarafı, yaklaşık yirmi yıllık MAME kodunun içinde gerekli sistemin zaten bulunmasıydı. Yeni bir save-state mimarisi yazmak yerine mevcut sistemi Xbox 360 tarafında tekrar ulaşılabilir hale getirmek yeterli oldu.

Favoriler de işin güzel bonusu oldu.


📁 Github:

Kaynak kod:
github.com/kadirdogan/MAME360

Hazır XEX / son sürüm:
github.com/kadirdogan/MAME360/releases/latest

Temel alınan MAME360 deposu:
github.com/mLoaDs/MAME360


MAME360 / MAME72 Release 11 üzerinde yaptığım bu değişiklikler Xbox 360 homebrew ortamında kullandığım kendi kurulumum üzerinden geliştirildi ve test edildi.