2026-06-03
2026-06-17

TersŞifre: Bubble Bobble |NES|

Küçüklüğümden beri ateri (ya da resmi ismiyle Nintendo Emulation System – NES) oyunlarına inanılmaz ilgi duydum. Çoğunu da ilerleyen yıllarda oyunlu VCD Player’larda ve bilgisayarda emulatörler aracılığıyla oynamaya devam ettim; hala da dönüp dönüp oynarım. Oyunların benim üzerimde, özellikle şu an olduğum kişiye dönüşmemde çok büyük etkileri olduğunu düşünüyorum. Buna en belirgin katkıyı koyan özelliklerinden biri de bu oyunların, kaldığınız yerden devam etmenizi sağlayan şifreleri olmasıydı…

Bu TersŞifre yazısı ile şifre algoritmasını anlamaya çalışacağım oyun 1988’de Taito tarafından yayınlanmış Bubble Bobble (I) isimli oyun olacak.

Oyunun işleyişi ve içeriği son derece basit: küçük dinozor benzeri bir yaratığı canlandırdığımız bu platform oyununda bölüm içerisindeki düşman yaratıklara yakalanmadan onları baloncukların içerisine hapsederek yok etmeye çalışıyoruz. İlk dönem NES oyunları gibi 41 KB’lık bir alan tutmak yerine bu oyun, grafiklerindeki ve müziğindeki zayıflıklarına rağmen 161 KB’lik bir alan tutuyor. Bunun en büyük nedeni, birbirinden farklı dizayn edilmiş 99 (x2) seviye bulunması. Oyunun bir de (tıpkı Super Mario’da olduğu gibi) bir kere bitirildikten sonra aktive edilen “süper” modu bulunuyor ki, bekleyeceğimiz üzere aynı oyunun daha zor bir versiyonu olarak karşımıza geliyor.

Hazırlık

Bu başlığın altında iki ayrı kaynağa atıf vermek isterim ki, bir tanesi beni keyiften dört köşe yapmıştı.

Oyunun şifre sistemi ile ilgili kaynaklara ve yazılanlara bakınırken Angus Kidman’a ait bir blog’a rastladım. Kidman kendi tabiriyle “tamamen kelimelerle alakalı” bir adam; parasını 1994’ten beri Sydney’de yazarlık yaparak ve özellikle teknoloji alanında yazı üreterek yapıyor. 1993’te Avustralya’daki University of New England’ın Dil Bilgisi bölümünden mezun olmuş ve şu anda Avustralya’nın önde gelen web tabanlı “mukayese” sistemi olan finder.com.au’da serbest editörlük yapıyor. İşinin yanında, bir şeyler yazmaya kendini adadığı için olsa gerek (ki sanırım ben de bu blog ile aynı şeyi hedefliyorum) bir blog sayfası da oluşturmuş ve burada ara ara pop kültür, televizyon, seyahat ve teknoloji ile ilgili yazılar kaleme alıyor. Benim ilgimi kendisinin burada 2025’in Ocak ayında yayınladığı, kabaca çevirisi “Bubble Bobble şifreleri: aşırı detaylı analiz ve tam liste” olan yazısı çekti. Yakın zamanda eline geçen bir el konsolunda oyuna yeniden sardığını belirttikten sonra oyunun içeriğinden bahsediyor ve hemen kendi tabiriyle “aşırı detaylı” şifre incelemelerine geliyor. Detaylı incelemeleri şifrelerin ortak özellikleri ile bazı harflerin kullanım istatistiklerine odaklanıyor ve yazısında “tam kendisinden beklediği gibi” bu şifrelerin arasında bir patern olup olmadığını analiz etmenin kayda değer olduğunu düşünüyor. Angus’un analizlerine aşağıdaki başlıklarda yeniden atıf yapacağım, keza paylaştığı bazı bilgiler benim için de yol gösterici oldular.

Vereceğim ikinci atıf ise sevgili Angus gibi saatlerce vakit harcadıktan sonra denk geldiğim bir Youtube videosu. Bisqwit’in 10 sene önce (ilk versiyonunu) yayınladığı söz konusu video kendisinin hala devam ettiği “Video Oyunu Şifrelerini Kırma” isimli video serisinin dördüncü videosu: bildiniz, Bubble Bobble. Açık konuşayım, bu içeriği birilerinin çoktan yaptığını görmek beni oldukça üzdü ilk başta (fark etmemiş olmam ayrıca üzdü keza 147k abonesi var kendisinin!). Videoyu izledikçe kendi kendime çözdüğüm kısımların gerçek algoritmadan uzak olduğunu, ama bir şekilde yine de her ikimizinkinin de çalıştığını fark etmek ise şaşırttı. Bisqwit olaya bir patern analizi ve bit-wise operasyonlar gözüyle değil, doğrudan yazılımsal ve teknik bir açıdan yaklaşıyor. Oyunun kodlarını inceleyerek, RAM içerisinde şifrelere ait bilgilerin işlendiği kısımları buluyor ve buradan bir ters mühendislik yürüterek şifre sistemini çözüyor. Bazı parametreler ile ilgili tam emin olamıyor, ancak bulduğu algoritmayı test ettiğimde çalıştığını (hem normal hem süper modlar için) teyit ettim. Müthiş bir iş çıkarmış kendisi.

