Gönderen Konu: Skate'in ZX Spectrum Maceraları - Vol 1  (Okunma sayısı 1635 defa)

0 Üye ve 1 Ziyaretçi konuyu incelemekte.

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #30 : 05 Mayıs 2022, 16:43:51 »
Şimdi bir yarım saat vakit buldum. Az daha optimize ettim plot rutinini, son halini paylaşmış olayım, ekte 15. ve 16. versiyonlar. 16 en son şu an için. Asıl başarısız olan denememi paylaşmak istedim.

Plot için bitleri OR'luyoruz ama aslında opcode olarak SET mevcut. C64'de bir karşılığı yok, o yüzden çok kafa yormamıştım bu opcode'a. Baktım, hangi biti set edeceğinde parametre almıyor, kendisi bir çok farklı opcode varyasyonu olarak mevcut. İhtiyacım olan "SET n, (hl)" kullanımı.

SET 0, hl => $c6
SET 1, hl => $ce
SET 2, hl => $d6
SET 3, hl => $de
SET 4, hl => $e6
SET 5, hl => $ee
SET 6, hl => $f6
SET 7, hl => $fe

değerlerine denk geliyor. Yani hangi biti set edeceğimizi okuduğumuz şu orBit tablosunu

Kod: [Seç]
db %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001

bitler yerine SET opcode karışıklarına çevirsek

Kod: [Seç]
db $fe, $f6, $ee, $e6, $de, $d6, $ce, $c6

sonra da;

Kod: [Seç]
    ld a, (hl)
    or c
    ld (hl), a

olan bölgeyi

Kod: [Seç]
setBit:
    set 0, (hl)

ile değiştirip, OR değerini okuyan kısmı da;

Kod: [Seç]
    ; get or bit pattern for given x in character position
    inc h   ; orBit is right after sinX
    ld c, (hl)

yerine

Kod: [Seç]
    inc h
    ld a, (hl)
    ld (setBit+1), a

ile değiştirsek teorik olarak çalışması lazım. Pratikte de çalıştı zaten. Plot başına 10 tstate fazladan harcadı ama. Başarısız da olsa en azından denemiş oldum. Hala da aklımın köşesinde var.

ld (setBit+1), (hl)

gibi kullanımlar olsa belki de kar edebilirdik. hele ki SET bir sürü opcode alternatifi olacağına register parametresi alsaymış OR kullanmam tamamen cahilliğim olurmuş. Hep sabit bir biti set edecek olsak kazanç sağlıyor OR'a göre. Ama dinamik olduğu durumda şimdilik hala OR doğru tercih gibi duruyor.

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #31 : 06 Mayıs 2022, 07:17:31 »
Bugün erken uyandım (6:15 civarlarında). Aklıma bir fikir geldi, aslında Y ekseni için uyguladığım bir şeyi X ekseni için kullandığım tablolara da uygulama fikri, bir tabloyu elimine edecek bir çözüm. Denedim, çalıştı. Kod çok kısalınca dedim artık loop'a gerek yok. unrolled olarak da plot edebiliriz. Tabii ki bu değişiklikler başka optimizasyonların da önünü açabilir. Bilgisayar başına oturalı 40 dakika olmuş durumda. Ama şu anki versiyonu paylaşıyorum. 17. versiyon bir tablonun uçtuğu, 18. versiyon artık çizim kısmının da unroll edildiği versiyonlar.

Önce bazı istatistikleri paylaşayım.

Sinüse bağlı 256 nokta çizdirme: 24828 t-state (%35.01 CPU kullanımı)
Çizilen alanın temizlenmesi: 4356 t-state (%6.14 CPU kullanımı)

Toplamda çizim+silme: 29184 t-state (%41.15 CPU kullanımı)

Çizim rutinine daha sonra silebilmek için eklemiş olduğumuz "push hl" de dahil. Tek bir plot'un basılmasını ele alacak olursak plot rutinimiz tam olarak 83 t-state ve 16 byte tutuyor. Plot sonrası bir "push" bir de "inc" yapıyoruz, onlar da 15 t-state ve 2 byte tutuyorlar. Yani bir noktadan diğer noktanın çizimine toplamda 98 t-state ve 18 byte harcanıyor.

