Retrojen Forum

Retro Sistemler => Amstrad => Konuyu başlatan: Fero - 24 Kasım 2018, 04:15:10

Başlık: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 24 Kasım 2018, 04:15:10
Birkaç gün önce sevgili Alcofribas 'ın beni "Yan dal olarak CPC 'ci" diye tanımlamasıyla gaza gelip, "CPC 'de çalışacak birşeyler yapmalıyım!" diyerek Winape 'i açıp bir hışımla F3 'e bastım! Unity ile anlaşabilecek kadar C# ile C64 'de ekrana renkli yazı ve petscii koyabilmekten ibaret olan muhteşem(!) programcılık altyapım ile yaptığım pixel artları CPC 'de görüntülemek o kadar da zor olmasa gerekiyordu...

Ancak, işte kazın ayağı öyle değilmiş :)

Başta register'lar flag'lar falan derken herşey anlaşılır gibi görünse de, iş ekranda bir görsel oluşturmaya gelince beynim ufaktan arıza sinyalleri vermeye başladı. İlk önce anlam veremediğim bir şekilde ekranda görsel oluşturmak ile ilgili hangi taşın altına bakarsam bakayım, ya C ile Asm rutinlerini birlikte kullanmaktan, ya da görselleri SCR formatına dönüştürerek, LOAD"FILENAME.SCR",&C000 şeklinde belleğe almaktan bahsediliyordu. Ancak bunlar tam olarak aradığım şey değildi.

Yapmak istediğim şey bitmap'i bir şekilde kodun içine gömerek istediğim anda bir loopu çağırarak ekrana verebilmek. Örneğin aşağıdaki gibi bir görseli ele alalım. Sonradan üzerine müzik, yazı vs ekleyip bazı demo efektlerinde kullanabilmek için görseli SCR olarak dışarıdan yüklemek bana pek doğru ya da optimize bir yöntem değilmiş gibi geliyor. (öyle değil mi?) Bunun için nasıl bir yöntem izlemek daha doğru ya da daha optimize olur?

Konuyla ilgili üstatlardan yönlendirme talep ediyorum :)

Şimdilik cpcrulez.fr 'deki makaleleri google translate ile çevire çevire bakınıyorum. Henüz donanımın mimarisi ile ilgili ve makine dili konusunda temel seviyede bile bilgi sahibi değilim ancak coderlığa soyunmak gibi bir niyetim olmadığından şimdilik işimi görecek kadarıyla yetinmek en mantıklısı :)

Şimdiden teşekkürler.

(https://i.ytimg.com/vi/t8VcI7hA_so/hqdefault.jpg)




Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Ref - 25 Kasım 2018, 12:39:30
ben spectrumcuyum fakat aynı familyanın aletleri olduğu için yardımcı olabilirim. Yine de yanlış bir yönlendirme yapmamak için önce matahari ve alco'ya lafı bırakmak istiyorum.

Temel olarak, bir assembler ile (ben pasmo kullanıyorum) scr dosyasını include edip, zamanı gelince de veriyi ram'de uygun bir yere (ekran tamponuna) kopyalamaktan ibaret o iş.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 25 Kasım 2018, 14:44:26
Merhabalar,

Öncelikle Retrojen Forum'a hoşgeldiniz!

Temel olarak, bir assembler ile (ben pasmo kullanıyorum) scr dosyasını include edip, zamanı gelince de veriyi ram'de uygun bir yere (ekran tamponuna) kopyalamaktan ibaret o iş.

Ref'e katılıyorum. SCR dosyası illaki ekran adresine yüklenecek diye bir kural yok. Bu dosyayı hafızanın istediğiniz yerine yükleyebilirsiniz.

Örneğin, bu işi BASIC'te şu şekilde yapabilirsiniz:

Kod: [Seç]
MEMORY &3FFF
LOAD "FILENAME.SCR", &4000

Aynı işlemi WinAPE Assembler içerisinde yapmak için incbin (include binary) direktifini kullanabilirsiniz.
(bkz: http://www.winape.net/help/assembler_directives.html (http://www.winape.net/help/assembler_directives.html))

Yapmak istediğim şey bitmap'i bir şekilde kodun içine gömerek istediğim anda bir loopu çağırarak ekrana verebilmek.

Madem başlangıç seviyesinde Z80 Assembly language kullanıyorsunuz, o zaman LDIR komutu ile yola çıkabilirsiniz.

Kod: [Seç]
LD HL, $4000       ; Yukarıdaki örnekte kullandığımız tampon adres
LD DE, $C000       ; Amstrad CPC 464/664/6128 için ekran adresi
LD BC, 16384       ; Kopyalanacak byte sayısı
LDIR

Elbette bu çözüm demo/oyun geliştirimi için çoğu kez yeterince hızlı değil. Ancak, işin mantığını kavrayabilmeniz açısından bir yerden başlamak gerekiyor. Kişisel görüşümce Z80 Assembly kodlamaya LDI, LDD, LDIR, LDDR, vb. komutlarla başlamanız faydalı olacaktır.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 25 Kasım 2018, 15:34:46
ben spectrumcuyum fakat aynı familyanın aletleri olduğu için yardımcı olabilirim. Yine de yanlış bir yönlendirme yapmamak için önce matahari ve alco'ya lafı bırakmak istiyorum.

Temel olarak, bir assembler ile (ben pasmo kullanıyorum) scr dosyasını include edip, zamanı gelince de veriyi ram'de uygun bir yere (ekran tamponuna) kopyalamaktan ibaret o iş.

Aslında bende öyle tahmin ediyorum ancak garip bir şekilde buna benzer bir örnek bulamayınca "acaba yanlış yolda mıyım?" diye bir şüpheye düştüm. Tabi şu anda yapmaya çalıştığım şey işi temelden öğrenmeye çalışmaktansa örnekler bulup oralardan mantığı anlamaya çalışarak kolaya kaçmak. O nedenle muhtemelen bir şeyleri kaçırıyorumdur. Sen söyleyince aklıma spectrum ile ilgili kaynaklara bakıp oradan fikir edinmek geldi. Biraz daha kurcalayayım :)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 25 Kasım 2018, 15:57:25
Merhabalar,

Öncelikle Retrojen Forum'a hoşgeldiniz!

Ref'e katılıyorum. SCR dosyası illaki ekran adresine yüklenecek diye bir kural yok. Bu dosyayı hafızanın istediğiniz yerine yükleyebilirsiniz.

Örneğin, bu işi BASIC'te şu şekilde yapabilirsiniz:

Kod: [Seç]
MEMORY &3FFF
LOAD "FILENAME.SCR", &4000

Aynı işlemi WinAPE Assembler içerisinde yapmak için incbin (include binary) direktifini kullanabilirsiniz.
(bkz: http://www.winape.net/help/assembler_directives.html (http://www.winape.net/help/assembler_directives.html))

Yapmak istediğim şey bitmap'i bir şekilde kodun içine gömerek istediğim anda bir loopu çağırarak ekrana verebilmek.

Madem başlangıç seviyesinde Z80 Assembly language kullanıyorsunuz, o zaman LDIR komutu ile yola çıkabilirsiniz.

Kod: [Seç]
LD HL, $4000       ; Yukarıdaki örnekte kullandığımız tampon adres
LD DE, $C000       ; Amstrad CPC 464/664/6128 için ekran adresi
LD BC, 16384       ; Kopyalanacak byte sayısı
LDIR

Elbette bu çözüm demo/oyun geliştirimi için çoğu kez yeterince hızlı değil. Ancak, işin mantığını kavrayabilmeniz açısından bir yerden başlamak gerekiyor. Kişisel görüşümce Z80 Assembly kodlamaya LDI, LDD, LDIR, LDDR, vb. komutlarla başlamanız faydalı olacaktır.

Hoşbulduk,

Ref 'e cevap yazarken misafir gelince ben postu atana kadar epey süre geçmiş. Arada bu cevabı kaçırmışım, kusura bakmayın. Aslında Ref 'e de dediğim gibi biraz kolaya kaçmaya çalışıyordum. Layığı ile assembler öğrenmek için ciddi bir vakit ayırmam gerekiyor ancak bu lükse sahip değilim. O nedenle sadece örneklerden gördüklerimle birşeyler yapmaya çalışırken, bir yandan da demoya da uygun olsun diye garip bir optimizasyon derdine düşerek kendimle çeliştim :)

Bu yanıtlarınızdan sonra da kafamda birşeyler netleşmeye başladı. Dediğiniz şekilde ilerlemek aslında daha az yorucu ve daha faydalı olacaktır. @ref, @matahari Yanıtlarınız için teşekkürler :)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 28 Kasım 2018, 15:01:16
Tekrar teşekkürler yanıtlarınız için! ConvImgCpc ile çevirdiğim bir resmi görüntüleyip seçtiğim paleti giydirmeyi başardım. Bundan sonrası artık oturup çizmeye kaldı.

(https://i.postimg.cc/t7Mmrzxd/cpc-image.jpg) (https://postimg.cc/t7Mmrzxd)

Açıkcası palet kısmını hala tam olarak anlayamadım. Bununla ilgili pek kaynak mevcut değil. O kısmı bulduğum bir Loader 'dan araklayıp kendime göre modifiye ettim. Çok saçma birşey de yapıyor olabilirim ama çalışıyor :)

Kodu da aşağı ekledim. Vakit ayırıp biraz yorumlayabilen olursa çok makbule geçer.

Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 28 Kasım 2018, 16:05:02
ConvImgCpc ile çevirdiğim bir resmi görüntüleyip seçtiğim paleti giydirmeyi başardım.

Harika!

Açıkcası palet kısmını hala tam olarak anlayamadım. Bununla ilgili pek kaynak mevcut değil.

Ekran mode'ları, renk paleti ve ekran hafızası hakkında uygulamalı tutorial için:
http://retrojen.org/fanzin/

Firmware kullanmadan, doğrudan port adresleyerek palet kullanımı için:
http://retrojen.org/fanzin1/

 8)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 28 Kasım 2018, 18:06:44
