Merhaba, Ziyaretçi. Lütfen giriş yapın veya üye olun.

Kullanıcı adınızı, parolanızı ve aktif kalma süresini giriniz

  Gelişmiş Arama
insanın içinde varsa, commodore.gen.tr açığa çıkarır bunu.. bir nevi retro olaylarının dolunayıyız.(Arda)
commodore.gen.trCommodoreCommodore YazılımC64 DMA Freeze (Fikirler/Yorumlar...)
Sayfa: [1]   Aşağı git
Yazdır
Gönderen Konu: C64 DMA Freeze (Fikirler/Yorumlar...)  (Okunma Sayısı 9109 defa)
0 Üye ve 1 Ziyaretçi konuyu incelemekte.
eins
Uzman
*****
Mesaj Sayısı: 1.816


A.K.A. deliMawi


Üyelik Bilgileri
« : Ekim 29, 2015, 00:04:24 ÖÖ »

Merhabalar,

C64'ü DMA ile freeze/defreeze yapmakla ilgili kafa yormaktayım. Bazı fikirler oluştu, yorum ve öneri almak istiyorum. Ayrıca bir kaç ufak tefek konu var aklıma takılan sormak istediğim.

Öncelikle Final III, AR vb. kartuşların nasıl freeze yaptıklarını incelemek için Vice üzerinde monitor kullanarak yapabildiğim kadar inceleme yaptım, bazı fikirler oluştu. Ancak bu sistemler, DMA kullanmadıkları için genelde tümü NMI interrupt yaratarak, NMI vectorlerinin olduğu bölgeye de kendilerini mapleyerek freeze yazılımını çalıştırıyorlar. Freeze yazılımları da temelde registerlar (A,X,Y,SP), memory configurasyonu ($00,$01) gibi anlık önemli bilgileri kopyalarak işe başlıyor. Ayrıca, interrupt yaratılarak bu koda sıçrandığı için, 6510 zaten Processo Status Flags ve PC (Kodun interrupt sırasında çalışmak olduğu adres) bilgisini stack'e atmış oluyor. Bu bilgiler de stackten kolayca alınabiliyor. Bunun haricinde daha birçok detay var tabiki, timerların kontrolü, interrupt oluştuğu andaki raster satır no vb vb başka bilgiler de snapshot ediliyor.

Ben nette özellikle AR için bir kaç disassembled source bulabildim. Ama malesef freezer bölümü yoktu kaynak kodlarda. İlk olarak bu konuda birşeyler bilen varsa paylaşırlarsa sevinirim.

Gelelim bizim DMA Freeze olayına. Doberman'da orjinal tasarımda NMI hattını bağlamamıştım. Nasıl freeze yaparım diye düşünürken aklıma ilk gelen NMI hattını da bağlayarak, AR vb nasıl freeze yapıyorsa benzer bir yöntem kullanmaktı. Fakat bugün aklıma başka yöntem geldi.

Freeze edilecek program oyun vb zaten kendi içinde mutlaka bir şekilde interrupt kullanıyordur diye düşündüm. Şimdilik IRQ kullanmayan programları hedef listemizden çıkardığımızı varsayalım.

1. Herhangi bir anda DMA başlatılacak, $FFFE/$FFFF IRQ Vectörleri DMA ile okunacak. Burada iki olasılık var. Oyun ya KERNAL'ı kapatmıştır, yada kapatmamıştır.
  a) Eğer kapatmış ise, bu vectorlerin işaret ettiği adres RAM olmalı. Bu adresi not et.
  b) Eğer KERNAL açık ise IRQ RAM'de $314/$315'in işaret ettiği yerde başlayacak. DMA ile bu adresi oku ve not et.

  NOT: Burada bir açıklama. DMA ile KERNAL açık mı değil mi nasıl anlayacağız? Eğer $FFFE/$FFFF vectörler, ROM'daki vectorlerden farklı ise kesin KERNAL kapalı. Eğer vectörler aynı ise o zaman $FF48 adresini JMP ($314) koduna kadar olan kısmı kontrol et. Eğer ROM ile aynı ise ya KERNAL açık yada kapalı olsa bile orjinal ROM la aynı işi yapıyor ve $314 de gösterilen adrese sıçranıyor demek...

