Retrojen Forum

Dijital Sanat => Kodlama => Konuyu başlatan: hades - 22 Nisan 2022, 11:13:45

Başlık: Spectrum'la ilgili bir soru.
Gönderen: hades - 22 Nisan 2022, 11:13:45
Soru spectrumda bir basic satırının yapısıyla ilgili. Önce sorunun ortaya çıkış sebebini yazıyım.

C64'te bir basic programı 2049 ($0801) adresinden  başlar ve 2022 SYS adres şeklindeki bir satırın yapısı şu şekildedir.
$0801-$0802: Bir sonraki basic satırının başlangıç adresi. Gösterilen adresin içeriği $0000 ise programın sonu demektir.
$0803-$0804: Satır numarası
$0805: SYS komutunun kodu ($9e)
$0806....: programın çalışma adresinin ascii değerleri
Son olarak o program satırının sonunu gösteren $00 değeri.
Arka arkaya üç adet $00'dan sonra ise makine kodu/data bulunur. Yani tek satırlık bir komutun devamında asıl program/data bulunur.

Spectrumda da aynı şey yapılabilir mi diye uğraşmaya başladım ama dump ettiğimde tek satırlık bir programda bile fazladan baytlar gözüküyor. Dokümanlara göre bir Basic programının bitiminde hemen değişkenler başlıyor. Program satırının uzunluğu falan derken işler karışıyor.

"2022 RANDOMIZE USR ADRES" + kod şeklindeki bir programda adres en düşük ne olabilir?

 
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: matahari - 22 Nisan 2022, 13:07:43
Efendim, madem bugün ZX Spectrum'un 40. yılı yüzü suyu hürmetine klavye başındayım (evet, sadece bugünlük! ;)), konunun uzmanı @Ref hocamızdan müsaade isteyerek sorunuzu yanıtlayayım.

... ama dump ettiğimde tek satırlık bir programda bile fazladan baytlar gözüküyor. Dokümanlara göre bir Basic programının bitiminde hemen değişkenler başlıyor. Program satırının uzunluğu falan derken işler karışıyor.

ZX Spectrum BASIC interpreter, her değişken için hafızada 2 değer saklar:

1.) LIST komutu ile ekrana basılacak "göstermelik" değer.
2.) Üzerinde hesap-kitap yapılacak "gerçek" değer.

Basit bir örnekle açıklayayım:

Kod: [Seç]
10 LET A=3
20 PRINT A

Bu kodu RUN komutuyla çalıştırdığımızda ekranda 3 sayısı belirir.

Kod: [Seç]
3
Şimdi, küçük bir hokus-pokus ile A değişkeninin "gerçek" değerini 255 yapalım.

Kod: [Seç]
POKE 23767,255
yazıp, ENTER'a basalım. Şimdi RUN komutunu çalıştırdığımızda ekranda 255 sayısı belirir.

Kod: [Seç]
255
İlginç olan, eğer LIST komutu ile kodu listelerseniz, ilk satırda hâlâ A=3 yazdığını görebilirsiniz. ;)

Kod: [Seç]
10 LET A=3
20 PRINT A

BASIC interpreter'ın token ve değişken yönetimi oldukça dinamik. &5C00-&5CB6 arasındaki sistem değişkenleri BASIC interpreter için pointer map görevi görüyor. Daha geniş bilgi için Dr. Ian Logan'ın kitaplarını tavsiye ederim. Zira, pek kapsamlı bir başlık bu...

"2022 RANDOMIZE USR ADRES" + kod şeklindeki bir programda adres en düşük ne olabilir?