Online versiyonu da güncelledim, CPU kullanımını temsil eden yeşil bölge epey küçüldü, son durumu oradan da görebilirsiniz. Eke de gerekli dosyaları ekledim.

http://speccy.akaydin.com/

Değişen kısımlar;

256 adet plotu basan rutin

Kod: [Seç]
i = 0
    WHILE i < $100
    ; --- put pixel

    IF i != 0
        inc b
    ENDIF

    ; get orBit of given position
    ld a, d
    add a, b
    ld l, a
    ld h, e ; e has the high byte of orBit table
    ld c, (hl)

    ; find char column
    inc h   ; charPosition is right after orBit
    ld a, (hl)

    ; find plot address
    ld l, b
    inc h ; posYLo is right after charPosition
    or (hl) ; add character X position
    inc h ; posYHi is right after posYLo
    ld h, (hl)
    ld l, a

    ; set pixel using OR
    ld a, (hl)
    or c
    ld (hl), a

    ; --- end of put pixel

    ; push pixel memory address to stack
    push hl
i = i + 1
    ENDW

Üretilen tabloların kodları düzenlendi, tekrar eden kodlar fonksiyonlara bölündü.

Kod: [Seç]
    ALIGN $100
orBit:
    LUA ALLPASS
        for i = 0, 255, 1 do
            _pc(' db ' .. 2 ^ (7 - bitoper(getX(i), 0x07, AND)))
        end
    ENDLUA

; charPosition must be right after orBit
    ALIGN $100
charPosition:
    LUA ALLPASS
        for i = 0, 255, 1 do
            _pc(' db ' .. math.floor(getX(i) / 8))
        end
    ENDLUA

; posYLo must be right after charPosition
    ALIGN $100
posYLo:
    LUA ALLPASS
        for i = 0, 255, 1 do
            _pc(' db ' .. (getY(i) % 256))
        end
    ENDLUA

; posYHi must be right after posYLo
    ALIGN $100
posYHi:
    LUA ALLPASS
        for i = 0, 255, 1 do
            _pc(' db ' .. math.floor(getY(i) / 256))
        end
    ENDLUA

...

        function getX(i)
            return math.floor(128 + 127.5 * math.sin(i / 64 * math.pi) * math.cos(i / 32 * math.pi))
        end

        function getY(i)
            y = math.floor(64 + 81.5 * math.sin(i / 128 * math.pi) * math.sin(i / 64 * math.pi))
            v = 0x4800 + bitoper(y / 64, 0xff, AND) * 0x800 + (y % 8) * 0x100 + bitoper((bitoper(y, 0x3f, AND) / 8), 0xff, AND) * 0x20
            return v
        end

Son durum budur.

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #32 : 06 Mayıs 2022, 08:25:20 »
Loopu açınca, daha çok register boşa çıkınca, X/Y faz farkı için de biraz farklı bir yöntem kullanınca kod iyiden iyiye optimize edildi. 19, 20 ve 21. versiyonlar ekte.

Sinüse bağlı 256 nokta çizdirme: 21752 t-state (%30.67 CPU kullanımı)
Çizilen alanın temizlenmesi: 4356 t-state (%6.14 CPU kullanımı)

Toplamda çizim+silme: 26108 t-state (%36.82 CPU kullanımı)

21. versiyon

Edit: Bu versiyonda sonunda @matahari'nin önerdiği yöntemi önerdiği noktada kullanabildim.

Ana döngü öncesi verilen değerler:

Kod: [Seç]
    ; b register is plot loop counter
    ; e register is frame and inner loop counter
    ; c register holds charPosition table high byte
    ; d register holds orBit table high byte
    ; reset counters before main loop
    ld b, e
    ld e, e
    ld c, high charPosition
    ld d, high orBit

256 noktayı döngü kullanmadan basan plot rutini:

Kod: [Seç]
i = 0
    WHILE i < $100
    ; --- put pixel

    IF i != 0
        inc b
        inc e
    ENDIF

    ; find char column
    ld l, e
    ld h, c ; c has the high byte of charPosition table
    ld a, (hl)

    ; find plot address
    ld l, b
    inc h ; posYLo is right after charPosition
    or (hl) ; add character X position
    inc h ; posYHi is right after posYLo
    ld h, (hl)
    ld l, a

    ; set pixel using OR
    ld a, (de)
    or (hl)
    ld (hl), a

    ; --- end of put pixel

    ; push pixel memory address to stack
    push hl
