"Sıkça Sorulan Sorular" sayfasının sürümleri arasındaki fark

Retrojen Wiki sitesinden
Şuraya atla: kullan, ara
(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...")
 
(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)
 

21:35, 18 Ocak 2015 itibarı ile sayfanın şu anki hâli