Saturday, October 17, 2026

Xbox 360’ta USB Kontrolcü Desteği: HidDriver360, Kernel 17511 ve Hori

MAME360'a save state ve favoriler ekledikten sonra bu kez kontrolcü meselesine geçtim. Elimdeki Hori Fighting Stick mini 4'ü Xbox 360'ta, özellikle de MAME'de kullanmak istiyordum.

Sonunda PlayStation Classic kolunu, bir USB çevirici üzerinden PS1/PS2 kollarını ve Hori'yi çalıştırdım. Orijinal DualShock 3'ü de USB kabloyla denedim. HidDriver360 V1.0 release altında şu anda hepsi çalışıyor. Bu noktaya gelene kadar kernel adresleri, XEX yükleme sorunları, USB raporları ve cihazın bağlantının ortasında kimlik değiştirmesiyle uğraştım.

Derlemeleri Windows'ta yaptım; Xbox denemelerini de gerçekleştirdim. Süreç çoğunlukla yeni bir XEX derlemek, konsola taşımak, sonucu görmek ve logu geri getirip PC'de incelemek şeklinde geçti.


Başlangıç: HidDriver360

Temel aldığım proje EinTim23/hiddriver360 oldu:

https://github.com/EinTim23/hiddriver360

Mevcut HidDriver360'ın kontrolcü okuma, eşleme ve Xbox'a sanal kontrolcü olarak sunma altyapısı üzerinden ilerledim. Başlangıç noktası v0.6-beta kaynaklarıydı.

Temel commit:
d42173a7e4d2eb967d1cc092d77638f42a40f246

Benim konsolun DashLaunch'ta görünen bilgileri şöyleydi:

Board: Jasper
Flash: Jasper
Type: Glitch
Kernel: 2.0.17511.0

Projenin başlangıçtaki desteklediği sistemler arasında 17559 retail ve 17489 devkit vardı. Bendeki 17511 için doğrudan çalışan bir uyarlama yoktu. Konsolun sistemini güncellemek yerine sürücüyü mevcut sisteme uydurmak istedim.


PlayStation Classic ile gelen ve PS1 koluna benzeyen Sony USB kontrolcüsünü Windows, Linux, RetroPie ve Android gibi farklı ortamlarda kullanmıştım. Bu yüzden ilk beklentim generic bir yapıda olduğunu düşündüğüm bu donanımın Xbox'ta da benzer şekilde çalışmasıydı.

Fakat USB bağlantısı ile işletim sisteminin o cihazı oyun kolu olarak kabul etmesi ayrı konular. HID bir kolun tuşlarını, yönlerini ve analoglarını diğerinden farklı bir rapor yapısında gönderebiliyor. Bazı cihazlar ise bağlantı sırasında bambaşka bir USB arayüzüne geçebiliyor. Hori'de gördüğüm bu oldu.

O yüzden bu forku “USB kolları takınca çalışan evrensel sürücü” olarak tanımlayamıyorum maalesef. Ortak bir altyapı var ama denediğim cihazların eşlemesi, başlatma davranışı ve gerektiğinde paket biçiminin ayrıca ele alınması gerekti.


İlk deneme: plugin kayıtlı, fakat hiçbir tepki yok

İlk olarak indirdiğim XEX'i Xbox'ın diskine attım, DashLaunch'ta plugin olarak kaydettim ve konsolu tamamen kapatıp açtım. Plugin satırının kaydedildiğini de tekrar kontrol ettim.

Aurora'da Hori'yi söküp taktım; yönlere ve tuşlara bastım. MAME'de de denedim. Hiçbir tepki yoktu. Bazı denemelerde log bile oluşmuyordu.

Burada ilk ayrım şuydu: DashLaunch'ta dosya yolunun kayıtlı olması, sürücünün başarıyla yüklendiğini veya kontrolcüyü çalıştırdığını kanıtlamıyor. Önce yükleme zincirini görünür hale getirmek gerekiyordu.


DVD tepsisinin bununla ne ilgisi var?

Bu sırada beklemediğim bir ayrıntı çıktı: sürücüde tepsi açıkken devreye girmemeyi sağlayan bir kontrol vardı. Benim konsolda DVD sürücüsü bulunmadığı için sistemin tepsiyi nasıl gördüğünü de kontrol ettim.

Original dashboard'daki ikondan optik sürücünün kapalı olduğunu görmekle yetinmedim ve teşhis uygulamasının SMC'den okuduğu gerçek değere de baktım:

SMC tray byte=0x62 (0x60 means bypass)

Bu denemede tray kontrolü sürücüyü atlatan koşula girmiyordu, yani sistem DVD-ROM tray'i kapalı kabul ediyordu. Dolayısıyla sessizliğin nedenini burada aramaya devam etmedim.


17511'e uyarlama: adres değiştirmek yetmiyor

Sürücü, Xbox'ın USB ve kontrolcü işlevlerinin bazılarına hook yerleştiriyor. Başka bir kernel sürümündeki adresleri aynen kullanmak çalışmıyor. Çok daha önceden yedeklediğim kendi sistemime ait dosyalar üzerinden 17511'deki ilgili kernel ve XAM kodunu karşılaştırdım. (Dijital istifçilik hastalığım sağolsun :) )

XAM tarafındaki adres hesabında önemli bir hata buldum. Belleğe açılmış görüntü ile diskteki PE dosyası düzeni aynı şekilde ele alınamayınca hedef adres yanlış hesaplanmıştı.

İlk kontrol edilen XAM adresi: 0x816DA108
Doğrulanan 17511 adresi:      0x816D8D08

Teşhis logunda ilk adres okunabiliyordu ama beklenen kodla eşleşmiyordu. İkinci adresteki kod ise karşılaştırmayı geçti. Bir adresin okunabilir olması, doğru fonksiyona ait olduğu anlamına gelmiyor.

Uyarlamaya, hook kurulmadan önce beklenen kod baytlarını kontrol eden korumalar eklendi. Eşleşme yoksa sürücü o adreslere müdahale etmiyor.


Önce uygulama açılıyor mu, sonra sürücü yükleniyor mu?

İlk teşhis uygulamalarında konsolun hemen hata verdiği, siyah ekranda kaldığı veya hiçbir log oluşturmadığı denemeler oldu. Bu yüzden başlangıçta sürücüyü bile yüklemeyen, yalnızca uygulamanın giriş noktasına ulaşıldığını yazan küçük bir test kullandım.

HID17511 diagnostic v2 - passive startup probe
Application entry reached. No driver load or patches attempted.
Kernel 2.0.17511.0
Waiting 10 seconds before returning to dashboard.
Probe finished.

Bu log, en azından teşhis XEX'inin açılabildiğini gösteriyordu. Sonraki sürümlerde sırayla sürücü yükleme çağrısı, thread'in başlayıp başlamadığı ve fonksiyon kontrollerini ekledim.

Yol boyunca şu sonuçlarla da karşılaştım:

XexLoadImage status=0xC0000022
XexLoadImage status=0xC0000221

Bunlar henüz tuş eşlemesi aşamasına gelinmediğini gösteren yükleme sorunlarıydı. Ana thread üzerinden yükleme ile sistem thread'i üzerinden yüklemeyi ayrı ayrı denedim. Sonunda CPU4 üzerinde çalışan sistem thread'iyle ilerleyen yükleme yolu kullanıldı.

XEX paketlemesi de düzeltildi. SDK'nın ürettiği şifreleme yapısını koruyup gerekli medya izinlerini ve başlık özetini doğru biçimde ele almak gerekti. Önceki yeniden paketleme denemelerini çalışmış kabul etmedim; konsolda uygulamanın gerçekten açılması ve sürücünün yüklenmesi esas ölçüttü.


Eski XDK ile derleme

HID17511-DERLE.cmd
HID17511-TESHIS-DERLE.cmd

İlki sürücüyü, ikincisi teşhis uygulamasını hazırlıyordu. Başarısız derlemeden kalan eski dosyayı yeniden denememek için sürüm işaretleri de kontrol edildi.


Modülün yüklenmesi de tek başına yeterli değil

Bir noktada logda sürücünün zaten yüklü olduğu görülmeye başladı:

Existing hiddriver-17511-sdk.xex: status=0x00000000
SKIP: driver already loaded; no second load.

Sonrasında canlı hook adresleri de incelendi. Fakat bunların hiçbiri kolun tuşlarının oyuna ulaştığını tek başına kanıtlamıyordu. Bir modül bellekte bulunabilir, hook kurulmuş olabilir, hatta ikinci oyuncu LED'i yanabilir; yine de geçerli kontrolcü verisi gelmeyebilir.

Bu yüzden teşhise USB rapor sayıları, bağlantı ve ayrılma zamanları, hata durumları ve XInput tuş değişimlerini ekledim. Konsol yeniden başladıktan sonra önceki yükleme durumunun korunmadığını da hesaba katmak gerekiyordu. Yeni plugin dosyasını konsolun HDD'sine kopyaladıktan sonra konsolu tamamen kapatıp açmak testlerin bir parçası oldu.


İlk çalışan kol: PlayStation Classic

Hori ile uğraşırken PlayStation Classic kolunu da denedim. LED'in yanması başlangıçta umut veriyordu ama yönler ve tuşlar çalışmıyordu. Bu kol için bilinen tuş sırası ve yön verisi mevcut sürücüye uygun şekilde eşlendi.

PlayStation Classic
VID: 054C
PID: 0CDA

Sonunda PlayStation Classic kolu sorunsuz çalışmaya başladı. Buradaki “çalışıyor” doğrulaması, benim konsolda kolu kullanarak yaptığım denemeydi. Bu noktada MAME'de SF2CE ve Shinobi'ye dalıp epey oyalandım :)

