30 Ağustos 2014 Cumartesi

Load and Display Koala PIC format in C64 Assembler


Koala PIC Format

Koala Painter Values:
Bitmap = $2000-$3f3f
Video = $3f40-$4327
Color = $4328-$470f
Background = $4710



; koala pic viewer for C64
; (c) 2014 Aug 30
; Coded by emarti, Murat Özdemir

*=$0900        

VIDEO      = $3F40
COLOR      = $4328
BACKGROUND = $4710

        JSR $E544       ; CLEAR SCREEN

        LDA #$00
        STA $D020       ; BORDERCOLOUR

        LDA BACKGROUND        
        STA $D021       ; BACKGROUNDCOLOUR

        LDA #$3B        ; bitmap mode on
        STA $D011

        LDA #$18        
        STA $D018       ; set bitmap address($2000) and screen($0400) 
        STA $D016       ; multi color on

        LDA #$03        ; set vic bank
        STA $DD00
        
        LDA #$40        ; set video ram
        STA $FB
        LDA #$3F
        STA $FC
        LDA #$04
        STA $FE
        LDA #$08
        STA VALBYTE
        JSR SET
        
        LDA #$28        ; set color ram
        STA $FB
        LDA #$43
        STA $FC
        LDA #$D8
        STA $FE
        LDA #$DC
        STA VALBYTE
        JSR SET

XXX     JMP XXX

; function move bytes
VALBYTE  BYTE $00

SET     LDY #$00
L1      LDA ($FB),Y
        STA ($FD),Y
        INY
        BNE L1
        INC $FC
        INC $FE
        LDX $FE
        CPX VALBYTE
        BNE L1
        RTS


Ne Mutlu Türküm Diyene!

27 Ağustos 2014 Çarşamba

Basic LIST'den Başlangıç Adresini Saklamanın Yolu

LIST komutu ile başlangıç adresi gizleme

Aslında makina dilini bilenler için etkin bir yöntem olmasada görsel olarak etkileyebiliyor. BASIC içinde bildiğiniz üzere LIST komutu ile programın dökümü elde edilir ki assembler ile kodlanmış bir program ise BASIC ile aktif hale getirilmek istenmişse genelde şu şekilde liste elde edilir.

READY.
LIST <return>

2014 SYS 2064: REM EMARTI.BLOGSPOT.COM

Peki bu komutu kullandıktan sonra sadece şu şekilde görünmesi hoşunuza gitmez miydi?

READY.
LIST <return>

2014 EMARTI.BLOGSPOT.COM

Ve bu RUN komutu verip çalıştırdığınız zaman hiçbir farklılık ile karşılaşmayacağınız bir durum olacak. SYS ile nereye dallanmak istiyorsa oraya gidecek ve makina dili programınızı çalıştıracak.

Kritik nokta ASCII kodlarından $14 (DEL).