i = i + 1
    ENDW

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 3093
  • Advanced User Simulator
    • ae unutmadan
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #33 : 06 Mayıs 2022, 09:37:14 »
hah tam denk gelmiş hatta biraz payın bile kalmış.

şöyle, zxspectrum 48k'da her raster 224 ts (128k'da 228ts)
üst border kalınlığı 64 raster. Sonra plush logosunun bulunduğu alan yine 64 raster.
yani noktalar 128 raster sonra basılıyor (128k'da 127).

48k için hesaplayalım, tv elektron tabancasının 129'uncu rasterin başına gelmesi
224*128=28.672ts  tutuyor.

sende 26108ts kullanmışsın, ula'nın ilk dot'u çizmesine daha 2564 ts var.
(28672-26108=2564ts)

Beam'de tam pozisyonuna gelmiş. şimdi attribute byte'larını doldurarak arkada dönen rasterbars falan multicolor efekt bile yapabilirsin :D


Yazdığın kodu incelediğimde resmen başka bir uzmanlık alanı olduğunu görüyorum :) Burda asm yok, asm parçalarını bir araya getiren bir lua script var. sanki işlemleri fonksiyonlara ayırmışsın ve onları kondüsyonel çağırıyorsun gibi. Ben bodoslama yazıyorum, arada bir iki unroll makrosu ancak :D Bu yazı dizisi tam benlik oldu.

Bu arada emülatörde profiling sonucu 48k zx spectrum için senin kodun, halt, out, jp'ler vs. dahil tuttuğu süre 27605ts (ula contention vs de arada bozuyor hesabı).

Çevrimdışı hades

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 192
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #34 : 06 Mayıs 2022, 10:02:48 »
Ana döngü öncesi verilen değerlerde ld e,e komutu var. Sanki fazladan gibi.
Bu arada forumda like butonu olması şart.

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 3093
  • Advanced User Simulator
    • ae unutmadan
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #35 : 06 Mayıs 2022, 11:17:06 »
Ana döngü öncesi verilen değerlerde ld e,e komutu var. Sanki fazladan gibi.
Bu arada forumda like butonu olması şart.

haha evet, hem de skate kendi yazmış, assembler öyle derledi sandım bir an :D olsun, çıkarılır, 4ts cepte.

eğer optimizasyonun dibine vuracaksak, en sondaki push hl ile HALT peşinden gelen pop hl de lazım değil, arada register değişmiyor :D ahahah ordan da 21 gelir :D

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #36 : 06 Mayıs 2022, 16:05:44 »
Ana döngü öncesi verilen değerlerde ld e,e komutu var. Sanki fazladan gibi.
Bu arada forumda like butonu olması şart.

Haklısın İsmail, uyardığın için sağol.

O ld e,e'nin hikayesi şöyle. Daha önce ld d,e idi o. E'nin değeri ld de, $5800 satırından sıfır geldiği için absolute value yerine e'yi kullanmıştım. Yani amaç sıfıra eşitlemek. Ancak plot rutininin sonundaki ld a, (de)'yi kullanabilmek için d ile başka bir register'ı swap ettim. Dolayısıyla kod içinde tüm d geçenleri e yap gibi bir işlem yapınca o da ld e, e şekline gelmiş, gözümden kaçmış. Ama performansı etkilemiyor. Çünkü main loop içinde değil. Oradan kazanç sağlayacak olsam öncesindeki ldir içeren kopyalama rutinlerini adam etmem gerekir zaten. O tür rutinler en fazla demo partının başlangıcında etkiler. Bir gün trackmo yapmaya karar verirsem büyük ihtimalle logoya bir açılış efekti yaparım, o kısım o şekilde değişir zaten. :)

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #37 : 06 Mayıs 2022, 16:12:08 »
Ana döngü öncesi verilen değerlerde ld e,e komutu var. Sanki fazladan gibi.
Bu arada forumda like butonu olması şart.