Çalışan noktayı kaybetmemek için yedek aldım. Bundan sonra Hori veya başka bir çevirici üzerinde değişiklik yaparken PlayStation Classic'in çalışan eşlemesini korumaya dikkat ettim.


Sök-tak, ikinci oyuncu ve MAME ayarları

İlk çalışan sürümlerde konsolu kol takılıyken açtığımda cihazın devralınması her zaman istediğim gibi değildi. Aurora açıldıktan sonra USB'yi söküp takmam gereken denemeler oldu. Bunun için açılışta bağlı cihazları inceleyen ve uygun durumlarda yeniden tanıtmayı deneyen geliştirmeler yaptım.

Son sürümde sök-tak yapmadan kullanabildiğimi de gördüm. Ancak bunu bütün kollarla, tekrarlanan soğuk açılışlarda sistemli biçimde test etmediğim için GitHub'daki “henüz doğrulanmadı” notunu şimdilik bırakmayı tercih ettim.

MAME'de ise başka bir karışıklık yaşadım: PlayStation Classic ikinci oyuncudayken yönler çalışıyor, tek başına birinci oyuncudayken oyun içinde ve ayar menüsünde çalışmıyordu. MAME altındaki ilgili CFG dosyasını temizlediğimde bu sorun ortadan kalktı. Yani sürücü ve sistem çapında bir sorun değil MAME'yle sınırlı lokal bir problemmiş.

Ayrıca ikinci oyuncunun MAME ayar menüsündeki alt seçeneklere girebilmesi için emülatörün menü seçme girdisi düzenlendi. Bu, HidDriver'dan ayrı bir MAME değişikliğiydi.


PS1/PS2 çevirici ve R3 kısayolu

Daha sonra PS1/PS2 kollarını USB'ye çeviren adaptörü denedim. Bu cihaz için de tuş eşlemesi eklendi:

PS1/PS2 USB çevirici
VID: 0810
PID: 0003

PS2 DualShock koluyla oyun kontrolü çalıştı. Fakat PlayStation Classic'te fiziksel R3 olmadığı için MAME'in ayar menüsüne girmek üzere bir kombinasyona ihtiyaç duydum.

İlk denemelerde kullandığım L1 + R1 kombinasyonu, MAME'e daha önce eklediğim save/load kombinasyonlarıyla çakıştı. Birkaç değişiklikten sonra kalan düzen şu oldu:

PlayStation Classic ve denenen PS1/PS2 çeviricide:
Start + R1 + R2 = R3

PS1/PS2 çeviricide fiziksel R3'ün beklediğim şekilde davranmaması ise daha sonra bakılacak küçük işler arasında kaldı. Kombinasyonla menüye girip devam edebildiğim için Hori tarafına geri döndüm.

Bu arada SF2CE'de kare/X tuşuna atanmış orta yumrukta gecikme hissettim. Aynı hareketi başka tuşa alınca sorun görünmüyordu; diğer oyunlarda da aynı sorunu yaşamıyordum. Bunu hem PlayStation Classic hem PS2 koluyla gözlemledim. Tek oyun için çalışan sürücüyü değiştirmek istemedim; bu gözlem çözülmüş bir sürücü hatası olarak kayda geçmedi.


Hori neden diğerleri gibi çalışmadı?

Asıl uzun uğraş Hori oldu. Elimdeki model:

Hori Fighting Stick mini 4
PS4-043(U/E)

Controller üzerinde PS3/PS4 konumları olan bir anahtar var. Windows'ta iki konumda da sorunsuz çalışıyor. Xbox'ta ise bağlandığında kısa süre ikinci kontrolcü LED'i yanıyor, sonra kayboluyordu. Erken sürümlerde birkaç sök-tak sonrasında sistemin siyah ekranda kaldığı denemeler de oldu.

USB bağlantısı kesilirken hâlâ devam eden callback'lerle belleğin serbest bırakılması arasındaki sırayı bu yüzden ayrıca ele aldım. Kontrolcü hemen silinmek yerine ayrılmış olarak işaretleniyor; bekleyen işlemler ve endpoint kapatma adımları tamamlandıktan sonra kaynakları temizleniyor.

HID parser tarafındaki kullanım listesi kapasitesi de Hori'nin rapor tanımlayıcısı için yetersizdi; bu kapasite artırıldı. Ama tanımlayıcının başarıyla okunup çözümlenmesi Hori'yi tek başına çalıştırmadı.


Yaklaşık 1,8 saniyelik bağlantı

Loglar arttıkça dikkat çeken düzen ortaya çıktı: Hori, tanındıktan yaklaşık 1,8 saniye sonra HID bağlantısını kaybediyordu. Farklı USB portunda da benzer süreyi gördüm.

Bir denemede: 1804 ms
Başka bir denemede: 1805 ms

PS3 ve PS4 konumlarıyla yapılan denemelerde farklı cihaz kimlikleri ve rapor tanımlayıcıları görüldü, fakat kısa süre sonra bağlantının kapanması devam etti. Bu yüzden yalnızca “yanlış tuş haritası” veya “ikinci oyuncuya atanmış” açıklaması yeterli değildi.

Hori'ye standart HID SET_IDLE isteği gönderen sınırlı bir deneme de yapıldı. İstek başarılı sonuçlanmadı ve 1,8 saniyelik davranış değişmedi. Bu denemeyi bir çözüm olarak kabul etmedim.


USBPcap ile Windows tarafına bakmak

Kol Windows'ta çalıştığı için bu kez bilgisayardaki USB trafiğini kaydettim. USBPcap listesindeki cihaz adı ilk bakışta şaşırtıcıydı:

Xbox 360 Controller for Windows

Hori'yi çıkardığımda listeden kaybolan cihaz buydu. Windows oyun kontrolcüsü ekranında ise şu isimle görünüyordu:

Controller (Fighting Stick mini 4 kai)

Yaklaşık 39 saniyelik kayıtta Hori'nin kimliği ve arayüzü şöyleydi:

VID: 0F0D
PID: 00ED
Interface: FF / 5D / 01

Xbox'ta önce gördüğüm 00EC/00EB HID arayüzünden farklıydı. Windows kaydında 00 14 başlıklı, 20 baytlık Xbox tipi giriş paketleri geliyordu.

Ancak kaydın ilk paketinde cihaz zaten 00ED durumundaydı. Bu kayıt tek başına hangi işlemin mod değişimini başlattığını göstermiyordu. Windows'taki komutları körlemesine Xbox'a taşımak yerine, Xbox'ta kaçırdığımız ikinci bir tanınma olayı olup olmadığına bakıldı.


V20: Hori kaybolmuyor, kimlik değiştiriyor

Önceki loglar ağırlıklı olarak HID sürücüsünün gördüğü olayları kaydediyordu. Cihaz HID dışındaki bir arayüze geçince o yolun dışına çıkıyordu. V20'de bu nedenle HID/XInput ayrımından önceki ortak USB sürücü eşleştirme noktasına kayıt ekledim.

Ve aradığım geçiş yakalandı:

47022 ms: 0F0D:00EC — HID, 03/00/00
48828 ms: HID bağlantısı kapanıyor
49281 ms: 0F0D:00ED — FF/5D/01 olarak geri geliyor

Yani Hori tamamen kaybolmuyordu. İlk HID bağlantısından sonra Xbox tipi başka bir USB arayüzüyle yeniden tanınıyordu. Mevcut HID okuma yolu bu ikinci arayüzü devralmadığından tuş eşlemesi üzerinde uğraşmak sorunun esas noktasına ulaşmıyordu.


V21: Xbox'ın yerel sürücüsü neden devam etmiyor?

Bir sonraki teşhiste, 00ED arayüzünün Xbox'ın yerel kontrolcü sürücüsüne ulaşıp ulaşmadığı ve kabul edilip edilmediği izlendi.

native-add-enter
add-complete-status ... value=C0051012 caller=800FA9AC

Yerel sürücü çağrılıyordu ama ilk uygunluk kontrolünde cihazı reddediyordu. Bu, daha endpoint ve tuş verisi işleme aşamasına gelmeden gerçekleşiyordu.

Hata noktasını kodla eşleştirdim. Sorun Hori'nin yerel başlatma yolundan geçemediğiydi.


V22: Hori'nin Xbox tipi paketlerini mevcut sürücüyle okumak

Çözüm, yalnızca gözlemlediğim Hori kimliğini ve arayüzünü mevcut USB okuma ve sanal gamepad altyapısına yönlendirmek oldu:

0F0D:00ED
FF / 5D / 01

Bu modda artık HID rapor tanımlayıcısı istenmiyor. Gelen sabit biçimli 20 baytlık paketler doğrudan çözümlenip mevcut ButtonsReport yapısına aktarılıyor. Tuşlar, yönler, analog değerler ve tetikler buradan sanal XInput kontrolcüsüne gidiyor.

Xbox 360'ın işlemcisi big-endian olduğu için USB paketlerini doğrudan bir XInput yapısına dönüştürmek yerine baytlar açıkça çözümlendi. Kısa paketler, yanlış başlıklar, okuma hataları ve yeniden okumadan önce tamponun temizlenmesi de ele alındı.

HID rapor bilgisi olmayan bu yeni yol için ayrılma sırasında sanal oyuncu kaydının kaldırılması da düzenlendi. Böylece yalnızca bağlanmayı değil, cihazın daha sonra çıkarılmasını da mevcut yaşam döngüsüne oturtmak hedeflendi.

Bilgisayar tarafında Windows kaydındaki 9.712 giriş paketi yeni çözücüden geçti. Tuş bitleri, analog bayt sırası, kısa paketler ve hata durumları için de testler yapıldı. Sonraki adım yine XEX'i derleyip gerçek cihazda denemekti.


Sonunda Hori de çalıştı

V22'yi konsolda denediğimde Hori'nin yönleri ve tuşları çalıştı.

Teşhis logu da bunu destekliyordu:

HORI XINPUT routed=1 ready=1 good=9838 bad=0 errors=0
stage=3 status=00000000 length=32

Aynı logda ikinci oyuncu için yön ve tuşların basılma/bırakılma olayları da görülüyordu. Buradaki length=32 okuma tamponuyla ilgili; çözümlenen giriş mesajının 00 14 başlıklı 20 baytlık biçimiyle karıştırılmaması gerekiyor.

Son durum: 9.838 geçerli paket, sıfır bozuk paket ve sıfır USB giriş hatası. Çalışan kaynakları ve bu logu ayrıca yedekledim.


DualShock 3, Forza 4 ve PS tuşu

Hori'den sonra orijinal DualShock 3 CECHZC2E'yi USB kabloyla denedim. Temel oyun kontrolü çalıştı. Forza Motorsport 4'te kamera değiştirmeyi ararken varsayılan Xbox Back tuşunun bizim DS3 eşlemesinde Select'e karşılık geldiğini de netleştirdim.

PS tuşunun Xbox Guide olarak çalışmasını istiyordum. Kodda bu eşleme zaten vardı. Sonra kendi kolumun PS tuşunun PS3'te de zor bastığını hatırladım. Bu yüzden sırf bu gözlem üzerine sürücü eşlemesini değiştirmedim; önce fiziksel tuşu tamir edip tekrar denemeye karar verdim.

Alternatif bir Guide kombinasyonu da eklemedim. Mevcut düzenin aynen kalmasını istedim.


Henüz olmayanlar: titreşim ve SNES çevirici

Titreşimli kollarda şu anda titreşim çalışmıyor. Mevcut sürücü, oyun tarafından gelen titreşim isteğini ilgili kontrolcünün USB çıkış komutuna dönüştürüp göndermiyor.

Dolayısıyla titreşim desteği yapılacak işler arasında.

Bir diğer hedefim Nintendo SNES kolunu kullanmak. Uygun bir USB çevirici edindiğimde onun cihaz kimliğine ve raporlarına da bakıp destek eklemek istiyorum.


Şu an hangi kolları kullanabildim?

  • PlayStation Classic USB kolu: oyun kontrolü çalışıyor.
  • PS1/PS2 kolları: denediğim 0810:0003 USB çeviriciyle çalışıyor; fiziksel R3 konusu takip listesinde.
  • Hori Fighting Stick mini 4: 00ED arayüzüne özel destekle çalışıyor.
  • Orijinal DualShock 3 CECHZC2E: USB kabloyla temel oyun kontrolü çalışıyor; titreşim henüz yok, PS tuşunu fiziksel tamirden sonra tekrar deneyeceğim.

Bunlar kendi kurulumumdaki denemeler. Bütün oyunları, bütün kernel sürümlerini veya aynı adla satılan bütün USB çeviricileri test etmiş değilim.


Kaynak GitHub'da

EinTim23'ün deposunu kendi hesabıma fork edip çalışan 17511 uyarlamasını push ettim.

Çalışma dalı: prototype/17511
Paylaşılan commit: 041c5298ad463007a903713676e629314f494a1f
Teşhis sürümü: v22
Hori desteği işareti: horixinput1

Temel değişiklikler main.cpp, HID parser, kontrolcü eşlemeleri ve 17511'e özel yardımcı başlıklarda bulunuyor. diagnostic klasöründe ayrı teşhis uygulaması var. Bu uygulama DashLaunch plugin'i değil; gerektiğinde çalıştırılan bir XEX uygulaması.

Kaynaktan derlemek için Xbox 360 XDK ve uygun Visual Studio araç zinciri gerekiyor. Konsolda kullandığım hedef VS2010 araç zinciriyle Release Retail / Xbox 360 yapılandırmasıydı.


📁 GitHub

17511 uyarlaması:
github.com/kadirdogan/hiddriver360

Türkçe durum ve yapılacaklar:
STATUS-TR.md

Bu yazıda anlatılan kaynak sürümü:
041c529 — 17511 kontrolcü desteği

Temel aldığım proje:
github.com/EinTim23/hiddriver360


Bu çalışma kendi Jasper RGH Xbox 360'ımda, 2.0.17511.0 kernel üzerinde yaptığım denemelere dayanıyor. İlk hedefim Hori ile MAME oynamaktı; yol boyunca PlayStation Classic ve PS1/PS2 kollarını da kullanabilir hale geldim. Titreşim ve SNES çevirici desteği bir sonraki işler arasında.

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 save state'i eksik.

Arcade sistemlerde save olmadığından aynı iş emülatörlerde state sistemiyle yapılıyor malum. MAME'in Xbox 360 portu MAME360 0.72 sürümünde state olmaması benim için halledilmesi gereken bir eksiklikti 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.

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. Ö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

Kaynak kodu incelediğimde MAME72'nin save/load altyapısının projede var olduğunu gördüm.

  • 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 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.

Thursday, October 1, 2026

Aruba Instant On AP11: Access Point'i Çalıştırmak İçin Windows ICS Kurmak


Yeni bir access point satın alırken beklentim oldukça basitti: cihazı Ethernet'e takacağım, bir IP alacak, web arayüzüne gireceğim, SSID ve şifreyi belirleyip hayatıma devam edeceğim.

Sonuçta ürünün adı Instant On.

Fakat HPE Aruba Instant On AP11 ile yaşadığım kurulum süreci, "instant" kelimesinin network dünyasında ne kadar esnek yorumlanabileceğini gösterdi. Kutudan çıkan cihazı çalıştırabilmek için DHCP Option 6, Windows Internet Connection Sharing, yerel debug arayüzü, cloud onboarding ve firmware partition değişimiyle uğraştım.

İşin daha komik tarafı ise cihaz güncellendikten sonra bütün problemlerin ortadan kalkmasıydı.

Başlangıç: AP11 ve 2020'den Gelen Firmware

Cihaz HPE Networking Instant On AP11. İlk açılışta ZTE H3600 router'a bağladım. Router cihazı düzgün şekilde gördü ve AP11'e:

IP      : 192.168.1.119
Gateway : 192.168.1.1

verdi.

Fakat AP'nin yerel debug ekranında ilginç bir şey vardı:

DNS server address : 0.0.0.0
Device onboarding  : Error
Firmware           : 1.4.1.0 (74478.1)

Firmware sürümü özellikle dikkat çekiciydi. Cihaz kutudan 1.4.1.0 ile çıktı ve build/tarih bilgileri 2020 dönemini işaret ediyordu.

Yerel web arayüzü de oldukça sınırlıydı. IP yapılandırmasında yalnızca:

  • DHCP
  • PPPoE

seçenekleri vardı. Statik IP veya elle DNS verme seçeneği yoktu.

ZTE DNS Vermiyor mu?

İlk şüpheli doğal olarak router oldu. ZTE H3600'ün DHCP ayarlarında DNS sunucuları zaten açıkça tanımlıydı:

Primary DNS   : 1.1.1.1
Secondary DNS : 8.8.8.8

Daha sonra aynı DHCP sunucusundan IP alan Windows PC'yi kontrol ettim:

DHCP Server : 192.168.1.1
DNS Servers : 1.1.1.1
              8.8.8.8

Yani ZTE, DHCP üzerinden DNS bilgisini gerçekten dağıtıyordu.

AP11 ise aynı DHCP sunucusundan IP adresi ve gateway alıyor, fakat DNS bilgisini 0.0.0.0 olarak gösteriyordu.

Router ve AP birkaç kez cold boot edildi. DHCP lease sıfırlandı. Sonuç değişmedi.

"Instant On" Fakat Önce Cloud'a Ulaşmanız Gerekiyor

Instant On serisinin başka bir sürprizi de klasik Aruba Instant / IAP cihazlarından farklı olarak tam yerel yönetim arayüzünün bulunmaması.

SSID, güvenlik, radyo ayarları ve esas konfigürasyon cloud portalı veya mobil uygulama üzerinden yapılıyor. Yerel IP'deki arayüz esas olarak bağlantı ve troubleshooting amaçlı.

Dolayısıyla ortaya güzel bir tavuk-yumurta problemi çıktı:

AP'nin firmware'ini güncellemek için cloud'a bağlanması gerekiyor.
Cloud'a bağlanmak için DNS gerekiyor.
Fakat kutudan çıkan firmware ZTE'nin DHCP'sinden DNS'i düzgün alamıyor.
Üstelik o firmware'de DNS'i elle girebileceğiniz Static seçeneği de yok.

Gerçek anlamda bir bootstrap deadlock.

Yerel Setup SSID'sini Çıkartmak Bile Bir Macera

AP Ethernet bağlantısı olmadan açıldığında bir süre sonra yeşil/turuncu LED kombinasyonuna geçiyordu, fakat setup SSID'si çıkmıyordu.

Sonunda AP'yi Ethernet linki olan fakat DHCP sunucusu bulunmayan bir bağlantıya taktım. Bir süre sonra LED sabit turuncuya geçti ve:

InstantOn-CA:...

şeklinde setup SSID'si ortaya çıktı.

Bu SSID'ye bağlandıktan sonra:

https://connect.arubainstanton.com