Ekran mode'ları, renk paleti ve ekran hafızası hakkında uygulamalı tutorial için:
http://retrojen.org/fanzin/

Firmware kullanmadan, doğrudan port adresleyerek palet kullanımı için:
http://retrojen.org/fanzin1/

 8)

Her yeri didik didik edip de forumda yardım istediğim adamın Turbo Loader koduna bakmayı akıl edememek... :S
Mis gibi de tutorial hazırlamışsın hemde :) Sıfırıncı sayı için de artık İstanbul'a gelince Alcofribas'ı sıkıştırayım.

Tekrar teşekkürler :)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 28 Kasım 2018, 19:31:31
Rica ederim. :)

İzninizle, bir üst mesajımdaki Firmware/Port kullanımına biraz açıklık getireyim.

Amstrad CPC ailesi için başlangıç seviyesinde Assembly kodu yazarken firmware adreslerini CALL komutu ile çağırmanız gayet doğal. Ancak, biraz daha ileri seviyede kodlar yazmaya başladığınızda göreceksiniz ki, kullanabileceğiniz her byte çok kıymetli! Bu durumda, hafızanın çeşitli yerlerine dağılmış (toplamda yaklaşık 4K yer tutan) firmware'i kapatmanız, BASIC'i devre dışı bırakmanız ve interrupt'ları disable etmeniz gerekecek. Bu yüzden, yapacağınız her işi "sanki firmware yokmuş, onun yerine OUT komutu ile portlara erişecekmişsiniz" gibi şimdiden zihninizde tasarlamanızda fayda var.

Umarım sizi "Turbo Loader" kodumun içindeki renk paleti kullanımına yönlendirmemin sebebi netleşmiştir.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 28 Kasım 2018, 23:02:28
Rica ederim. :)

İzninizle, bir üst mesajımdaki Firmware/Port kullanımına biraz açıklık getireyim.

Amstrad CPC ailesi için başlangıç seviyesinde Assembly kodu yazarken firmware adreslerini CALL komutu ile çağırmanız gayet doğal. Ancak, biraz daha ileri seviyede kodlar yazmaya başladığınızda göreceksiniz ki, kullanabileceğiniz her byte çok kıymetli! Bu durumda, hafızanın çeşitli yerlerine dağılmış (toplamda yaklaşık 4K yer tutan) firmware'i kapatmanız, BASIC'i devre dışı bırakmanız ve interrupt'ları disable etmeniz gerekecek. Bu yüzden, yapacağınız her işi "sanki firmware yokmuş, onun yerine OUT komutu ile portlara erişecekmişsiniz" gibi şimdiden zihninizde tasarlamanızda fayda var.

Umarım sizi "Turbo Loader" kodumun içindeki renk paleti kullanımına yönlendirmemin sebebi netleşmiştir.

Kesinlikle netleşti. En kısa zamanda vakit ayırıp kodu geliştirmeye çalışacağım. Aşamalarımla forumu epeyce rahatsız ederim. :)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Ref - 30 Kasım 2018, 01:34:30
Matahari lafa girmiş ve bir çaresiz CPC'ci daha mutlu olmuş.

Sen söyleyince aklıma spectrum ile ilgili kaynaklara bakıp oradan fikir edinmek geldi. Biraz daha kurcalayayım :)

CPC için ZX Spectrum kaynaklarının işe yarayacağını sanmıyorum. CPC'nin grafik donanımı spectrumundan çok farklı, interrupt davranışı da çok daha komplike. Genel z80 konusunda da zaten heryer bilgi dolu. Ben de çok nadir asm kodladığım için zamanla unutuyorum bu sebepten her seferinde bolca internet taraması gerekiyor, en faydalı bulduğum iki temel döküman var bu (http://www.z80.info/z80code.htm) ve şu (http://www.z80.info/z80time.txt). 

Retrojen fanzin haricinde, internet üzerindeki CPC kaynaklarını bilmiyorum ama az da olsa dökümante edilmiş (http://www.cpcwiki.eu/index.php/CRTC) olduğunu düşünüyorum. Bir de pouet'deki CPC demolarının bazılarında kaynak kodları bulunuyor, son dönemdeki trend sebebiyle. Bir bakmaya değer.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 30 Kasım 2018, 05:34:19

..en faydalı bulduğum iki temel döküman var bu (http://www.z80.info/z80code.htm) ve şu (http://www.z80.info/z80time.txt). 
Bunları kaydettim. En kısa zamanda hatim edicem. Çok teşekkürler!

Retrojen fanzin haricinde, internet üzerindeki CPC kaynaklarını bilmiyorum ama az da olsa dökümante edilmiş (http://www.cpcwiki.eu/index.php/CRTC) olduğunu düşünüyorum. Bir de pouet'deki CPC demolarının bazılarında kaynak kodları bulunuyor, son dönemdeki trend sebebiyle. Bir bakmaya değer.

Asıl sıkıntı benim bulabildiğim kaynakları anlamakta biraz zorlanmam. Daha çok temel şeyleri anlamadan "ben ekrana resim basıcam" diye girmem hata oldu :)

@Matahari, Turbo Loader 'ından çalıp çırptıklarımla kodu şöyle bir duruma getirdim. Firmware zımbırtıları kullanmadan mis gibi çalışıyor.
Kod: [Seç]
org &8000
di
ld    hl,&4000
        ld    de,&c000
        ld    bc,16384
ldir

setmode:
ld bc,&7f00
ld a,%10001100
out (c),a

ld hl,PaletteArray
pcolor: out (c),c
ld a,(hl)
inc hl
out (c),a
inc c
bit 6,c
jr z,pcolor

halt

PaletteArray:

db &54,&4B,&40,&47,&43,&44,&5C,&46,&5E,&56,&58,&59,&4F,&5B,&5F,&54 ;Hardware Color Codes
;;   0, 26, 13, 16, 25,  1,  3, 10, 12,  9,  4, 22, 17, 23, 14,  0 ;Firmware Color Codes

org &4000
incbin "fero.scr"

Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: wizofwor - 30 Kasım 2018, 11:30:04
Asıl sıkıntı benim bulabildiğim kaynakları anlamakta biraz zorlanmam. Daha çok temel şeyleri anlamadan "ben ekrana resim basıcam" diye girmem hata oldu :)

Benzer yollardan geçmekte olan biri olarak bu hissiyatının assembler'ın öğrenme eğrisinin dik olmasından kaynaklandığını söylemek istedim. Başlangıçta koda baktığında hiç bir şey anlamıyorsun. Tek tek komutları çözsen bile kodun bütünü bir şey ifade etmiyor. Sonra yavaş yavaş desenler oluşmaya başlıyor. Ancak belli bir etkinliğe ulaştıktan sonra olaylar değişiyor. Sabır lazım yani.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 30 Kasım 2018, 13:41:46
Benzer yollardan geçmekte olan biri olarak bu hissiyatının assembler'ın öğrenme eğrisinin dik olmasından kaynaklandığını söylemek istedim. Başlangıçta koda baktığında hiç bir şey anlamıyorsun. Tek tek komutları çözsen bile kodun bütünü bir şey ifade etmiyor. Sonra yavaş yavaş desenler oluşmaya başlıyor. Ancak belli bir etkinliğe ulaştıktan sonra olaylar değişiyor. Sabır lazım yani.

wizofwor harika bir tespit yapmış, konu ancak bu kadar güzel özetlenebilirdi.

Asıl sıkıntı benim bulabildiğim kaynakları anlamakta biraz zorlanmam. Daha çok temel şeyleri anlamadan "ben ekrana resim basıcam" diye girmem hata oldu :)

Ekrana resim basma hedefinize ulaştığınıza göre;

Bu aşamada kod yazmaya ara verip, yavaş yavaş Z80 işlemcisinin mimarisini (Amstrad'ın değil, sadece işlemcinin mimarisini!) ve içerdiği komutları tanımanızda fayda var. Zilog Z80 CPU User Manual'ı tavsiye ederim. İlk okuduğunuzda her şeyi anlayamamanız gayet doğal. Sakın moralinizi bozmayın, tekrar tekrar okudukça zaman içerisinde parçalar yerine oturmaya başlayacaktır. Kendinizi hazır hissettiğinizde kodlamaya geri dönebilirsiniz.

Son olarak,
amacıyla, Assembly kodumuza 'küçük mutlu ağaçlar' ekleyelim. ;)

Kod: [Seç]
org &4000
incbin "fero.scr"

;----------------------------------------------------------------
; CODE Segment
;----------------------------------------------------------------

org &8000

;------ Mission starts here! ----------------------------

di ; disable interrupts
; and, free iy register + shadow registers

;------ Copy from memory to screen ----------------------

ld hl,&4000
        ld de,&c000
        ld bc,16384
ldir

;------ Set mode, and disable upper/lower ROM -----------

ld bc,&7f00
ld a,%10001100
out (c),a

;------ Set ink colours ---------------------------------

ld hl,PaletteArray
pcolor: out (c),c
ld a,(hl)
inc hl
out (c),a
inc c
bit 6,c
jr z,pcolor

;------ Mission accomplished. Now, stop forever! --------

halt ; do nothing, plz.

;----------------------------------------------------------------
; DATA Segment
;----------------------------------------------------------------

PaletteArray:

;Hardware Color Codes
db &54,&4B,&40,&47,&43,&44,&5C,&46,&5E,&56,&58,&59,&4F,&5B,&5F,&54

;Firmware Color Codes
;;   0, 26, 13, 16, 25,  1,  3, 10, 12,  9,  4, 22, 17, 23, 14,  0

Başlık: my first cpc code..
Gönderen: hades - 30 Kasım 2018, 21:49:36
Screen effect.

Ekrandaki her satırı baş aşağı çeviriyor. Oyun yükleme ekranında veya full screen text varken denemek lazım.

Kod: [Seç]
;-------------------------------------------------------;
; CPC RUTINI #01 - EKRAN EFEKTI ;
; EKRANDAKI HER SATIRI BAS ASAGI CEVIRME ;
; 30-11-2018 / HADES ;
; PROGRAM UZUNLUGU 58 BYTE ;
;-------------------------------------------------------;
org &8000

ld ix,&c000
ld hl,&f800

ld b,25
loopxx push bc
push hl
push ix

ld c,4
loop01 ld b,80
loop00 ld a,(ix+0)
ld d,a
ld a,(hl)
ld (ix+0),a
ld a,d
ld (hl),a
inc ix
inc hl
djnz loop00
ld de,&07b0
add ix,de
ld de,&0850
sbc hl,de
dec c
jr nz,loop01

pop ix
pop hl
pop bc
ld de,80
add hl,de
add ix,de
djnz loopxx
ret
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: hades - 01 Aralık 2018, 12:14:37
Kod: [Seç]
;-------------------------------------------------------;
; CPC RUTINI #02 - EKRAN EFEKTI ;
; EKRANI BAS ASAGI CEVIRME ;
; 01-12-2018 / HADES ;
; PROGRAM UZUNLUGU 59 BYTE ;
;-------------------------------------------------------;
org &8000

ld ix,&c000
ld hl,&ff80

ld b,25
loopxx push bc
push hl
push ix

ld c,4
loop01 ld b,80
loop00 ld a,(ix+0)
ld d,a
ld a,(hl)
ld (ix+0),a
ld a,d
ld (hl),a
inc ix
inc hl
djnz loop00
ld de,&07b0
add ix,de
ld de,&0850
sbc hl,de
dec c
jr nz,loop01

pop ix
pop hl
pop bc
ld de,80
sbc hl,de
add ix,de
djnz loopxx
ret
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 01 Aralık 2018, 13:13:13
Benzer yollardan geçmekte olan biri olarak bu hissiyatının assembler'ın öğrenme eğrisinin dik olmasından kaynaklandığını söylemek istedim. Başlangıçta koda baktığında hiç bir şey anlamıyorsun. Tek tek komutları çözsen bile kodun bütünü bir şey ifade etmiyor. Sonra yavaş yavaş desenler oluşmaya başlıyor. Ancak belli bir etkinliğe ulaştıktan sonra olaylar değişiyor. Sabır lazım yani.

Bunu okuduktan sonra daha da bir motive oldum :) Sabırlıyımdır. Boşa kürek çekmediğimi bildiğim sürece üşenmem.


wizofwor harika bir tespit yapmış, konu ancak bu kadar güzel özetlenebilirdi.

Asıl sıkıntı benim bulabildiğim kaynakları anlamakta biraz zorlanmam. Daha çok temel şeyleri anlamadan "ben ekrana resim basıcam" diye girmem hata oldu :)

Ekrana resim basma hedefinize ulaştığınıza göre;

Bu aşamada kod yazmaya ara verip, yavaş yavaş Z80 işlemcisinin mimarisini (Amstrad'ın değil, sadece işlemcinin mimarisini!) ve içerdiği komutları tanımanızda fayda var. Zilog Z80 CPU User Manual'ı tavsiye ederim. İlk okuduğunuzda her şeyi anlayamamanız gayet doğal. Sakın moralinizi bozmayın, tekrar tekrar okudukça zaman içerisinde parçalar yerine oturmaya başlayacaktır. Kendinizi hazır hissettiğinizde kodlamaya geri dönebilirsiniz.

Son olarak,
  • kod yazım disiplinini korumak,
  • takibi güç "data overwrites code" türü hatalara izin vermemek için org direktiflerinin küçükten büyüğe doğru sıralanmasını sağlamak,
  • gelecekte bu sayfayı sizden başka Z80 programcılarının da referans olarak kullanabileceğini göz önüne almak,
amacıyla, Assembly kodumuza 'küçük mutlu ağaçlar' ekleyelim. ;)

Valla çiçek gibi oldu kod :) Açıkcası bir süredir Unreal Engine 'da hazırladığım bazı screen efektleri shader olarak yazabilmek için HLSL 'e sarmıştım ancak cpc ile uğraştığım şu kısa aralık bile bana kat kat daha zevkli geldi. Korkunç derecede zor görünmesine rağmen iyi kötü bir sonuca ulaşıldığında bir o kadar da tatmin edici. Artık bunun peşini kolay kolay bırakmam gibi görünüyor. Verdiğiniz bilgilerden ziyade, vakit ayırıp şu kodu düzenlemeniz bile benim için altın değerinde. :)

@hades abi zaten senin elinden birşey kurtulmuyor. Volkan senin bu işe sarmana ayrıca sevinecek :)
Başlık: CPC'de karakter seti değiştirme hakkında.
Gönderen: hades - 01 Aralık 2018, 22:05:48
Daha önce Spectrum için yazdığım karakter seti değiştirme kodlarını CPC için düzenlemeye karar verdim.
Öğrendiğim kadarıyla cpc'de karakter seti lower romda $3800-$3fff adresleri arasında. lower rom disable edildiğinde tuşlara basınca ekrana bir şey yazılmaması gerekiyor veya -ram devrede olduğu için- o anda font datalarını okuduğu adreste abuk subuk değerler olabileceği için ekranda karışık bir şeyler olması gerekiyor.

org &8000

di
ld hl,&c9fb
ld (&0038),hl

call &b909    ;lower romu disable et
ei
ret


call komutu yerine doğrudan out komutunu mu kullanmak gerekiyor yoksa?
Başlık: Ynt: CPC'de karakter seti değiştirme hakkında.
Gönderen: matahari - 02 Aralık 2018, 00:10:26
Daha önce Spectrum için yazdığım karakter seti değiştirme kodlarını CPC için düzenlemeye karar verdim.

Amstrad CPC ailesi bu konuda çok esnek. Hem Assembly seviyesinde hem de BASIC içerisindeki SYMBOL ve SYMBOL AFTER komutları yardımıyla karakter setini dilediğinizce değiştirebilirsiniz.

Amstrad CPC 6128 User Manual

(https://i.postimg.cc/TLpyKCTc/01.png) (https://postimg.cc/TLpyKCTc)
(https://i.postimg.cc/r00mVs9n/02.png) (https://postimg.cc/r00mVs9n)
(https://i.postimg.cc/0K7yS4F7/03.png) (https://postimg.cc/0K7yS4F7)

Ek referanslar:

http://www.cpcwiki.eu/forum/programming/modify-the-font-appearance/

https://www.sean.co.uk/books/amstrad/amstrad4.shtm

call komutu yerine doğrudan out komutunu mu kullanmak gerekiyor yoksa?

Bu sorunun yanıtı, yapmak istediğiniz işi bitirdikten sonra 'geri döneceğiniz yere' bağlı.

Eğer Lower ROM’u disable edip, tüm işleriniz bittikten sonra;
Eğer amacınız sadece karakter setini değiştirmekse, ROM ile ilgili hiçbir işlem yapmanıza gerek yok. Bu işi BASIC yardımıyla kolaylıkla halledebilirsiniz.
Başlık: Ynt: CPC'de karakter seti değiştirme hakkında.
Gönderen: Ref - 02 Aralık 2018, 13:22:55
Daha önce Spectrum için yazdığım karakter seti değiştirme kodlarını CPC için düzenlemeye karar verdim.

Amstrad CPC ailesi bu konuda çok esnek. Hem Assembly seviyesinde hem de BASIC içerisindeki SYMBOL ve SYMBOL AFTER komutları yardımıyla karakter setini dilediğinizce değiştirebilirsiniz.
...
Eğer amacınız sadece karakter setini değiştirmekse, ROM ile ilgili hiçbir işlem yapmanıza gerek yok. Bu işi BASIC yardımıyla kolaylıkla halledebilirsiniz.

öhö öhhö... Akışı bölmiyim diye kendimi tutmaya çalıştım, ama konuyu spectruma bağlama şansı bulunca duramıyorum biliyorsunuz. Sanırım matahari de benim gibi aynı soruyu soruyor kafasında... "Spectrum için yazdığım karakter seti değiştirme kodları" acaba ne iş yapıyordu?

(edit: araştırdım buldum, sanırım bu programı kastetmiş: http://retrojen.org/pano/index.php?topic=539.msg4244#msg4244 )
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 03 Aralık 2018, 16:08:51
Link için teşekkür ederim Ref.

Anladığım kadarıyla 'karakter setini değiştirmek' ile kastınız, karakter setini sıfırdan oluşturmak (ya da başka bir set ile değiştirmek) değil, mevcut set üzerinde değişiklikler yapmak. O zaman, benzer bir örnek teşkil etmesi açısından, hades hocamın Spectrum için yaptığını Amstrad için yapalım.

Ekteki kod, Amstrad karakter setindeki 'A' (büyük a) harfini ters çeviriyor. Lower ROM, port, vs. gibi karmaşık işlere girmiyorum. Firmware kullanarak karakter setini dump etmek dışında, gerisi tamamen standart Z80 kodu. İşlem bittikten sonra kod BASIC'e geri dönüyor. Bu aşamadan itibaren BASIC'teki büyük A harfinin ters basıldığını test edebilirsiniz.

Umarım yeterince basit bir örnek yazmayı becerebilmişimdir. Size yol göstermesi açısından koda bolca açıklama ekliyorum. Takıldığınız bir yer olursa, lütfen sormaktan çekinmeyiniz.

Kod: [Seç]
LET CONST_Char_A = 65
LET CONST_TotalBytesPerChar = 8
LET CONST_Char_A_Offset = CONST_Char_A * CONST_TotalBytesPerChar

LET ADDR_CHAR_FULLSET = &5000
LET ADDR_CHAR_A = ADDR_CHAR_FULLSET + CONST_Char_A_Offset

;----------------------------------------------------------------
; CODE Segment
; Invert character 'A' - chr$(65)
;----------------------------------------------------------------

org &4000

;------ Dump full character set -------------------------

ld de,0 ; First character in the table
ld hl,ADDR_CHAR_FULLSET ; Addr to dump character map data
call &bbab ; Firmware Call = TXT SET M TABLE

;------ Perform inverting! ------------------------------

ld hl,ADDR_CHAR_A ; 1st line addr of char 'A'
ld de,ADDR_CHAR_A + 7 ; 8th line addr of char 'A'
ld c,4 ; Number of times to swap
; Step#1 = Swap 1st and 8th lines
; Step#2 = Swap 2nd and 7th lines
; Step#3 = Swap 3rd and 6th lines
; Step#4 = Swap 4th and 5th lines

Invert: ld a,(hl) ; A = top line
ex af,af' ; save A (by swapping A and A')
ld a,(de) ; A' = bottom line
ld (hl),a
ex af,af' ; restore A (by swapping A and A')
ld (de),a
inc hl ; next upper line
dec de ; previous lower line
dec c
jr nz,Invert

ret

Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: hades - 03 Aralık 2018, 19:20:57
Teşekkürler @matahari ustad. Verdiğiniz ipucu çok işime yaradı.

Programı winape'nin Assemblerinde yazıp derliyoruz. Emülatör ekranında call 32768 yazarak çalıştırıyoruz ve yeni karakter seti emrinizde. Eğer tekrar call 32768 yazarsanız karakter seti normale dönüyor.

Son olarak karakter setini sadece Bank1 ve Bank2 içerisinde gösterebiliyoruz. Örnekte rutinin bittiği yerde karakter seti başlıyor.


Kod: [Seç]
;-------------------------------------------------------;
; CPC RUTINI #03 - YENI KARAKTER SETI ;
; VERTICAL MIRROR KARAKTER SETI ;
; 03-12-2018 / HADES ;
; PROGRAM UZUNLUGU 58 BYTE ;
;-------------------------------------------------------;
org &8000

; LET ADDR_CHAR_FULLSET = &6000
;------ Dump full character set -------------------------

ld de,0 ; First character in the table
ld hl,new_font ;ADDR_CHAR_FULLSET ; Addr to dump character map data
call &bbab ; Firmware Call = TXT SET M TABLE

                ld      ix,new_font ;&6000;Yeni karakter seti baslangic adresi
                ld      de,2048         ;Karakter setinin byte sayaci
loop01          ld      b,8             ;Okunan byte icin islem sayaci
                ld      a,(ix+0)        ;Setten bir bayt okuyoruz
loop00          rl      a               ;7. biti "elde" bitine yukluyoruz
                                        ;diger bitler sola kayiyor
                rr      c               ;C registeri bit dondurme icin kullanylacak
                                ;"Elde" bitini 7. bite yukluyoruz diger bitler saga kayiyor
                djnz    loop00          ;islemi 8 kez tekrarliyoruz
                ld      (ix+0),c        ;C registerindeki degeri yeni set icin ram'e yaziyoruz.
                inc     ix              ;Set adresini 1 arttir
                dec     de              ;Bayt sayacini 1 azalt
                ld      a,d
                or      e
                jr      nz,loop01       ;0 olmadiysa islemleri tekrarla
ret
new_font
end
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 03 Aralık 2018, 20:28:49
Teşekkürler @matahari ustad. Verdiğiniz ipucu çok işime yaradı.

Rica ederim, hades hocam. İşinize yaramasına çok sevindim. 8)

karakter setini herhangi bir yerde gösterebiliyoruz.

Maalesef hayır!

Neden?

Z80 işlemci birim zamanda 64K (16K x 4 Bank) adresleyebilir.

Bank#0: &0000-&3FFF - (RAM)
Bank#1: &4000-&7FFF - (RAM)
Bank#2: &8000-&BFFF - (RAM)
Bank#3: &C000-&FFFF - (RAM)

Amstrad için konuşursak;

CALL komutu ile herhangi bir firmware fonksiyonu çağırdığınızda, Z80 geçici olarak Lower ROM için Bank#0 ve Upper ROM için Bank#3’ü READ ONLY olarak aktive eder. Bu durumda 64K’lık hafıza haritası şu şekilde değişir:

Bank#0: &0000-&3FFF - (Lower ROM)
Bank#1: &4000-&7FFF - (RAM)
Bank#2: &8000-&BFFF - (RAM)
Bank#3: &C000-&FFFF - (Upper ROM)

Bu sebeple, karakter setimiz (ve firmware çağırımından sonra hayatta kalmasını istediğimiz diğer kod ve veriler) sadece Bank#1 ve Bank#2 (ortadaki 32K) içerisinde olmalıdır. İşte bu yüzden intro/demo/oyun yazarken firmware’i kapatıp, 64K’nın tamamına hakim oluyoruz. ;)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: hades - 03 Aralık 2018, 21:24:05
Ufak bir sorum olacak.
Alıntı
Amstrad için konuşursak;

CALL komutu ile herhangi bir firmware fonksiyonu çağırdığınızda, Z80 geçici olarak Lower ROM için Bank#0 ve Upper ROM için Bank#3’ü READ ONLY olarak aktive eder. Bu durumda 64K’lık hafıza haritası şu şekilde değişir:

Bank#0: &0000-&3FFF - (Lower ROM)
Bank#1: &4000-&7FFF - (RAM)
Bank#2: &8000-&BFFF - (RAM)
Bank#3: &C000-&FFFF - (Upper ROM)


Bank#3 adreslerinde aynı zamanda Screen Memory var. CPC ilk açılışta/resette Upper Rom devrede mi? Yoksa sistem daha sonra 16K Lower Rom + 48K Ram olarak mı düzenleniyor?

İlk paylaştığım kodlarda ekran belleğinden okuma yaparak işlem yapıyordum. Bu durumda Upper Rom'un devre dışı gözüküyor.

Sanırım $8000-$BFFF arasındaki bir kod içinde geçen CALL komutu donanımsal olarak takip ediliyor ve adres Bank0 veya Bank3 aralıklarında ise otomatik olarak romlar aktif hale getiriliyor. (Z80'den çıkan /M1 sinyali="0" ve Databus =&CD ise bu kontrol işlemi yapılabilir gibi.)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 03 Aralık 2018, 22:09:35
Bank#3 adreslerinde aynı zamanda Screen Memory var.

Doğru.

CPC ilk açılışta/resette Upper Rom devrede mi? Yoksa sistem daha sonra 16K Lower Rom + 48K Ram olarak mı düzenleniyor?

Amstrad CPC ailesi ilk açılış/Reset sırasında, hafızayı

Bank#0: &0000-&3FFF - (Lower ROM)
Bank#1: &4000-&7FFF - (RAM)
Bank#2: &8000-&BFFF - (RAM)
Bank#3: &C000-&FFFF - (Upper ROM)

şeklinde düzenliyor. Bu sebeple ekranda çok kısa bir süre için garbage data (aslında Upper ROM'u) görüyoruz.

Sanırım $8000-$BFFF arasındaki bir kod içinde geçen CALL komutu donanımsal olarak takip ediliyor ve adres Bank0 veya Bank3 aralıklarında ise otomatik olarak romlar aktif hale getiriliyor.

Açılış/Reset prosedürünün sonunda, &A600-&BFFF adresleri arasında 'Firmware Adres Tablosu' oluşturuluyor. Bu tablo sayesinde, herhangi bir firmware CALL yapılması (örneğin CALL &BB18 çağırılması) durumunda, geçici olarak hangi Bank'in aktive edileceği ve o Bank'te hangi adrese Jump edileceği önceden bilinmiş oluyor.

Açılış/Reset prosedürü tamamlanır tamamlanmaz ROM'lar devre dışı kalıyor, 64K'nın tamamı

Bank#0: &0000-&3FFF - (RAM)
Bank#1: &4000-&7FFF - (RAM)
Bank#2: &8000-&BFFF - (RAM)
Bank#3: &C000-&FFFF - (RAM)

şeklinde kullanıcıya teslim ediliyor. Ekrana Copyright bilgileri + 'Ready' yazılıyor, ardından da BASIC devreye giriyor.

İlk paylaştığım kodlarda ekran belleğinden okuma yaparak işlem yapıyordum. Bu durumda Upper Rom'un devre dışı gözüküyor.

Siz açmadığınız, yani bir firmware CALL yapmadığınız ve/veya BASIC'te yazılmış bir kodu RUN etmediğiniz sürece, Lower/Upper ROM hep kapalı.

Firmware çağırımlarının çok hantal olması, her CALL yüzünden tekrarlanan Bank switching sebebiyle kaybedilen zamandan kaynaklanıyor. Özellikle Upper ROM'un aktive edilmesini gerektiren firmware CALL'lar, ekran hafızası ile çakışması sebebiyle, görüntünün flicker etmemesi için ekran çizimi tamamlandıktan ve henüz başlamamışken çağırılıyor. Eğer bu koşul sağlanmamışsa, koşul sağlanana dek bekleniyor! İşte bu yüzden mümkün olduğunca firmware kullanmamaya (ve hatta tamamen kapatmaya) özen gösteriyoruz.

* NOT: Yukarıdaki bilgilere ek olarak, Amstrad CPC 6128'de ROM Bank sayısının 2 değil 3 olduğunu belirtmekte fayda var. Üstte anlattığım her şey birebir geçerli, sadece fazladan 1 ROM Bank daha var.

(https://i.postimg.cc/PNvB3xDS/6128.png) (https://postimg.cc/PNvB3xDS)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: hades - 05 Aralık 2018, 19:48:59
Verdiğiniz bilgiler için çok teşekkürler.
CPC'nin tasarımı gerçekten ilginçmiş. Bu arada interrupt rutinine baktım. interrupt rutini firmware adres tablosuna jump yapıyormuş. Her ne kadar hafıza tamamen Ram gibi gözükse bile restart adresleri yüzünden &0000'dan itibaren kod yazmak riskli olabilir. Bu durumda şöyle bir sorum olacak.
Yazdığımız kodda herhangi bir firmware call olsun veya olmasın, kodumuzu yazmaya başlayabileceğimiz en küçük adres kaçtan başlıyor?
Ek soru : Yıllar önce elo elektronik dergisinde amstrad ile ilgili bir yazıda "300 Hz interrupt" ifadesi geçiyordu. Böyle bir şey var mı?
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 06 Aralık 2018, 00:22:20
Verdiğiniz bilgiler için çok teşekkürler.

Rica ederim.

Yazdığımız kodda herhangi bir firmware call olsun veya olmasın, kodumuzu yazmaya başlayabileceğimiz en küçük adres kaçtan başlıyor?

Normal koşullarda, 64K'lık hafızanın &0170-&A600 adresleri arasında kalan bölümünü, BASIC + Assembly language ile kod yazmak amacıyla kullanabilirsiniz. &C000-&FFFF arasındaki ekran hafızasına da her zaman erişebilirsiniz.

Amstrad CPC ailesinde hafızanın en kritik bölgesi, &0000-&003F adresleri arasında kalan ve 'RST Area' olarak bilinen 64 byte'lık alandır. Interrupt'lar açık ve BASIC devrede olduğu sürece bu minik bölgeye dokunmamakta fayda var.

Ancak, şöyle bir istisna söz konusu; Eğer,
o zaman, bu minik alanı kullanabilirsiniz.

Amstrad CPC ailesi, Assembly language ile 'low-level' kodlama yapmanız ve yukarıda sıralanan koşulları sağlamanız durumunda, 64K'nın tamamını (!) kullanmanıza izin verir. RST Area ve Firmware Adres Tablosu’na ait yerleri bile kullanabilirsiniz. Hatta, normalde &BFFF adresinde bulunan Stack'in yerini bile değiştirebilirsiniz. ;)

Yıllar önce elo elektronik dergisinde amstrad ile ilgili bir yazıda "300 Hz interrupt" ifadesi geçiyordu. Böyle bir şey var mı?

Sözünü ettiğiniz makaleyi bilmiyorum, ama "300 Hz interrupt" ifadesi ile ne kastedildiğini açıklayabilirim.

Amstrad CPC ailesinde saniyede 300 kez (her frame'de 6 kez X 50 frame) FAST TICKER olarak bilinen bir interrupt oluşur. Bu interrupt'ın gerçekleşmesi durumunda, Z80 işlemci önce tüm interrupt'ları disable eder, ardından da &0038 adresini CALL eder. Normal koşullarda bu adreste 3 byte'lık (C3, 41, B9) jp &B941 kodu bulunur. Bu sebeple her interrupt'ta &B941 adresine jump edilir, o adresten sistemi idame ettirmek için gerekli birkaç firmware çağırısı yapılır, bu işlem bittikten sonra tüm interrupt'lar tekrar açılır ve hayat kaldığı yerden devam eder. Bu işlem her frame'de 6 kez tekrar edilir.

İşin en keyifli yanı, FAST TICKER interrupt oluşumunda gidilen &0038 adresinin içindeki 3 byte'lık kodu değiştirerek, kendi interrupt kodlarımızı yazabiliyor olmamız.

Örneğin;
Kod: [Seç]
ld hl,&C9FB
ld (&0038),hl
NOT: Yukarıdaki her iki durumda &0038 adresi üzerinde bir değişiklik yapmadan önce DI komutu ile interrupt'ları kapatmanız, işiniz bittikten sonra da EI komutu ile interrupt'ları tekrar açmanız gerekir.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 03 Ocak 2019, 08:29:13
Ödevi şöyle bırakayım :) Hades 'in yaptığının tersi şeklinde aşağıdan yukarı doğru siliyor. Kodun tamamı ve resim dosyası da ekte mevcut. Bunu yaparken screen memory 'i komple yanlış anladığımı fark ettim. Şimdi iyice taşlar yerine oturdu. Skate 'in paletle ilgili fikrini de uygulamayı deneyeceğim. Umarım becerebilirim.

Kod: [Seç]
cls: ld hl,&ffcf
call clear
ld hl,&ffbb
call clear
ld hl,&ffa7
call clear
ld hl,&ff93

clear: ld a,25 ;rows
clear02: ld c,8 ;lines
push hl
clear01: ld b,20 ;Video Mem +-14
clear00: ld (hl),0
dec hl
ld d,100
delay00: dec d
jr nz,delay00
djnz clear00
ld de,2048-20 ;previous/next row.
sbc hl,de ;previous line
dec c
jr nz,clear01
pop hl
ld de,80 ;previous/next line.
sbc hl,de ;previous line
dec a
jr nz,clear02
ret
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Ref - 03 Ocak 2019, 09:51:27

  • FAST TICKER interrupt'ının düzenli olarak gerçekleşmesini, ama kıymetli zamanımızı çalmaması için 'hiçbir iş yapmamasını' istiyorsanız, &0038 adresine (C9, FB) RET, EI yazmanız yeterli.

önce EI, sonra RET (FB C9) olmayacak mı o, yoksa amstrad PC'yi azaltarak mı ilerliyor :D Olur olur, komut işletmek için vblank bekleyen sistemden herşey beklenir. 80'ler makineleri çok çılgınca saçmalıklar yapmış, derme çatma sistem hepsi. Commodore disk sürücüsünü 10 kat yavaşlatarak kullanıyor, amstrad rom'a erişmek için bekliyor, Oric ekranı HAM modu gibi boyuyor, spectruma başlamaya gerek yok... BBC, Acorn neler yaptı kimbilir... Neyse...

Peki eğer ROM'da işlenen komutun uzun sürerek, sayfa eski haline çevrilmeden çizime başlandığı oluyor mu? Yani basic kullanırken bir şekilde anlık bile olsa ekranı garbage haline getirebilmek mümkün mü?

Ayrıca, @fero,
ekteki grafikte raat#5 metni görüyorum ama partide bunu göstermedin. Yoksa ben mi kaçırdım? Yoksa amstradda batman demo açıldı diye misafilrler kaçar ihtimaliyle mi gizlediniz bu çizimi?
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 03 Ocak 2019, 11:47:07
  • FAST TICKER interrupt'ının düzenli olarak gerçekleşmesini, ama kıymetli zamanımızı çalmaması için 'hiçbir iş yapmamasını' istiyorsanız, &0038 adresine (C9, FB) RET, EI yazmanız yeterli.
önce EI, sonra RET (FB C9) olmayacak mı o, yoksa amstrad PC'yi azaltarak mı ilerliyor :D

Uyarı için çok teşekkür ederim Ref.

LD (addr), reg16 instruction format gereği, 16-bit register içindeki değer hafızaya low-byte ve high-byte şeklinde ters yazılacağı için (C9, FB) sıralaması doğru. Maalesef açıklamasını yanlış yazmışım. Elbette doğrusu EI, RET şeklinde olacak. Gözümden kaçmış, özür dilerim.

Orijinal mesajımdaki muğlak cümleyi şu şekilde düzeltip, bir de örnek ekledim:

  • FAST TICKER interrupt'ının düzenli olarak gerçekleşmesini, ama kıymetli zamanımızı çalmaması için 'hiçbir iş yapmamasını' istiyorsanız, &0038 adresine EI (&FB), RET (&C9) yazmanız yeterli.
Kod: [Seç]
ld hl,&C9FB
ld (&0038),hl

Sanırım böylesi daha açıklayıcı oldu. Daha önce örnek kod yazmak neden aklıma gelmedi acaba?! :o

Olur olur, komut işletmek için vblank bekleyen sistemden herşey beklenir. 80'ler makineleri çok çılgınca saçmalıklar yapmış, derme çatma sistem hepsi. Commodore disk sürücüsünü 10 kat yavaşlatarak kullanıyor, amstrad rom'a erişmek için bekliyor, Oric ekranı HAM modu gibi boyuyor, spectruma başlamaya gerek yok... BBC, Acorn neler yaptı kimbilir... Neyse...

Bu listeye, ekranda kar yağarken görüntünün netleşmesi için ZX Spectrum'un 'lambalı amfi misali' ısınmasını beklememizi de ekleyebilir miyiz? ;)

Peki eğer ROM'da işlenen komutun uzun sürerek, sayfa eski haline çevrilmeden çizime başlandığı oluyor mu? Yani basic kullanırken bir şekilde anlık bile olsa ekranı garbage haline getirebilmek mümkün mü?

ROM'da yapılan işlerin birçoğu (hepsi değil, örneğin teyp/disk erişim routine'leri hariç) ona göre tasarlanmış, toplamda belli bir süreyi asla geçmiyorlar. BASIC ile ekranı garbage etmek elbette mümkün, hele bir de READ/DATA/POKE kombinasyonu ile 'inline' machine code eklenirse iyice kontrolden çıkabilir. :)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 03 Ocak 2019, 13:22:05
Ayrıca, @fero,
ekteki grafikte raat#5 metni görüyorum ama partide bunu göstermedin. Yoksa ben mi kaçırdım?

CPC paletiyle ilk denememdi. Pek istediğim gibi olmadı. Arada kaynattım :)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 03 Ocak 2019, 13:27:08
Ödevi şöyle bırakayım :)

Harika, elinize sağlık Fero! Z80 kodlamanız giderek çok daha iyi oluyor. :)

Henüz yolun başındayken, kod yazma disiplininden taviz vermemeniz ve bu disiplini bir alışkanlık haline getirebilmeniz için, izninizle birkaç tavsiyem olacak.

Bu foruma post edilen herşey aslında 'arşiv' niteliğinde. Buraya yazdığımız kodların ileride 'referans' olarak kullanılabilmesi için, post edilenlerin mümkün olduğunca düzgün ve eksiksiz olmasında fayda var diye düşünüyorum.

Bu bağlamda;
biraz daha titiz davranabilirsek, bizden sonra bu sayfaları ziyaret edeceklere faydamız olabilir.

*NOT: RAAT#5'te sabaha karşı 04:00 sularında "İsterseniz bug'ı bulmanıza yardım edeyim!" diyerek gıcır gıcır bilgisayarınızın başına sinsice (!) oturmam, Z80 Assembler karşısında saatlerce sizi esir almam, üstüne de Skate'in önerdiği colour trick'i gözümden uyku akarak kodlamam hususunda gösterdiğiniz hoşgörü ve sabır için teşekkür ederim.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 04 Ocak 2019, 12:05:24
Teşekkürler! Henüz tüm yapabildiğim çalıp çırptığım kodların nasıl çalıştığını anlamak ve değiştirmekten ibaret olduğundan, pek öyle kodluyormuş gibi hissetmiyorum. Yazım disiplini konusunda çok haklısınız. Daha dikkatli ve titiz olmaya gayret edeceğim.

*NOT: RAAT#5'te sabaha karşı 04:00 sularında "İsterseniz bug'ı bulmanıza yardım edeyim!" diyerek gıcır gıcır bilgisayarınızın başına sinsice (!) oturmam, Z80 Assembler karşısında saatlerce sizi esir almam, üstüne de Skate'in önerdiği colour trick'i gözümden uyku akarak kodlamam hususunda gösterdiğiniz hoşgörü ve sabır için teşekkür ederim.

Aksine bende bir anlığına "adamı resmen bağladım buraya, içinden bana küfrediyor olabilir" diye bir düşünceye kapılmıştım. Bilgisayarın başına geçmenizden de çok büyük mutluluk duydum. İşin üstatlarını problem çözerken canlı olarak izlemekten daha iyi ve keyifli bir öğrenme yöntemi düşünemiyorum. Ancak raat öncesinde de uykusuz bir gece geçirdiğimden, kodda olan biteni algılamakta ve doğru soruları sormakta biraz zorlandım. Yine de benim için muhteşem bir deneyimdi. Ben teşekkür ederim :)


Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 06 Ocak 2019, 07:53:25
Geceleri uyku tutmayınca hemen CPC 'ye sarıyorum. Bugün bakalım iyice anlayabilmiş miyim diye biraz kendimi zorlamaya karar verdim. Ekranı sol üstten ve sağ alttan aynı anda silecek bir kod yazmak için kolları sıvadım. Zorlu birkaç saatin ardından ilk satırları güzelce temizleyebildim ancak 2. satırlara başladığında sağ altta işler epey karıştı. Koda yazdığım commentlerde detaylı şekilde aklımdan geçenleri anlatmaya çalıştım. Umarım becerebilmişimdir.

Son satırlardaki POP HL ve SBC HL,DE satırlarını açtığımda garip bir şekilde düzgün silinen üst taraf ta bozuluyor. Screen memory ile ilgili birşeyleri kaçırıyor olabilirim. Bir de interrupt'ı açıp kapatmanın bunun gibi basit birşeyi nasıl ve neden etkilediğini anlayamadım.

İlerleme kat edemiyorum, bari yazım şekline dikkat edeyim de üstatları kızdırmayayım dedim  ;)

Kod: [Seç]
;---------------------------------------------------------------------------------------;
; ;
;      CPC - CIFT YONLU DIKEY SILME DENEMESI - 1 ;
;       06.01.2019 / F3R0 ;
; ;
;---------------------------------------------------------------------------------------;

TOP_LINE equ &c000
BOT_LINE equ &ff80

org &8000

di ;Interrupt'lari kapatirsak ust taraf 1 satir = 8 dizi fazladan siliyor.

;-------------------------------- Ekrani dolduruyoruz ----------------------------------;

DrawImage:
ld    hl,&c000
        ld    de,&c000+1 ;Ekrani kirmizi renk ile
        ld    bc,16384 ;dolduruyoruz.
ld    (hl),255
ldir

;----------------------------------- On hazirliklar ------------------------------------;

ld hl,TOP_LINE ;Yukaridan silme baslangic adresi
exx
ld hl,BOT_LINE ;Asagidan silme baslangic adresi
exx
;Bunun sonucunda HL=&C000, HL'=&FF80
;olarak tanimlamis oluyoruz. Shadow
;registerlari degistirerek bir alttaki
;adresten, bir ustteki adressten silerek
;ilerleyecegim.

VerticalLines: ld a,12 ;Toplam silinecek satir sayisi /2
VerticalRows: ld c,8 ;Her satir arasinda 8 dizi var.

exx ;; Stack dan daha sonra istedigim sirada
push hl ;; cekebilmek icin 2 kere shadowlar ile
exx ;; degistirip push yaptim. Boylece
push hl ;; stack: 1.top_line 2.bot_line
;; seklinde siralandi.

RowLength: ld b,80 ;Bir dizideki toplam byte. 1 byte = 2 pixel
;silinecek alanin yatay uzunlugu.

;--------------------------------- Dizileri siliyoruz ----------------------------------;

ClearRows: ld (hl),0 ;;HL deki mevcut TOP_LINE (&c000) adresinin
inc hl ;;ilk byte'i siliniyor. Bir arttiktan sonra
exx ;;shadow register'lar ile degistiriliyor.
ld (hl),0 ;;Boylece HL deki mevcut adress BOT_LINE (ff80)
inc hl ;;oluyor. Ayni sekilde ilk byte 'i silinip
exx ;;bir arttirildiktan sonra dizideki toplam byte
ld d,100 ;;kadar tekrar ediyor.
Delay: dec d
jr nz,delay ;;Her tekrarda bir miktar bekletiyorum.
djnz ClearRows ;;80. tekrardan sonra devam.

NextRow: ld de,2048-80 ;;Mevcut adresi 80 byte sildik. Bir sonraki
add hl,de ;;dizinin basina ulasmak icin, 2048 ekleyip,
;;80 geri geliyorum.

exx ;;HL 'ye alttaki adresi aldim.

ld de,2048+80 ;;Alttan silinen dizide de ters yonde silerek
sbc hl,de ;;asagidan yukari ilerledigimiz icin tam
;;tersini yapiyorum.
exx
dec c
jr nz,RowLength

;--------------------------------- Satirlari siliyoruz ---------------------------------;

;;8 diziyide sildikten sonra bir sonraki satira
NextLine: ;;geciyoruz. Bunun icin HL 'deki mevcut adrese
pop hl ;;asagiya gitmek icin +80, yukari gitmek icin-80
ld de,80 ;;verecegim.
add hl,de
;pop hl ;;....
;sbc hl,de ;;...
dec a ;;..
jr nz,VerticalRows ;;.


halt

Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 06 Ocak 2019, 13:56:10
Son satırlardaki POP HL ve SBC HL,DE satırlarını açtığımda garip bir şekilde düzgün silinen üst taraf ta bozuluyor.

Çünkü sorun(lar) sözünü ettiğiniz son satırlarda.

NextLine etiketiyle başlayan bölümde;

-Bug#1: HL'yi POP edip, üstüne 80 ekleyerek bir sonraki satıra geçiyorsunuz, ama elde ettiğiniz bu değeri saklamayı (EXX ile shadow register setine switch etmeyi) unutuyorsunuz. Bir sonraki POP komutu, hesapladığınız mevcut değerin üzerine yazıyor.

-Bug#2: Aynı sorun ikinci POP işlemi için de geçerli, yine EXX yapmayı unutuyorsunuz.

-Bug#3: EXX komutu HL, DE, BC ve onların shadow'larını etkiler. LD DE,80 komutu ile yüklediğiniz değer EXX komutu ile birlikte shadow DE register'ına gidiyor, onun değeri de mevcut DE'ye geliyor. Yüklediğiniz 80, diğer DE register'ında kalıyor. Bu yüzden DE'yi tekrar 80'e eşitlemeniz gerekiyor.

Doğrusu şöyle olacak:

Kod: [Seç]
...

NextLine: pop hl
ld de,80
add hl,de
exx
pop hl
ld de,80
sbc hl,de
exx
dec a
jr nz,VerticalRows

...

Bir de interrupt'ı açıp kapatmanın bunun gibi basit birşeyi nasıl ve neden etkilediğini anlayamadım.

Hmmmm... Evet bu başlı başına bir sorun. Eğer interrupt'ları açık bırakırsanız, her interrupt ile birlikte arkaplanda bir sürü firmware CALL yapılır. Bu routine'ler, mevcut DL, DE ve BC register değerlerini bozmamak için shadow register'ları kullanır. Bu yüzden ilk firmware CALL sonrasında, sizin shadow register değerleriniz buhar oluyor. Eğer EXX komutunu kullanacaksanız, (ihtiyaca göre geçici ya da kalıcı olarak) interrupt'ları kapatmanız gerekir.

İlerleme kat edemiyorum, bari yazım şekline dikkat edeyim de üstatları kızdırmayayım dedim  ;)

:)

Yok canım, estağfurullah. Kızmak diye birşey söz konusu değil.

Bu kadar detaylı comment'ler yazmanız çok iyi olmuş. Açıkcası, neyi/nasıl yapmak istediğinizi tam olarak bilemediğim için, yukarıdaki bug'ları yazdığınız comment'leri takip ederek yakaladım diyebilirim. Elinize sağlık!
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: hades - 06 Ocak 2019, 14:40:30
Ferhat'a yardımcı olayım dedim ve yapmak istediği efekti kodladım. Açıklamalar yardımcı olur umarım.

Kod: [Seç]
org &8000

; di ;Interrupt'lari kapatirsak ust taraf 1 satir = 8 dizi fazladan siliyor.

;-------------------------------- Ekrani dolduruyoruz ----------------------------------;

DrawImage:
ld    hl,&c000
        ld    de,&c000+1 ;Ekrani kirmizi renk ile
        ld    bc,16383 ;dolduruyoruz.
ld    (hl),255
ldir
;----------------------------------- On hazirliklar ------------------------------------;

;***************************************************************************************
ld ix,&c000 ;ust
ld hl,&ff80 ;alt

ld a,12 ;ekran satir sayisi/2
clear_new_line push ix ;bir sonraki satir hesaplamasi
push hl ;icin yiginda sakliyoruz
ld c,8 ;bir karakter satirindaki pixel sayaci
new_pixel_line ld b,80 ;kolon sayaci
clear_a_pixel_line ld (hl),0 ;ust tarafi temizle
ld (ix+0),0 ;alt tarafi temizle
inc hl
inc ix
djnz clear_a_pixel_line
;---------------------------------------------------------------
; yeni pixel satirina gecmeden once bekleyelim
;---------------------------------------------------------------
ld de,&1000 ;gecikme sayaci
delay00 dec de
ld a,d
or e
jr nz,delay00
;---------------------------------------------------------------
; yeni pixel satirlari icin hesaplamalar
;---------------------------------------------------------------
ld de,2048-80 ;yeni ust satir icin fark (&07b0)
add ix,de ;ornek c050+07b0=c800
ld de,2048+80 ;yeni alt satir icin fark (&0850)
sbc hl,de ;ornek ffd0-0850=f780
dec c ;pixez satir sayacini 1 azalt
jr nz,new_pixel_line
;---------------------------------------------------------------
; yeni karakter satiri icin hesaplamalar
;---------------------------------------------------------------
pop hl ;alt adresi geri al
pop ix ;ust adresi geri al
ld de,80 ;adresler arasi fark
add ix,de ;yeni ust satir icin +80
sbc hl,de ;yeni alt satir icin -80
dec a
jr nz,clear_new_line
halt

Bu arada ufak bir ekleme yapayım.

ld hl,&c000
ld de,&c000+1
ld bc,16384
ld (hl),255
ldir

komutlarında BC=16383 olması daha iyidir. Cünkü 16384 döngü sonunda HL=FFFF iken DE=0000 olacak ve ldir komutu nedeniyle 0000 adresine 255 yüklenecektir. Dolayısıyla &0000'ki restart rutini &FF ile başlamış olacaktır.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 06 Ocak 2019, 16:05:43
@matahari, bunu düşünemediğime inanamıyorum. Hemde debug'la da defalarca üzerinden geçmeme rağmen! Halbuki işin başında shadow registerları nasıl kullanacağıma epey bir kafa yormuştum. Neyse, en azından çalışan bir kod yazmaya çok yaklaşmışım. Bu da benim açımdan sevindirici oldu :)

@hades, harikasın! Aynı işi farklı bir yöntemle görünce şimdi bazı şeyler kafamda daha da iyi oturdu. Her nasılsa, IX register'ında add ix,de şeklinde bir kullanımın hatalı olduğu yanılgısına kapılıp, shadow register'lara başvurmaya karar vermiştim. Eğer sen bu kodu paylaşmasaydın muhtemelen bir yerlerde kullanımı dikkatimi çekene kadar durumun farkına varmayacaktım.

Çok teşekkürler ikinize de, sizin de ellerinize sağlık!
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 06 Ocak 2019, 23:10:24
Süpeeeeer! hades'in kodu 3 byte daha kısa. Elinize sağlık hocam! :)

Bu aşamada elimizde, aynı işi farklı yöntemlerle yapabilen iki routine'imiz oldu. Yazım tekniği açısından, her ikisi için de 'size optimization' odaklı diyebiliriz. Peki, bu kodlar daha kısalır mı? Elbette. Gerek var mı? Bence yok, çünkü burada amaç ekran silme algoritmasının nasıl çalışacağını pseudo-code mantığı ile örneklemek.

Neden 'pseudo-code' terimini kullandım?

Çünkü bu routine'leri bir oyun/demo içerisinde kullanmaya kalkarsak;
ve benzeri sebeplerle, bu tarz kodlamanın başımıza çok iş açacağını şimdiden öngörebiliriz.

Bu bağlamda, yukarıda saydığım sorunların nasıl giderileceğine yönelik örnek bir kod yazdım. İşlevsel olarak, hades ve Fero'nun yazdığı kodlarla birebir aynı işi yapıyor.

Bonus olarak,
Eğer gerçek anlamda bir oyun/demo kodlaması yapılacaksa, bu tür bir teknik kullanılmasında fayda var. Zira, bu minimalist kod tamamen 'hız odaklı'. Gerekmedikçe hiçbirşeyi kapatmıyor/kullanmıyor.

Daha kısası/hızlısı yazılabilir mi? Elbette mümkün, o konuda bir iddiam yok.

Amacım, gerçek hayatta bu tür bir kodun nasıl yazıldığına dair bir 'şablon' sunabilmek. Umarım size yeni bir pencere açabilmişimdir.

Kod: [Seç]
LET ADDR_CodeExec = &4000
LET ADDR_ScrFirstLine = &c000
LET ADDR_ScrLastLine = &ff80

;----------------------------------------------------------------------
; Fast bidirectional screen cleaning routine v1.2
; for Amstrad 464/664/6128 computers
;
; (c) matahari - (Jan 06, 2019)
;----------------------------------------------------------------------

run CodeExec
org ADDR_CodeExec

CodeExec: ;------ Generate a dummy interrupt handler ----------------------------

di ; Disable interrupts
im 1 ; Interrupt mode = 1
ld hl,&c9fb ; Interrupt handler = EI,RET
ld (&0038),hl ; Overwrite interrupt vector

;------ Fill whole screen with red pixels -----------------------------

ld hl,ADDR_ScrFirstLine ; Screen addr to fill
ld de,ADDR_ScrFirstLine + 1
ld bc,16383 ; Number of bytes to fill
ld (hl),255 ; Colour = Red
ldir ; Memory fill using LDIR

;------ Press any key to continue -------------------------------------

call &bb18 ; Wait for a key!

;**********************************************************************
; MAIN LOOP - INITIALIZE!
;**********************************************************************

push bc ; Due to LDIR, BC=0. Save it!
pop af ; Load &0000 (16-bit) to AF
ex af,af' ; Save clean AF to AF'
ld hl,ADDR_ScrFirstLine + 80 ; Set addr of first upper line
ld de,ADDR_ScrLastLine  + 80 ; Set addr of last lower line
ld c,13 ; Number of char loop

;**********************************************************************
; MAIN LOOP - BEGIN
;**********************************************************************

LoopFillChars: ld b,8 ; Number of pixels in a char

LoopFillLines: ld a,b
ld (Buffer8bit),a ; Save B
ei ; Enable interrupts, and give
; some time to interrupt
; driven routines to breathe!

;------ Check for vertical blanking -----------------------------------

ld b,&f5 ; PPI port B
WaitVBlanking: in a,(c) ; Read current value from port
rra ; bit 0 -> carry
jr nc,WaitVBlanking ; If bit 0=1 then VSYNC is OK,
; else try again...

halt ; You may replace these two
halt ; instructions with your
; favourite music player ;-)

di ; Disable interrupts, again!
ld a,(Buffer8bit)
ld b,a ; Restore B

;------ Fill upper line -----------------------------------------------

ex af,af' ; Get clean AF from AF'
ld sp,hl ; Stack = UPPER LINE ADDRESS

REPEAT 40 ; Paste 'PUSH AF' for 40 times
push af ; Poke clean AF to screen
REND ; End paste

;------ Fill lower line -----------------------------------------------

ex de,hl ; Swap HL and DE values
ld sp,hl ; Stack = LOWER LINE ADDRESS

REPEAT 40 ; Paste 'PUSH AF' for 40 times
push af ; Poke clean AF to screen
REND ; End paste

ex af,af' ; Save clean AF to AF'

;------ Calculate next line addresses ---------------------------------

ld sp,2048-1
sbc hl,sp ; Lower line
ex de,hl ; Swap HL and DE values
inc sp
add hl,sp ; Upper line

djnz LoopFillLines ; Decrease B, and loop
; for all pixels in a char

;------ Calculate next char addresses ---------------------------------

ld sp,2048*8-81
sbc hl,sp ; Upper line
ex de,hl ; Swap HL and DE values
inc sp
add hl,sp ; Lower line
ex de,hl ; Swap HL and DE values

dec c ; Decrease C,
jr nz,LoopFillChars ; and loop for all chars

;**********************************************************************
; MAIN LOOP - END
;**********************************************************************

LoopForever: jr LoopForever

Buffer8bit: db 0


Release Notes:

v1.0
v1.1
v1.2
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: hades - 07 Ocak 2019, 00:04:43
Bir efekt için 3 farklı rutin. Çok güzel kodlar bunlar. cpc donanımına henüz tam olarak hakim olmadığım için yolun başındayım diyebilirim, ancak Fero'daki öğrenme ve bir şeyler üretmeye olan hevesi, gayreti beni de gaza getiriyor.

Bu arada naçizane bir öneri olarak;

push   bc            ; Due to LDIR, BC=&00. Save it!
pop   af

komutları yerine XOR A yazarak hem A'yı sıfırlamış oluruz, hem de kod 1 byte daha kısalmış olur. Ayrıca PUSH-POP ikilisinin harcadığı zamandan kurtulmuş oluruz.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 07 Ocak 2019, 00:16:20
Bir efekt için 3 farklı rutin. Çok güzel kodlar bunlar. Fero'daki öğrenme ve bir şeyler üretmeye olan hevesi, gayreti beni de gaza getiriyor.

Bunu duyduğuma çok sevindim. Yeni kodlarınızı heyecanla bekliyoruz. 8)

Bu arada naçizane bir öneri olarak;

push   bc            ; Due to LDIR, BC=&00. Save it!
pop   af

komutları yerine XOR A yazarak hem A'yı sıfırlamış oluruz, hem de kod 1 byte daha kısalmış olur. Ayrıca PUSH-POP ikilisinin harcadığı zamandan kurtulmuş oluruz.

Tavsiyeniz için çok teşekkür ederim. Sıkça kullandığım bir yöntemdir, ve fakat burada maalesef bir işe yaramıyor. Amacım sadece A'yı sıfırlamak değil, hem A hem de F'yi sıfırlamak. 16-bit'lik AF register'ının tamamı sıfır olacak ki, tek PUSH AF komutu ile 2 byte birden silebileyim. ;)

Bildiğim kadarıyla, Z80 mimarisinde F register'ına LD komutu ile erişmek mümkün değil. F'ye 8-bit bir değer yüklemenin tek yolu, yüklenecek değeri POP etmek.
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: Fero - 07 Ocak 2019, 02:18:45
Şahanesiniz. Matahari'nin son paylaştığı kodu anlayabilmem için z80 heaven 'da biraz zaman geçirmem gerekecek. :)
Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: matahari - 07 Ocak 2019, 17:00:05
Matahari'nin son paylaştığı kodu anlayabilmem için z80 heaven 'da biraz zaman geçirmem gerekecek. :)

Aynı tekniği kullanan basit bir örnek, konuyu daha hızlı kavramanıza yardımcı olabilir. ;)

Kod: [Seç]
LET ADDR_CodeExec = &4000
LET ADDR_ScrFirstPixel = &c000
LET ADDR_ScrMemoryEnd = &ffff + 1

LET CONST_InitialColour = &ff
LET CONST_ClearColour = &0000

;----------------------------------------------------------------------
; Fast screen clear/fill routine v1.0
; for Amstrad 464/664/6128 computers
;
; (c) matahari - (Jan 07, 2019)
;----------------------------------------------------------------------

run CodeExec
org ADDR_CodeExec

CodeExec: ;------ Generate a dummy interrupt handler ----------------------------

di ; Disable interrupts
im 1 ; Interrupt mode = 1
ld hl,&c9fb ; Interrupt handler = EI,RET
ld (&0038),hl ; Overwrite interrupt vector

;------ Fill whole screen with a single colour (for test purpose) -----

ld hl,ADDR_ScrFirstPixel ; Screen addr to fill
ld de,ADDR_ScrFirstPixel + 1
ld bc,16383 ; Number of bytes to fill
ld (hl),CONST_InitialColour ; Fill using this colour
ldir ; Memory fill using LDIR

;------ Press any key to continue -------------------------------------

call &bb18 ; Wait for a key!

;**********************************************************************
; MAIN LOOP - INITIALIZE! - (Only SP,DE,B registers are used!)
;**********************************************************************

ld (OldSP),sp ; Save current SP value
ld sp,ADDR_ScrMemoryEnd ; SP = screen end addr
ld de,CONST_ClearColour ; Clear using this colour
ld b,128 ; Number of times to loop

;**********************************************************************
; MAIN LOOP - BEGIN
;**********************************************************************

LoopClear: REPEAT 64 ; Paste 'PUSH DE' for 64 times
push de ; Poke clear colour using DE
REND ; End paste

djnz LoopClear ; Decrease B, Loop B times

; 1 PUSH pokes 2 bytes on scr
; 2 bytes * 64 PUSH * 128 times
; => 16384 bytes

;**********************************************************************
; MAIN LOOP - END - (Back to normal life)
;**********************************************************************

ld sp,(OldSP) ; Restore previous SP value
ei ; Enable interrupts

LoopForever: jr LoopForever

OldSP: dw 0

Başlık: Ynt: CPC'de Assembler ile imtihanım...
Gönderen: hades - 07 Ocak 2019, 22:42:38
Kodlamalara devam.

Kod: [Seç]
;---------------------------------------------------------------;
; CPC RUTINI #06 - EKRAN EFEKTI #03 ;
; PIXEL PIXEL YATAY EKRAN KOPYALAMA ;
; (C) 06-01-2019 / HADES ;
;---------------------------------------------------------------;
; Bu rutin hafizadaki ekran goruntusunu pixel satirlari
; seklinde ekran belleginin pixel satirlarina kopyalar
;===============================================================;
run start
org &8000
;===============================================================;
; ekran modunu ayarla ve renkleri duzenle
;===============================================================;
start call &bc14 ;firmware cls
di
setmode ld bc,&7f00
ld a,%10001100
out (c),a
ld de,PaletteArray
pcolor out (c),c
ld a,(de)
inc de
out (c),a
inc c
bit 4,c
jr z,pcolor
ld bc,&7f10 ;select border
out (c),c
ld bc,&7f54 ;set border colour to black
out (c),c
;===============================================================;
call effect_03
halt
;===============================================================;
PaletteArray db &54,&4b,&43,&44,&4e,&4c,&5c,&5b
       ;blk;wht;yel;dbl;org;brd;red;lcy
db &57,&55,&45,&46,&40,&58,&4b,&54
       ;lbl;blu;pur;cya;gry;mgn;bmg;blk

;---------------------------------------------------------------;
; EFEKT RUTINI BURADAN BASLIYOR
;---------------------------------------------------------------;
effect_03 ld ix,&4000 ;hafizada saklanan ekran
ld iy,&c000 ;default ekran bellegi
ld h,25 ;ekrandaki karakter satiri sayaci
next_line push ix ;ix registerini yigina sakla
push iy ;iy registerini yigina sakla
;===============================================================;
; hafizadan o anki pixel satirini kopyala
;===============================================================;
ld c,8 ;kopyalanacak pixel satir sayaci
next_pixel ld b,80 ;bir pixel satirindaki byte sayisi
next_byte ld a,(ix+0) ;hafizadaki ekrandan bir byte oku
ld (iy+0),a ;default ekrana bellegine yaz
inc ix ;hafizadaki ekran adresini 1 arttir
inc iy ;default ekran adresini 1 arttir
djnz next_byte ;80 byte kopyalanincaya kadar tekrarla
;===============================================================;
; biraz bekleyelim
;===============================================================;
ld de,&0400
bekle dec de
ld a,d
or e
jr nz,bekle
;===============================================================;
; bir alttaki pixel satiri icin hesapla
;===============================================================;
ld de,2048-80 ;bir sonraki pixel satiri icin adres farki
add ix,de ;yeni pixel satirinin adresini hesapla
add iy,de ;yeni pixel satirinin adresini hesapla
dec c ;pixel satir sayacini 1 azalt
jr nz,next_pixel ;0 oluncaya kadar islemleri tekrarla
;===============================================================;
; bir sonraki karakter satiri icin islem yap
;===============================================================;
pop iy ;iy registerini yigindan geri al
pop ix ;ix registerini yigindan geri al
ld de,80 ;bir sonraki karakter satiri icin adres farki
add ix,de ;yeni karakter satirinin adresini hesapla
add iy,de ;yeni karakter satirinin adresini
dec h ;karakter satiri sayacini 1 azalt
jr nz,next_line ;0 oluncaya kadar islemleri tekrarla
ret
;===============================================================;
org &4000

screen incbin "BatR2.scr"
;===============================================================;