Basic'te program yazıp saklamaya başladığınızda, başlangıcı bilindiği üzere $0801'dir (C64'te). 

Aşağıdaki örneği derleyin ve çalıştırın, LIST komutu verin. Sonra Monitor programınıza girip M 0801 0840 komutunu verip baytları inceleyin.

; 2014 SYS2080:REM 64738
; 2014 SYS 64738

*=$801

        BYTE    $1B, $08, $DE, $07, $9E, $32, $30, $38
        BYTE    $30, $3a, $8f, $14, $14, $14, $14, $14
        BYTE    $14, $14, $14, $20, $36, $34, $37, $33
        BYTE    $38, $00, $00, $00

*=$0820
        NOP     ; No Operation
        RTS     ; Basic'e dön
 
Programın başlangıç adresi aslen $0820=2080'tür. Basic'ten SYS 2080 ile çağrılır. Programın dökümünde ise SYS 64738 listelenmektedir. Normalde SYS 64738 yazıp returne basarsanız makina reset atar. Ama böyle görünmesine rağmen RUN ile SYS 2080'e dallanıp program çalışmaktadır. 


$0801 - $0802'deki  1b 08 baytları $081b 'ye kadar BASIC satırını okuyacağını belirtir.
$0803 - $0804'deki de 07 baytları BASIC satır numarasını verir. Bu örnekte $07de=2014.
$0805 9E BASIC komut karşılığı SYS'dir.
$0806 32 30 38 30 sıralı baytları ASCII kodlamasıyla SYS'den sonra 2080 yazar
$080A 3a ise : karşılığıdır.
$080B 8f Basic'te REM
$080C'den itibaren başlayan $14'ler ise DEL tuşuna basar işlev görür. Sonrası baytlar 64738 yazar.
8 tane $14 baytı DEL tuşuna 8 kere basılmıştır anlamına gelir SYS sonrasına kadar herşeyi siler görünür. Daha doğrusu BASIC'ten böyle görünür.



26 Ağustos 2014 Salı

C64 Rutinlere Devam

C64 Rutinlere Devam

Daha önceki blog girişlerinde ekranı silmek için BASIC'teki

PRINT CHR$(147)

komutu karşılığı

LDA #$93
JSR $FFD2
RTS

kullanmıştık. Ama daha kolay bir rutin var $E544. Örneği inceleyin.

; 10 SYS2176

*=$801

        BYTE    $0B, $08, $0A, $00, $9E, $32, $31, $37, $36, $00, $00, $00



*=$0880

        
basla   JSR $E544       ; ekranı sil
        
        LDX #$00        ; ekrana mesaj adresindeki texti yaz
dongu   LDA MESAJ,X
        STA $0428,X
        INX
        CPX #$27
        BNE dongu


bekle   LDA $DC01
        CMP #$EF        ; space veya fire tuşuna basana kadar bekle
        BNE bekle
        
        RTS             ; BASIC'e dön

mesaj   TEXT    'space tusuna basarak programi sonlandir'

Daha önce GETIN kernal rutinini klavye tamponundan karakter (ASCII) yakalamak için kullanmış ve akumulatore aktarıp işlem yapmıştık. Burada $DC01'deki değere göre space veya ateş tuşuna basılana kadar bekliyor.

$DC01 aslında PORTB yani joystick#1'e ait bitleri okuyabildiğimiz adres. Şöyle ki:
Örneğimizde CMP#$EF ile akumulatorü karşılaştırdık. 
$EF yi ikilik düzende yazarsak %11101111, burada sağdan saymak ve sıfırdan başlamak üzere 4. bitin 0 olduğunu görürüz. Yani burası FIRE (Ateş) yada SPACE tuşuna basıldığının bit karşılığıdır. Peki diğer bitler ne işe yarar?

0. bit YUKARI (UP)
1. bit AŞAGI (DOWN),
2. bit SAĞ (RIGHT)
3. bit SOL (LEFT)
4. bit ATEŞ, BOŞLUK TUŞU (FIRE, SPACE)

Burada dikkat ettiyseniz aktif olan bit 0 oluyor.

25 Ağustos 2014 Pazartesi

Load Windows on C64 :)

C64'te 8 bit ile DOS ekranı hem de Windows klasöründe

Başlığa bakarak bunun mümkün olmadığını düşünüyor olabilirsiniz. Derleyin ve görün demekten başka bir delil sunamıyorum.

Bu sefer ekran belleği ve renk ramını kullanmayı, zamanlama döngüsünün nasıl oluşturulacağı hakkında bilgi edinecek ayrıca disketteki başka bir programı assembler ile nasıl hafızaya yükleyebileceğinizi öğreneceksiniz.

Şöyle düşünün: Disketteki LOAD"*",8 komutu ile ilk programı yükleyip çalıştırıyorsunuz. Diyelim ki bu bizim boot edici prg olsun. Bunun içinden de dos'u yükleyip windows klasörüne ulaşalım :) İnanılmaz değil mi?

Hadi kodlamaya...

CBM Prg Studio programı ile yeni bir assembler projesi oluşturun boot.asm dosyası içeriği ve açıklamaları aşağıdadır.

; 10 SYS2176:REM emarti.blogspot.com

*=$801

        BYTE    $22, $08, $0A, $00, $9E, $32, $31, $37, $36, $3a, $8f, $20, $45, $4D, $41, $52, $54, $49, $2E, $42, $4C, $4F, $47, $53, $50, $4F, $54, $2E, $43, $4F, $4D, $00, $00, $00



*=$0880

; kernal rutinler
SETLFS = $FFBA  ; mantıksal, birincil ve ikincil adresleri yerleştir
SETNAM = $FFBD  ; dosya ismi ver
LOAD   = $FFD5  ; cihazdan RAM'a yüklemek
GETIN  = $FFE4  ; klavye tamponundan karakter al
CHROUT = $FFD2  ; kanaldan karakter çıkışı
        

        LDA #$93        ; ekranı sil
        JSR CHROUT
        
        LDA #$0E        ; küçük harf moduna geç
        JSR CHROUT

        LDY #$00        ; ekrana mesaj adresindeki texti yazar
LOOP    LDA mesaj,Y
        STA $0429,Y
        LDA mesaj2,Y
        STA $0451,Y
        INY
        CPY #$19
        BNE LOOP

BEKLE   JSR GETIN       ; bu rutin klavye kuyruğundan bir karakter alır
        CMP #$4C        ; bu değer ASCII olarak a'ya yüklenir.
        BNE BEKLE       ; 'L' tuşuna basılana kadar bekle 

; Load"WINCMD",8 komutunun icrası

        LDA #$01        ; file#1
        LDX #$08        ; sürücü 08 (disket)
        LDY #$0F        ; ikincil adres
        JSR SETLFS

        LDA #$06               ; dosya adının uzunluğu
        LDX #<PROGRAMADI       ; dosya adının bulunduğu adresin
        LDY #>PROGRAMADI       ; x ve y registerlerine kaydı
        JSR SETNAM

        LDA #$00        ; a yükleme işlemi için mutlaka 0 olmalıdır
        LDX #$00        ; programın başlangıç adresininin x ve y registerine
        LDY #$C0        ; alt üst bayt olarak atanması ($C000)
        JSR LOAD

        JMP $C000       ; yüklenen programı çalıştır.
        RTS

PROGRAMADI TEXT         'WINCMD'
mesaj      TEXT         'Windows Komut istemi icin'
mesaj2     TEXT         'L tusuna basiniz         '

boot.prg programımız hazır. Şimdi de wincmd.prg programını oluşturmalıyız ki boot programı ile yüklenecek ve çalıştırılacak. Bu iki programın mutlaka aynı disket içine kaydedilmesi gerekmektedir. Dikkat edin ki boot $0801'den itibaren hafızaya yüklenir, wincmd programının başlangıç adresi ise $C000'dır.

Yeni bir assembler projesi oluşturun. wincmd adındaki projenin wincmd.asm dosya içeriği aşağıdaki gibidir. Derleyin ve aynı diskete kaydedin (ya da d64 image dosyasına).

wincmd.prg kaynak kodları:

; XP içinden dos açılış ekranını andıran program
; Linux daha iyi olurdu ama :)


*=$C000

basla   LDA #$00        ; çerçeve ve arkaplan rengi siyah yapalım
        STA $D021
        STA $D020
        
        LDA #$93        ; ekranı sil
        JSR $FFD2

        LDA #$01        ; cursor rengi beyaz olsun
        STA $0286

        LDA $D018       ; küçük harf moduna geç
        ORA #$02
        STA $D018
        
        LDX #$00        ; ekrana M1, M2 ve M3 adreslerinde kayıtlı texti yaz
dongu1  LDA M1,X        ; aslında burada FFD2 veya AB1E rutinleri kullanılabilir
        STA $0400,X     ; Ekran Belleğinin kullanımını göstermek için
        INX             ; böyle kodlamak istedim. 
        CPX #$25        ; Ekran belleği varsayılan olarak $0400'dan başlar ve
        BNE dongu1      ; 1000 baytlık (40x25 karakter) boyutundadır.

        LDX #$00
dongu2  LDA M2,X
        STA $0428,X
        INX
        CPX #$1D
        BNE dongu2

        LDX #$00
dongu3  LDA M3,X
        STA $0478,X
        INX
        CPX #$0B
        BNE dongu3

        LDX #$00
dongu4  LDA #$01
        STA $D800,X     ; Renk RAM'ını kullanarak karakterlerin rengini
        INX             ; beyaz yapalım. (Akumulatorun değeri $01)
        BNE dongu4      ; Renk RAM'ı $D800-$DBE7 arasında 1000 baytlıktır

        LDX #$00
dongu5  LDA CURSOR,X    ; X 0 ve 1 arası değerden başka değer almamalı
        STA $0483       ; cursor yanan sönen değeri basılır
        INX             ; x = x + 1
        TXA             ; a = x
        AND #$01        ; a = a AND 1
        TAX             ; x = a
        JSR BEKLE       ; bekleme döngüsü
        JMP dongu5 

BEKLE   LDY #$00        
X       LDA $D012       ; raster satırını oku ve 255 olana kadar x'e dallan
        BNE X
        INY
        CPY #$80        ; y $80 olana kadar x'e dallanır
        BNE X
        RTS        
        
; 1. satır içeriği
M1      BYTE    $4D,$09,$03,$12,$0F,$13,$0F,$06
        BYTE    $14,$20,$57,$09,$0E,$04,$0F,$17 
        BYTE    $13,$20,$58,$50,$20,$1B,$42,$15 
        BYTE    $09,$0C,$04,$20,$35,$2E,$31,$2E
        BYTE    $32,$36,$30,$30,$1D
        
; 2. satır içeriği
M2      BYTE    $28,$43,$29,$20,$31,$39,$38,$35
        BYTE    $2D,$32,$30,$30,$31,$20,$4D,$09
        BYTE    $03,$12,$0F,$13,$0F,$06,$14,$20
        BYTE    $43,$0F,$12,$10,$2E

; 4. satır içeriği       
M3      BYTE    $43,$3A,$2F,$57,$49,$4E,$44,$4F
        BYTE    $57,$53,$3E

CURSOR  BYTE    $64, $60

Aslında wincmd programını kodlarken ekran belleği ve renk ramını kullanmayı gördünüz. En önemlisi belkide raster line kullanarak ($D012) bekleme döngüsü hazırladık ve bunu cursorun yanıp sönmesi için kullandık.

Bu arada telif hakkına saygı gösterip C: sonrası / (slash) koydum. Küçük harf modunda ters slash yoktu. Bill Gates ne me lazım yamuk yaparsa diye bir önlem ...

Bu arada d64 image dosyası oluşturup kolayca dosya eklemek, silmek vb.işlemler için DirMaster 3.0 kullanıyorum. http://style64.org/release/dirmaster-v3.0.0-style adresinden ilgili Wİndows sürümünü indirebilirsiniz. 



İki programın da aynı diskette olması önemli. emartiblogspot.d64 imajlı disketi buradan download edebilirsiniz. 

Aşağıdaki görüntüler gösteriyor ki C64'e herşey yüklenebilir.

Disket içeriği

boot.prg

wincmd.prg


24 Ağustos 2014 Pazar

$FFD2 (CHROUT)


$FFD2 (chrout) kernal rutini

Çıkış kanalına ki bu varsayılan olarak ekran oluyor bir bayt gönderir. Örneğin şu basic satırını hatırlayın.

print"<shift><clr-home>"

Ekranı tamamen siler. Bunu assembler olarak kodlamanın bir yolu da şöyledir:

LDA #$93
JSR $FFD2
RTS

Aşağıdaki program kodlarını cbm prg studio'da derleyebilirsiniz.

; 10 SYS2080

*=$801

        BYTE    $0B, $08, $0A, $00, $9E, $32, $30, $38, $30, $00, $00, $00

*=$0820

chrout=$FFD2

        LDX #$00        ; X=0
DEVAM   LDA mesaj,x     ; mesaj adresindeki veriyi x'deki değişime göre al
        JSR chrout      ; çıkış kanalı default ekrana yazdır
        INX             ; x = x + 1
        CPX #$12        ; x 18'e eşit değil ise devam'a dallan
        BNE DEVAM
        RTS

mesaj   byte $0e, $93 ; küçük harf moduna geç ve ekranı sil
        byte $cd, $45, $52, $48, $41, $42, $41, $a0 ; Merhaba Dostum
        byte $c4, $4f, $53, $54, $55, $4d, $0d, $0d


Dizi Yazdırma $AB1E (strout) BASIC rutini


Dizi Yazdırma

CBM Prg Studio ile yeni bir assembler projesi oluşturun. ASCII kodları ile ekrana diziyi yazdıran $AB1E (strout) basic rutinini kullanmayı öğreneceğiz. Bu dizi mutlaka $00 ile sonlandırmalıdır. Yoksa $00'ı buluna kadar yazıyor deli dumrul :)

Diyelim ki yazdırmak istediğiniz mesaj yada text adresi $4580'da olsun.

.M 4580 CD 45 52 48 41 42 41 00 

strout basic rutinini kullanabilmek için mesaj içeriğinin başlangıç adresi olan $4580'nin alt ve üst byte olarak A ve Y registerlerine atamalı sonra rutini çağırmalıyız. A registerine alt, Y registerine ise üst byte tanımlanmalıdır.

Aşağıdaki kodları IDE içine yazıp derleyin. Çabuk sonuç için emulator kullanabilirsiniz. IDE ayarlarından emulator ayarlarını yaptıktan sonra CTRL + F5 ile kolaylıkla derleyip sonucu görebilirsiniz.

; String output
; strout $AB1E basic rutini

*=$0820 ; başlangıç adresi

strout    = $AB1E 

;        LDA $D018       ; küçük harf moduna geç
;        ORA #$02
;        STA $D018

        LDA #<mesaj     ; mesaj adresinin a ve y için tanımlanması
        LDY #>mesaj
        JSR strout      ; diziyi yazdır
        RTS             ; basic'e dön (programı bitir)

mesaj   byte $0e, $93 ; küçük harf moduna geç ve ekranı sil
        byte $cd, $45, $52, $48, $41, $42, $41, $a0 ; Merhaba Dostum
        byte $c4, $4f, $53, $54, $55, $4d, $0d, $0d
        byte $00

; mesajın sonu mutlaka $00 ile bitmelidir                   
; mesaj ASCII kodları ile yazılmalı          


23 Ağustos 2014 Cumartesi

C64 (Commodore 64) 6510 (6502) Assembler

6510 (6502) Assembler

Zaman buldukça C64 üzerinde isterseniz emulatorlerinde de deneyebileceğiniz assembler kodlarını paylaşmaya çalışacağım. Ne biliyorsam onu yazacağım için aşırı teknik ayrıntılara dalmadan kodların ne işe yaradıklarından da bahsedeceğim.

İlk öğrendiğim assembler olduğu için (ilk aşklar unutulmaz misali) ayrı bir yeri var benim için. Zamanında elimize aylık çıkan Commodore dergisinden başka kaynak yoktu. Bu dergiyi satır satır okuya okuya, o demo benim şu intro senin deyip kodlarını multi ice kartuşları ile kırarak öğrenmeye çalıştığımız makina dili. Bu dili sevmemin nedenlerinden biride donanımı yazılım ile evirip çeviriyorsunuz bunun zevki 64 bitlik i7'de bile yok emin olun. Bana 1 ve 0'ları sevdiren C64'e sonsuz teşekkürler.

Kodlamaları http://www.ajordison.co.uk/ adresinde bulunan cbm prg studio adlı Windows üzerinde rahatlıkla derleyebileceğiniz ide ile yazmayı uygun buldum. Buradan elde edilen p00, prg uzantılı dosyaları isterseniz direkt emulatorlerde deneyebilirsiniz. 


Gerçek C64'te denemek için benim tercihim d64 formatını kullanmak üzere e-bay.com 'dan satın aldığım 1541 drive taklitçisi SD2IEC emulator cihazıhttp://www.sd2iec.co.uk/id14.html sitesinde özelliklerini öğrenebileceğiniz cihaz fiyat olarak uygun ve yeterli düzeyde. 



Sipariş sonrası İngiltere'den 10 gün içinde elime ulaştı. Tek eksiği (pek de eksik sayılmaz bana göre) turbolu kayıt yapamaması. Bu da zaten sd2iec cihazlarının genel özelliği ama ileride yeni firmware sürümleri ile çözebilirler mi bilmem.

Neyse kodlamaya hazır mıyız?