2. Not ettiğin adresten itibaren küçük bir bölümü DMA ile kendi hafızana yedekle, çünkü birazdan o bölgeye kod enjekte edeceğiz. Bu arada bu not ettiğimiz adres eminiz ki RAM'de bir yerlerde ve ilk interrupt geldiğinde çalışacak.

3. Not ettiğin adresten itibaren çok basit bir kodu DMA ile yerleştir. Bu kod 0,1 adreslerinin durumunu, A,X,Y,SP,PC,Flags, D012 Raster line no vb yi, gene DMA ile okunabilir bir RAM bölgesine yazsın. Örneğin hemen bu kodun bittiği yere.

4. DMA'yı serbest bırak ve beklemeye başla... Kahkaha

Şimdi bu noktadan sonra oyunun içindeki ilk orjinal IRQ geldiği anda oyunun kendi interrupt handler'i değil, bizim yerleştirdiğimiz trojan kod çalışacak. Normalde DMA ile okuyamadığımız A,X,Y,SP,PC,Flags bilgilerini RAM'de DMA ile okunabilir bir yere yazacak. Bizde bunları bir güzel DMA ile alacağız. Sonrası kolay. Gene trojan kod bizim için 01 adresi ile oynayarak tüm RAM'i açacak. Gene DMA ile RAM'i alacağız. Sonra gene trojan kod IO bölgesi ve Color RAM'i açacak. Gene DMA ile D000-DFFF arasını yedekleyeceğiz.

De-Freeze de gene teorik olarak kolay. RAM ve IO'yu yerli yerine koy. Örneğin $0400 e basit bir defreeze kodu at. Bu kod da A,X,Y,SP,Flags vb yi restore etsin, D012'yi beklemeye başlasın. istenilen raster satırına gelinince bir basit JMP ile orjinal IRQ kodunun adresine sıçra. (Madde 1 de not ettiğimiz adres)

Soru1: Sizce bu seneryo da gözümden kaçan birşeyler var mı? İlk fırsatta denemeyi düşünüyorum.

Soru2: C64 de aslında hiçbir şekilde tam olarak snapshot almak mümkün değil. Çünkü bazı registerlar okuma ve yazma durumlarında farklı işlevlere sahip. Özellikle CIA lerde bu durum bolca var. Bir başka örnek VIC. D012 okunduğu zaman o anki raster satırını veriyor. Ama buraya yazdığınız zaman Raster Interrupt'ın hangi satırda olmasını istediğinizi belirtiyorsunuz. Yani aslında kurulmuş olan raster interrupt satır noyu okumanın yolu yok. (Ancak raster interrupt oluşmasını bekleyip D012 yi okumak falan olabilir.) AR vb de dahil olmak üzere alınan snaphotlarda bazen müziğin belli bir süre gelmediği vb söyleniyor. Bu gibi durumlara karşı diğer freezer nasıl çözümler üretiyor, bilgisi yada dökümanı olan var mı?

Son olarak NMI Freeze yöntemine göre DMA Freeze'in benim gördüğüm bir kaç avantajını belirteceğim.

- Aslında oyunun içinde varolmayan bir interrupt yaratılmadığı için sanki daha doğal ve sağlıklı. Kahkaha (Ne demekse ben bile güldüm yazarken.)
- NMI Freeze karşı alınan önlemlerden etkilenmemiş olacak. (NMI IRQ Disable etme yöntemi var. Disable edilmiş olsa bile eğer oyun içinde kendi kullandığı bir interrupt varsa freeze edilebilir oluyor teorik olarak.)

Fikir ve yorumlarınızı paylaşırsanız sevinirim...
Logged