Sanırım RANDOMIZE USR komutuyla çağırılan adresi kastediyorsunuz. İçeriği geçerli olduğu sürece, 16-bit adres olması yeterli.
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: hades - 22 Nisan 2022, 15:23:59
Soruyu doğru ifade edemedim. Adres değerinde bir sıkıntı yok.
Ekran görüntüsünde 2022 RANDOMIZE USR 23800 satırının bellekteki yerleşimine baktığımızda ilk olarak satır numarasının HI-LO formatında 07 E6 olarak görüyoruz. Ancak dump incelendiğinde 2022'nin bu kez tek tek ascii kod olarak saklandığı görülüyor. (Kırmızı çizgili)
Aynı şekilde RANDOMIZE ($F9) ve USR ($C0) değerleri 2022'nin ascii değerlerinden sonra tekrar yer alıyor. Çalışma adresi olan 23800 de aynı şekilde ascii olarak sıralanıyor.
Diğer yandan çalışma adresi 23800 LO-HI şeklinde $F85C olarak iki kez yer alıyor.
Dumpa göre bir randomize usr şeklindeki bir satırın devamında yer alacak bir kodun konuşlanacağı ve çalışacağı en düşük adres 23800 olarak gözüküyor. Aradaki bytları dikkate almadan çalışma adresi daha düşük olabilir mi biraz uğraşayım.
Satır uzunluğu ilk komuttan itibaren sayarak 14 byte, ki $0E komut satırının uzunluğu. Tek satırlık bir program hafızada daha çok yer kaplıyor.

Hem komutların hem de diğer sayısal değerlerin tekrarlanması kafamı karıştırdı.

Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: matahari - 22 Nisan 2022, 16:13:56
@hades: Açıklayıcı yanıtınız için teşekkür ederim. Sorununuzu şimdi çok daha iyi anladım.

Sizin örneğinizi biraz geliştirelim:

Kod: [Seç]
2022 RANDOMIZE USR 23800
2023 REM MATAHARI
2024 REM HADES

Şimdi bu kodun hafızadaki yerleşimine bakalım:

 


Kolayca görüleceği üzere 2022 ve 2023 nolu satırlar gayet optimized biçimde konumlanmış, ancak son girilen 2024 nolu satır 2 kez tekrar edilmiş. Neden? Çünkü, "aktif olarak girmekte olduğunuz kod" (yani henüz enter'a basmadan önce sayfanın altındaki komut satırına tuşladığınız bölüm), mevcut BASIC kod bloğunun hemen ardına "buffer"lanıyor. Siz Enter'a bastığınız anda o satır interpret edilerek en son satır olarak kod bloğuna ekleniyor, ancak buffer olarak kullanılan alan temizlenmiyor. En sonda gördükleriniz, artık garbage olmuş data. 8)
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: Ref - 22 Nisan 2022, 17:02:52

Arka arkaya üç adet $00'dan sonra ise makine kodu/data bulunur. Yani tek satırlık bir komutun devamında asıl program/data bulunur.

Spectrumda da aynı şey yapılabilir mi diye uğraşmaya başladım ama dump ettiğimde tek satırlık bir programda bile fazladan baytlar gözüküyor. Dokümanlara göre bir Basic programının bitiminde hemen değişkenler başlıyor. Program satırının uzunluğu falan derken işler karışıyor.

"2022 RANDOMIZE USR ADRES" + kod şeklindeki bir programda adres en düşük ne olabilir?
Şimdi ben de anlamaya çalıştım soruyu, c64'den hiç anlamadığım için yaya kaldım. Amacın basic programı içinde çok yakına bir makine kodu sıkıştırmak mı acaba?

Eğer buysa, söylediğin şey mataharinin açıkladığı sebeple basic'in peşinde (LineBuffer orada duruyor) olmaz ama genelde REM satırına (ya da bir stringin içine) konuyor o durumda makine kodu.

örnek
Kod: [Seç]
10 REM XXXXXXXXXXX buraya relocatable ASM KODUNU DERLEYECEKSİN XXXXXXXX (~240byte lık data tutabilir, tam rakam ezberimde yok)
20 RANDOMIZE USR ((PEEK 23635+256*PEEK 23636)+5)
(basic'in konumu kullanıcının daha önce yaptığı işlemlere göre nadiren değişebildiği için onu sistem değişkeninden okumak daha garanti, 20.satırdaki PEEK'ler o yüzden var)