haha evet, hem de skate kendi yazmış, assembler öyle derledi sandım bir an :D olsun, çıkarılır, 4ts cepte.

eğer optimizasyonun dibine vuracaksak, en sondaki push hl ile HALT peşinden gelen pop hl de lazım değil, arada register değişmiyor :D ahahah ordan da 21 gelir :D

Çok zekice. Optimizasyon optimizasyondur, sadece sonunucuyu etkiliyor deyip es geçmem asla. 22. versiyon ekte. :)

matahari

  • Ziyaretçi
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #38 : 06 Mayıs 2022, 16:19:32 »
@matahari bana dün bir optimizasyon önermişti. Yazıyı bitirene kadar kafayı odaklayamadım. Yazı bittikten sonra önerdiği noktada değil ama başka bir yerde aynı tavsiye yerini buldu.
Bu versiyonda sonunda @matahari'nin önerdiği yöntemi önerdiği noktada kullanabildim.

  [ You are not allowed to view attachments ]  

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #39 : 06 Mayıs 2022, 16:40:01 »
Son ulaştığımız noktada sadece plot rutinini olan kısım 6 tanesi 4 tstate, 6 tanesi 7 tstate tutan toplam 12 opcode, 12 byte ve 66 t-state'den oluşuyor.

Kod: [Seç]
    ; find char column
    ld l, e
    ld h, c ; c has the high byte of charPosition table
    ld a, (hl)

    ; find plot address
    ld l, b
    inc h ; posYLo is right after charPosition
    or (hl) ; add character X position
    inc h ; posYHi is right after posYLo
    ld h, (hl)
    ld l, a

    ; set pixel using OR
    ld a, (de)
    or (hl)
    ld (hl), a

Bu daha ileri taşınabilir mi bilmiyorum. Tabii bu rutinin aynı zamanda sinüse tablolarına bağlı olarak plot bastığını da hatırlatmam lazım. Gerçi herhangi x, y için de çok bir şey değişmeyebilir.

Şu noktadan sonra ben biraz tıkandım gibi. @Ref'in ve @hades'in önerileri gibi gözüne bir şey takılan olursa lütfen paylaşsın. Örneğin push/pop kısmını o şekilde yaptım ama belki daha iyi bir yöntem vardır. İlk versiyonumda pop etmek yerine stack alanının en tepe noktasından ileriye doğru kendim değerleri okuyup sıfırlamayı denemiştim. Rutinin sonunda da stack pointer'ı resetlemiştim. Ancak sorun şu oluyor. Hafızada peş peşe 16 bit olarak duran iki byte'ın işaret ettiği byte değerini sıfırlayıp, sonra low pointer'ı da 2 ileri almayı denediğimde "pop hl", "ld (hl), a" 17 t-state ile en hızlı çözüm gibi gelmişti. Ancak bunun undocumented opcode'u olur, şu olur bu olur. Bunu daha hızlı yapmanın yolunu bilen var mıdır?

Z80 ile ilgili araştırma yaparken Ghost'n Goblins grafik rutinlerini açıklayan bir siteye denk gelmiştim.

http://www.emix8.org/ggdisasm/

Burada ağır bir push/pop kullanımı var. O nedenle en hızlı yöntemin bu olabileceğini düşünüyorum. Yine de dediğim gibi sizlere bir sormak istedim.

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #40 : 06 Mayıs 2022, 17:00:19 »
Yazdığın kodu incelediğimde resmen başka bir uzmanlık alanı olduğunu görüyorum :) Burda asm yok, asm parçalarını bir araya getiren bir lua script var. sanki işlemleri fonksiyonlara ayırmışsın ve onları kondüsyonel çağırıyorsun gibi. Ben bodoslama yazıyorum, arada bir iki unroll makrosu ancak :D Bu yazı dizisi tam benlik oldu.