Doberman ♦ megaOne ♦ HDMI-64 ♦ HDMI-520 ♦ NewSchool
i_r_on
Uzman
*****
Mesaj Sayısı: 2.873



Üyelik Bilgileri WWW
« Yanıtla #1 : Ekim 29, 2015, 00:16:04 ÖÖ »

İlk aklıma gelen,

Cycle exact çalışması gereken bir irq rutini varsa cycle'larını yersin. Onların freeze'inde sorun olur.

2. sorunun cevabı expansion port'a bir adet clone 6510 koyup paralelde çalıştırmak. Tüm read access'lere erişebileceğin için paralel 6510'da ana işlemci üstünde çalışan kodu çalıştırman mümkün. Bu paralel 6510'un paralel ram'inde yazma yapılan her yerdeki son değeri bulabilirsin. Tabii bunun için sana 6510'u simüle edebilecek büyük bir cpld yahut fpga lazım.

Kartuşların bir kısmı 6510 emülasyonu yapıyor, büyük bir kısmı da fail safe değerler yerleştiriyorlar ne yazıldığını bilmedikleri yerlere. Bence nihayetinde çok büyük problem olmayabilir.
Logged

Every imagination is one's self reflection but not every self reflection is imagination. <I.R.on - 2001>

twitter | blog
eins
Uzman
*****
Mesaj Sayısı: 1.816


A.K.A. deliMawi


Üyelik Bilgileri
« Yanıtla #2 : Ekim 29, 2015, 00:21:01 ÖÖ »

2. Cevabın bu projeyi aşıyor... Kahkaha

İlk cevabın içinse, cycle exact çalışması gereken bir rutin varsa neden cycle yiyorum onu anlayamadım tam. Şöyle düşün. IRQ'sunu bozdum adamın kendime yönlendirdim. IRQ oluştu, benim kodum çalıştı ve snapshotumu aldım. Artık o C64 session çöp oldu diye düşünebiliriz. RESET at makinaya yani artık.

Snapshotu defreeze ederken de, sanki tam o interrupt oluştuğu andaki state'i geri yükledim ve bir jump ile adamın IRQ suna dallanarak kendi loop'u ne ise o şekilde çalışmasına yol verdim. O aşamada artık benim koduma hook olmayacak kendi IRQ seneryosu... Bence çalınan bir cycle yok ortada.


Logged

Doberman ♦ megaOne ♦ HDMI-64 ♦ HDMI-520 ♦ NewSchool
i_r_on
Uzman
*****
Mesaj Sayısı: 2.873



Üyelik Bilgileri WWW
« Yanıtla #3 : Ekim 29, 2015, 00:36:35 ÖÖ »

Vic ok ama Cia çipleri çalışmaya devam ediyor. Set ettiği bir timer'ı kontrol edip oyun seni rahatlıkla bozabilir. Oyunlar dma yapacak bir kartuşa önlemlerini almışlar mıdır bilemiyorum
Logged

Every imagination is one's self reflection but not every self reflection is imagination. <I.R.on - 2001>

twitter | blog
eins
Uzman
*****
Mesaj Sayısı: 1.816


A.K.A. deliMawi


Üyelik Bilgileri
« Yanıtla #4 : Ekim 29, 2015, 00:43:31 ÖÖ »

Evet, AR de iki CIA'de de kurulu timer var mı kontrol ediyor. Freeze kodunu disassemble ederken aşağıdakini gördüm. Sanırım bu timer önlemi var mı onu test ediyor.

Kod:
.C:ebce  AD 08 DD    LDA $DD08		; CIA 2 TOD değerini al

.C:ebd1  A2 60       LDX #$60 ; Bekle 24576 Cycles (~24 Msec)
.C:ebd3  88          DEY
.C:ebd4  D0 FD       BNE $EBD3
.C:ebd6  CA          DEX
.C:ebd7  D0 FA       BNE $EBD3
.C:ebd9  CD 08 DD    CMP $DD08 ; CIA 2 TOD Hala aynı mı ?
.C:ebdc  F0 01       BEQ $EBDF ; Evet, devam et ... :)
.C:ebde  18          CLC
Logged