Fakat bir hatırlatma, basic'in bu ilk kısmı ilk 16K'lık ram'de bulunuyor. Bu bölge ekran kaşesi ile aynı çipte kalıyor. Bu sebepten ekran çizilirken Z80 o bölgeye ulaşmak için ara sıra beklemek zorunda kalacaktır. Yani eğer kodunuz 32768'den küçük bir adreste çalışıyorsa gecikmeye uğrayacaktır. Bu bölgede çalışan kodun değişik davranışları olacaktır. Contention konusunda uzmanlaşmadan burada time critical kod çalıştırmak çizimde rastlantısal sonuçlar almana sebep olabilir. Ayrıca yaklaşık %5 yavaş çalışacaktır.

Bu arada basic değişkenlerinin yerini değiştirmek mümkün, CLEAR komutu ile yapılabilir. fakat değişkenler zaten ram'in dibinde $FDE8 civarı tutuluyor.
CLEAR 24800 vb gibi birşey yaparsan değişkenler basic'e yaklaşır hatta birleştirebilirsin. Eğer birbirinin üzerine yazmaya başlarlarsa Ramtop no good hatası alırsın.



Ek olarak Basic'in ekrandaki temsili ile ilgili bir komik program paylaşıyorum, ters çalışan basic!
 


deneyin ve mucizeyi görün! :)
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: hades - 22 Nisan 2022, 17:37:32
@matahari açıklamalar için teşekkürler. Konuyu daha iyi anladım. Garbage baytlar kafa karıştırıyormuş.
@Ref evet tahmin ettiğin gibi. Basic dibine kod eklemek ve load"" code kullanmadan tüm kodu sadece load"" ile basic programıymış gibi yüklemek.

En düşük adres 23774 oluyor. Garbage datalar yüzünden evdeki bilgisayarda hatalı çalışan/çalışmayan kodu düzeltme zamanı geldi.

Kod: [Seç]
org $8000

xor a
ld hl,23755 ; basic başlangıç
clr ld (hl),0
inc hl
dec a
jr nz,clr

ld hl,data
ld de,23755
ld bc,32
ldir

; arada asıl kodu 23774'ten itibaren taşıma
; ve save rutini olacak
ret
;--------------------------------------------
; 2022 RANDOMIZE USR 23774 satırının dataları
;--------------------------------------------
data db $07,$e6,$0e,$00,$f9,$c0,$32,$33
db $37,$37,$34,$0e,$00,$00,$de,$5c
db $00,$0d,$80
;---------------------------------------------
ld a,1
out (254),a

; ld hl,maincode
; ld de,$8000
; ld bc,lenght
; ldir
; jp $8000
ret

end $8000
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: matahari - 22 Nisan 2022, 17:56:03
@matahari açıklamalar için teşekkürler. Konuyu daha iyi anladım. Garbage baytlar kafa karıştırıyormuş.

Rica ederim, faydalı olabildiğime sevindim.

Basic dibine kod eklemek ve load"" code kullanmadan tüm kodu sadece load"" ile basic programıymış gibi yüklemek.

bkz: Speedlock 8)
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: hades - 22 Nisan 2022, 18:15:53
@matahari zaten speedlock konusunu okuduktan sonra problemi yazmaya karar verdim. Her zaman öğrenilecek bir şeyler vardır.
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: matahari - 22 Nisan 2022, 18:40:47
zaten speedlock konusunu okuduktan sonra problemi yazmaya karar verdim.

Çok sevindim, @hades hocam.

RANDOMIZE USR'li versiyonu bitirdikten sonra belki bir de RANDOMIZE USR'siz (sadece PEEK/POKE kullanarak ON_ERROR_GOTO sistem değişkenlerini değiştiren) bir tane yazmayı düşünebilirsiniz. Böylece benim reverse engineering ile anlatmaya çalıştığım konuyu, siz literatürümüze doğrudan source code olarak sunabilirsiniz. Bizden sonrakiler için çok faydalı bir arşiv olur diye düşünüyorum. Elbette son karar sizin, benimkisi sadece bir temenni...

Her zaman öğrenilecek bir şeyler vardır.

Size içtenlikle katılıyorum. Bu yüzden forumdayız.
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: Skate - 22 Nisan 2022, 18:46:31
Dün ben de bu konuyu merak ettim, hafızada son satırı tekrar ederken gördüm, ama en son şimdilik bu kısmı es geçip, internetten hazır biçimde şu byte bloğunu buldum.