Aslında düşündüğün kadar işin içinde LUA falan yok @Ref, yalnızca tablolar var. Bunu ben ilk rasterbar çekmek istediğimde telefonda Mert Hekimci'den öğrenmiştim. Bana "iki tane tablon olacak. biri renkler, biri zamanlamalar için" demişti. Yaş 10 civarı. Tablo dendiğinde aklımda sadece duvara astıklarımız vardı. :) Kısa sürede ne yapmam gerektiğini anlamıştım. Ama elimde günümüzün fancy cross development teknolojileri olmadığı için tabloları ya Basic'den hesaplatıyordum, daha da komiği bir çoğunu elle tek tek oluşturuyordum. Hatta ekrana sinüs benzeri hareketlerle giren logolar, serbest düşme hareketi yapan objelerin tabloları matematiksel değildi, elle deneme yanılmayla oluşturuyordum. :) Yani şimdi sen LUA scripting görünce "ya iş bambaşka bir yerde dönüyormuş" diyorsun. Aslında 30 sene öncesinde de ben birebir böyle kod yazıyordum. Tek farkı şimdi daha bir hesaplı kitaplı tablolar. :)

Bu kod yapısı aslında benim de hoşuma gitmiyor, her şeyi tablolamak, matematiği opcodelardan çıkarmak, üç tane bit shifting'i bile tablodan bakarak yapmak. Ancak bunun için sizinle tüm bu macerayı paylaştım. Gördüğün gibi hala elim tablo dışı yöntemlere gidiyor. Ama günün sonunda rutinlerin ulaştığı nokta bu oluyor.

3d efektlere sarma nedenlerimden biri de buydu açıkçası. 3d efektlerde yine arkaplan tablo deryası tabii ki. Ama çok ciddi de opcodelar üzerinden dönen işlemler oluyor, olmak zorunda. Matris hesapları, dot product alma şu bu, hepsini tek tek kodlamak zorunda kalıyorsun. İş nokta basma rutinine geldi mi demoscene'de elle tutulur bir şey yapmak istiyorsan tablo manyağı olmak zorundasın ne yazık ki. Yoksa bir başkası senden daha iyisini yapıyor, sen de kalkıp "ama ben senin kadar tablo kullanmadım" diyemiyorsun, adam "kullansaydın" diyor. :)

Çevrimdışı hades

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 192
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #41 : 06 Mayıs 2022, 17:22:28 »
Aklımda bir kaç optimizasyon var ama plot rutini için değil. im2 setup ve ldir kısmıyla ilgili. Bir kaç bayt kazandırır sadece. Önce ldir kısmını yazayım.
Logonun $0800 byte uzunluğunda olduğunu kabul ediyorum. İlk ldir komutu çalışınca DE'nin değeri $4800 oluyor. İkinci ldir için ld de,$5800 yerine ld d,$58 yazarak 1 bayt tasarruf ediyoruz. ldir sonrası BC=0 olduğu için ld b,e komutuna da gerek kalmıyor. Hatta renk tablosu 256 byte olduğu için ikinci ld bc yerine inc b yazılabilir. 4 byte kazandık :)
im2 setup kısmı için
Alıntı
    ; set irq
    ld hl, im2Jump
    ld (hl), 0xc3
    inc l
    ld (hl), low irq
    inc l
    ld (hl), high irq
    ld a, high im2Table
    ld i, a
    im 2
    ei

yerine

Alıntı
                    org $8000

                    defs 257,$81       ; im2table

                    di
                    ld   a,$80
                    ld   i,a
                    im   2
                    ei

yazarak 8 byte ile im2setup yapabiliyoruz. $8000-$8101 arasını $81 ile dolduruyoruz. Dolayısıyla irq rutini $8181'de yer alacak. Programın çalışma adresi $8101 gözükse de $81 ADD A,C olup programı $8000'den başlatmamıza engel değil. EI'den sonra $8181'e kadar 121 baytlık boş yer var ve logo/renk transfer/diğer ayarlar için kullanılabilir. $8183'ten itibaren tamamen serbest olur. irq set rutini ile hafızanın $FDFD'den sonrası boş kalır.