Doberman ♦ megaOne ♦ HDMI-64 ♦ HDMI-520 ♦ NewSchool
i_r_on
Uzman
*****
Mesaj Sayısı: 2.873



Üyelik Bilgileri WWW
« Yanıtla #5 : Ekim 29, 2015, 02:30:45 ÖÖ »

Ilaveten. Sırf irq handler da kaç cycle geçireceğim diyen bir kod etkilenmeyebilir ancak Vic'i durduramadigin icin ayni satirda unfreeze edebilsen bile satirin neresinde 6510'a yol verdiğin önemli olur.
Ps: ha olay gorsel bir seyse bir framede bozuk gosterir cok sorun olmaz.
Logged

Every imagination is one's self reflection but not every self reflection is imagination. <I.R.on - 2001>

twitter | blog
Metallic
Uzman
*****
Mesaj Sayısı: 1.081



Üyelik Bilgileri
« Yanıtla #6 : Ekim 29, 2015, 16:08:52 ÖS »

delimawi, bahsettiğin senaryo belirttiğin gibi çalışmakta olan programda irq'nun kullanıldığı durumlarda işe yarar görünüyor. Aklıma şunlar geliyor:

$FFFE-FF ve $0314-15 vektörlerinin işaret ettikleri adreslere yerleştireceğin kodun farklı olacağını hatırlatayım. $FFFE-FF'in işaret ettiği adrese PHA TXA PHA TYA PHA TSX TXA PHA şeklinde başlayacaksın, $0314-15'de ise A,X,Y ve SP'ı korumaya gerek yok, zaten $FF48'de stack'e atılıyorlar.

Ayrıca her iki vektörün işaret ettiği adreslere yerleştireceğin kod içerisinde PC ve Processor Status'ı korumana gerek yok, irq oluştuğunda 6510 onları stack'e atıyor zaten.

Dediğin gibi CIA, VIC ve SID yazmaçlarının çoğu için önceden set edilmiş olan değerleri freeze anında okumak mümkün değil. Mevcut kartuşların freezer'larında bunu nasıl hallediyorlar şuana kadar merak edip bakmışlığım yok. Bazı kayıpları gözardı ederek çalıştıkları kesin. Sonra bu konuya bir bakayım, kolay gelsin.
Logged
eins
Uzman
*****
Mesaj Sayısı: 1.816


A.K.A. deliMawi


Üyelik Bilgileri
« Yanıtla #7 : Ekim 29, 2015, 23:23:01 ÖS »

Teşekkürler Metallic,

Evet haklısın $FFFF ve $0314 vectörlerinden hangisinin kullanıldığına bağlı olarak A,X,Y,SP yi de korumak gerekiyor. PC ve Flagleri aslında koruma amaçlı değil defreeze esnasında kullanmak için okumak istiyordum ama düşününce bu da çok gereksiz. Defreeze edilirken tüm RAM geri geldiği için Stack bölgesi de gelmiş oluyor ($0100-). SP doğru atandıktan sonra bir problem kalmıyor.

Ben ilk planlarken örneğin freeze anında PC vb yi direkt okuyamadığım için, stackten pull eder okurum diye düşünmüştüm. Sonra defreeze yapacağım zaman da bu PC adresine JMP ederim demiştim. Ama şimdi stack'in de geri geldiğini düşününce, defreeze ederken, sanki bir interruptan dönüyormuş gibi, A,X,Y,SP yi pull et, RTI yap yeterli. Yada daha da doğrusu defreeze ederken oyunun orjinal irq rutinine dallan, oldu bitti.

Neyse, bugün freeze kısmını test etmeye başladım. Yukarıda yazdığım seneryodan ufak bir fark oldu. IRQ vectorlerinin gösterdiği adresteki orjinal kodun üzerine freeze kodunu atacağımı söylemiştim, bunun yerine freeze kodunu attığım yerin adresini $FFFF yada $0314'e yazdım, daha mantıklı oldu. Freeze işlemi bitince sadece orjinal vectörleri restore ettim, oyun kaldığı yerden hiçbirşey olmamış gibi çalışmaya devam etti.