Kod: [Seç]
basic_loader:
  db $00,$0a,$0e,$00,$20,$fd,"32767",$0e,$00,$00,$ff,$7f,$00,$0d     ; 10 CLEAR 32767
  db $00,$14,$07,$00,$20,$ef,$22,$22,$20,$af,$0d                     ; 20 LOAD "" CODE
  db $00,$1e,$0f,$00,$20,$f9,$c0,"32768",$0e,$00,$00,$00,$80,$00,$0d ; 30 RANDOMIZE USR 32768
basic_loader_end:

SjASMPlus'da kodun sonuna şunları ekleyerek TAP üretebildim ve çalıştı.

Kod: [Seç]
    EMPTYTAP "first.tap"
    SAVETAP "first.tap", BASIC, "loader", basic_loader,basic_loader_end - basic_loader, 10
    SAVETAP "first.tap", CODE, "first", main, endOfCode - main, main

İşin güzel tarafı "şimdilik diğer kısımlara odaklanayım, daha sonra çözerim şu basic listing tarafını" diyordum ki @hades bu soruyu sordu @matahari de dört dörtlük cevapladı. Z80 tanrıları benim yanımda. :D
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: Ref - 22 Nisan 2022, 21:55:55
Dün ben de bu konuyu merak ettim, hafızada son satırı tekrar ederken gördüm, ama en son şimdilik bu kısmı es geçip, internetten hazır biçimde şu byte bloğunu buldum.

Kod: [Seç]
basic_loader:
  db $00,$0a,$0e,$00,$20,$fd,"32767",$0e,$00,$00,$ff,$7f,$00,$0d     ; 10 CLEAR 32767
  db $00,$14,$07,$00,$20,$ef,$22,$22,$20,$af,$0d                     ; 20 LOAD "" CODE
  db $00,$1e,$0f,$00,$20,$f9,$c0,"32768",$0e,$00,$00,$00,$80,$00,$0d ; 30 RANDOMIZE USR 32768
basic_loader_end:

SjASMPlus'da kodun sonuna şunları ekleyerek TAP üretebildim ve çalıştı.

Kod: [Seç]
    EMPTYTAP "first.tap"
    SAVETAP "first.tap", BASIC, "loader", basic_loader,basic_loader_end - basic_loader, 10
    SAVETAP "first.tap", CODE, "first", main, endOfCode - main, main

İşin güzel tarafı "şimdilik diğer kısımlara odaklanayım, daha sonra çözerim şu basic listing tarafını" diyordum ki @hades bu soruyu sordu @matahari de dört dörtlük cevapladı. Z80 tanrıları benim yanımda. :D


Pasmo'da compile ederken --tapbas switch'i ekleyince basic loader bloğunu başına otomatik ekliyor, bence sjasmplus'da da vardır o özellik. ama neyse çözmüşsün. Ama burda hades'in sorduğu basic bloğu içinde code kısmınıda tek yüklemeyle çözmek.

Bu arada skate, senin ürettiğin kaset imajı, önce bir code block loader oluşturuyor, o basic de asm kodunu ayrıca ikinci bir blok olarak yüklüyor ve sonra önceden yüklediğin basic programı devam edip 30 satırda senin asm kodunu çalıştırıyor.

Hades istiyor ki, tek bir basic loader'i, hem basic'i hem asm kodu bir arada, tek seferde yüklesin ve yükleme bittiği gibi ikinci bir teyp yüklemesi olmasın, demo hemen çalışsın.
Benim söylediğim yöntem küçük introlar için en basit pratik yöntem. Tabi ötesi de mümkün, işte mataharinin speedlock yazısı var ERR_SP ayarlanarak yapılan bir sürü numara var orada, bir de bence tam bir sihirbazlık olan wizball loader'i var ki.. ne sihirbazlığı bildiğin cadı işi. Basic Loader yüklemeye başlıyor, kesmeden ekranı yüklüyor kesmeden programı da yüklüyor (halbuki spectrum hafıza haritasında önce ekran, sonra basic geliyor, arada geri dönüp o kısmı yüklüyor falan filan).