;irq rutin
org $8181
ei
ret
;--------------

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #42 : 06 Mayıs 2022, 17:40:58 »
Teşekkürler @hades. Özellikle logo transfer rutini bir fade in efektiyle değişecek gibi gözüküyor, o nedenle henüz o kısma el atmadım. irq ile ilgili kısımda da haklısın, gereksiz zaman harcıyoruz orada. Ama hepsi initialization rutini kapsamında olduğu için oralara pek aldırış etmedim. Hafıza dizilimi konusunda da henüz çok ZX Spectrum tecrübem olmadığı için en düz mantık olarak yerleştirdim her şeyi. En son ASM kısmını loader ile yükletmeyip tek parça haline getirecekken hepsini gözden geçireceğim. Hatta sadece şu anki hali için belki 16k modellerinde de çalışacak hale getirmeyi deneyebilirim. Tabii conditional olarak 16k'ya özel derlenecek biçimde, ona özel hafıza yerleşimi yaparım. Diğer platformlarda aynı kod ve tablolar farklı adreslere yerleşir.

Bir de aklımda ekranın tamamına daha fazla nokta basmak var. O zaman logo tamamen çöpe gidebilir, daha ince şerit halinde logo, logolar ya da başka grafikler söz konusu olabilir, @Ref'in dediği gibi rasterbarlar falan da olabilir. Daha o kısmı tasarlamaya başlamadım kafamda. Büyük ihtimalle son ulaşacağım rutinde plot rutini bu versiyondan daha fazla zaman yiyebilir daha dinamik bir efekt olması açısından. O yüzden önce bunun suyunu sıkmaya çalışıyorum ki ekstra özelliklere yer açılsın.

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 199
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #43 : 07 Mayıs 2022, 16:41:32 »
@matahari'nin bitmek tükenmek bilmeyen desteği sayesinde kod anlamsız derecede kısa bir hal aldı. :)

Commodore 64'de zamanlama çok kritik olan durumlarda, örneğin yan borderların açılması ve aynı anda her satırda başka hardware registerlarının da set edilmesi gerekmesi gibi hallerde değerleri tablodan okumak yerine doğrudan absolute value (lda #$15 sta $d027 gibi) ile yazıp, daha sonra zaman kritik olmayan alandan tablodan okuyup parametreleri yerlerine yerleştirdiğimiz olur. Ancak bu normalde toplamda daha çok cycle harcamamıza neden olur, yani tek seferde tablodan okusak daha iyi sonuç alırız. Bu bize zaman kazandırmaz, sadece zamanlama yetmeyen kısımda daha çok iş yapabilmemizi sağlar.

Z80'e geldiğimizde "ld a, (hl)" ve "ld a, 1" kıyaslandığında aynı zamanı harcıyorlar. Tabii ki hl değerini set etmek de zaman harcayan bir kısım. Ama tek başına tablodan değer okumak yerine değeri kodun içine yazmak bize zaman kazandırmıyor. Matahari de tam olarak bana bunu teklif etti özelden. Artık loop'u açmış olduğumuz için tablodan değer okumak yerine değerleri doğrudan kodun içine yazmak. Bu tabloyu da çöpe atan bir faktör. Ama teklif ettiği yer ilk denediğimde t-state anlamında bir kazanç sağlamadı. Yani tablo çöpe gitti, dolayısıyla hafıza kullanımı düştü, ama hala rutin aynı zamanı harcıyordu. Ama bana bu teklifi yaptığı mesajında "bonus" olarak bazı registerları boşa çıkarabileceğimizi ve bunu daha fazla optimize etmek için de kullanabileceğimizi yazmıştı ve öyle de oldu.

Kısacası benim Commodore 64'de farklı koşullarda kullandığım ancak burada işe yarayacağı hiç aklıma gelmeyen bir optimizasyon işe yaramış oldu. Ekte bu versiyonları bulabilirsiniz. Şu anki kod şu şekilde.

Kod: [Seç]
n = 0
    WHILE n < $100
    ; --- put pixel

    IF n != 0
        inc c
    ENDIF

    ; find plot address
    ld a, (bc)
    ; or with char column
    LUA ALLPASS
        _pc(' or ' .. math.floor(getX(_c("n")) / 8))
    ENDLUA

    ; get posYHi
    ld l, c
    ld d, (hl)
    ld e, a

    ld a, (de)
    ; set pixel using OR
    LUA ALLPASS
        _pc(' or ' .. 2 ^ (7 - bitoper(getX(_c("n")), 0x07, AND)))
    ENDLUA
    ld (de), a

    ; --- end of put pixel

    ; push pixel memory address to stack
    IF n != $ff
        push de
    ENDIF