Daha defreeze kısmına geçmedim, bakalım neler olacak, defreeze edebilecek miyim göreceğiz.

NOT: Gene herzaman ki belalı oyunum commando, freeze işlemi sonrası basic prompta düşüp READY yazdı. Detayına bakamadım neden bilmiyorum, diğer oyunlarda bir sıkıntı ile karşılaşmadım.




Logged

Doberman ♦ megaOne ♦ HDMI-64 ♦ HDMI-520 ♦ NewSchool
Metallic
Uzman
*****
Mesaj Sayısı: 1.081



Üyelik Bilgileri
« Yanıtla #8 : Ekim 30, 2015, 00:24:24 ÖÖ »

Rica ederim delimawi. Oyunların depacker'larını pas geçmek için uğraştığın freeze işlemi işe yarar gerçekten.

Ama şimdi stack'in de geri geldiğini düşününce, defreeze ederken, sanki bir interruptan dönüyormuş gibi, A,X,Y,SP yi pull et, RTI yap yeterli. Yada daha da doğrusu defreeze ederken oyunun orjinal irq rutinine dallan, oldu bitti.
Evet oyuna geri dönerken RTI yaparak main code'a geri dönmek yerine, irq vektörlerinin işaret ettiği irq handler'a jump yapmak daha iyi olabilir.

IRQ vectorlerinin gösterdiği adresteki orjinal kodun üzerine freeze kodunu atacağımı söylemiştim, bunun yerine freeze kodunu attığım yerin adresini $FFFF yada $0314'e yazdım, daha mantıklı oldu.
İyi fikir =)

NOT: Gene herzaman ki belalı oyunum commando, freeze işlemi sonrası basic prompta düşüp READY yazdı. Detayına bakamadım neden bilmiyorum, diğer oyunlarda bir sıkıntı ile karşılaşmadım.
Freeze kodunu yerleştirdiğin yere göre etkileniyor olabilir. $0400'ü kullanıyorsan, orası her zaman için güvenli değil, kod da çalıştırılıyor olabilir. En başlarda orayı kullanırsın, ama en güvenli yer SP'nin işaret ettiği adresin altında kalan adresler.
Logged
eins
Uzman
*****
Mesaj Sayısı: 1.816


A.K.A. deliMawi


Üyelik Bilgileri
« Yanıtla #9 : Ekim 30, 2015, 00:42:40 ÖÖ »

Freeze kodunu yerleştirdiğin yere göre etkileniyor olabilir. $0400'ü kullanıyorsan, orası her zaman için güvenli değil, kod da çalıştırılıyor olabilir. En başlarda orayı kullanırsın, ama en güvenli yer SP'nin işaret ettiği adresin altında kalan adresler.

Evet, aynen problem bu çıktı, 0400'ü kullanıyormuş bu oyun. Debug edebilmek için DMA ile yaptığım işi VICE'de emule etmeye çalışıyorum, aynı problem ortaya çıktı. Freezer'ı $33F e aldım, sorun çözüldü. Sanırım freeze işlemini bitirince ana koda dallanmadan önce kendini oradan kaldırıp, orjinal kodu geri yüklemek en doğrusu olacak.

Bu arada bir not. Sadece oyunların depacker'ını pas geçmek için değil, Doberman'ın bir özeliği olarak düşünüyorum eğer becerebilirsem bu freeze işini. Oyun oynarken, freeze tuşuna basıp kapatacaksın bilgisayarı. Sonra başka zaman kaldığın yerden devam...
Logged

Doberman ♦ megaOne ♦ HDMI-64 ♦ HDMI-520 ♦ NewSchool
Sayfa: [1]   Yukarı git
Yazdır
Gitmek istediğiniz yer: