commodore.gen.tr

Commodore => Commodore Yazılım => Konuyu başlatan: i_r_on üzerinde Mayıs 11, 2017, 02:21:30 ÖÖ



Konu Başlığı: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 02:21:30 ÖÖ
Elinizde data transferinde kullanabildiğiniz 8 bit bir port var. Bu port $80FF adresinde yer alıyor. Bu port aracılığıyla bir mikrokontrolcünün C64'e veri göndermesi söz konusu.
 

Kurallar
1. Transferi asenkron yapmak zorundasınız. Veriyi gönderen taraf ile alan C64'ün saatlerini eşitleyelim senkron transfer yapalım gibi bir imkanımız yok.
2. Veriyi gönderen tarafın veriyi nasıl kodlayacağı konusunda serbestsiniz.
3. Gönderen tarafın porttaki bilgiyi sizin kodunuza senkron bir şekilde değiştirdiği varsayımı ile hareket edebilirsiniz. Gerçekte asenkron olacak, yani her port okumanızda geçerli bir değer okuyabilmeniz için mikrokontrolcünün portu c64'ün okuyacağı kadar aynı değerde tutması gerekirken siz her okuma yaptığınızda mikrokontrolcünün yaptığı bir sonraki gönderimi okuduğunuzu varsayabilirsiniz.
4. Kod 128 byte'tan kısa olmalı.
5. Tüm C64 donanımını kullanabilirsiniz.
6. I/O bölgesindeki RAM'e veri aktarabilmelisiniz.
7. Transfer edeceğiniz verinin başlangıç adresi $0800 ($FB, $FC adreslerinde), Toplam sayfa sayısını ise F0 olarak alabilirsiniz. Yani $0800-F7FF aralığına yükleme yapılacak. $0801'e 256 byte yükleme yapıp run etmeniz yeterli. (Test için 256 byte bir demo kullanacağım)
8. VIC'in cycle çalmadığı ekran/sprite'ların kapatıldığı varsayılacak.
9. Kod başlangıçta rom'da olacak, ancak siz transferin yapılmadığı cassette buffer'a yazıyormuşsunuz varsayabilirsiniz. (Kaset buffer şu adres aralığında : $033C-$03FB)
Yüklenecek programın çalışmasına engel olmayacak şekilde kodu yazmak için istediğiniz adres aralığını kullanabilirsiniz. Başka bir yükleyicinin kodunuzu istediğiniz bellek aralığına attığını varsayabilirsiniz.

10. $80FF adresi rom üstündeki bir adres. $8000-$9FFF aralığını okuduğunuzda rom'u okursunuz. Yazdığınızda altındaki RAM'a yazarsınız.

Tüm datanın transferi için toplamda en az cycle tüketen çözüm kazanır.

Ödül : Kazanan transfer yöntemini kullanan bir adet imzalı IRQHack64 kartuşu.
Son cevap tarihi : 18 mayıs 2017

Ps : 8 bit alır alır yazarım basit çözümü aklınıza gelmesin. Net anlaşılması için örnek yavaş bir çözümü paylaşacağım.



Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: blackturk üzerinde Mayıs 11, 2017, 10:58:14 ÖÖ
heycanlandık.Yarışmacı arkadaşlara başarılar dilerim. :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: emarti üzerinde Mayıs 11, 2017, 11:23:32 ÖÖ
Veri transferi güzel konu. Şimdiye dek User Porttan Assembly ile led yakıp söndürmus biri olarak yavaş çalışan kodu merak ettim


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 11:39:16 ÖÖ
Veri transferi güzel konu. Şimdiye dek User Porttan Assembly ile led yakıp söndürmus biri olarak yavaş çalışan kodu merak ettim

Sizin yazacağınıza nispeten yavaş diyelim ona :) Ölçmedim ama saniyede rahat 20-30KB yapar herhalde yavaş olan da :)

Yavaş olan her seferinde 4 bit gönderim yapıyor.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: wizofwor üzerinde Mayıs 11, 2017, 15:01:46 ÖS
Gelen veri $0800'den başlayarak F7FF'ye kadar kopyalancaksa bizim port altta ($80FF) kalıyor. ::)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 15:08:56 ÖS
Gelen veri $0800'den başlayarak F7FF'ye kadar kopyalancaksa bizim port altta ($80FF) kalıyor. ::)

İki şeyi belirtmeyi unutmuşum. Düzenliyorum.

8. Kod başlangıçta rom'da olacak, ancak siz transferin yapılmadığı cassette buffer'a yazıyormuşsunuz varsayabilirsiniz.
9. $80FF adresi rom üstündeki bir adres. $8000-$9FFF aralığını okuduğunuzda rom'u okursunuz. Yazdığınızda altındaki RAM'a yazarsınız.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 21:53:16 ÖS
Anlaşılabilir olması için bahsettiğim 4 bitlik transfer rutini aşağıdaki gibi. Bu sadece 256 byte yüklüyor. Port'tan data stabil olsun diye yapılan ikinci okumalarda harcanan zaman sizin çözümler için hesaba katılmayacak. Data transferinden sorumlu olan ana loop'un harcadığı zamandan sorumlusunuz. Geri kalan kısım zaten devede kulak kalacaktır. Transferi senkron yapamamamızın sebebi anlaşılmıştır umarım.

Hız farkını yaratacak olan datayı nasıl sunduğunuz ve nasıl işlediğiniz.

Aşağıdaki örnekte önce low nibble sonra high nibble olmak üzere 4'er bit transferi yapılıyor.

Kod:
; Buradan daha üstte $01 portunun ayarlanması, VIC display'inin 
; ve interrupt'ların kapatılması var. Teferruat kod olduğu için
; çözüme dahil etmek zorunda değilsiniz.

TAPEBUFFER = $033C
CARTPORT = $80FF
TEMPSTORE = $FE
; Load stub
LDX #$00

ASYNCTRANSFER
-
LDA CARTPORT
BMI -

LDA CARTPORT ; Port tam set edilmemişken erişme durumunu bertaraf etmek için bir daha okuyoruz.
STA TEMPSTORE
-
LDA CARTPORT
BPL -

-
LDA CARTPORT ; Port tam set edilmemişken erişme durumunu bertaraf etmek için bir daha okuyoruz.
BMI -

LDA CARTPORT
ASL
ORA TEMPSTORE
STA TAPEBUFFER, X
-
LDA CARTPORT
BPL -

INX
BNE ASYNCTRANSFER

; Jump to the stub
JMP TAPEBUFFER


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 11, 2017, 22:25:27 ÖS
Tek ASL ile nasıl 4 bit kaydırdın ben onu çözmeye çalışıyorum. :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 22:28:30 ÖS
Tek ASL ile nasıl 4 bit kaydırdın ben onu çözmeye çalışıyorum. :)