n = n + 1
    ENDW

Çizim bölgesi 16643 t-state ve %23.47 CPU kullanımına düştü (sadece opcodeların harcadıklarını sayıyorum).

"Artık bu kadarı da fazla" diyenlere hak veririm. Ama sonuç olarak hala aynı efekti görüyoruz ekranda, hafıza kullanımı da artacağı yerde düşüyor. Bu nedenle çok da kabul edilemez bir yöntem değil kanımca.

Peki optimizasyon olasılıkları bitti mi? Tabii ki hayır. Aklımda son bir versiyon daha var iyice işi karman çorman edecek ama CPU kullanımını düşürecek. Vakit bulduğum gibi deneyeceğim.

Çevrimdışı nightlord

  • RAAT
  • Tedavideki Retromanik
  • *
  • İleti: 389
    • Night Network
Ynt: Skate'in ZX Spectrum Maceraları - Vol 1
« Yanıtla #44 : 09 Mayıs 2022, 09:21:54 »
Sevgili @Skate

Bu başlık altında paylaştığın detaylı bilgilere, hak ettikleri derinlik ve dikkatle eğilmeye henüz vaktim olmadı. Sadece tarihçe ve geliştirme araçları bölümlerini ful okudum ve diğer mesajları hızlı-okudum. O yüzden, bu çabanın hak ettiği özende bir cevap veremeyeceğimi bilerek ve bu konuda affına sığınarak yine de bir şeyler söylemek istiyorum.

Bu yazılar benim için birkaç yönden inanılmaz değerli. Sevgili Matahari’nin yazılarında da söylediğim gibi, burada senin de bu yazıların sayesinde bir başka dünya çapında, ‘öncü’ Türk mühendisinin, öğrenme süreçlerinden oldukça da detaylı bir kesit görmüş oluyoruz. Burada, senin metodunu, problem çözmeye yaklaşımını, sorun çıktığında ne tepki verdiğini, nasıl aştığını, sabrını, deneyselliğini, desen tanıma yaklaşımını veya bildiklerinden nasıl güç alıp bilmediklerine saldırdığını adım adım görme şansı buluyoruz. Bu gerçekten inanılmaz zengin bir kaynak.

Ayrıca ben kendi adıma bencilce şu faydayı da görüyorum. Özellikle 6502 uzmanı birisinin Z80’e geçerken yaşadığı ‘mental model adaptasyonunu’ o kadar güzel dokümente etmişsin ki. Bir gün ben de Z80’de birşeyler kodlamak istersem, şu an biliyorum ki bu sırf senin sayende, senin bu yazın olmasa olacağından on kat kolay olacak belki.

Son olarak de senin bu yazın ve kodun bana şunu düşündürdü: Bazen uzun yıllar tanıdığımız ve samimileştiğimiz arkadaşlarımızın aslında ne kadar sıradışı insanlar olduğunu unutuyoruz. Bunun neden olduğunu açıklamak zor. Ama hani Skate’in benim kakara kikiri samimi bir arkadaşım olması, Norvax’ın ortaokulda beraber makara yaptığımız biri olması falan bana bu insanların aslında gezegende ince elekle köşe bucak gezsen belki karşına bir avuç zorla çıkan, ne kadar sıradışı, ne kadar ‘nadide’ insanlar olduğu gerçeğini gözden kaçırmama sebep oluyor. Yani daha az değer vermiyorum elbette, ama ne kadar değer verdiğimi de yeterince dillendirmiyorum galiba.

Velhasıl, sevgili dostum, burada benim için senin Speccy’de 700 küsur sine dot yapman elbette sürpriz değil. Bunu birkaç günde yapabilmen de sürpriz değil. Ama işte bu ‘şaşırmama’ ile takdiri hakkıyla dillendirmeyi birbirine karıştırmamak lazım.

Şu başlıkta yazdığın ve paylaştığın hem yazın hem kod, çok üstün bir yetenek ve birikimin ve çok temiz kalpli bir iyi niyetin sonucu, çok değerli, çok nadide. Eminim ki daha bu gördüklerimiz de senin daha sonra yapacaklarının yanında hiçbirşey.