Sıkça Sorulan Sorular

Retrojen Wiki sitesinden
15.34, 16 Ocak 2015 tarihinde İlkerg (mesaj | katkılar) tarafından oluşturulmuş 73 numaralı sürüm (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...")
(fark) ← Önceki sürüm | Güncel sürüm (fark) | Sonraki sürüm → (fark)
Gezinti kısmına atla Arama kısmına atla

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)