Kurcala kurcala video oynatma konusunda ufak tefek bir şeyler elde ettim bu arada. Sizlerle de paylaşayım.
Daha fazla kurcalanırsa çözünürlük, renk sayısı, saniyedeki frame sayısı vesaire arttırılabilir. Kartuşun kapasitesinin %25'i falan aslında bu. Yazılım anlamında yaptığım cinliklerin bir miktar daha ötesine geçmek gerekiyor

Full ekran fli oynatmak falan pek tabii 1541 ultimate'de olduğu gibi ancak doldurulabilecek ek bir hafıza gibi bir kısım varsa mümkün olur, bu videonun süresi de pek tabii kısıtlı olur.
Aslında bu video gösterme işi ile ilgili hiç uğraşmayacaktım ancak koala resimlerini gösterme demosundan sonra direkt ilgi video'ya kaydığı için bir deneyeyim dedim.
Gösterilen video 80x48 çözünürlüğünde ve sadece 4 gri tonu kullanıyor. C64'deki siyah, beyaz, açık gri, koyu gri. Dolayısıyla sadece bitmap data transfer ediliyor. Renkler $D800 alanında ve ekran ram'inde önceden fix olarak set ediliyor. Ayrıca bir renk transferi yapılmıyor. 80x48 çözünürlük için bir frame'in boyutu (80/4) * 48 = 960 byte.
Bu videodaki demo programda program badline'ları raster irq'leri ile atlatıp kartuşun transfer rutinini her bir frame'de 15 defa çağırıyor. Her seferinde sadece 8 byte transfer ediyor. Yani 15*8 = 120 byte, 960/120 = 8 taramada 1 frame gösteriyor.
Bir iki sorunsal ile karşılaştım bu yüzden bu demoyu hazırlamak epey bir zaman aldı.
1. Arduino tarafında sd card'dan data okuma latency'si (hızı değil) yüksek olduğu için c64'de her bir 8 raster satırında data okuma ihtiyacını karşılayamıyordu. Epey bir debug seansının çok sonunda bunun farkına vardım. Çözüm olarak bir frame'i arduino üstünde buffer'lama ve buffer'ı doldurmayı transferler bittikten sonra c64'de vic bir sonraki kare için ilk interrupt'ı oluşturmadan önceye aldım. Bu şekilde sorun çözüldü. Daha iyi sonuçlar için sdfat kütüphanesinin içine girilebilir. Arduino üstünde kullanabileceğim maksimum ram kısıtlı bu arada
2. İlk yöntemim bir frame içinde DEN (Display enable) biti ile oynayıp ekranın bir satırından itibaren ekranı kapatıp kartuş üstünden doyasıya transfer yapmaktı. Burada da sonradan şöyle bir tespitim/sorunsalım oldu : Acaba VIC bir frame içinde DEN bitini sadece bir defa mı kontrol ediyor? Bu sorunun cevabını bulamadığım için demoda da kullandığım yönteme geçtim. Aslında basit bir test programı yazıp anlamak mümkün.
Şuradaki dokümantasyonda VIC sanki sadece $30 no'lu raster satırında bu bit'i kontrol ediyormuş gibi bir izlenim edindim. :
http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt3. Son uyguladığım yöntem ile ilgili aşılması gereken bir diğer sorun da C64'deki IRQ handler'ın ciddi cycle tüketmesi idi. Akla ilk gelen çözüm ROM'daki $0314'e dallanan kısımla hiç uğraşmayıp 6502'nin default IRQ vektörünü kullanmak. Ancak işin içine kartuş girdiği zaman bunun bu kadar kolay olmadığını anladım.
Şöyle ki, kartuşun çalışabilmesi için kartuş rom'unun $8000 adresinde okunabilir olması lazım. Default IRQ vektörünü değiştirebilmem için de Kernal rom'un okuma için devre dışı kalması lazım.
Aşağıdaki tabloya baktığımızda $8000-$9FFF ve $E000-$FFFF kolonlarında $8000-$9FFF'in CART ROM LO, $E000-$FFFF'in ise RAM olduğu bir seçenek gözükmüyor
https://www.c64-wiki.com/index.php/Bank_SwitchingIRQ handler'ın yediği cycle'ı azaltayım derken her bir şeyi değiştirip deveye hendek atlatmak gerekiyor, ben de mecburen o yola girdim