Burada bir itiraf ile birlikte, amacımı da bir kere daha belirtmek isterim. NES oyunlarında kullanılan şifreler bit ve byte mertebesinde işleyen algoritmalarla saklanıyor ve çözülüyorlar. Bu şifreler (aşağıda “Şifre Dizaynı”nda da bahsedeceğim gibi) oyunlardaki “sayılabilir” ve “kalıcı” olan seviye numarası, eşya sayısı, can miktarı gibi parametrelerin kademeli artışıyla uyumlu şekilde kademeli/düzenli olarak değişiyorlar. Bu değişimin takibi hem nümerik, hem de patern olarak inceleme imkanı sunuyor. Benim hedeflediğim kısım bu nümerik ve patern analizleri üzerinden çözümleme yapmak keza bana zevk veren kısım bu. Sizlerle de bu yolda izlediğim adımları ve vardığım sonuçları paylaşacağım. İtirafa gelince: benim izlediğim yol ile bu oyunun şifre algoritmasının tamamını çözebilmiş değilim ve açıkçası bir ay boyunca ara ara baktıktan sonra pes ettim… Ancak süreçte keşfettiklerim ve ulaşabildiğim nokta o kadar güzeldi ki, yine de paylaşmadan edemedim. Gelin birlikte ne haltlar yediğime, nasıl otistik otistik işlerle uğraştığıma bakalım.

Şifre Dizaynı

Oyunun şifre ekranında karşımıza 5 haneli bir kod girebileceğimiz bir alan çıkıyor. Bu beş hanenin her biri A-J aralığında harfler içeriyor ve doğru harf kombinasyonu girildiğinde dilediğimiz seviyeden oyuna devam edebiliyoruz. Örneğin ACJJI kombinasyonu girildiğinde doğrudan normal modun 25’inci seviyesinden başlıyorsunuz. İnternette bu şifrelerin hemen hemen hepsi paylaşılmış durumda; hemen hemen diyorum çünkü paylaşılan şifrelerin bazıları yanlış yazıldığı için çalışmıyorlar ya da bazı seviyeler için normal mod yerine süper modu için olan şifreler yazılmış. Daha önceki yazıda bahsetmiştim: yaklaşık 200 tane seviyesi olan bir oyun için her seviyeye ayrı ayrı şifre tanımlamaktansa, bu seviyelere karşılık gelecek şifreler hesaplayan bir algoritma kurmak depolama alanı olarak çok daha verimli olacaktır. Dolayısıyla burada hedefimiz, bu beş haneli şifrelerin ardışık seviyelerdeki karşılıklarını bularak bir patern yakalamaya çalışmak olacak.

Envanter

Şifre envanterimizde yalnızca iki parametremiz var: seviye ve süper mod. Süper moda geçtiğimizi muhtemelen şifreye eklenen bir değer ile anlıyor olacağız, seviyeler ise belirli matematiksel kuralları izleyerek değişiyor olacak. Bunun izlerini görebiliyoruz zaten, örneğin birinci seviyenin şifresinin BBAAB, ikinci seviyeninkinin BAAAB olması, yalnızca ikinci hanenin B’den A’ya geçmesi ile bir seviye ileri gittiğimizi gösteriyor. Süper mod için işler biraz daha karışık, gel gelelim o kısma varamadan havlu atmış bulundum zaten.

Geçmiş denemelerimden yola çıkınca bu oyun için tahminim ise şu şekildeydi: beş haneli şifrenin bazı haneleri ya da hepsi, seviyeler arttıkça (sabit numaralar olduklarını düşündüğümüzde) şifreler de belirli bir miktar artarak değişmeli, süper mod için ise aynı sistem şifredeki bazı hanelerin ya da tümünün belirli bir miktar artırılması/kaydırılması şeklinde değişmeli. Yine oyunlarda gördüğüm kadarıyla farklı sayısal tabanlarda (2 bit, 4 bit, 8 bit, vb.) bu değerleri artırmak ve kendi içlerinde gruplamak da karşıma yüksek ihtimalle çıkacaktır. Mental hazırlığımı bu şekilde yaptıktan sonra temiz bir excel sayfası açtım, internette bulabildiğim şifreleri alt alta dizdim ve beyin fırtınası başladı.

Dil Kod Şeması

İlk aşamada şifrelerde kullanılan harfler ile az öne bahsettiğim sayısal düzen arasında bir bağlantı bulmam gerekiyordu. Bunun tam karşılığı şu: şifrelerde kullanılan harfler farklı bir sayısal tabandaki rakamları ifade ediyor olmalıydı. Şifrelerin alfabenin A ve J arasındaki ilk 10 harfini kullandığını görüyoruz, o halde dil kod şemamız ABCDEFGHIJ = 0123456789 gibi bir şey olmalı. Ancak şifrelerdeki harflere doğrudan bu değerleri verdiğimizde ortaya çıkan sayıların düzenli bir artış göstermediğini fark ediyoruz. Ve eğer bunların seviye ilerledikçe kademeli olarak arttığından şüpheleniyorsam, ilk seviyelerdeki şifrelerin mümkün mertebe 0 ve 1’lerden oluşması gerektiğini kabul etmem gerekirdi. Bu yüzden dizdiğim şifrelerdeki harfleri inceleyerek bu düzeni yakalayıp yakalayamayacağımı görmeliydim. İlk on seviyenin şifrelerini bu bağlamda inceleyerek başladım, ve doğrudan bir gariplik dikkatimi çekti. Genellikle şifreli oyunlarda ilk değeri tekrarlı şekilde girdiğinizde, henüz hiçbir ilerleme olmadığı için tüm haneler aynı olmalıdır, fakat bu oyunun ilk seviyesi BBAAB şeklinde bir düzen ile başlıyor; bu düzene aykırı. Bunun iki anlamı olabilir: ya tüm şifre değerleri en başından beri belirli bir miktar kaydırılmış (shift edilmiş) ya da sistemin birinci seviye için olan şifresi aslında var olmayan sıfırıncı bir seviyenin şifresi ile değiştirmiş olmalı. Bunu test etmesi basitti: oyunun şifre ekranına gelip, BBBBB şifresini denedim ve BBAAB ile bire bir aynı yere geldiğini gördüm. Böylelikle ikinci senaryonun doğru olduğunu anlamakla kalmadım, B karakterinin sayısal olarak “0”a denk geldiğini de teyitlemiş oldum. Bu aynı zamanda Angus’un en çok B harfi ile karşılaşmasını açıklıyor, keza B=0 olduğundan ilk şifreler çoğunlukla bu harfi içeriyorlar. Bu aynı zamanda Angus’un en çok B karakterini görmesini de destekliyor, çünkü ilk seviyelerin şifrelerinin çoğunlukla 0 içeriyor olması mantıklı Bu mantıkla ilerlersek A’nın 1’e, daha sonra karşılaştığımız karakterlere bakınca da I’nın 2’ye ve F’nin 3’e denk geldiğini varsayabilirdik. Bunu teyit etmenin çok daha kolay bir yolu var neyse ki. Henüz dil kod şemasına bakmadan şifrelerin tümüne baktığımızda, ilk haneler içerisinde bir düzen görüyoruz. Üstelik bu düzen her 16 seviyede bir değişiyor ki, 16 sayısı bitwise operasyonlar için çok güzel bir sayı. Aşağıda şifrelerin tümünün 16’lı gruplar halinde yan yana dizilmiş hallerini listeliyorum.

Bu tablo bizlere şunu söylüyor: seviyelere ait şifreler hesaplanırken, hanelerden biri her 16 seviyede bir kademe atlatılıyor ve bizim durumumuzda bu hane ilk hanemiz. Her grubun son şifresinden sonra bir sonraki grubun ilk şifresine geçilirken aralarında ne kadar farklar olduğuna bakın; besbelli bir “resetleme” olduğu görülüyor. Bu durumda dil kod şemasının ilk yedi hanesini çözmüş olduk: “0123456789” = “BAIFJCG???”. Geriye üç hane kaldı.

Diğer üç hane için yapmamız gereken çok bir şey olmadığını fark etmek çok da zor olmadı. Öncelikle sevgili Angus’un bloğunda not ettiği güzel bir şey var: "Şifrelerin hiçbiri D ve H harflerini kullanmıyor. Trollemişler gibi duruyor.". Ve tam olarak söylediği gibi, bu harfler hiçbir şifrede yoklar, çünkü hesaplamaya dahil değiller. Geriye bu listede kullanılmamış tek bir harf kalıyor ki, bu da bizim 7 sayısına karşılık gelecek olan E harfi. 7 sayısı da bizim için büyülü bir sayı, çünkü 0-7 arasındaki sayılar, 8 tabanındaki rakamlara denk geliyorlar ve aynı 16 sayısı gibi 2’nin bir kuvveti olarak karşımıza çıkıyor. Bu noktada acaba ikinin diğer kuvvetleriyle; 4, 32 ve 64 ile de karşılaşıp karşılaşmayacağımı merak ediyordum artık ki, bu merakımı kısmen haklı çıkaran bir şey fark ettim. 5 haneli şifrelerimizin HEPSİNDE, üçüncü ve dördüncü haneler birbirlerinin aynısı. Bu durumda şifrelerimiz 5 değil, 4 haneli oluyor. Boom! Bu keşif aslında ilerideki denemelerim için güzel bir ipucu veriyor bana: 10 haneli bir işlem mi var? Bu muhtemelen 8 hanelidir ve 2 tanesi “troll” olarak koyulmuştur. Ya 5 haneli bir şey mi? Muhtemelen biri ekstradır ve aslında 4 hanelidir, çünkü 2’nin kuvvetleri bitwise işlemlerde kutsaldır. Muazzam!

