Sıkça Sorulan Sorular: Revizyonlar arasındaki fark

Retrojen Wiki sitesinden
Gezinti kısmına atla Arama kısmına atla
İlkerg (mesaj | katkılar)
Yeni sayfa: "'''Soru 1 (HADES):''' Yazdığım kodlarda IM 2'yi kullanıyorum ama Basic ekranına geri dönüş yapmayıp normal rutinde JR ile döngü yapıyorum. Hem Irq kullanıp hem Basic na..."
 
İlkerg (mesaj | katkılar)
Sayfayı boşalttı
 
1. satır: 1. satır:
'''Soru 1 (HADES):'''
Yazdığım kodlarda IM 2'yi kullanıyorum ama Basic ekranına geri dönüş yapmayıp normal rutinde JR ile döngü yapıyorum.
Hem Irq kullanıp hem Basic nasıl kullanılır? Aklıma IM 1 kullanmak geliyor ama nasıl olacak?


'''Cevap 1 (REF):'''
Anladığım kadarıyla bir basic programı çalışırken, diğer taraftan asm ile müzik çaldırmak istiyorsun.
Spectrumda bir tek IM2'yi kullanabiliyoruz. IM1 ROM'a göre zıplıyor, dolayısı ile yapacak bişey yok.
IM2'yi kurması da gıcık aslında. Çünkü şöyle bir durum var. IM2 işaretçi adresinin hesaplanacağı adres şu şekilde hesaplanıyor (evet suyunun suyu şeklinde):
Adresin üst byte'ı I yazmacında tutuluyor. Fakat alt byte'ı takılı olan aygıt belirliyor. Eğer bir aygıt takılı değil ise, floating bus sebebi ile bu alt byte random olabiliyor. Dolayısı ile IM2 kurmak için 257 byte'lık bir alanı *aynı* byte'lar ile doldurmak gerekiyor ki, adres nereye düşerse düşsün pointer değişmesin.
Örnek. Diyelim ki I'yı 254 yaptınız. Bu şekilde IM2 pointer'ının okunacağı adres (yüksek byte'a göre) 65024 oldu. Fakat IM2 düşük byte 0-255 arasında rast gele bir değer. Dolayısı ile eğer düşük byte 0 olursa sizin kesme rutininizin bulunacağı adres 65024 ve 65025 byte'larından hesaplanacak. Eğer bu adreslerin ilkinin değeri "1", ikincisinin değer i"0" olursa, interrupt olduğunda, 255 adresine zıplanır.  Fakat IM2 düşük byte başka bir rakam olsa, zıplanacak adres başka bir lokasyondan hesaplanacağı için, IM2 başka bir yere zıplar.
Ben asmp multicolor aracını kodlarken şöyle bir yöntem izledim. 65024'den itibaren 257 byte boyunca #FD ile doldurdum. I'ya 254 yükleyince her durumda IM2 vektörü #FDFD oluyor, yani 65021'e zıplanıyor. Bu adrese istediğin şekilde dallanabilirsin, ben timing için yaptığım için buraya RET girdim, böylece halt ile durduktan sonra IM2 olduğu gibi program senkronize olarak devam ediyor.
Dikkat, Interrupt rutini asla 32768'den aşağıda olmamalı!
Senin durumunda ise basic çalışsın istiyorsun, fakat IM1 servis rutinide çalışsın istiyorsun. Bu durumda servis rutininin yaptığı işi senin yapman gerek.
Neyse benim kodu asmp'den copy-paste ediyorum:
Önce IM2'yi kuralım
di  ;interrupt'ı kapatalım
ld hl,65021
ld (hl),#C3 ;jump kodunu yerleştirelim, dikkat bu şekilde yapmak mecburi değil
inc hl        ;vektör tablosunu 253'le değil başka bir rakamla doldurursanız
ld hl, #c0  ;istediğiniz yere zıplatırsınız zaten
inc hl
ld hl, #c7  ; yani #C3 #C0C7 (JP 47040)
               
ld  hl,65024  ;şimdi aralığı FD ile dolduracağız.
ld  de,65025
ld  (hl),253
ld  b,e
ld  c,e
ldir
ld  a,254  ;Artık IM2'yi kurabiliriz.
ld  i,a
im  2 ;im2'ye geçtik
ei  ;interruptlar açık
Bu da basic'i çalışır durumda tutmanın bir yöntemi:
org #C0C7  ;yukarıdaki örneğe göre kod 47040'dan başlamalı.
di  ;alışkanlık
ld (stackpointer),sp ;mecbur değilsen sp'yi yazmayabilirsin
ld sp,stackpointer  ;garanti olsun diye yerini de değiştiriyorum (18 byte'lık bir yer lazım)
Push HL  ;basic'in kullandığı yazmaçları saklayalım
Push BC
Push DE
Push AF 
exx        ;söylentiye göre basic için alternatif yazmaçları saklamaya gerek yok
Push HL  ;ama yine de koyalım bir kenara
Push BC
Push DE
CALL muzik  ;müziğimizi çalalım
rst 56 ;ROM'daki servis rutini, klavyeyi okur, sayacı ilerletir
LD sp,stackpointer-14 ;basic'e dönmeden önce herşeyi geri yerleştirelim
Pop DE
Pop BC
Pop HL
exx
pop af
pop de
pop bc
pop hl
ld sp,(stackpointer) ;herşeyi geri aldık
;IM1 ;Bu noktada IM1 işletsek, basic'e olduğu gibi geri dönülmüş olur.
ei  ;interrupt'ı çalıştır.
ret  ;geri dön, dilerseniz RETI de kullanabilirsiniz.
stackpointer:
defb 0
----------------------
Bu koda göre IX/IY registerini kullanamazsınız, basic kullanıyor, istiyorsanız onları da kaydetmelisiniz.
Bu efektif yöntem mi bilmiyorum ama benim kullandığım yöntem bu. Özetlersek (değerler decimal):
1. IM2 için 257 byte uzunluğunda vektör tablosu oluştur. (tablo 220'lerden oluşursa adres 220*256+220= 56540 olacak)
2. I'yı bu tablonun başına point et.
3. vektör tablosundaki adrese rutinini koy
4. rutin başladığında basic değişkenlerini sakla (PUSH <hepsi>)
5. işini yap: (CALL x)
6. basic servis rutinini çağır (rst 56)
7. basic değişkenlerini geri çağır (POP <hepsi>)
8. geri dön (reti/ret)

18.35, 18 Ocak 2015 itibarı ile sayfanın şu anki hâli