Bir kere şu gereksinim ortaya çıkıyor, uygun bir bellek konfigürasyonu olmadığı için bellek konfigürasyonunu bir yerlerde değiştirmem lazım. Kartuş NMI interrupt'ları için kernal'ın default vektörünü kullanıyor ve arduino üstündeki transfer rutini de nmi interrupt'ı yaratma ve gönderilecek datayı eprom'un bank'ını switch ederken oldukça zamanlaması ayarlanmış bir koda sahip. Bu anlamda mevcut transfer rutinini kullanmak mümkün değil. Transfer rutinin başı, sonu değiştirilip her şey tekrar düzenlenebilir, yeniden bir eprom oluşturulabilir. Ancak bu noktada tercihimi farklı bir yönden kullanıyorum. Diyorum ki, madem IRQ vektörü programın içinde ve RAM'de olacak. O zaman nmi vektörünü de ram'den kullanıp transfer rutinini de c64'de çalışan kodun içine alırım. Arduino tarafında da video streaming işi için ayrı bir transfer rutini yazarım.
Geriye tek bir sıkıntı kalıyor, sadece bellek konfigürasyonunu değiştirmenin benim işimi görmediğini görüyorum. Yukarıda paylaştığım linkteki tabloya dikkatle bakılınca şu da görülebiliyor. $8000-$9FFF'in CART ROM LO olduğu ve $E000-$FFFF'in RAM olduğu iki farklı bellek konfigürasyonu da yok. #$!!%%?? diye iç geçirmek elde değil
Neyse ki çözümü buluyorum. Kartuş normalde transferlere başladığında EXROM'u low'a çekip eprom'un $8000-$9FFF aralığında gözükmesini sağlıyor ve ancak tüm yükleme vesaire bittiğinde EXROM'u high'a çekip elini eteğini çekiyor. Normal şartlarda bunda sıkıntı yok ancak burada şunu yapmak gerekiyor. NMI interrupt RAM'deki vektör kullanılıp da tetiklendikten sonra EXROM'u low'a çekiyoruz. Kartuşun çalışma prensibi eprom'daki bank'lar arasında gönderilecek byte'a karşılık gelen bank'a switch yapmak ve bunun arduino ile c64'de çalışan kod arasında senkron olması olduğu için EXROM'u ancak yapılacak parça transfer bitip de c64'deki kodun kartuş rom'una ihtiyacı olmadığı anda HIGH'a çekmek gerekiyor. Bunu da arduino üstündeki nmi interrupt'ını generate eden ve bank switch eden transfer rutini içine gömüyorum.
Genel olarak yöntem şu, kartuş rom'una ihtiyaç daha yok iken IRQ interrupt'ları açmadan önce $35 bellek konfigürasyonunu seçiyorum, böylece ROM'daki varsayılan vektörleri değiştirebiliyorum, hem NMI hem de IRQ vektörlerini programım içindekilerine değiştiriyorum. IRQ interrupt çalışmadan önce konfigürasyon hep $35 değerinde olmalı.
Arduino tarafında NMI oluşturduktan kısa bir süre sonra kartuş rom'unu devreye alıyorum, NMI handler'ın başında da bellek konfigürasyonunu default olan $37'ye alıyorum. Böylece c64'deki kod kartuş rom'unu görebilecek. Transferi yaptıktan sonra da nmi handler içinde bellek konfigürasyonunu tekrar $35 değerine çekiyorum.
Deve bu arada baya bildiğin helak oldu
Bu arada normalde benim kartuş eprom'undaki transfer kodumda şöyle bir kısım var esas transferi yapan. Buradaki $EA yerine o an hangi bank seçilmişse o değer geliyor.
LDA #$EA
STA (ACTUAL_LOW), Y
INY
Bu transfer rutinini ram'e koyduk, öyle kodun içinde löp löp elimize gelmiyor artık arduino'nun transfer ettiği byte. Çözüm? Kodun içinde olmasa da arduino bank switch yaptığı için aslında transfer edilen byte eprom üzerinde okunacak değişik adreslerde mevcut. Hatta bir tane rahat ulaşım için koymuş olduğum var, bugünler görülerek çok önceden yerleştirilmişti. Eprom üstünde $XXFF adresi her zaman için arduino tarafında switch edilmiş bank'ı yani transfer edilecek byte değerini veriyor.
Kodu şu hale getirmem RAM'de iken çalışmasını sağlayacak,
LDA $80FF
STA (ACTUAL_LOW), Y
INY
Pek tabii dönüp arduino üstünde daha önce bahsettiğim transfer rutinini de bu zamanlamayı dikkate alarak değiştiriyorum. Çünkü LDA #$EA immediate adresleme kullanırken LDA $80FF ise absolute adresleme kullanıyor. İlki 2 cycle, ikincisi ise 4 cycle. Bu zamanlama işini de tembelliğimden osiloskop ile ölçme değerlendirme yöntemi yerine deneme ve yanılma yöntemi ile yaptığım için deve bu noktada "hendek demiştin hacı?" formatına kayıyor biraz