üzerinden yerel arayüze erişebildim.

Ancak burada da eski firmware yüzünden yalnızca DHCP ve PPPoE vardı. Statik IP/DNS seçeneği hâlâ yoktu.

Çözüm: Windows ICS ile AP'ye Başka Bir DHCP Sunucusu Vermek

Bu noktada problemi izole etmek için AP'yi doğrudan PC'nin ikinci Ethernet portuna bağladım.

PC'de iki adet Intel 82575EB Gigabit Ethernet portu vardı. İnternet bağlantısını taşıyan Hyper-V virtual interface üzerinden, ikinci fiziksel Ethernet portuna Windows Internet Connection Sharing (ICS) açtım.

Windows ICS otomatik olarak:

PC / Gateway : 192.168.137.1
DHCP         : Windows ICS
DNS          : 192.168.137.1

şeklinde küçük bir NAT ağı oluşturdu.

AP11 yeniden başlatıldığında bu kez Windows ICS'den düzgün IP, gateway ve DNS aldı:

IP      : 192.168.137.75
Gateway : 192.168.137.1
DNS     : 192.168.137.1

Yani cihaz başka bir DHCP implementasyonundan DNS'i düzgün alabiliyordu.

Bu aynı zamanda problemin genel bir "AP11 DNS alamıyor" problemi olmadığını, eski firmware ile ZTE H3600 DHCP arasında belirli bir interoperability problemi olduğunu düşündüren en güçlü test oldu.

Cloud Nihayet Cihazı Gördü

DNS geldikten sonra AP11 Instant On cloud'a ulaşabildi. Mobil uygulama üzerinden cihaz seri numarasıyla bulundu ve durum bir süre:

Updating

olarak göründü.

AP firmware'i cloud üzerinden indirip birkaç kez reboot etti. Sonunda cihaz online oldu ve SSID oluşturulabildi.

Telefon yeni SSID üzerinden internete çıktı. MacBook ile yaptığım ilk hızlı testte ise yaklaşık 300 Mbit/s gördüm. Yani cihaz çalışmaya başladıktan sonra donanım tarafında söyleyecek pek kötü bir şey yoktu.

Firmware 1.4.1.0 → 3.4.2.0

Firmware güncellemesinden sonra yerel arayüze tekrar girdiğimde tasarımın ve bağlantı seçeneklerinin ciddi biçimde değiştiğini gördüm.

Yeni firmware:

3.4.2.0

idi.

Ve artık IP yapılandırma bölümünde:

  • Automatic
  • Static
  • PPPoE

seçenekleri bulunuyordu.

Ayrıca Primary ve Secondary DNS sunucuları elle girilebiliyordu.

Aynı ekranda:

Portal status     : Connected
Onboarding status : Onboarded

bilgileri de görünüyordu.

Restart sebebinde ise:

CLOUD cmd ... switch-partition-reboot

ifadesi yer alıyordu. Yani firmware güncellemesi cloud üzerinden gerçekleştirilmiş ve cihaz yeni firmware partition'ına geçirilmişti.

Final Test: Tekrar ZTE H3600

Asıl önemli test cihazı Windows ICS'den çıkarıp tekrar ZTE H3600'e bağlamaktı.

İlk bağlantıda AP, Windows ICS'den aldığı eski 192.168.137.78 lease'ine bir süre tutundu.

Daha da ilginci, ZTE H3600 cihaz listesinde AP'nin MAC adresiyle birlikte bu eski 192.168.137.78 adresini görebiliyordu.

Bu, ZTE'nin 192.168.137.0/24 ağına route ettiği anlamına gelmiyordu. AP eski DHCP lease bilgisini kullanmaya devam ediyor ve ağ üzerinde o adresle kendisini duyuruyordu.

Tam bir cold boot sonrasında ise eski lease bırakıldı ve AP yeni DHCP isteği gönderdi.

ZTE'de AP'nin MAC adresine daha önce:

192.168.1.119

rezervasyonu vermiştim.

Yeni firmware ile AP artık ZTE'den her şeyi doğru aldı:

IP            : 192.168.1.119
Subnet        : 255.255.255.0
Gateway       : 192.168.1.1
Primary DNS   : 1.1.1.1
Secondary DNS : 8.8.8.8

Portal status     : Connected
Onboarding status : Onboarded
Firmware          : 3.4.2.0

Peki Problem Neydi?

Elimde paket seviyesinde DHCP capture olmadığı için "1.4.1 firmware'de şu satırda bug var" demek doğru olmaz.

Fakat yapılan testlerin sonucu oldukça güçlü:

  1. ZTE H3600 DHCP üzerinden 1.1.1.1 ve 8.8.8.8 DNS adreslerini düzgün dağıtıyordu.
  2. Aynı DHCP sunucusundan Windows PC DNS adreslerini sorunsuz aldı.
  3. AP11 firmware 1.4.1.0 ile IP ve gateway almasına rağmen DNS'i 0.0.0.0 gösterdi.
  4. AP11 Windows ICS DHCP'sinden DNS'i düzgün aldı.
  5. Bu bağlantı üzerinden firmware 3.4.2.0'a güncellendi.
  6. Aynı AP, aynı ZTE ve aynı DHCP ayarlarıyla 3.4.2.0 üzerinde DNS'i artık sorunsuz aldı.

Dolayısıyla en mantıklı sonuç, AP11'in eski 1.4.1.0 firmware'i ile ZTE H3600 DHCP arasında DNS / DHCP Option 6 seviyesinde bir uyumsuzluk olduğu.

Firmware güncellemesinden sonra aynı donanım, aynı router ve aynı DHCP yapılandırmasıyla problemin tamamen ortadan kalkması bunu oldukça güçlü biçimde destekliyor.

"Instant On"

Donanım çalışmaya başladıktan sonra AP11 gayet iyi. 5 GHz performansı güzel, bağlantı stabil ve cihaz küçük. İlk testte MacBook üzerinden yaklaşık 300 Mbit/s görmek de gayet tatmin ediciydi.

Ama kurulum deneyimi için aynı şeyi söylemek zor.

Bir access point'i devreye almak için:

  • cloud hesabı açmak,
  • site oluşturmak,
  • seri numarasıyla onboarding yapmak,
  • LED renklerini yorumlamak,
  • yerel debug arayüzüne girmek,
  • DHCP ve DNS problemini teşhis etmek,
  • Windows ICS kurmak,
  • cloud üzerinden firmware güncellemek

zorunda kaldım.

Ve bütün bunlar üzerinde Instant On yazan bir cihazda oldu.

En azından maceranın sonunda AP11 gerçekten "On" oldu.

"Instant" kısmı ise biraz tartışmalı.

Ben Asrı

Yazar: Kaan Karsan

Adam Curtis’in 2002 yapımı BBC belgeseli “Ben Asrı” (The Century Of The Self), tüketim toplumunun nasıl virajlar aşılarak ya da nasıl engeller konularak yaratıldığını anlatan ufuk açıcı bir belgesel. Dört saatlik süresi boyunca izleyicisini ‘defalarca’ baştan yaratıyor.

Sigmund Freud’un harflerden oluşan siyah beyaz portresi
Sigmund Freud — tipografik portre.

Her şey Sigmund Freud’la başlıyor: “İnsan rasyonel değildir. Bu sebeple rasyonel kararlar vermeye yardıma muhtaçtır. İçgüdülerinin kölesi olarak yaşayan insanoğlunun kontrol edilmesi gerekir.” Psikanalizin dünyanın en mühim çalışma alanlarından biri haline geldiği erken 1900’lerin Freud çağında artık ‘özgürleşmeye’ yönelmiş dünya, zıtlıkların doğurduğu bir kaos tarafından yönetiliyor. Ringin bir köşesinde Freud gibi düşünceler, yani, insanın sadece içgüdülerine bağımlı bir şekilde karar veren, büyük bir felakete sürüklenen ve mutlak suretle gizli bir denetim ağına bağlı olarak ‘kontrol’ altına alınması gereken bir tür olduğu düşüncesi var. Diğer köşede ise ‘liberal’ ütopyaya sınırsızca biat edilmesi gerekliliğini şart koşan psikanalist paradigma... Adam Curtis’in dört saat süresince kafa karıştırdığı kadar zihin billurlaştıran belgeseli “Ben Asrı”, mevzubahis fikirler karşıtlığından yola çıkarak ‘ben olmak’ın tarihini anlatıyor. Elbette ki bu ‘benleşme’ mevzusunun tüm izleği temelde ‘kimlik’ kavramının en yüce belirleyicisi olan kapitalist kitle yönetim metodolojisine dayanıyor. “Ben Asrı”, insanın hikayesini anlattığı kadar insanı kendi ihtiyaçları doğrultusunda biçimlendiren, ‘çok bilinmeyenli’ düzenin tarihini de anlatmaya soyunuyor.

Spot ışıklarının altında değil, kontrol odasında bir adam var. Bu adamın adı Edward Bernays. Bernays bir ‘Freud’cu. Olmaması için hiçbir sebep yok, zira kendisi aynı zamanda Sigmund Freud’un yeğeni... Freud’un çalışmalarının İngilizceye çevrilip alanını genişletmesinde de büyük bir payı var. Lakin Bernays’in ismi psikanaliz alanına yaptığı bu yararsal katkılardan ziyade başka bir atılımıyla anılıyor. Artık her şirkette bir departman olarak rastladığımız ‘Halkla İlişkiler’ biliminin mucidi Bernays. Başka bir deyişle ‘arzu yaratma’ mesleğinin, yani, kapitalizmin direğinin...