Verinin mikro tarafından nasıl sunulduğu size kalmış :) 4 ASL yapmamak için 0XXXX000 şeklinde gönderiyorum high nibble'ı.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 11, 2017, 22:32:14 ÖS
Mikro tarafı yok. Biz var yalnızca software guru olmak. :)

Bana sorsan o zaman XXXX0000 olarak gönderirim, hiç ASL kullanmam. Ama olayın hardware tarafı canlanmıyor kafamda. Emülatörü yok bir şeyi yok. Teorik olarak yazacaksam iyice ıncık cıncık anlatacaksın detayları. Yoksa ben mal, ben anlamıor. :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 22:41:19 ÖS
Kabul anlaşılması biraz zor, makul bir şey yazması da.

C64'e veri gönderen meret 1Mhz'den yüksek bir saat frekansında çalışıyor. Sallıyorum 4Mhz olsun, sen portu okuduğunda o değiştiriyor olabilir. Ancak bir kere değiştirdikten sonra senin okuman için sana süre tanıyor. Yani değiştiğini gördükten sonra yaptığın okumalar port'a gönderilmiş doğru değeri veriyor.

Benim kodumda kullandığım porttaki değer negatif olduğu sürece bekle, pozitiften negatife dönene kadar bekle kısmını şablon olarak kullanıp donanım kısmını düşünmeyebilirsin. Bu tamamen aradaki senkronu tutturmak için kurduğum bir yapı.

Ben misal 4'er bit transfer ettim. Sayının negatif olduğunu anlamak için 7. bit yeterli halbuki, 7şer bit transfer etseydim mesela? Yahut 6'şar bit? Herhangi bir gönderilen bit sayısı için gönderimin bit sırasını da değiştirmem mümkün. Gönderen tarafta bit dizilimini değiştirmenin maliyetinin  ihmal edilebilir olduğu kabul edilmeli.

Üstteki C64 kodu için kontrol eden mikrodaki kodum aşağıdaki şekilde

Kod:
void CartInterface::TransmitByteAsync(uint8_t value)  {
  /* Cart software waits for data while page is negative */
  SetPage(0x80);
 
  /* Delay a bit to keep the pace */
  myDelay();
 
  /* Send the lower nibble as [0000XXXX], a positive value */
  SetPage(value & 0x0F);
 
  /* Delay a bit to keep the pace */
  myDelay();
  /* Cart software waits for data while page is negative */
  SetPage(0x80);
 
  /* Delay a bit to keep the pace */
  myDelay();
 
  /* Send the upper nibble as [0XXXX000], a positive value] */ 
  SetPage((value & 0xF0)>>1);
  /* Delay a bit to keep the pace */
  myDelay();
}


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 11, 2017, 22:48:08 ÖS
O zaman şöyle yapalım. Ben bu olayı adam gibi simüle edeyim. Elimde Arduino var. Arduino ile kendime simülatör yaratabilirim herhalde. Ne tavsiye edersin?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 11, 2017, 22:55:17 ÖS
Ben çözümü buldum sanırım. Vice ile daha önce çok oynaşmışlığım var. Vice'a telnet üzerinden memory'e dışarıdan data yazdıran bir script ile simüle ederim bu olayı. Hardware'e bulaşmadan temiz çözerim.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 22:59:49 ÖS
@Skate : Elinde IRQHack64 hali hazırda varsa elinde tüm imkan var aslında. Sorunun kaynağı da biraz benim kartuş. ESP8266 ile ilk denemeleri yaptığımda NMI interrupt gönderip transfer yapma çalışmayınca böyle bir yöntemi denemek istedim.

Elinde Usb2Ttl kablo varsa VCC hariç kartuşa bağlayıp, diğer tarafta da Arduino IDE'sini kullanabilirsin.

Kartuş üstündeki yazılımın source'ları şurada : http://www.tepetaklak.com/data/IRQHack64TurboSrc.zip (http://www.tepetaklak.com/data/IRQHack64TurboSrc.zip)

Daha temelden gideyim dersen Arduino uno / pro mini gibi bir 5v destekleyen arduino yeter.

Userport'taki CIA'in B portuna dediğim tarzda gönderim yapabilirsin. Basit olsun diye sürekli 0'dan 255'e artan değerler gönderirsin sallıyorum.

IRQHack64 source'larında Eprom'un A15..A8 bacaklarını kontrol ettiğim yöntemi örnek alabilirsin, hatta aynı bağlantıyı yapabilirsin.

C64'de çalıştıracağın programı da alışık olduğun yöntemlerle yüklersin böylece.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 11, 2017, 23:01:21 ÖS
Vice'a dışarıdan memory injection sanırım en pratiği olacak. Ne dersin?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 23:02:11 ÖS
Vice'a dışarıdan memory injection sanırım en pratiği olacak. Ne dersin?

Böyle bir imkan varsa kesinlikle daha kolay olur evet :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: wizofwor üzerinde Mayıs 11, 2017, 23:19:54 ÖS
Soruyu doğru anlamış olduğumu umut ederek derme çatma kodumu aşağıya kopyalıyorum.

Kod:
.const port 		= $80FF
.const startAddr = $0800
.const endAddr = $F7FF
.const tapeBuffer = $033C


/*
transfer rutinini kaset tamponuna kopyala
ve oraya atla
*/
selfCopy: {
!: ldx transferEnd-transfer
lda transfer,x
sta tapeBuffer,x
bne !-
jmp tapeBuffer
}

/*
transfer rutini
*/
transfer: {
// başlamak için porttaki değerin değişmesini bekle
firstByte:
lda port // 4
cmp port // 4
beq firstByte // 2 = 10 Cycle
bit $02 // 3
bit $02 // 3
bit $02 // 3
bit $02 // 3
bit $02 // 3
nop // 2
    jmp loop // 6 = 33 Cycle


wait:
bit $02 // 3
bit $02 // 3
bit $02 // 3
bit $02 // 3
nop // 2
nop // 2 = 16 Cycle

loop:
lda port // 4
sta tAddr:#startAddr // 4 = 8 Cycle

// adresi arttır
inc tAddr // 6
bne wait // 2(+1) = 8(9) Cycle
inc tAddr+1 // 6
lda >endAddr+1 // 4
cmp tAddr+1 // 4
bne loop // 2(+1) = 24(25) Cycle

// hedef addresi sıfırla
reset:
lda #>startAddr
sta tAddr
lda #<startAddr
sta tAddr+1
rts
}
transferEnd:


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 23:31:09 ÖS
@wizofwor : $02 adresinde hangi değer var?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: emarti üzerinde Mayıs 11, 2017, 23:37:29 ÖS
@wizofwor : $02 adresinde hangi değer var?
Ben de onu çözmeye çalışıyordum


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: wizofwor üzerinde Mayıs 11, 2017, 23:37:45 ÖS
BIT komutlarını sadece 3 cycle harcamak için kullandım. $02 adresindeki değerin önemi yok.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 11, 2017, 23:47:23 ÖS
BIT komutlarını sadece 3 cycle harcamak için kullandım. $02 adresindeki değerin önemi yok.

Cycle'lar bize lazım, niye harcadın? :)

Cevapla beraber gönderilecek bilginin sunumu ile ilgili de bilgi verirseniz süper olur. Mesela senin kodda değişimi algılıyorsun. Ya hiç değişmeyen bir veri akışı gelirse?

Şunu dersen ok, ben micro'dan her bir byte gönderimi için ekstra ondan farklı bir byte göndereceğim, bu sayede gerçek datayı ayıklayacağım.

Mantık bu herhalde senin koddaki değil mi?

ps:Busy waiting kısımları hesaplamanın dışına alabiliriz.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: blackturk üzerinde Mayıs 11, 2017, 23:57:26 ÖS
Bende kod yazmadım.ama pseudo olarak kodladım.

1 port değeri $ff mi hayır tekrarla
2 evet ise veri çekmeye başla
3 port değeri pozitif mi ?
4 okunan değerin 7 biti data buffer memory sakla
5 portu değerini oku pozitif ise tekrar 5 . Adım
6 evet negatif ise 7 bit data buffer memory sakla
7 buffer doldu mu ? Hayır 2. Adıma git
8 buffer datalarını 8 bit duruma getir.
9 programı bitir


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: emarti üzerinde Mayıs 12, 2017, 00:06:24 ÖÖ
$FB $FC gibi zero page kullanarak indirect indexed adresleme kullanarak verileri ilgili yere yerleştirerek @wizofwor 'un kodunu optimize etsek çok mu cycle harcar?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: wizofwor üzerinde Mayıs 12, 2017, 00:07:25 ÖÖ
kurmaya çalıştığım mantık şuydu:

- transfer kodunu kaset tamponuna at
- port adresindeki değer değişene kadar bekle
- değer değiştiği andan itibaren sabit hızaı kopyala
- kopyalama bitince hedef adresi resetle

Değer değişmesini sadece İlk başta senkronize olabilmek için bekliyor. Hatta o ilk değeri kopyalamıyor. Sonrasında her  33 cycle'da bir byte gelmesi lazım.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 00:13:17 ÖÖ
Vice'ın telnet interface'i çok buglı. Daha önce de başıma gelmişti benzer problemler. İlk komut düzgün gidiyor, sonrakilerde patlamaya başlıyor falan. Çözebilirsem düzgün bir simülasyonla test etmek istiyorum. Şimdilik unstable bir durum söz konusu.

Edit: İlk komutu remote monitör ile gönderiyorum, çalışıyor. Sonrakiler "ERROR -- Wrong syntax:" hatası veriyor. Sanırım Enter tuşuyla arası hoş değil arkadaşın.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 12, 2017, 00:13:29 ÖÖ
kurmaya çalıştığım mantık şuydu:

- transfer kodunu kaset tamponuna at
- port adresindeki değer değişene kadar bekle
- değer değiştiği andan itibaren sabit hızaı kopyala
- kopyalama bitince hedef adresi resetle

Değer değişmesini sadece İlk başta senkronize olabilmek için bekliyor. Hatta o ilk değeri kopyalamıyor. Sonrasında her  33 cycle'da bir byte gelmesi lazım.


Senkron yapı kuramıyoruz. Çünkü, bu 33 cycle'a tam senkron olamıyor karşı taraf.

@emarti : self modifying kod büyük transferlerde indirect indexed'den hızlı. biri. sırf saklama için bile biri 6 cycle yerken diğeri 5 cycle yiyor.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 00:53:52 ÖÖ
Vice'ın telnet interface'ini kullandığımda komutlar arasında 20 milisaniye geçmesini bekliyor. Bu durumda saniyede en fazla 50 byte transfer edebilirim. Bu şekilde olmadı kısacası. Aslında monitör'e remote olarak erişebildiğim için tek komutla çötenk diye tüm hafızayı doldurabilirim. Ama amaç byte byte transfer simüle etmek olduğu için bu yöntem işe yaramadı. :(


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 12, 2017, 00:55:46 ÖÖ
@Skate :  Şöyle de simüle edebilirsin, gönderimi yapan c64'de ön tarafta çalışan kod olsun. Bellekte belli bir adrese yazsın. Hatta yazarken yarım yarım yazsın.

Transfer rutini de interrupt rutini olarak çalışsın.

Ps: önemli olan loop'ta kaç cycle harcadığın. 500 byte transfer etsen de ölçüm için yeter.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 01:05:24 ÖÖ
Interrupt ile tam simülasyon yapamazsın. Yarım yarım bile yazsan interrupt rutini içinde çalışan kod interrupt dışından bölünemeyeceği için o şekilde işe yaramaz. Ancak CIA kullanıp sürekli yeni interruptlar üreterek belki benzer bir simülasyon yapılabilir. Yani interrupt içinde loop olmayacak da her bir byte yazdıktan sonra yeni bir interrupt tetiklenecek ve arada belli bir delay bırakılacak. Bana çok hoş bir yöntem olarak gözükmedi.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 01:24:41 ÖÖ
@i_r_on, mikroişlemci tarafındaki kodu tek byte gönderiyor şeklinde düşünmek sorunda mıyız? Yoksa örneğin 128 yada 256 byte gönderecek şekilde kurgulayabilir miyiz?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 01:28:26 ÖÖ
@delimawi: diyorsun ki byte'ı sıralı getirtmem. bit pairler halinde gelen bitleri bir buffer'a shift ede ede yolumu bulurum. :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 12, 2017, 01:30:03 ÖÖ
Burada amaç asenkron bir byte transferini optimize etmek. Microcontroller tarafı da hesaba katılmaya çalışılırsa işler karışır. Atmega328'in realtime hassasiyeti ile sallıyorum esp8266'nın yahut başka bir kontrolcünün hassasiyeti farklı olacaktır.

Kodu asenkron çalışmaya müsait yazıp senkronu sağlayan bekleme noktalarını ihmal etmek gerekiyor.

Ben bu şekilde bir rutini mesela önce yüksek bekleme süreleri ile deniyorum. Tatlı noktayı bulacak delay değerleri ile sonra uğraşıyorum. Burada amaç o tatlı değerlerin 0 olduğunu kabul etme üzerine. Ama kod asenkron transfer düşünülerek yazılacak.

Nmi senkronizasyonu ile mesela bir byte transferi page sınırları içinde 38 cycle civarı. Page aşılınca bunun biraz üstüne  çıkıyor. Ekstra sinyal kullanıldığı için daha hızlı olacağı düşünülebilir ancak interrupt'a girip çıkmanın da bir overhead'i var. Bu sorunun cevabı biraz da bunu bulacak.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 12, 2017, 01:34:12 ÖÖ
@delimawi : Senkron transfer söz konusu değil. Ama dersin ki, benim gönderdiğim data öyle encode edilmiş ki senkronizasyona ihtiyacı yok. Ben işlem yapıp ayıklayacağım. O olur.

Bu durumda da yine her bir burst için tatlı bir senkronizasyon gerekecektir ancak buffer bazlı asenkron denebilir.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 01:35:11 ÖÖ
@i_r_on, peki kodun uzunluğunu geçtim, memory usage limitimiz nedir? $0800-f7ff dışındaki hafızaya müdahele edebiliyor muyuz istediğimiz gibi? kod yine 128 bytedan kısa olacak ama ek hafıza kullanacak. uygundur di mi?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 01:44:23 ÖÖ
Kodu yazmadım ama algoritma şu şekilde. Olur dersen yazacağım.

bekle:
Port değişti mi?
Hayır, goto bekle

decode_sign++

Port 0 mı? Evet, goto bekle

deger=port xor decode_sign
goto bekle


Bu kodda amaç şu: uC her seferinde bir önceki byte'tan farklı bir deger göndermeli. Bu ayede receiver asenkron olarak yeni byte geldiğini anlıyor. Şöyleki decode_sign diye bir sayaç var. Bu iki tarafta da var ve 0 ile başlayıp gönderilen her byte için 1 artıyor. Gönderilen veri bu sayaç ile xorlanıp gönderiliyor. Öneğin arka arkaya 0 gönderilecek ise bile xorlanan deger değiştirildiğinden her seferinde byte değişiyor.

Püf nokta da şu, uC eğer yeni hesapladığı xorlanmış veri bir önceki ile aynı ise, ki olabilir, bir adet 0 gönderiyor. REceiver 0 görünce bunu discard ediyor, ama counter arttırılıyor, bir sonraki transferde xorlanmış değer artık 0 olamaz...

Son olarak ya gerçekten xorlanmış değer 0 ise ne olacak. Aynı mantık, uC 0 göndericek ama bir sonraki byte için tekrar aynı veriyi gönderecek bu sefer başka bir değer ile xorlanacağından 0 dışında bir değer elde edilecek.

Şimdi istatistik olarak tamamen aynı değeri içeren 256 byte transfer edilse, hiç bir xorlanmış değer bir önceki ile aynı olmayacak ancak bir adet 0 değer için ekstra bir byte gönderilecek. Yani kayıp oranı 1/256 ...

Eğer 1,2,3,4 ... şeklinde sıralı bilgi gönderilecek olsa sanki tamamı yeniden gönderilecek gibi geliyor ama ilk çakışmada xor counter değeri ile data pointer senkronu bozulmuş olacağından, sadece 1 adet tekrar veri + 0 için bir adet gönderim, 2/256 oluyor.

Bence verimli.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 12, 2017, 01:48:10 ÖÖ
@skate : İstediği kadar ram kullanabilir. Bir kısıt yok. 128 byte sınırı da öylemesine konulmuş bir sınır. Daha fazlasına daha hızlı bir çözüm varsa duymak isterim.

@delimawi : Evet bu çözüm olur


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 01:48:58 ÖÖ
Ancak benim anladığım porta bit bit yazıldığından bir atomic time problemi var burada. XOR ile gönderilen datada bu çözülmüş oluyor mu? Okunan değerde bir bit değişti ancak henüz diğer bitler değişmedi durumu yani.

Edit: Bunu i_r_on'ın "port tam set edilmemişken erişme durumunu bertaraf etmek için bir daha okuyoruz." commentinden çıkarım yaparak yazdım.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 01:52:19 ÖÖ
Aslında atomik ama gene de onu iron ikinci kez okuyarak çözmüş.
Bir bit bile değişse, port değişti/değişiyor demek. Tetiklenmek için yeterli.
İkinci okumada zaten net değeri alıyorsun.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 01:53:55 ÖÖ
Anladım, sonuçta yine 2. kez okuyorsun yani. Ok.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 01:59:48 ÖÖ
O kısma takılmayın demiş ya. Yani aslında örneğin benim kullandığım pic mikrolarda 8 bit birden aynı anda değişir. Ama böyle olmak zorunda değil. Misal donanım gereksinimlerinden ötürü 8 bit bilgi işlemcinin farklı port bacaklarından çıkıyorsa atomik olmaz. Yada 8 bitin kablo uzunluklarının yada empedanslarının farklı olmasından dolayı bile nano sn bazında farklılıklar oluşabilir. Bu da tam c64 örnekleme anına denk gelirse karışık bir değer okunabilir.

EDIT: @skate, bu arada ben uygun bir zamanda kodu yazar post ederim de, sen de dakikasında kodu kuşa çevirip atarsın... :) Korkuyorum. Hiç yazmasam mı...


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 12, 2017, 02:06:13 ÖÖ
Benim kodumda olan ikinci okumayı kodunuza koyabilirsiniz isterseniz ama cycle hesabında dikkate almayın. Uygulamada zaten işin içine bir miktar delay mikrokontrolcü tarafında girecek.

Pratikte bir bit değiştiğini anladıktan sonra yaptığınız okuma her zaman gerçek değeri verecek.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 02:09:52 ÖÖ
O zaman diyorsun ki

-
lda cartport
cmp cartport
beq -

ile bekletebiliriz bir nevi.

Edit: "bir nevi"nin nedeni bu kodun kullanılmayacak olması tabii ki. :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 02:50:09 ÖÖ
Teorik çalıştığım için test yapamadan gönderiyorum ulaştığım noktayı ama çalışır gibi duruyor.

Bitleri 7 bit - 1 bit şeklinde gönderiyoruz. Gönderen kod şu şekilde;

Kod:
void CartInterface::TransmitByteAsync(uint8_t value)  {
  /* Cart software waits for data while page is negative */
  SetPage(0x80);
 
  /* Delay a bit to keep the pace */
  myDelay();
 
  /* Send the upper 7 bits as [0XXXXXXX], a positive value */
  SetPage((value >> 1) & 0x7F);
 
  /* Delay a bit to keep the pace */
  myDelay();
 
  /* Cart software waits for data while page is negative
     with 8th bit value as [X000000X] */ 
  SetPage(0x80 | (value & 0x01));
  /* Delay a bit to keep the pace */
  myDelay();
}

C64 tarafındaki kod;

Kod:
; load stub
ldx #$00

asynctransfer
- lda cartport
bmi -
sta tapebuffer,x
- lda cartport
bpl -
lsr
rol tapebuffer,x

inx
bne asynctransfer

ROL sonrasında porttaki value hala negatif olacağı için ek bir kontrole gerek kalmıyor.

Gönderen koddaki ilk;

SetPage(0x80);

de sadece ilk gönderimde işe yarıyor. Kaldırılabilir ancak ilk giriş değeri olarak set edilmesi lazım.

Not: Delimawi'nin xor yöntemini kafamda canlandırdım, bundan çok daha efektif gözüküyor. Bu benim çözümüm olarak dursun kenarda, Delimawi'nin çözümünü bekliyoruz.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 12, 2017, 10:01:38 ÖÖ
Ödül belli oldu bu arada :)

Kazanan kendi transfer yöntemini kullanan bir IRQHack64 kartuşa sahip olacak :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 12, 2017, 10:33:24 ÖÖ
@i_r_on: Benim teori pratikte çalışıyor mu, denedin mi?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 12, 2017, 10:41:22 ÖÖ
@Skate : Akşam denerim. Gözle baktığımda çalışır gözüküyor.

Bir optimizasyon ipucu : 7. Bit 1 set edilerek gönderilen senkronizasyon byte'ına da veri koyabilirsiniz.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 10:57:48 ÖÖ
Ben proof of concept çalışmasını yaptım. Öngöremediğim bir exception oluştu ama çözdüm, aşağıda anlatacağım...

Peş peşe gelen encode edilmiş iki byte aynı olduğu zaman 0 basıyordum ya, burada sorun yok. Ancak bu işlemden sonra gelen byte da tesadüfen 0 olur ise, arka arkaya iki 0 basılmış oluyor. Benim her yeni gelen byte mutlaka bir öncekinden farklı olacak teorimi (self clocking data aslında bu) bozuyor... Ender olsa da karşılaştım bu durmla.

Çözüm olarak, placeholder olarak sadece 0 değil, hem 0 hem de 1 byte'ını kullandım. Placeholder koymak istediğimde, eğer bir önce bastığım byte 0 ise, bu sefer 1 basıyorum. Tabi bu durumda hem 0 hem de 1 değeri kullanılamaz oluyor. Yani 2/256 gibi bir fire mevcut. Bir de peş peşe gelen byte olasılığından dolayı bir overhead var, ortalamada istatistiksel olarak beklentim 3/256 byte şeklinde...

Bunu denemek için bir command line packer/unpacker yazdım. Gerçekte bu yazılıma ihtiyaç yok, encode işini uC yapacak decode işini C64...

Denemek için kullanımı:
Encode için > xorpck64 infile.prg
Decode için > xorpck64 -d infile.xor

Encode edince aynı isimli xor uzantılı bir dosya oluşturuyor. Bu dosyada arka arkaya gelen hiç bir byte aynı değil. (Bunu program ayrıca kontrol ediyor ve Sequence Check Passed yada Fail şeklinde bildiriyor.)

Decode edince de xor dosyasından bir prg dosyası üretiyor. Ama uzantı olarak prx kullandım ki, orjinal dosya bozulmasın, encode/decode sağlıklı yapılmış mı kontrol edebilelim...

Encoder Kodu: (Not bu pascal kodu ama mantığı anlaşılsın diye post ediyorum zaten.)

Kod:
    while not eof(f) do
    begin
      // Read a byte ...
      read(f,dta);

      repeat
        // Encode Byte ...
        res:=dta xor ctr;
        inc(ctr);

        // If the result is same with previous result,
        // or if the result is a placeholder, Encode not completed. Push a placeholder and re-encode the byte...
        done:=(res<>pdta) and (res<>0) and (res<>1);

        if not done then
        begin
          // Generate a non-repeating placeholder ...
          if pdta=0 then res:=1 else res:=0;
        end;

        // Push the byte ...
        if res=pdta then SeqCheck:=false;
        write(g,res);
        pdta:=res;

      until done;
    end;



Decoder Kodu:
Decode tabiki daha basit olacak şekilde optimize edildi. Zira asm ile C64 içinde koşacak bu kısım.

Kod:
    while not eof(f) do
    begin
      repeat
        // Fetch a byte And Decode it.
        read(f,dta);
        res:=dta xor ctr;
        inc(ctr);

        // Discard if a placeholder ...
        done:=(dta<>0) and (dta<>1);
      until done;
      write(g,res);
    end;

Bir kaç gerçek dosya ile deneme yaptım. Sonuçlar tabiki dosyaya göre değişiyor ancak ortalamada 1.9% gibi bir overhead gözlemledim. Eğer 7/8bit şeklinde bir encoding yapıyor olsa idik, %12.5 gibi bir overhead olacaktı ki, c64 tarafında 7/8bit decoding için yazacağımız code ve cycle da cabası. Bu yöntem byte based çalıştığı için bence çok daha efektif.

İlk uygun zamanımda c64 tarafını yazacağım...

EDIT: Tek dezavantajı, streaming işlerde byte/sn aktarım hızı sabit olmadığı için bazı projelere limon sıkıyor. Bir şekilde ayrıca buffer underrun, overrun kontrolü yapılarak çözülebilir.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 12:50:16 ÖS
Asm kodum da aşağıdaki gibi.

Kod:
	lda #$00
sta $ff
tax
tay

asynctransfer

- cpy cartport ; 4cyc/3byte Wait for a change on port
beq - ; 3cyc/2byte
inc $ff ; 5cyc/2byte increment xor counter

lda cartport ; 4cyc/3byte fetch new value ...
beq asynctransfer ; 3cyc/2byte if 0 discard byte
cmp #$01 ; 2cyc/2byte if 1 discard byte
beq asynctransfer ; 3cyc/2byte

tay ; 2cyc/1byte

eor $ff ; 3cyc/2byte Decode using xor counter
sta tapebuffer,x ; 5cyc/3byte Store to destination
inx ; 2cyc/1byte Increment destination pointer
bne asynctransfer ; 3cyc/2byte

Teorik olarak loop uzunluğu maks 37 cycle.
uC'nin delay kısmını es geçersek, max transfer hızı 27000Byte/sn gibi.
Encodingden gelen ortalama %2 overhead'i de ilave edince 22000Byte/sn hız ile yükleme mümkün...

Toplam kod 30byte civarı. Kod içerisindeki $ff herhangi bir zero page değişken.

Kesin daha kısası yazılabilir, hatta başlangıça destination adres ve uzunluk gönderilerek 256 byte üzeri yüklemeler de yapılabilir.

EDIT: Bu arada ilk cpy kontrolünden sonra, port değişince, lda ile port bir daha okunuyor. Aslında bu noktada optimizasyon için tya kullanılabilirdi ve aşağılardaki tay ye de gerek kalmazdı. Ama örnek koddadki ataomik olamama durumu yüzünden bu şekilde bıraktım.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 13:12:51 ÖS
Bir nebze daha optimize olanı. Tek kontrol ile 0 yada 1 mi karar veriliyor.
#11111110 ile andleyince 0 çıkıyorsa, ya 1 dir ya da 0 ... İkisi de placeholder.

Kod:
	lda #$00
sta $ff
tax
tay

asynctransfer

- cpy cartport ; 4cyc/3byte Wait for a change on port
beq - ; 3cyc/2byte
inc $ff ; 5cyc/2byte increment xor counter
ldy cartport ; 4cyc For atomic problem ...

tya ; 2cyc
and #254 ; 2cyc
beq asynctransfer ; 3cyc/2byte if 0 or 1 discard byte

tya ; 2cyc
eor $ff ; 3cyc/2byte Decode using xor counter
sta tapebuffer,x ; 5cyc/3byte Store to destination
inx ; 2cyc/1byte Increment destination pointer
bne asynctransfer ; 3cyc/2byte


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: wizofwor üzerinde Mayıs 12, 2017, 13:32:33 ÖS
Hız olarak delimawi'nin metoduna yaklaşabileceğini zannetmiyorum ama beklemesiz kodum aşağıda:

Çalışma mantığı verinin ilk önce 7. biti değiştirerek, ikinci defasında doğru değeri vererek iki kez gönderilmesine dayanıyor.

İlk gönderilen veri kontrol değeri oluyor. Program bu değer değişene kadar beklemede kalıyor.



Kod:
transfer: { 
// başlamak için porttaki değerin değişmesini bekle
read:
lda port
bmi wait_pl
wait_mi:
lda port
bpl wait_mi
jmp write
wait_pl:
lda port
bmi wait_pl

// değeri kopyala
write:
sta tAddr:#startAddr

// adresi arttır
inc tAddr
bne read
inc tAddr+1
lda >endAddr+1
cmp tAddr+1
bne read

// hedef addresi sıfırla
reset:
lda #>startAddr
sta tAddr
lda #<startAddr
sta tAddr+1
rts
}
transferEnd:


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 14:27:26 ÖS
@wizofwor, benim çözümüm efektif gibi görünse bile cycle bazında bakmak lazım. Yanlış saymadıysam benim kod 37cycle/byte. x1.2 overhead, totalde 44.5cycle/byte düşünülebilir...

Yani aslında her byte'ı senin çözümde olduğu gibi iki kere gönderip, %100 overhead'i göze alıp cycle bazında kısmak daha efektif sonuç verebilir. Senin çözümdeki byte/cycle oranı nedir, nehsapladın mı?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 12, 2017, 14:33:17 ÖS
Meselea aşağıdaki kod çok saçma gibi görünüyor, ilk aldığı veriyi doğrudan çöpe atıp ikinci aldığını yazıyor.

Kod:
-	lda cartport		; 4cyc/3byte Wait for a change on port
beq - ; 3cyc/2byte
- lda cartport ; 4cyc/3byte Wait for a change on port
beq - ; 3cyc/2byte

sta tapebuffer,x ; 5cyc/3byte Store to destination
inx ; 2cyc/1byte Increment destination pointer
bne asynctransfer ; 3cyc/2byte

Ama çok efektif, çünkü loop 24cycle/byte.
Gönderen yazılımın da her iki byttab birinin çöpe gittiğini bilerek, arka arkaya aynı byte gelmeyecek şekilde aralara random veri serpiştirmesi yeterli..

EDIT: Bu arada kodu yanlış yamışım, arada cmp cartport lar olacak unutulmuş...


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 13, 2017, 00:20:09 ÖÖ
Bu haliyle 32 cycle dersek memory'nin izin verdiği kadar unroll ederek 28.75 cycle ortalamaya düşürebiliriz.

Kod:
	ldx #$00
asynctransfer
!for i, 4 {
lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
sta tapebuffer+(i-1),x ; 5 cyc
}
txa ; 2 cyc
sbx #-4 ; 2 cyc
bne asynctransfer ; 3 cyc

Bu kod parçası 82 byte kaplıyor, geri kalan kod için 45 byte yer kalıyor. Tabii ki daha çok yer ihtiyacı olursa unroll edilen kısım 4'den daha az tekrara düşürülebilir.

Edit: Index kısmında ufak bir mantık hatası var. Az sonra düzelteceğim.

Edit 2: Düzelttim.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 13, 2017, 00:33:28 ÖÖ
Artık bunu yeni mesaj olarak yazayım. 20 kere editledim mesajı, özür. :) Son hali budur.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 13, 2017, 00:34:34 ÖÖ
Gerçi çoğunluk uymadı ama :) F7 blok transfer etme gereksinimini kaldırıyorum.

256 byte transferi benim de test etmem kolay.

Çözümlerinizin çalışıp çalışmadığını test etmek için düzeneği hazırlıyorum. Aslında kafamda esp'nin wireless özelliğini kullanıp programları web'den yükleme fikri de vardı ancak şimdilik kolay ama amele olan firmware'in içine gömme yoluna gideceğim.

Bu arada hangi assembler'ı kullandığınızı da yazarsanız süper olur.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 13, 2017, 14:51:27 ÖS
Ben compile etmeden teorik olarak yazdım ancak kullandığım format ACME'nin formatı. Şu anda KickAssembler kullanıyorum aslında ama 10 yılı aşkın bir süre ACME kullanmış olduğum için hızlıca yazarken o formata dönüşüyor kod bir anda.

Eğer ACME kullanacak olursanız aklınızda olsun, illegallerin çalışması için kodun başına;

Kod:
!cpu 6510

eklemeniz gerekir.

Kodun loop açılmış düz syntax'ı da şu şekilde

Kod:
	ldx #$00
asynctransfer
lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
sta tapebuffer,x ; 5 cyc

lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
sta tapebuffer+1,x ; 5 cyc

lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
sta tapebuffer+2,x ; 5 cyc

lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
lda cartport ; 4 cyc
- cmp cartport ; 4 cyc
beq - ; 3 cyc
sta tapebuffer+3,x ; 5 cyc

txa ; 2 cyc
sbx #$fc ; 2 cyc
bne asynctransfer ; 3 cyc

Kullandığınız editör "sbx" desteklemiyorsa "axs" de deneyebilirsiniz, bazen böyle geçiyor. Her ikisini de desteklemiyorsa "sbx #$fc" yerine;

Kod:
!byte $cb, $fc

ya da

Kod:
.byte $cb, $fc

deneyebilirsiniz. Birinden biri tutacaktır. :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 13, 2017, 23:32:18 ÖS
@skate, ben şöyle bir çözüm buldum, ne diyorsun?
NOT: Kod teorik, denenmedi...

Çözüm 8'lik bytelar halinde çalışıyor, hedef hiçbir şekilde arka arkaya glen iki byte'ın aynı olmaması. Bunu sağlamak için de encoder, 0. biti override edip devamlı olarak 0,1,0,1 ... şeklinde değiştiriyor. Yani 0. bit decoder tarafından kullanılamıyor. Amacı sadece synch pulse.

8 byte gönderildikten sonra bu 8 byte'ın gerçek LSB degerlerini iceren bir ekstra byte daha gönderiliyor.

Kod:
	lda #0			; 2cyc
ldx #32 ; 2cyc

loop:

; (8 kere tekrarla) = 16cyc * 8 = 128cyc

- cmp cartport ; 4cyc Port değişimini bekle ...
bne - ; 3cyc
lda cartport ; 4cyc Port degisti, degeri al,
sta buffer+n,x ; 5cyc yerine koy

; Simdi bu 8 byte'ın LSB bitleri bir byte olarak gelecek .... 13+8*9+2+5 = Toplam 92cyc

- cmp cartport ; 4cyc Port değişimini bekle ...
bne - ; 3cyc
lda cartport ; 4cyc Port degisti, A içerisinde önceki 8 byte'ın LSB degerleri var.
tay ; 2cyc Bunu şimdilik saklayalım çünkü port değişimi kontrolünde ihtiyacımız var ...

rol a ; 2cyc 7.biti Carry'e al
ror buffer+0,x ; 7cyc İlgili adrese yerleştir ...
rol a ; 2cyc 6.biti al
ror buffer+32,x ; 7cyc
rol a ; 2cyc
ror buffer+64,x ; 7cyc
rol a ; 2cyc
ror buffer+96,x ; 7cyc
rol a ; 2cyc
ror buffer+128,x ; 7cyc
rol a ; 2cyc
ror buffer+160,x ; 7cyc
rol a ; 2cyc
ror buffer+196,x ; 7cyc
rol a ; 2cyc
ror buffer+228,x ; 7cyc

tya ; 2cyc

dex ; 2cyc
bne loop ; 3cyc

Yanlış hesaplaması isem 27.5cyc/byte


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 13, 2017, 23:43:51 ÖS
Hatta bu versiyonu da 27.375cyc/byte

Kod:
	lda #0			; 2cyc
ldx #32 ; 2cyc

loop:

; 14cyc

- cmp cartport ; 4cyc Port değişimini bekle ...
bne - ; 3cyc
lda cartport ; 4cyc Port degerini al, bu sonraki 8 byte'ın gerçek MSB degeri olacak ...
sta $FF ; 3cyc Zero page'de dursun ...

; (8 kere tekrarla) = 25cyc * 8 = 200cyc

- cmp cartport ; 4cyc Port değişimini bekle ...
bne - ; 3cyc

lda cartport ; 4cyc Port degisti, degeri al,
rol $FF ; 5cyc Zero page'de duran MSB bit degiskeninin 7.bitini caarry'e al.
ror a ; 2cyc Carry deki deger A'ya kaydır ...
sta buffer+n,x ; 5cyc yerine koy
rol a ; 2cyc A'yı eski haline cevir ...

; loop control 5cyc

dex ; 2cyc
bne loop ; 3cyc


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 14, 2017, 02:22:31 ÖÖ
Test mekanizmasını kurmak epey uğraştırdı.

Şu an sadece ilk paylaştığım basit rutini ve Skate'in ilk paylaştığını test edebildim.

Öncelikle, ikisi de çalışıyor.

Skate'in ilk paylaştığı için mikro tarafındaki kod şöyle

Kod:
void CartInterface::InitCustomTransfer()  {
  /* Cart software waits for data while page is negative */
  SetPage(0x80);   
  delayMicroseconds(d1); 
  /* Enable cartridge so on restart rom code is executed */   
}

void CartInterface::TransmitCustomByteAsync(uint8_t value)  {   
  /* Send the upper 7 bits as [0XXXXXXX], a positive value */
  SetPage((value >> 1) & 0x7F);
 
  /* Delay a bit to keep the pace */
  delayMicroseconds(d2);
 
  /* Cart software waits for data while page is negative
     with 8th bit value as [X000000X] */ 
  SetPage(0x80 | (value & 0x01)); 
  /* Delay a bit to keep the pace */
  delayMicroseconds(d3);   
}

d1=0, d2=15, d3=3 tatlı noktası. d0 fasaryadan gerçi de, d2 ve d3 daha fazla azaltılamıyor.

mikronun portu set etmesi vesairesi ile beraber 256 byte için 8232 mikrosaniye sürdü. (sadece ana loop içinde geçirilen süreyi hesaplıyorum)

Test ettiğim kod şuydu.

Kod:
;------------------------------------------------ TEST BED	
; load stub
ldx #$00

asynctransfer
- lda cartport ;4
bmi - ;3
sta buffer,x ;5
- lda cartport ;4
bpl - ;3
lsr ;2
rol buffer,x ;7

inx ;2
bne asynctransfer ;3

;------------------------------------------------ TEST BED

Test için 256 byte demo a mind is born'u kullanmak mantıklı mı oldu bilemedim :)

Kurduğum mekanizmadan bahsedeyim.

Soruyu sorarken kod rom'dan çalışsın derken büyük hata etmişim. Zira ben bu test'leri yaparken rom'dan çalıştırmaya kalksaydım eprom yaz, dene, tekrar yaz sürecine girecektim. ESP8266 ile kartuşu ilk çalıştırırken elimdeki shift register'ların arızalı olmasından dolayı hali hazırda yaşadım bunu. Aslında kodda hiç değişiklik gerektirmeyen bu arıza yüzünden NMI olmadan transfer denemeleri yaptım. Onu geçtim yine aslında çalışan kodu sırf ekranı tekrar açmayı unuttuğum için çalışmıyor zannedip diye de bir sürü uğraştım. Her zaman yazdığım loop koduna mel mel ne sorunu olabilir acaba diye baktım anlayacağınız :)

Kartuşta şöyle bir mekanizma var, rom üstünde ilk yüklenecek programın adresi, uzunluğu vesaire transfer olurken ardından rom'daki kodun uzantısı olacak bir rutinin yüklemesi yapılıyor. Bu rutin kaset buffer'ına yükleniyor. Sonra da esas yüklenecek programın yüklemesi yapılıp bu rutine dallanılıyor.

Sizin transfer rutinleri için her seferinde eprom yazmayayım, kaset buffer'a yüklediğim rutin sizin transfer rutinleri olsun. Yüklenecek ana program da dummy 256 byte'lık bir şey olsun.

Sizin rutinlerinizin yükleyip çalıştıracağı da bir programa ihtiyaç var. 256 byte transfer edilmesinden sebep aklıma 256 byte bir demo çalıştırmak makul gözüktü.

Özetle şöyle oluyor.

1. Kartuş aktif hale getiriliyor, C64 resetleniyor
2. Eprom'daki stock rutinle 256 byte'lık dummy bir data yükleniyor. Stub loader olarak sizin transfer rutini de kaset buffer'a yükleniyor. (Rutinlerinizdeki data transfer ettiğiniz adresi kaset buffer değil $0801 olacak şekilde değiştirdim)
3. Kaset buffer'daki transfer rutininiz çalıştırılıyor. Zamanlama ölçümü düzgün olsun diye ESP8266'nın ram'ine yerleştirdiğim 256 byte'lık demo programın yüklemesi yapılıyor. Kartuş disable edilip program çalıştırılıyor.


Vakit buldukça diğer rutinleri de test edip her birini ayrı bir klasörde saklayacağım. Benim yaptığım test rutinin çalışıp çalışmadığının testi aslında. En düşük çalışma zamanı hangisinin diyebilmek için cycle saymak lazım.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 14, 2017, 20:28:51 ÖS
@delimawi: Senin versiyonunu inceleyecek vakit bulamamıştım. Şimdi inceledim, en süper çözüm bu olmuş. Tek sıkıntısı 8 kere tekrar eden blok tek başına 120 byte tutuyor. 128 byte'dan küçük olması kuralına uymak için loop eklersek de yavaş kalıyor. 128 byte üstü çözüm olarak en iyisi bu olmuş. Benim 128 byte üstü çözüm olarak aklıma gelen başka yöntemler de vardı (aralarında 16 bytelık 16 farklı adreste konumlandırılmış tablo içerenleri falan da vardı). Bunu 128 byte limitine sıkıştırmanın yolu bulunursa en ideal çözüm bu olacaktır.

edit: Bu arada ikinci gönderdiğinden bahsediyorum. İlkinde sanırım bir mantık hatası var. Gözle takip ettiğimde eksik kalan bir şeyler var.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 14, 2017, 21:08:00 ÖS
Bu arada bir soru, kaset buffer'ından veya daha gerideki bir adresten yüklenen ne kadar program vardır?

Pratikte kaset buffer'ı sonrasında default ekran belleği var. Sallıyorum $0801'den itibaren yüklenecek programlar için oraya kadar olan belleği kullanmanın bir sakıncası yok. İlaveten yükleyicide I/O kullanılmadığı için $D000'dan itibaren tüm 12k da kullanılabilir.

Diğer soru, kartuşta i/o altına ve kernal altına yükleme imkanı var ancak bunu kullanan prg program var mıdır?


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: eins üzerinde Mayıs 14, 2017, 21:36:05 ÖS
@skate, 120 byte olmuş mu yaw? Hiç aklıma gelmedi saymak nasılsa çok tutmaz dedim. 8 değil de 4 lü transfer eden birşeyler çıkar mı bakayım. Bu kadar efektif olmayabilir...

@i_r_on, ben bildiğim maksimum 50KB civarı en uzun prg dosyaları. 0801 den başladığını düşününce CFFF'e gelmeden bitiyor. Ama elimdekilere baktım, belki daha büyük IO ve KERNAL kısmına taşan da vardır.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 14, 2017, 23:13:18 ÖS
@i_r_on: Action Replay 6 $0340-$ffff aralığını sorunsuz bir biçimde kaydedip, yükleyebiliyordu. 254 block dosya kaydedip yüklettiğimi çok bilirim. Yani mümkün ama epey range kontrol eklemek gerekiyor tabii ki.


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 14, 2017, 23:39:43 ÖS
@i_r_on: Action Replay 6 $0340-$ffff aralığını sorunsuz bir biçimde kaydedip, yükleyebiliyordu. 254 block dosya kaydedip yüklettiğimi çok bilirim. Yani mümkün ama epey range kontrol eklemek gerekiyor tabii ki.

IRQHack64 1 portuna $33 yazıp yükleyebiliyor. Ama loader'ın kaset buffer'da olması yahut ekran hafızasına doğru taşması uyumluluk anlamında sıkıntı yaratır mı onu merak ettim. Pratikte diskten yüklenecek programın autorun etmesi için basic ile değil daha geriye kaydedilmiş olması lazım. Bu şekilde program da çok yoktur diye tahmin ediyorum. Benim kartuşta disk uyumluluğu olmadığı için olan programlar da benim kapsamıma girmiyordur.



Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: Skate üzerinde Mayıs 14, 2017, 23:50:19 ÖS
Çok standart değil ancak özellikle bazı (orjinal) oyunlar bu şekilde yükleme yaparlar. 0801'den değil de 0300'lerden yüklemeye başlarlar. Iron Lord aklıma gelen bir örnek. Yüklemeye tam 0400'den başlayarak ilk olarak ekrana bir şeyler yükleyen oyun, program da epey var. 0400 öncesinden başlayanların çoğu kendi loaderlarını install edip hızla kendi turbolarıyla yükleme yapma işine giriştikleri için çok uzun PRG'ler olmuyorlar. Yani adam 200 block değil 3-4 blockluk bir dosya yükletiyor o adreslerden, sonra o dosya run edip bin sonraki dosyayı yüklüyor. Block halinde $0340-$ffff arası PRG'ler benim eski çalışma disketlerimde bulunur en çok. Hafızada TASS, source code, assetler her şey yükletilmiş halde tüm hafızayı disketin ilk dosyası olarak kaydedip, sonrasında sadece değişen dosyalar, sourceların güncel hallerini kaydederdim. Bu nedenle 250+ block PRG manyağıdır benim eski source disketlerim. Çalışırken çok pratik oluyordu ama. İlk dosyayı yüklet, TASS'a gir, güncel source ya da asset varsa onları yüklet, kaldığın yerden işine devam et. Cross dev öncesi hayal gibiydi. Çalıştırdığımda source'unu ya da TASS'ı overwrite ediyorsa bir nevi mecburiyetti. :)


Konu Başlığı: Ynt: C64 Assembly kod yarışması - Ödüllü
Gönderen: i_r_on üzerinde Mayıs 15, 2017, 00:11:31 ÖÖ
O tip dosyalara destek verebilmek için her şeyi eprom'daki 255 byte'a (Sondaki 1 byte port değişkeni) sığdırmak lazım. Hız optimizasyonu yaparken yer optimizasyonu konusu geliyor, hiç girmeyelim :)