Son gelişmeler ışığında artık dil kod şemamızın tamamını çıkarmış bulunuyoruz. Sonraki adım şifrelerin bulunduğu tablodaki harfler ile karşılık geldikleri sayıları birbiri ile değiştirerek patern analizinin yanına matematiksel operasyonları da dahil etmek olacaktır.

Secret Item Found: Gri-Kare!

Bu noktaya kadar şifrelerin 4 haneli olduğunu, alfabenin ilk 10 harfinden 8 tanesinin kullanıldığını ve her harfin 0-7 arasındaki hangi sayıya denk geldiğini tespit etmiş durumdayız; patern analizine hazırız. Şifrelerin her bir hanesini ayrı kolonlara aktarıp her birini koşullu biçimlendirmeyle renklendirerek başladım.

İlk 16’lık gruba bakınca oldukça heyecanlandım, çünkü ikinci hanelerin ikişerli gruplar halinde giderek arttıklarını gördüm. Diğer 16’lık gruplarda da ikişerli değerler devam etse de kademeli bir artış göstermiyorlardı. Bu durum da ilk hanenin farklı sayılar alması ile buradaki düzenin değişebileceğini düşündüm ve keyfini çok da kaçırmadım. Üçüncü hanelerde bu şekilde sıralı artış olmasa da belirli bir düzen izleniyor gibi görünüyordu, ancak grupların son hanelerinde bu düzenin de bozulduğu görülüyordu. Dördüncü hane ise yine şu an için tam bir muamma…

İlk denediğim şey bir toplama işlemi yürütmekti, işin ilginci şifrelerin yarısından fazlasını sağlayan bir operasyon da bulmuştum. İlk hanenin 14 katı ile geri kalan haneleri dosdoğru topladığımda seviye numarasını elde edebiliyordum. 16 yerine 14 olmasının sebebi de gri kareden bir +2’nin her türlü ekleniyor olmasıydı. Mesela 5’inci seviyenin sayısal karşılığı 0230 -> 0*14 + 2 + 3 + 0 = 5 veriyor, ya da 11’inci seviye 0*14 + 5 + 4 + 2 = 11, ya da 25’inci seviye 1*14 + 5 + 4 + 2 = 25. Ama diğer çoğu seviyede bu düzenek patlıyordu maalesef. Sonrasında da epeyce farklı şekillerde bu işlemleri deneyerek görüntülemeyi denedim aşağıdaki gibi, ancak bir sonuca ulaşamadım.

İkinci ve üçüncü hanelere bir arada baktığımda bir patern fark ettim. Tetris oyunundaki Z harfi şeklindeki bloğun yan dönmüşü gibi görünen bu patern ilk 4 seviyede 0 ve 1’ler ile, ikinci 4 seviyede 2 ve 3’ler, sonrakinde 4 ve 5’ler ile… ifade ediliyordu. İkinci 16’lık gruba geldiğimizde aynı paternin olduğunu, sadece sayıların yer değiştirdiğini fark ettim. Üçüncüde aynı paternin olduğunu, ancak bu sefer sayıların sıralı artmadığını gördüm. Ve hepsinde de 16’lık grupların sonlarına doğru bu düzenin bozulması dikkatimi çekti. Belli ki bu “Z” paterni şifrelerde temelde yer alıyordu ve bu patern seviyeler ilerledikçe manipüle ediliyordu. Sevgili dostumuz yapay zekaya bu paterni sorduğumda yeni bir terim öğrendim: “Grey Square – Gri Kare”. 80 ve 90’ların oyunlarında bolca kullanılan bir patern imiş ve asıl amacı standart bit işlemlerine biraz çeşitlilik katmakmış. Bunun tanımlanması ve manipüle edilmesi yalnızca 8 karakterden oluşan bir matris gerektirdiğinden çok fazla yer de kaplamıyordu. O halde düzenimiz: “şu gri kareyi al, bulunduğun seviye şu 16’lık grupta ise bunu yap, şu dörtlükte ise bu değer ile topla” gibi bir şeyler olmalıydı. Buna odaklanmaya karar verdim.