Bernays’in böyle bir fikirle çıkagelmesinin ardında Freud’un ideaları var. Sadece ihtiyaçları peşinde koşan insanların o güne kadar asla düşünmedikleri şeyleri arzulamaları gerekiyor. Bu, hayatın dizginini katiyen elinde bulundurmaması gereken insanın dikkatini dağıtmak için geliştirilen, bir nevi bir kontrol mekanizması... Hatta bir açıdan da yeni bir demokrasi anlayışı... Kendi bilinçaltıyla rasyonel kararlar veremeyecek olan, gizli kimliği denetim altında tutulması elzem insan türünün ve aşina hale geldiği demokrasi kavramının ‘rıza mühendisliği’ refakatinde dönüştürülmesi süreci... Böylece yaklaşık yüz yıldır ‘tüketici’ adını verdiğimiz, yani, tahmin edilebilir ve hesaplanmış insan türü üretilecekti.

Edward Bernays, tıpkı şu an tanıdığımız birçok lider gibi demokrasinin muhteşem bir kavram olduğunu, lakin insanların demokrasiye güdümlü olarak kesinlikle ‘mantıklı’ kararlar veremeyeceğini düşünüyor. Mimarı olduğu yeni meslek alanı olan ‘Halkla İlişkiler’ de bu muhtemel irrasyonel kararların dikkatini dağıtacak bir politika üretmeye yönleniyor: Kitleleri yönetenler, insanların doğal ahlaksızlıklarını türlü yöntemlerle ‘uzaklaştırmalılar’. Bu noktada belgeselde çok sembolik bir yer ve önem tutan ‘sigara’ örneğinden bahsetmemiz şart. Tütün şirketleri, kadınların sigara kullanmamasından kaynaklanan bir zarar etme dönemine giriyorlar ve bu gidişatı değiştirmesi için Bernays’in yöntem dağarcığına başvuruyorlar. Dönem toplumunda kadınların sigara içmesini ‘uygun’ görmeyen bir inanış var. Mesleki hayatını Freud’un tespitleri üzerine kuran Bernays, acilen Freud’cu psikanalistlere başvuruyor. Psikanalistler de sigaranın çok derinlerde cinsel bir sembol olduğunu ve eğer ki kadınlar doğru şekilde manipüle edilirse sigara kullanmaya başlayabileceklerini söylüyorlar. Böylece Bernays, sigara ve özgürlük arasında bir bağ kurarak gazetelere tam sayfa ilanlar veriyor; kadınların sigara içerek özgürleşebileceklerini telkin eden metinler yayımlatıyor. Bu sayede erkeklerin dünyasında ‘ayrıcalıklı’ bir yeri olan sigara, kadınların dünyasına bir özgürlük belirteci olarak giriveriyor. Curtis’in belgeseli benzer örneklerle, eşsiz arşiv görüntüleriyle ve tanık göstermelerle özellikle ilk iki bölümü boyunca kitle yönetim formüllerini gözler önüne seriyor.

Belgeselin son iki saatinde ise Freud’cu paradigma, Marilyn Monroe’nun ölümü gibi sembolik olaylarla alaşağı edildikten sonra türeyen ‘ikinci yeni’ tüketici modelinin peşinden gidiyor. Artık dünya insanın baskılanamayacağına ve özellikle cinsel açıdan özgür bırakılması gerektiğine ikna olmuş durumda. Böylece cinsel devrim başlıyor; yeni insan kendi katmanlarını birer birer yok ederek özüne ulaşıyor. Tüketicisinin nasıl davranacağını öngöremeyen sermaye de yeni bir oyun planı geliştirmeye başlıyor. Kabuğunu kıran insan, sonradan ‘tek kişilik sosyalizm’ olarak adlandırılacak bir psikolojinin içine giriyor. Bir şekilde bu ‘öz’ ve ‘kendini gerçekleştirmiş’ insanı kazanmak zorunda olan politik dünya da sıradaki adımlarını bu insanların ışığında atmaya koyuluyor. Adam Curtis, bu yeni vaziyeti iki çok net örnekle, Reagan ve Thatcher iktidarıyla örnekliyor.

Curtis’in iki başyapıtından biri olan “Ben Asrı”, hem insan kimliğine hem de bilincine anlam kazandırıyor. Ziyadesiyle enformatif, ziyadesiyle çarpıcı... İzledikten sonra hiçbir şeyin ‘eskisi gibi’ olmayacağı belgesellerden...


Kaynak: Kaan Karsan, “Ben Asrı”, paylaşılan dergi sayfası. Metin görselden aktarılmıştır.

Anahtar kelimeler: Adam Curtis, Ben Asrı, The Century of the Self, Sigmund Freud, Edward Bernays, belgesel, tüketim toplumu, halkla ilişkiler.

Friday, September 25, 2026

MS 3d Viewer'ı modlamaktan bıkıp sıfırdan STL Viewer yazmak.


Windows üzerinde STL dosyalarını hızlı şekilde kontrol etmek için kullandığım Microsoft 3D Viewer'ın desteği sonlandırıldı. Uygulama çalışmaya devam ediyordu, ancak her açılışta örnek Bee modeli yükleniyor ve arayüzün üst bölümünde 3D Viewer'ın artık desteklenmediğini bildiren bir banner gösteriliyordu.

İlk amaç yeni bir program yazmak değildi. Bee modelini ve banner'ı mevcut uygulamadan kaldırmak yeterli olacaktı.

1. Bee.glb nereden geliyor?

İlk olarak uygulamanın kullanıcı profili altındaki geçici dosyaları incelendi. Başlangıç modeli burada görünüyordu:

C:\Users\...\AppData\Local\Packages\
Microsoft.Microsoft3DViewer_8wekyb3d8bbwe\
TempState\Assets\Bee.glb

Dosya yaklaşık 20 MB büyüklüğündeydi. Bee.glb silinip uygulama yeniden başlatıldığında dosya tekrar oluşturuldu. Aynı davranış ağ bağlantısı olmadan da devam etti.

Bu nedenle modelin internetten indirilmediği, uygulama paketinin içerisinde başka bir kopyasının bulunduğu açıktı.

Paket içerisindeki Assets\Archive.zip incelendiğinde kaynak bulundu:

Assets\Archive.zip
└── ModelShelf
    └── Bee.glb

Archive içerisindeki Bee.glb ile TempState altında oluşturulan dosyanın büyüklüğü aynıydı:

Bee.glb
Length           : 20177864 bytes
CompressedLength : 16013449 bytes

2. WindowsApps paketini doğrudan değiştirmemek

Kurulu uygulama şu dizindeydi:

C:\Program Files\WindowsApps\
Microsoft.Microsoft3DViewer_7.2602.8012.0_x64__8wekyb3d8bbwe

WindowsApps altındaki paket üzerinde doğrudan değişiklik yapmak yerine uygulamanın tamamı ayrı bir çalışma dizinine kopyalandı:

C:\Users\...\Desktop\3DViewerMod

Store paketine ait imza ve metadata dosyaları çalışma kopyasından çıkarıldı:

AppxSignature.p7x
AppxBlockMap.xml
AppxMetadata\
microsoft.system.package.metadata

Daha sonra AppxManifest.xml içerisindeki package identity değiştirildi:

Microsoft.Microsoft3DViewer
        ↓
Kadir.3DViewerMod

Developer Mode altında paket yeniden register edildi:

Add-AppxPackage -Register ".\AppxManifest.xml"

Sonuçta Microsoft Store tarafından kurulan orijinal uygulama yerinde kalırken, dosyaları değiştirilebilen bağımsız bir development package elde edildi.

3. Bee'yi boş bir GLB ile değiştirmek

İlk denemede Archive.zip içerisindeki Bee.glb yerine sözdizimsel olarak geçerli 112 byte'lık boş bir GLB yerleştirildi.

Bee kayboldu ancak uygulama bu kez model yükleme hatası verdi:

Couldn't load 3D model
Try again later.


Daha sonra tek üçgenden oluşan geçerli bir GLB oluşturuldu. Sonuç değişmedi. Bu test uygulamanın yalnızca GLB parser'ından geçen herhangi bir dosyayı başlangıç modeli olarak kabul etmediğini gösteriyordu.

Bu noktada yeni bir GLB üretmek yerine orijinal Bee.glb'nin yapısını koruyup yalnızca geometrisini etkisiz hale getirmek daha güvenliydi.

4. GLB dosyasının iç yapısı

GLB 2.0 dosyası temel olarak bir header, JSON chunk ve binary BIN chunk'tan oluşuyor:

+-----------------------+
| GLB Header            |
| magic / version / len |
+-----------------------+
| JSON Chunk Header     |
+-----------------------+
| JSON                  |
+-----------------------+
| BIN Chunk Header      |
+-----------------------+
| Binary vertex data    |
| indices               |
| animation data        |
| ...                   |
+-----------------------+

Orijinal Bee modeli analiz edildiğinde aşağıdaki yapı elde edildi:

Magic       : 0x46546C67
Version     : 2
TotalLength : 20177864

Meshes      : 1
Nodes       : 112
Accessors   : 1934
BufferViews : 1938
Materials   : 1
Animations  : 3

Mesh'in POSITION verisini kullanan accessor bulundu:

POSITION accessor : 1
ComponentType     : 5126 (FLOAT)
Type              : VEC3
Count             : 29614

BufferView        : 1
ViewByteOffset    : 310388
ViewByteLength    : 355368

Boyut da beklenen değerle tam olarak eşleşiyordu:

29614 vertices
× 3 coordinates
× 4 bytes / float
-----------------
355368 bytes

5. Bee geometrisini tek noktaya çökertmek

GLB içerisindeki BIN chunk'ın başlangıç adresi hesaplandı:

jsonLength      = *(uint32_t *)(GLB + 12)
binHeaderOffset = 20 + jsonLength
binDataOffset   = binHeaderOffset + 8

POSITION verisinin gerçek dosya offset'i ise:

positionStart =
    binDataOffset
    + bufferView.byteOffset
    + accessor.byteOffset

Bu dosyada hesaplanan değerler:

BIN data starts : 397920
POSITION starts : 708308
POSITION bytes  : 355368

JSON, node yapısı, material, animation, index buffer ve diğer bütün veriler korundu. Yalnızca POSITION accessor'a ait 355368 byte sıfırlandı.

[Array]::Clear(
    $bytes,
    $positionStart,
    $positionBytes
)

Böylece 29614 vertex'in tamamı:

(0.0, 0.0, 0.0)

koordinatına taşındı. Dosya hâlâ orijinal Bee modelinin bütün yapısına sahipti, ancak mesh geometrisi tek bir noktaya çökmüştü.

Bee geometrisi kaldırılmış Microsoft 3D Viewer

Değiştirilmiş GLB tekrar Archive.zip içerisine yerleştirildiğinde başlangıç modeli görünmedi ve uygulama herhangi bir model yükleme hatası da üretmedi.

6. Deprecation banner

Bee problemi çözüldükten sonra ikinci hedef destek sonlandırma banner'ıydı.



resources.pri içerisinde banner'a ait localization resource'ları bulundu:
InfoBannerPromptAfterText
InfoBannerPromptBeforeText
InfoBannerDialogTitleAfter
InfoBannerDialogTitleBefore
InfoBannerDialogBodyAfter
InfoBannerDialogBodyBefore
InfoBannerDialogCloseButtonText

Mevcut banner metni InfoBannerPromptAfterText tarafından sağlanıyordu. Ancak resource string'i silmek yalnızca metni ortadan kaldıracaktı. Banner'ın kapladığı alan ve container ekranda kalacaktı.

7. 3DViewer.dll içerisinde banner kodu

Resource isimlerinin UTF-16 referansları 3DViewer.dll içerisinde bulundu. Banner metnini hazırlayan fonksiyonlardan biri 0x180EB59E0 adresindeydi.

180eb59e0  push   ...
...
180eb5a10  lea    0x1807cecb8,%rcx
           ; InfoBannerPromptBeforeText

           call   0x1809f4880
           mov    %rax,%rsi

180eb5a25  lea    0x1807ced08,%rcx
           ; InfoBannerPromptAfterText

           call   0x1809f4880
           mov    %rax,%rdi

...

180eb5a5d  test   %al,%al
180eb5a5f  cmove  %rdi,%rsi

180eb5a63  mov    $0x1,%r8b
180eb5a66  mov    %rsi,%rdx
180eb5a69  call   0x180dce7b0

180eb5a71  mov    0x3a0(%r14),%rdx
...
180eb5a9d  call   0x180ad3d40
           ret

Kod hem Before hem de After metnini yüklüyor, çalışma zamanındaki duruma göre birini seçiyor ve this + 0x3A0 alanındaki XAML nesnesine uyguluyordu.

Üst seviye initializer içerisindeki çağrı da bulundu:

180edd9e9  call  0x180e97aa0
180edd9f1  call  0x180eb5be0
180edd9f9  call  0x180eb5970
180edda01  call  0x180eb59e0

Son çağrı geçici olarak NOP ile değiştirildi:

VA          : 0x180EDDA01
File offset : 0xEDAA01

Original:
E8 DA 7F FD FF

Patched:
90 90 90 90 90

Test sonucu fonksiyonun görevi konusunda doğrudan doğrulama sağladı: banner metni kayboldu ancak kırmızı container ekranda kaldı.

8. Generated XAML

Bir sonraki adım compiled XAML tarafına indi. Uygulamada fiziksel XAML dosyaları bulunmuyordu. UI bağlantıları 3DViewer.dll içerisinde generated code olarak bulunuyordu.

İlgili Connect fonksiyonu 0x180EB4C40 adresindeydi:

180eb4c40  push   ...
180eb4c4b  mov    %rcx,%rdi
180eb4c4e  lea    -0x1(%rdx),%eax

           ; connectionId - 1

180eb4c51  cmp    $0x2b,%eax

           ; 43 connection IDs

180eb4c54  jae    0x180eb54aa
180eb4c5a  movslq %eax,%rdx

180eb4c5d  lea    0x18032e220,%rax

           ; jump table

180eb4c64  movslq (%rax,%rdx,4),%rdx
180eb4c68  add    %rax,%rdx
180eb4c6b  jmp    *%rdx

Bu klasik generated-XAML Connect(connectionId, target) dispatch yapısıydı.

Banner metninde kullanılan this + 0x3A0 member'ı connection ID 41 tarafından atanıyordu:

180eb5349  mov    %r8,%rcx
180eb534c  lea    0x18001f968,%rdx
180eb5353  call   *0x180749b20
180eb5359  mov    %rax,%rdx

180eb535c  lea    0x3a0(%rdi),%rcx
180eb5363  call   *0x180749af0

180eb5369  jmp    0x180eb54aa

Komşu XAML member'ları da aynı dispatch içerisinde görünüyordu:

Connection ID 39  → this + 0x390
Connection ID 40  → this + 0x398
Connection ID 41  → this + 0x3A0
Connection ID 42  → event-connected control
Connection ID 43  → event-connected control

Örneğin ID 40:

180eb5324  mov    %r8,%rcx
180eb5327  lea    0x18005e630,%rdx
180eb532e  call   *0x180749b20
180eb5334  mov    %rax,%rdx

180eb5337  lea    0x398(%rdi),%rcx
180eb533e  call   *0x180749af0

Bu aşamada banner'ın text element'i ile surrounding XAML controls arasındaki bağlantılar incelenebiliyordu. Ancak yapılmakta olan iş artık STL görüntülemek için gereken işin çok ötesine geçmişti.

9. Burada reverse engineering'i bırakmak

Başlangıç modeli için GLB vertex buffer değiştirilmiş, Store paketinin development copy'si oluşturulmuş, resources.pri incelenmiş, PE section adresleri hesaplanmış, 3DViewer.dll disassemble edilmiş ve generated XAML connection table'a kadar inilmiştir.

Ama ihtiyaç değişmemişti:

Open STL.
Rotate model.
Inspect geometry.

Bu nedenle 3D Viewer üzerinde çalışmaya devam etmek yerine aynı işi yapan küçük bir native Windows programı yazmak daha uygun hale geldi.

10. Native STL Viewer

Yeni uygulama C++17, Win32 API, Windows Common Controls ve OpenGL kullanılarak yazıldı.

STLViewer.exe
│
├── Win32
│   ├── HWND
│   ├── HMENU
│   └── message loop
│
├── comctl32.dll
│   ├── ToolbarWindow32
│   ├── SysTreeView32
│   ├── SysListView32
│   └── msctls_statusbar32
│
├── uxtheme.dll
│
├── WGL
│   └── OpenGL context
│
└── STL loader
    ├── Binary STL
    └── ASCII STL

Qt, Electron, CEF, WinUI, HTML/CSS veya .NET UI katmanı kullanılmadı. Viewport da ayrı bir native child HWND üzerinde çalışan WGL context'tir.

11. Binary STL parser

Binary STL formatı yeterince basit olduğu için ayrı bir model import framework'ü kullanılmadı.

80 bytes  header
 4 bytes  uint32 triangle count

for each triangle:

12 bytes  normal       (3 × float32)
12 bytes  vertex 1     (3 × float32)
12 bytes  vertex 2     (3 × float32)
12 bytes  vertex 3     (3 × float32)
 2 bytes  attribute

---------------------------------
50 bytes per triangle

Binary STL kontrolünde beklenen dosya büyüklüğü:

expected_size =
    84 + triangle_count * 50

ile gerçek dosya boyutu karşılaştırılıyor. Eşleşme yoksa parser ASCII STL okumayı deniyor.

12. İlk build

İlk build'de iki küçük Win32/CMake problemi çıktı.

Mouse koordinatlarında kullanılan:

GET_X_LPARAM
GET_Y_LPARAM

makroları için windowsx.h eklenmesi gerekiyordu:

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>

İkinci problem manifest'in hem resource script hem de Visual Studio tarafından eklenmesiydi:

CVTRES : fatal error CVT1100:
duplicate resource. type:MANIFEST, name:1

LINK : fatal error LNK1123:
failure during conversion to COFF

Tekrarlanan manifest resource kaldırıldıktan sonra executable oluşturuldu.

STL Viewer ilk çalışan build

13. İlk STL testi

İlk gerçek test dosyası:

sadboys_mirror_battery_cover_mod.STL

Dosya binary STL olarak algılandı ve 8712 triangle sorunsuz yüklendi. Hesaplanan bounding dimensions:

X : 43.501 mm
Y : 25.244 mm
Z : 49.200 mm

Triangles : 8712
Format    : Binary STL
File size : 425 KB
STL Viewer v0.1 gerçek STL modeli

Version 0.1 bu aşamada binary ve ASCII STL açabiliyor, modeli OpenGL ile çizebiliyor, orbit ve zoom yapabiliyor, shaded/wireframe görünüm sunuyor, grid ve XYZ axes gösterebiliyor ve model boyutlarıyla triangle sayısını hesaplayabiliyor.

14. Arayüz

Arayüz için yeni bir UI framework kullanılmadı. Program geleneksel Windows desktop uygulaması olarak tutuldu.

Ana pencere ve bütün yardımcı kontroller Win32/Common Controls. Bu nedenle menü, TreeView, ListView, status bar ve pencere davranışı Windows tarafından çiziliyor.

Windows desktop UI tasarım referansı

Geliştirme sırasında hedeflenen arayüz yoğunluğu Windows 7 / Office 2010 dönemi desktop utility uygulamalarına yakın tutuldu: küçük toolbar ikonları, standart menüler, sol model/property paneli, büyük viewport ve status bar.

15. Mevcut durum

Proje şu anda ilk çalışan prototip aşamasında. Renderer bilinçli olarak legacy OpenGL immediate mode kullanıyor. Bu, ilk aşamada STL parser ve Win32 shell'i renderer optimizasyonundan bağımsız geliştirmeyi kolaylaştırıyor.

Sonraki adımlar arasında gerçek fit-to-view hesabı, pan, daha kontrollü orbit, splitter, toolbar image list ve daha sonra gerekirse VBO/VAO tabanlı renderer bulunuyor.

Programın kapsamı değişmeyecek:

No cloud.
No account.
No AI.
No telemetry.
No bees.

Opens STL files.

16. Kaynak kod ve v0.1 release

Uygulamanın kaynak kodu GitHub üzerinde yayınlandı. Repository, CMake tabanlı Win32/OpenGL kaynak ağacını içeriyor; derlenmiş executable ise repository içine eklenmek yerine ayrı bir GitHub Release asset'i olarak tutuluyor.

Kaynak kod:
https://github.com/kadirdogan/STLViewer

STL Viewer v0.1:
https://github.com/kadirdogan/STLViewer/releases/tag/v0.1

Release sayfasından hazır STLViewer.exe indirilebilir. Kaynaktan derlemek için repository içindeki README.md dosyasında CMake/Visual Studio 2022 komutları bulunuyor.

Sunday, September 20, 2026

Tüketici Elektroniğinde Kaliteye Ne Oldu?

Bu yazı aslında yeni bir pil şarj cihazı ararken başladı. Elimde uzun zamandır kullandığım bir Energizer Universal CHEUF vardı. Cihaz bir süre kullanılmadan durduktan sonra tekrar elime aldığımda garip davranmaya başlamıştı. Şarj edilebilir AA pilleri takıp adaptörü bağladığımda ekran açılıyor, kapanıyor, tekrar açılıyor ve cihaz sürekli reset atıyormuş gibi davranıyordu.

İlk bakışta arıza şarj cihazının kendisindeymiş gibi görünüyordu. Fakat birkaç ölçüm sonunda bizi 470 µF'lik sıradan bir elektrolitik kondansatörden 1950'lerin Japon kalite devrimine kadar götüren güzel bir hikâye çıktı.

Boşta 12 volt, yükte kaos

CHEUF'un harici adaptörü 12 V / 600 mA. İlk yapılacak şey doğal olarak adaptörü ölçmekti. Multimetreyle boşta ölçtüğümde çıkış gayet normaldi:

Adaptör nominal çıkışı : 12 V / 600 mA
Boşta ölçülen çıkış    : ~12 V

Dolayısıyla adaptör ilk bakışta sağlam görünüyordu. Fakat anahtarlamalı güç kaynaklarında boşta doğru gerilim görmek pek bir şey kanıtlamıyor. Kurumuş veya ESR değeri yükselmiş bir çıkış kondansatörü nedeniyle güç kaynağı yüksüzken 12 V gösterebilir, fakat birkaç yüz miliamper çekildiği anda regülasyon bozulabilir.

Bunu ayırmanın en kolay yolu şarj cihazını laboratuvar güç kaynağıyla beslemekti. 12 V verdiğimde CHEUF tamamen normal çalıştı.

2 adet pil ile giriş akımı : ~250 mA
4 adet pil ile giriş akımı : ~550 mA
Besleme                    : 12 V

Bu ölçüm önemliydi. Dört pil takıldığında cihaz yaklaşık 550 mA çekiyordu; yani 600 mA nominal adaptör kapasitesinin oldukça yakınına çıkıyordu. Laboratuvar kaynağında cihazın düzgün çalışması, şarj elektroniğini büyük ölçüde temize çıkarırken adaptörü doğrudan şüpheli durumuna getiriyordu.



Energizer Universal CHEUF. Arıza ilk bakışta şarj cihazındaymış gibi görünüyordu.

Adaptörü açınca suçlu zaten elini kaldırmıştı

Adaptörü açınca fazla ölçüm yapmaya gerek kalmadı. Sekonder taraftaki 470 µF elektrolitik kondansatör gözle görülecek kadar şişmişti. Üstteki emniyet yarığı dışarı doğru kubbeleşmişti. Kondansatör resmen "buradayım" diyordu.



Adaptörün sekonder tarafındaki şişmiş 470 µF elektrolitik kondansatör.

Arızanın davranışı da buna tam uyuyordu. Kondansatörün kapasitesi düşmüş veya ESR değeri yükselmişse çıkış filtresi artık yük değişimlerini karşılayamaz. CHEUF çalışmaya başlar, şarj devresi akım çekmeye başlar, 12 V hattı çöker, kontrol elektroniği reset olur. Reset olunca yük ortadan kalkar, adaptörün çıkışı tekrar yükselir ve cihaz yeniden çalışmaya teşebbüs eder.

             CHEUF çalışır
                   │
                   ▼
             Akım yükselir
                   │
                   ▼
          Adaptör çıkışı çöker
                   │
                   ▼
              MCU reset olur
                   │
                   ▼
               Yük azalır
                   │
                   ▼
            12 V geri gelir
                   │
                   └──────────────► tekrar

Ekranın sürekli açılıp kapanmasının nedeni buydu.

470 µF / 25 V ve cihaz tekrar hayatta

Eski kondansatörün yerine 470 µF / 25 V bir elektrolitik taktım. Kapasiteyi değiştirmedim; gerilim dayanımını ise 25 V seçtim. Fiziksel ölçüler uygunsa 12 V'luk bir hatta 25 V sınıfı kondansatör kullanmanın herhangi bir sakıncası yok.

Sonuç oldukça antiklimaktikti: adaptör düzeldi, CHEUF dört pille normal şekilde çalışmaya başladı.

Yani LCD, mikrodenetleyici, şarj kontrol elektroniği, güç transistörleri ve cihazın geri kalanı sağlamdı. Koca ürünün çalışmasını engelleyen şey tek bir elektrolitik kondansatördü.

İşte hikâyenin daha ilginç kısmı burada başlıyor.

Birkaç sentlik komponent neden bütün ürünü öldürüyor?

Bir tüketici elektroniği ürününü açıp üzerinde tanınmayan bir üreticinin elektrolitik kondansatörünü görmek artık şaşırtıcı değil. Fakat ürünün üzerinde Energizer gibi dünya çapında bilinen bir marka olduğunda insan ister istemez şu soruyu soruyor:

470 µF'lik kondansatörde birkaç sent tasarruf etmek gerçekten buna değer mi?

Burada hemen "planlı eskitme" sonucuna atlamak doğru olmaz. Bir üreticinin cihazı belirli bir tarihte bozulsun diye bilinçli olarak zayıf komponent seçtiğini söylemek için bundan çok daha fazla kanıt gerekir.

Fakat modern seri üretimde başka ve daha sıradan bir mekanizma var: minimum şartnameyi minimum maliyetle karşılayan BOM.

Büyük marka ürünü doğrudan kendi fabrikasında üretmek zorunda değil. Tasarım ve üretim bir OEM veya ODM firmasına yaptırılabilir. Şartnamede çıkış gerilimi, akım, güvenlik standartları, sıcaklık sınırları, garanti hedefi ve maliyet belirtilir. Eğer marka özellikle "şu üreticinin şu serisi kullanılacak" demiyorsa, fason üretici doğal olarak teknik şartları geçen daha ucuz komponentlere yönelebilir.

Bir kondansatörde 10 veya 20 cent önemsiz görünebilir. Bir milyon cihazda ise:

$0.10 × 1.000.000 = $100.000
$0.20 × 1.000.000 = $200.000

Satın alma departmanının Excel tablosunda bu tasarruf gayet görünürdür. Buna karşılık daha iyi kondansatör sayesinde cihazların sekiz veya on yıl sonra daha az bozulmasının şirkete sağlayacağı değer aynı tabloda kolay kolay görünmez.

Problem tam olarak burada ortaya çıkıyor. Mühendislik açısından soru:

Bu devreyi ne kadar güvenilir yapabiliriz?

iken finansal optimizasyon açısından soru kolaylıkla şuna dönüşebiliyor:

Şartnameyi ve garanti süresini geçen en ucuz tasarım hangisi?

İki soru birbirine benziyor ama aynı şey değil.

Peki 1980'lerin Japon cihazları neden farklı görünüyor?

1980'lerden veya 1990'ların başından kalma bir Sony, Panasonic, Pioneer, JVC, NEC veya Toshiba cihazını açınca elektronikle ilgilenen insanların sık fark ettiği bir şey var: kullanılan parçaların önemli bölümü bugün "premium" diye ayrıca aradığımız üreticilerden geliyor.

Nichicon, Nippon Chemi-Con, Rubycon, ELNA ve Matsushita elektrolitikler; Alps potansiyometreler ve anahtarlar; Omron röleler; Murata ve TDK pasifler... Bunlar dönemin Japon elektronik endüstrisinin kendi tedarik ekosisteminin parçalarıydı.



1980'ler Japon tüketici elektroniğinde kaliteli yerli komponent tedarik zinciri önemli bir avantajdı.

Bunun nedenlerinden biri Japon elektronik sektörünün son derece güçlü ve kısmen dikey entegre olmasıydı. Matsushita yalnızca televizyon veya müzik seti yapan bir şirket değildi; komponentlerden pillere kadar geniş bir üretim ekosistemine sahipti. NEC, Toshiba, Sony, Sanyo ve diğer büyük üreticiler de yarıiletken ve komponent tarafında önemli kabiliyetlere sahipti.

Dolayısıyla kaliteli Japon komponenti kullanmak, bugünkü bir ODM'nin katalogdan pahalı bir "premium alternatif" seçmesine her zaman benzemiyordu. Bu parçalar zaten yerel endüstriyel ekosistemin içindeydi.

Derating: 16 V çalışıyorsa neden 25 V kullanalım?

Eski cihazlarda görülen bir başka tasarım alışkanlığı da derating, yani komponenti katalogdaki maksimum sınırına dayamadan kullanmaktır.

Örneğin 12 V'luk bir hatta 16 V elektrolitik teknik olarak kullanılabilir:

12 V / 16 V = 0,75

Komponent nominal gerilim sınırının %75'inde çalışıyor.

Bu tek başına kötü tasarım anlamına gelmez. Elektrolitik kondansatörün ömrünü gerilimden başka sıcaklık, ripple akımı, ESR, seri özellikleri ve güç kaynağının gerçek çalışma koşulları da belirler. Ancak maliyet ve fiziksel hacim izin veriyorsa 25 V sınıfı kullanmak daha fazla gerilim marjı sağlar.

Aynı düşünce dirençte, transistörde, diyotta ve diğer komponentlerde de uygulanabilir. 0,25 W'lık direnci sürekli 0,24 W'ta çalıştırmamak; 100 V'luk transistöre sürekli 98 V darbe bindirmemek gibi.

Eski Japon cihazlarında bazen devreyi incelerken "Bunun burada bu kadar yüksek değerli olmasına ne gerek var?" dedirten parçaların bir kısmı tam olarak bu mühendislik marjının sonucudur.

Ve burada W. Edwards Deming çıkıyor karşımıza

Japon kalite kültürünün hikâyesinde ilginç bir isim var: William Edwards Deming. Daha da ilginci, Deming Japon değil Amerikalı bir istatistikçiydi.



W. Edwards Deming (1900–1993). Savaş sonrası Japonya'daki kalite yönetimi dönüşümünün önemli isimlerinden biri.

Deming 1950 yılında Japanese Union of Scientists and Engineers, yani JUSE tarafından Japonya'ya davet edildi. Mühendislere, yöneticilere ve araştırmacılara istatistiksel kalite kontrol yöntemleri üzerine dersler verdi. 1951'de JUSE onun katkılarını onurlandırmak ve kalite çalışmalarını teşvik etmek amacıyla Deming Prize'ı kurdu.

Buradaki temel fikirlerden biri son derece güçlüydü: kalite, üretim hattının sonunda kötü ürünleri ayıklamak değildir.

Diyelim ki bir fabrika 100.000 kondansatör üretiyor ve son kontrolde 2.000 tanesinin hatalı olduğunu buluyor. Klasik yaklaşım bu 2.000 parçayı ayırıp kalanları göndermektir.

İstatistiksel proses kontrolünün sorduğu daha önemli soru ise şudur:

Bu 2.000 parçayı hatalı üreten süreç neden böyle davranıyor?

Sıcaklık mı değişiyor? Elektrolit miktarı mı dağılıyor? Makine ayarı mı kayıyor? Hammadde partileri arasında fark mı var? Operasyonun varyansı nereden geliyor?

Amaç yalnızca hatayı yakalamak değil, hatayı üreten sistemi değiştirmek.

Kalite kontrol departmanının işi değildir

Deming'in yaklaşımının daha radikal tarafı kaliteyi yalnızca üretim hattındaki QC departmanına bırakmamasıydı. Tasarım, yönetim, tedarikçi ilişkileri, proses ve organizasyon birlikte ele alınmalıydı.

Japonya'da bu yaklaşım zamanla TQC/TQM uygulamaları ve kalite çemberleri gibi yöntemlerle daha geniş bir endüstriyel kültüre dönüştü. JUSE'nin kalite çemberleri tarihçesine göre üretim sahasındaki QC-circle hareketi 1962'de kurumsal biçimde örgütlenmeye başladı.

Bu bakış açısından maliyet azaltmanın yolu yalnızca:

470 µF kondansatör → 12 cent daha ucuz olanı kullan

değildir.

Mühendislik yoluyla maliyet azaltmak çok daha geniş bir alan açar:

PCB'deki parça sayısını azalt
Montaj operasyonlarını azalt
Fire oranını düşür
Test süresini kısalt
Ortak komponent kullanımını artır
Mekanik parçaları sadeleştir
Proses varyasyonunu azalt
Arıza ve garanti dönüşlerini azalt

Yani maliyeti düşürürken ürünün kritik komponentlerini aşağı doğru tıraşlamak zorunda değilsiniz. Hatta iyi mühendisliğin ilginç tarafı, bazen ürünü hem daha ucuz hem daha güvenilir yapabilmesidir.

Japonları da romantikleştirmemek gerekiyor

Buradan "1980'lerde Japonlar kusursuz cihaz yapıyordu" sonucu çıkarmak da doğru değil. Eski Japon elektroniklerini tamir eden herkes bazı kronik problemleri bilir.

Özellikle bazı dönemlerin SMD elektrolitik kondansatörleri bugün ciddi sızıntı problemleri çıkarabiliyor. Bazı cihazlarda kullanılan yapıştırıcılar yaşlandıkça korozif veya iletken hale gelebiliyor. Plastik dişliler çatlıyor, kayışlar eriyor, optik mekanizmalar yaşlanıyor.

Yani mesele Japon mühendislerinin hata yapmaması değildi.

Asıl farklardan biri, ürünün uzun vadeli güvenilirliğinin marka değerinin bir parçası olarak görülmesiydi.

On yıl çalışan cihaz reklamın kendisiydi

1980'lerde Sony, Panasonic veya Pioneer gibi markaların rekabet avantajlarından biri kalite algısıydı. Bir tüketici 1984'te aldığı televizyonu 1994'te hâlâ kullanıyorsa bunun zihnindeki karşılığı basitti:

Bu marka sağlam yapıyor.

Bu deneyim bir sonraki televizyonun, müzik setinin veya video cihazının satışına katkıda bulunuyordu. Uzun ürün ömrü yalnızca tüketiciye verilmiş fazladan bir hediye değildi; markanın itibarı için çalışan uzun vadeli bir reklamdı.

Bugünkü şirket yönetiminde ise BOM'dan çıkarılan 20 cent hemen ölçülebilirken, on yıl sonra hâlâ çalışan bir cihazın marka değerine katkısını aynı kesinlikle Excel hücresine yazmak çok daha zordur.

Satın alma masasında biraz mühendislik gerekebilir

Bu yüzden teknik satın alma yalnızca fiyat karşılaştırması olmamalı. Satın alma kararında en azından şu soruların cevabı bilinmeli:

Bu komponent devrede ne yapıyor?
Çalışma sıcaklığı ne?
Ripple akımı ne kadar?
ESR sınırı önemli mi?
Arızalandığında yalnız kendisi mi gider?
Arızası bütün ürünü kullanılamaz mı yapar?
Daha iyi parçanın gerçek maliyet farkı ne?
Bu fark ürünün toplam maliyetinin yüzde kaçı?

Her yere en pahalı komponenti koymak mühendislik değildir. Gereksiz overengineering de maliyet, hacim ve enerji açısından kötü tasarım olabilir.

Ama kritik noktadaki birkaç sentlik komponentin bütün cihazın ömrünü belirlemesine izin vermek de iyi optimizasyon değildir.

Tekrar o 470 µF'ye dönelim

Masadaki Energizer CHEUF şimdi tekrar çalışıyor. Adaptörün içindeki tek bir kondansatörü değiştirmek yeterli oldu:

Arıza       : Yük altında adaptörün çökmesi
Belirti      : LCD'nin sürekli açılıp kapanması
Adaptör      : 12 V / 600 mA
CHEUF akımı  : 2 pilde ~250 mA
               4 pilde ~550 mA
Arızalı parça: 470 µF elektrolitik
Yeni parça   : 470 µF / 25 V
Sonuç        : Normal çalışma

Elektronik tamirinin sevdiğim taraflarından biri de bu. Bazen küçük bir arızayı takip etmeye başlıyorsunuz ve devre size ürünün nasıl tasarlandığını, hangi maliyet kararlarının verildiğini ve hatta onu üreten endüstrinin kültürünü anlatmaya başlıyor.

Bu kez hikâye AA pil şarj cihazıyla başladı. Sonunda 1950'de Japonya'ya gidip istatistiksel kalite kontrolü anlatan Amerikalı bir istatistikçiye kadar ulaştı.

Ve bütün yolu açan şey, adaptörün köşesinde şişip bizi bekleyen 470 µF'lik bir kondansatördü.


Kaynak notu: W. Edwards Deming'in 1950'de JUSE davetiyle Japonya'da kalite kontrol dersleri vermesi ve Deming Prize'ın 1951'de kurulmasına ilişkin tarihsel bilgiler JUSE ve W. Edwards Deming Institute arşivleri esas alınarak kontrol edilmiştir.

Kaynaklar:
JUSE — Deming Prize / History of the Deming Prize
W. Edwards Deming Institute — Deming Timeline
JUSE — QC Circle History