Dosyayı ekliyorum merak edenler specemu'dan yükleyip bakabilirler. 48k modunda hızlı yükleme yapmadan izlenebilir. Demo gibi bişey.
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: Skate - 22 Nisan 2022, 22:10:33
Soru gayet açıktı. Ben @hades'in basic kodlarının durduğu bölgeyi görüp, oradaki duplicate junk datayı da görüp kafasının karışması, @matahari'nin de basic kodlarının olduğu bölgeyle ilgili yaptığı detaylı açıklamalara istinaden paylaştım bunu. Bu "al böyle de yaparsın" şeklinde paylaşılmış bir şey değil. Ben dün bunu yaparken de basic kodlarının durduğu bölgeyi inceledim, aynı şeye denk geldim. Ben bunu paylaşmadan sorun çözülmüştü zaten.

Ekşi sözlük kuralıdır. Bir enrty'de düzgün açıklama geldikten sonra muhabbet serbesttir. ;)
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: Ref - 23 Nisan 2022, 00:51:34
Soru gayet açıktı. Ben @hades'in basic kodlarının durduğu bölgeyi görüp, oradaki duplicate junk datayı da görüp kafasının karışması, @matahari'nin de basic kodlarının olduğu bölgeyle ilgili yaptığı detaylı açıklamalara istinaden paylaştım bunu. Bu "al böyle de yaparsın" şeklinde paylaşılmış bir şey değil. Ben dün bunu yaparken de basic kodlarının durduğu bölgeyi inceledim, aynı şeye denk geldim. Ben bunu paylaşmadan sorun çözülmüştü zaten.

Ekşi sözlük kuralıdır. Bir enrty'de düzgün açıklama geldikten sonra muhabbet serbesttir. ;)
Muhabbet değil ya, o bilgi de önemli, bir eleştiri değildi, laf lafı açıyor şeklinde gitsin muhabbet. Fakat sen böyle diyince asıl soruyu hiç yanıtlamadığımızı gördüm.

Asıl soru şuydu:
"2022 RANDOMIZE USR ADRES" + kod
şeklindeki bir programda adres en düşük ne olabilir?
Hades başka birşey kast ediyordu ama yine de soruyu olduğu gibi cevaplamaya çalışalım.

Bunu şöyle düşünüyorum, oradaki ADRES makine kodumuzu koyabileceğimiz güvenli bir adres olmalı, makine kodumuz basic'in çalışmasına engel olmamalı (kod uygulandıktan ve tamamlandıktan sonra basic'e dönebilmeliyiz diyelim)

Basic'in başlangıcı 23755 olduğunu var sayalım (bazen ileri geri oynuyor takılan donanıma göre).

Şimdi burada birkaç düzeltme yapalım, randomize usr <adres> yerine randomize usr val "<adres>" yapalım 3 byte kazanalım (15 byte).

şu anda basic cursor'u 23770'e geldi.
bu durumda VARS vb ekleyelim, NXTLIN 23794'e geldi, girilecek satırla birlikte 35 byte diyelim, aslında eğer basic'i kasetten yükleyeceksek edeceksek buna gerek yok çünkü rom loader yükleme tamamlanınca otomatik basic'i çalıştırabiliyor ama geri döndüğümüzde halen bir satır ram olsa iyi olur.
eğer asm kodumuzu sihirli değneğimizle yerleştirebilirsek, bu durumda  23805 güvenlidir diyebiliriz.
eğer onu da kasetten yüklememiz gerekiyorsa LOAD "" CODE : komutu eklememiz gerek o da 5 byte tutuyor, dolayısıyla 23810 sanırım teorik güvenli en küçük adres olacaktır.

Ama burada tek yüklemede işlem hallolmuyor, fakat basic'in dayandığı dip burası olacaktır. Ekteki dosyada loader ve 36 byte'lık makine kodu bloğu var. Bunu 23810'a yerleştirdim ve ekranı ters çevirip (hades sanırım bu senin kodundu) tekrar basic'e dönüyor. Sorun yok. Basic umrumda değil diyorsan 23795 (NXTLIN) ya da olmazsa 23796 işi çözecektir. 

yetmedi, bir ihtimal daha var :D
sadece CODE bloğu vermek. Bunun için genelde tüm basic sistem değişkenlerini de dahil eden bir kayıt yapıyorsun ve yükleyecek kişiye, mesela 48k modunda load""code ile yüklemelisin diyorsun. SAVE "demo" code 22528, 1500
şeklinde kaydedip, yükleyenin konfigürasyonu ile senin konfigin tutması için dua ediyorsun :D hatta istersen biraz daha önden başlayıp ekrana grafik de yükleyebilirsin bu arada :D Ekte örnek veriyorum ship of the line oyunu...
 
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: hades - 15 Ağustos 2022, 00:41:39
Basic programının dibine kod ekleyip oluşan programı sadece load komutuyla yükleme işini hallettim sayılır. Yıllar önce birileri yapmıştır mutlaka.

Program çalışınca 6161 RANDOMIZE USR 23755 şeklinde bir basic satırı üretiyor ve kısa bir transfer rutininin dibinden başlayan asıl kodu normal bir basic programı gibi save ediyor. Save işlemi bitince "C Nonsense in BASIC, 40:1" mesajı çıkıyor. Böyle bir mesajın çıkması da saçma zaten :)

6161 RANDOMIZE USR 23755 satırının satır numarası aslında JR $11 komutuna karşılık geliyor ve basic satırı çalışınca 23755 üzerinden $5CDE'deki relocator rutinine sıçrıyor.
Programın biraz daha geliştirilmesi gerekiyor.  Printer Buffer bölgesinde çalışacak şekilde ve mesela önceden $8000'den itibaren derlenen bir programı relocator rutinin dibine transfer edip save yapacak hale getirmeyi planlıyorum.


Kod: [Seç]
;********************************************************
; BASIC+CODE
; Basic programının dibine makine kodu ekleme ve kodu
; normal bir basic programı gibi save etme rutini

; 12.08.2017 HADES/RET - İlk denemeler
; 14.08.2022 Final öncesi denemeler
; Final versiyonu printer buffer'da çalışacak şekilde
; yapılacak.
;********************************************************
org $8000
;--------------------------------------------------------
; PROGRAM SAVE BÖLÜMÜ
;--------------------------------------------------------
; START TAPE... MESAJINI YAZDIR VE TUŞA BASILMASINI
; BEKLE (Bu kısım alıntıdır!!!)
;--------------------------------------------------------
start ld a,$fd ; Ensure that channel 'K' is open.
               call $1601
               xor a ; Signal 'first message'.
               ld de,$09a1 ;'Start tape, then press any key.'
               call $0c0a
               set 5,(iy+$02) ;Signal 'screen will require to be cleared'
               scf
               call $15d4 ;Bir tuşa basılmasını bekle
;;-------------------------------------------------------
; Header'i kaydet
;--------------------------------------------------------
               ld a,0
               ld ix,header
               ld de,17
               call $04c2
;--------------------------------------------------------
               ld b,20
wait halt
djnz wait
;--------------------------------------------------------
; Basic+code kısmını 23755'ten itibaren kopyala
;--------------------------------------------------------
ld hl,basic_line
ld de,23755
ld bc,finish-basic_line
ldir
;--------------------------------------------------------
; Programı kaydet
;--------------------------------------------------------
               ld a,$ff
               ld ix,23755
               ld de,finish-basic_line
               scf
               call $04c2
               ret
;========================================================
; TAPE HEADER BİLGİSİ
;========================================================
header;
file_type defb 0 ;dosya tipi: program
file_name defm "basic+code"
data_lenght defw finish-basic_line
start_line defw 6161 ;programın çalışma satırı
prog_lenght defw finish-basic_line
;--------------------------------------------------------
; 6161 RANDOMIZE USR 23755 satırının dataları (19 byte)
; ve relocator / çalıştırma rutini (14 byte)
;--------------------------------------------------------
basic_line db $18,$11,$0e,$00,$f9,$c0,$32,$33
db $37,$35,$35,$0e,$00,$00,$cb,$5c
db $00,$0d,$80
;--------------------------------------------------------
relocator ld hl,23755+(program-basic_line)
     ld de,$8000 ; programın gerçek adresi
     ld bc,finish-program
     ldir
     jp $8000 ; programın çalışma adresi
;========================================================
; DENEME AMAÇLI RUTİN
;========================================================
program defs 8192,0

call $0d6b
xxx ld a,r
out (254),a
jr xxx
;========================================================
finish:
end start ;$8000
;========================================
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: Ref - 15 Ağustos 2022, 11:42:36
Basic programının dibine kod ekleyip oluşan programı sadece load komutuyla yükleme işini hallettim sayılır. Yıllar önce birileri yapmıştır mutlaka.

Program çalışınca 6161 RANDOMIZE USR 23755 şeklinde bir basic satırı üretiyor ve kısa bir transfer rutininin dibinden başlayan asıl kodu normal bir basic programı gibi save ediyor. Save işlemi bitince "C Nonsense in BASIC, 40:1" mesajı çıkıyor. Böyle bir mesajın çıkması da saçma zaten :)

6161 RANDOMIZE USR 23755 satırının satır numarası aslında JR $11 komutuna karşılık geliyor ve basic satırı çalışınca 23755 üzerinden $5CDE'deki relocator rutinine sıçrıyor.
Programın biraz daha geliştirilmesi gerekiyor.  Printer Buffer bölgesinde çalışacak şekilde ve mesela önceden $8000'den itibaren derlenen bir programı relocator rutinin dibine transfer edip save yapacak hale getirmeyi planlıyorum.



Henüz denemedim ama çok güzel bilgilerle dolu bir kod olmuş hades. Sayende bir sürü şey öğrendim yine. eline ve azmine sağlık.
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: Skate - 15 Ağustos 2022, 13:19:04
Ben de biraz yoğunum, kafamı vererek inceleyemedim. Ama henüz uğraşmadığım, bir gün mutlaka uğraşmam gerekecek bir konu olduğu için şimdiden teşekkür edeyim İsmail'e. :)
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: hades - 18 Ağustos 2022, 21:28:08
Alıntı
Save işlemi bitince "C Nonsense in BASIC, 40:1" mesajı çıkıyor. Böyle bir mesajın çıkması da saçma zaten :)

Bir önceki mesajda belirttiğim hata mesajından kurtulmak için programı save eden kısmın en sonundaki RET komutu yerine

rst 8
defb 255    ; hata kodu-1

yazınca ekrana "0 OK, 40:1" çıkıyor ve hata mesajından kurtuluyoruz.

Hata kodu 27 ve sonrası değerlerde olursa saçma sapan mesajlar çıkıyor. 48K ve +2 modellerde farklı sonuçlar oluyor.

Edit: Ufak bir ekleme yapıyorum.

Listedeki tape header bilgisi kısmında file_name satırını aşağıdaki şekilde değiştiriyoruz.

Alıntı
file_name      defb   $16,1,0      ; AT 1,0
                    defb   249,192      ; RANDOMIZE USR
                    defm   "23755"      ; 23755

Oluşan yeni program yüklenirken artık klasik "PROGRAM : ........" yerine RANDOMIZE USR 23755 çıkacak.
File_name uzunluğu 10 baytı geçmemelidir.

 
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: Ref - 21 Ağustos 2022, 23:38:30
Listedeki tape header bilgisi kısmında file_name satırını aşağıdaki şekilde değiştiriyoruz.

Alıntı
file_name      defb   $16,1,0      ; AT 1,0
                    defb   249,192      ; RANDOMIZE USR
                    defm   "23755"      ; 23755

Oluşan yeni program yüklenirken artık klasik "PROGRAM : ........" yerine RANDOMIZE USR 23755 çıkacak.
File_name uzunluğu 10 baytı geçmemelidir.

 


Spectrumdaki en sevdiğim tricklerden biri bu. "Program:" kelimesinin üzerine yazdırmaya çalışmaca. elbette sadece yükleme yapılmadan önce ekran kullanılmamışsa ya da cls ile temizlenmişse çalışıyor. Spectrumda birşey yüklemeden önce herkes reset ettiği için %99 durumda çalışıyor olur.
Başlık: Ynt: Spectrum'la ilgili bir soru.
Gönderen: hades - 16 Temmuz 2023, 22:28:31
Kod: [Seç]
;********************************************************
; BASIC + CODE
; Basic programının dibine makine kodu ekleme ve kodu
; normal bir basic programı gibi save etme rutini
;********************************************************
;========================================================
prg_adr equ $af00
run_adr equ $af00
uzunluk equ (prg_end-prg_str)+35
;--------------------------------------------------------
org prg_adr
;========================================================
; INCLUDE edilen dosyada END komutu olmamalıdır !!!.
;       INCLUDE edilen dosyada ORG komutları olmamalıdır. !!!
; INCLUDE edilen dosya ve varsa ilgili .bin
; dosyaları ile basic+code.asm dosyası aynı klasörde
; bulunmalıdır.
; BASIC + CODE haline getirilecek kod burada olmalıdır.
;========================================================
prg_str:
include "dikey_simetrik_ekran.asm"
prg_end:
;--------------------------------------------------------
; PROGRAM SAVE BÖLÜMÜ
;--------------------------------------------------------
; START TAPE... MESAJINI YAZDIR VE TUŞA BASILMASINI
; BEKLE (Bu kısım alıntıdır!!!)
;--------------------------------------------------------
basicode ld a,$fd ; Ensure that channel 'K' is open.
               call $1601
               xor a ; Signal 'first message'.
               ld de,$09a1 ;'Start tape, then press any key.'
               call $0c0a
               set 5,(iy+$02) ;Signal 'screen will require to be cleared'
               scf
call $15d4 ;Bir tuşa basılmasını bekle
;--------------------------------------------------------
; Basic satırını + relocatoru kendi yerine kopyala
;--------------------------------------------------------
ld hl,basic_line
ld de,23755
ld bc,35
ldir
;--------------------------------------------------------
; Asıl programı Basic satırının dibine kopyala
;--------------------------------------------------------
ld hl,prg_adr
ld de,$5cee
ld bc,uzunluk
ldir
;--------------------------------------------------------
; Header'i kaydet
;--------------------------------------------------------
               xor a
               ld ix,header
               ld de,17
               call $04c2
;--------------------------------------------------------
; Basic + Code haline getirilen programı kaydet
;--------------------------------------------------------
               ld a,$ff
               ld ix,23755
               ld de,uzunluk
               scf
               call $04c2
               rst 8
               defb 255 ; Hata kodu-1
;========================================================
; TAPE HEADER BİLGİSİ
;========================================================
header:
file_type defb 0 ;dosya tipi: program
file_name defb $16,1,0 ; AT 1,0
defb $af,$3a            ; CODE
defm "HADES"
data_lenght defw uzunluk
start_line defw 6151
prog_lenght defw uzunluk
;========================================================
; 6151 RANDOMIZE USR 23755 satırının dataları (21 byte)
; relocator dataları (14 byte) --- Toplam 35 byte
;--------------------------------------------------------
basic_line: defb $18,$07,$0e,$00,$f9,$c0,$32,$33
defb $37,$35,$35,$0e,$00,$00,$cb,$5c
defb $00,$0d,$80,$0d,$80
;--------------------------------------------------------
relocator ld hl,$5cee ; main_prg
ld de,prg_adr ; programın asıl adresi
ld bc,prg_end-prg_str
ldir
jp run_adr ; programın run adresi
main_prg ; $5cee
;========================================================
end basicode
;========================================================

Sonunda bitti gibi. Bu kısa rutinle hafızada bulunan bir kodu -Maksimum 20K- artık normal basic programı gibi kaydedip sadece LOAD "" ile yükleyip çalıştırabilirsiniz. Bu rutin ve basic+code haline gelen kod aynı tap dosyasına kaydedilir. Satır numarasını sakın değiştirmeyin. Basic+code haline gelen programın ismini değiştirebilirsiniz.
Rutin relocatable olup başlangıç adresi $AF00 olursa 20K'lık bir kod basic+code haline getirilebilir. Rutinin başlangıcına basic+code haline getirilecek kodun asm dosyası include ile eklenir. Kod içerisinde açıklamalar mevcut.
incbin ile binary kod ekleyip basic+code haline getirmeyi denemedim.