Merak edenler için niha kod da şöyle bir şey oldu (Eski kodlardan standart kullandığım şeyler include edilen dosyalarda)
.enc screen
ACTUAL_LOW = $6C
ACTUAL_HIGH = $6D
INITIALWAITTIME = 150
CHROUT = $FFD2
IRQ6502 = $FFFE
NMI6502 = $FFFA
CURRENTFRAGMENT = $08
CURRENTSTEP = $09
*=$080E
JSR INIT ;Clears screen, disables interrupts.
LDX #$00
STX CURRENTSTEP ;[0..14] the raster line to invoke an IRQ and start a partial transfer of 8 bytes.
.CHANGEBANK 3
JSR INIT_GFX_MEM
JSR SET_LO_COLOR
JSR SET_HI_COLOR
JSR SETMULTICOLOR
JSR KICKSTART ; Send video stream command to arduino
LDA #$00
STA $D01A
STA $D015
JSR INITIALWAIT
LDA $d011 ; clear high bit of raster line
AND #$7f
STA $d011
LDX #$00
LDA RPP, X
STA $D012
LDA #<MRH
STA IRQ6502
LDA #>MRH
STA IRQ6502+1
LDA #<COPIEDNMIHANDLER
STA NMI6502
LDA #>COPIEDNMIHANDLER
STA NMI6502+1
LDA #$35
STA $01
LDA #$01
STA $D01A
LDY #$00
LDX #$00
CLI
HAYDI
LOOP
CLV
BVC LOOP
JMP LOOP
MRH
SEI
LDA VIDEO_LO_B0, X
STA ACTUAL_LOW
LDA VIDEO_HI_B0, X
STA ACTUAL_HIGH
INX
CPX #120
BNE CONTINUED
LDX #$00
CONTINUED
LDY CURRENTSTEP
INY
CPY #15
BNE SETRASTER
LDY #$00
SETRASTER
LDA RPP, Y
STA $D012
STY CURRENTSTEP
LDY #$00
ASL $D019
RTI
COPIEDNMIHANDLER
LDA #$37 ;2 cycles
STA $01 ;3 cycles
NOP
LDA $80FF
STA (ACTUAL_LOW), Y
INY
LDA $80FF
STA (ACTUAL_LOW), Y
INY
LDA $80FF
STA (ACTUAL_LOW), Y
INY
LDA $80FF
STA (ACTUAL_LOW), Y
INY
LDA $80FF
STA (ACTUAL_LOW), Y
INY
LDA $80FF
STA (ACTUAL_LOW), Y
INY
LDA $80FF
STA (ACTUAL_LOW), Y
INY
LDA $80FF
STA (ACTUAL_LOW), Y
LDA #$35 ; Switch kernal+basic roms off
STA $01
RTI
WASTELINES
LDX #20
CONSUME
DEX
BNE CONSUME
RTS
INITIALWAIT
LDY #INITIALWAITTIME
-
LDA $D012
BNE -
JSR WASTELINES
DEY
BNE -
RTS
INIT ; Input : None, Changed : A
CLD
LDA #$93
JSR CHROUT
LDA #$00
STA $D020
LDA #$0B
STA $D021
JSR DISABLERASTERIRQ
JSR KILLCIA
RTS
.include "Common.65s"
.include "Transfer.65s"
VIDEO_B0 = PICTURE_LO
VIDEO_B1 = PICTURE_HI
L0 = VIDEO_B0 + 2960 + range(0, 160, 8)
L1 = VIDEO_B0 + 3280 + range(0, 160, 8)
L2 = VIDEO_B0 + 3600 + range(0, 160, 8)
L3 = VIDEO_B0 + 3920 + range(0, 160, 8)
L4 = VIDEO_B0 + 4240 + range(0, 160, 8)
L5 = VIDEO_B0 + 4560 + range(0, 160, 8)
VIDEO_LO_B0
.byte <(L0)
.byte <(L1)
.byte <(L2)
.byte <(L3)
.byte <(L4)
.byte <(L5)
VIDEO_HI_B0
.byte >(L0)
.byte >(L1)
.byte >(L2)
.byte >(L3)
.byte >(L4)
.byte >(L5)
RPP .byte 119, 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231