Autor Wątek: Asembler ZX Spectrum - Pytania na początek (Cartridge).  (Przeczytany 13521 razy)

siudym

  • **
  • Wiadomości: 83
  • Miejsce pobytu:
    IŁAWA
Nadszedł czas aby zacząć coś porobić w ASM na ZX Spectrum wiec mam kilka szybkich pytań :)

- Jaki asembler/kompiler najlepiej używać? PASMO ?
- Jak się ma format Cartridge w ZX? Chyna nie jest popularny, ale nawet jeśli chciałbym zrobić coś używając tego formatu.
Gdzie mapuje sie ROM w Carcie na pamie pamieci? Czy przejmuje miejsce BASIC czyli $0000-3FFF ?
Czy trzeba coś dodatkowo zdefiniować w kodzie gdy chcę stworzyć kod dla Carta? Czy wystarczy ORG $0000 i wielkość max 16KB.

ZX Spectrum nie posiada Sprites, tak? Wiec wszelkie obiekty sprajto-podobne generowane sa tak samo jak piksele ekranu ale podczas przemieszczania
ich poprzednie miejsce jest kasowane z ekranu i wstawiane i iles-tam pix dalej zaleznie od ich szybkosci?

Są jakieś ograniczenia podczas zapisu do pamięci ekranu? Czy można sobie zapisywać w dowolnej chwili zmieniając coś na ekranie?

matofesi

  • *****
  • Wiadomości: 2073
  • Miejsce pobytu:
    Toruń/Poland
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #1 dnia: 2023.01.09, 12:19:18 »
Nadszedł czas aby zacząć coś porobić w ASM na ZX Spectrum wiec mam kilka szybkich pytań :)

- Jaki asembler/kompiler najlepiej używać? PASMO ?

Pasmo jest stosunkowo "bezpiecznym" wyborem - ma obsługuje wszystko, co może być potrzebne z makrami, pętlami itp. I pozwala generować w wyniku wszystkie istotne formaty.

Cytuj
- Jak się ma format Cartridge w ZX? Chyna nie jest popularny, ale nawet jeśli chciałbym zrobić coś używając tego formatu.
Gdzie mapuje sie ROM w Carcie na pamie pamieci? Czy przejmuje miejsce BASIC czyli $0000-3FFF ?

Cartridge to po prostu podmiana ROMu - 16 kilo od adresu 0 i bez dostępu do ROMu systemowego.

Cytuj
Czy trzeba coś dodatkowo zdefiniować w kodzie gdy chcę stworzyć kod dla Carta? Czy wystarczy ORG $0000 i wielkość max 16KB.

Powinien wystarczyć ORG.

Cytuj
ZX Spectrum nie posiada Sprites, tak? Wiec wszelkie obiekty sprajto-podobne generowane sa tak samo jak piksele ekranu ale podczas przemieszczania
ich poprzednie miejsce jest kasowane z ekranu i wstawiane i iles-tam pix dalej zaleznie od ich szybkosci?

W dużym uproszczeniu - tak. Wszystko co chcesz mieć na ekranie musisz wyrysować na piechotę :)

Cytuj
Są jakieś ograniczenia podczas zapisu do pamięci ekranu? Czy można sobie zapisywać w dowolnej chwili zmieniając coś na ekranie?

Są - poczytaj o memory contention. W uproszczeniu - jeśli kod usiłuje dostać się do "niskiego" RAMu ($4000-$7fff) w tym samym czasie kiedy ULA pobiera z niego dane procesor zostanie wstrzymany na 1-6 taktów. Dokładny pattern tych wstrzymań oraz liczba "bezpiecznych" taktów od początku ramki jest zależna od modelu.


A tak z czystej  ciekawości... dlaczego cartridge? Bo w wypadku ZXów to takie trochę perwersyjne samoograniczanie ;)

« Ostatnia zmiana: 2023.01.09, 12:26:55 wysłana przez matofesi »

siudym

  • **
  • Wiadomości: 83
  • Miejsce pobytu:
    IŁAWA
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #2 dnia: 2023.01.10, 11:47:08 »
Dzięki. Co do Carta to takie konsolowe "zboczenie" :) Oczywiscie nigdy tego nie wymagam, ale zawsze z ciekawosci na początku chcę coś zrobić w tym formacie.

Jakie są metody synchronizacji petli CPU z predkoscia ramki? Szperam w gogle, ale na razie nic spewnego nie doczytalem, jedynie, ze HALT wystarczy, ale nie jest zalecany (chyba).

matofesi

  • *****
  • Wiadomości: 2073
  • Miejsce pobytu:
    Toruń/Poland
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #3 dnia: 2023.01.10, 12:14:22 »
HALT wstrzymuje procesor (wewnętrznie wykonuje nieskończoną pętlę NOP) aż do wywołania następnego przerwania - w wypadku ZXów przerwanie wywołuje ULA raz na ramkę. Jeśli piszesz kod od $0000 wystarczy procedurę przyjęcia przerwania umieścić pod adresem $38. Albo umieścić tam EI+RET i synchronizować samym HALTem.

Jeśli robisz kod pracujący normalnie w RAMie to synchronizacja HALTem bez dodatkowych przygotowań wywołuje najpierw procedurę w ROMie, która skanuje klawiaturę i robi kilka innych drobiazgów. A to powoduje, że synchronizacja nie jest płynna - zależnie od tego co akurat robi ROM twój kod uruchomi się trochę wcześniej albo trochę później.

Żeby w takiej sytuacji mieć cały czas dla siebie należy przygotować procedurę obsługi w RAMie, ustawić tablicę wektorów, wycelować w nią rejestr I i przełączyć procesor w tryb IM 2. Tak w jednym zdaniu ;)

Można też - jeśli kod ma działać tylko na prawdziwych ZXach (nie zadziała na Timexach a na innych klonach będzie różnie) użyć "pływających atrybutów" i synchronizować się (z dokładnością do prędkości pętli) do ekranu według zawartości atrybutu. Ale to jest już zupełnie inna bajka ;)


siudym

  • **
  • Wiadomości: 83
  • Miejsce pobytu:
    IŁAWA
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #4 dnia: 2023.02.07, 10:30:44 »
Mam przykładowy kod, ale nie mam pojęcia jak go uruchomić  ;D
Skompilowałem go PASMO i próbowałem uruchomić Spectaculator jako .BIN bo nie wiem jakie powinno być rozszerzenie tak skompilowanego kodu. Niestety nic nie uruchamia się. Potrzebuje jakieś podstawowe info.

org 32768 ;we can ORG (or assemble) this code anywhere really
;a beginner's, unoptimised sprite routine
main: halt ;this stops the program until the Spectrum is about to refresh the TV screen
;the HALT is important to avoid sprite flicker, and it slows down the program
call deletesprite ;we need to delete the old position of the sprite
call movesprite ;move the sprite! Could be based on player key input or baddy AI
call drawsprite ;get correct preshifted graphic, and draw it on the screen
jr main ;loop!
;
deletesprite: ;we need to delete the old sprite before we draw the new one.  The sprite is 3 bytes wide & 16 pixels high
ld a,(x_coordinate) ;make C=xcor and B=ycor
ld c,a
ld a,(y_coordinate)
ld b,a
call yx2pix ;point DE at the corresponding screen address
ld b,16 ;sprite is 16 lines high
deleteloop: ;NEW!
ld a,0 ;empty A to delete
ld (de),a ;repeat a total of 3 times
inc e ;next column along
ld (de),a
dec e ;NEW
call nextlinedown ;move DE down one line
djnz deleteloop ;repeat 16 times
ret
;
movesprite: ;very simple routine that just increases the x coordinate
ld a,(x_coordinate)
inc a
ld (x_coordinate),a
cp 232 ;check if the sprite has moved all the way to the right (256-24)
ret c ;return if not
ld a,0 ;if yes then back to left
ld (x_coordinate),a
ret
;
drawsprite:
ld a,(x_coordinate) ;make C=xcor and B=ycor
ld c,a
ld a,(y_coordinate)
ld b,a
call yx2pix ;point DE at corresponding screen position
ld a,(x_coordinate) ;but we still need to find which preshifted sprite to draw
and 00000111b ;we have 8 preshifted graphics to choose from, cycled 0-7 in the right hand 3 bits of the x coordinate
call getsprite ;point HL at the correct graphic
ld b,16 ;sprite is 16 lines high
drawloop: ;NEW
ld a,(hl) ;take a byte of graphic
ld (de),a ;and put it on the screen
inc hl ;next byte of graphic
inc e ;next column on screen
ld a,(hl) ;repeat for 3 bytes across
ld (de),a
inc hl
dec e
call nextlinedown
djnz drawloop ;repeat for all 16 lines
ret
;
x_coordinate: db 0
y_coordinate: db 0
;
nextlinedown: ;don't worry about how this works yet!
inc d ;just arrive with DE in the display file
ld a,d ;and it gets moved down one line
and 7
ret nz
ld a,e
add a,32
ld e,a
ret c
ld a,d
sub 8
ld d,a
ret
;
yx2pix: ;don't worry about how this works yet! just arrive with arrive with B=y 0-192, C=x 0-255
ld a,b ;return with DE at corresponding place on the screen
rra
rra
rra
and 24
or 64
ld d,a
ld a,b
and 7
or d
ld d,a
ld a,b
rla
rla
and 224
ld e,a
ld a,c
rra
rra
rra
and 31
or e
ld e,a
ret
;
getsprite: ;don't worry much about how this works!  for an alternative method that
;uses a table see 'getsprite_alternativemethod'
;Arrive A holding which pixel within a byte (0-7), point HL at correct graphic
ld h,0 ;we need to multiply A by 48, do it in HL
ld l,a
add hl,hl ;x2
add hl,hl ;x4
add hl,hl ;x8
add hl,hl ;x16
add hl,hl ;x32
ld bc,spritegraphic0
add hl,bc ;HL now pointing at correct sprite frame
ret
;
spritegraphic0: ;8 preshifted graphics, each one 3 bytes wide and 16 pixels high, this one a simple square
; ASM data file from a ZX-Paintbrush picture with 16 x 128 pixels (= 2 x 16 characters)

; block based output of pixel data - each block contains 16 x 16 pixels

; block at pixel position (0,0):

db 126, 0, 255, 0, 219, 0, 255, 0
db 189, 0, 195, 0, 255, 0, 126, 0
db 24, 0, 24, 0, 24, 0, 24, 0
db 24, 0, 36, 0, 66, 0, 129, 0

; block at pixel position (0,16):

db 63, 0, 127, 128, 109, 128, 127, 128
db 94, 128, 97, 128, 127, 128, 63, 0
db 12, 0, 12, 0, 12, 0, 12, 0
db 12, 0, 18, 0, 33, 0, 64, 128

; block at pixel position (0,32):

db 31, 128, 63, 192, 54, 192, 63, 192
db 47, 64, 48, 192, 63, 192, 31, 128
db 6, 0, 6, 0, 6, 0, 6, 0
db 6, 0, 9, 0, 16, 128, 32, 64

; block at pixel position (0,48):

db 15, 192, 31, 224, 27, 96, 31, 224
db 23, 160, 24, 96, 31, 224, 15, 192
db 3, 0, 3, 0, 3, 0, 3, 0
db 3, 0, 4, 128, 8, 64, 16, 32

; block at pixel position (0,64):

db 7, 224, 15, 240, 13, 176, 15, 240
db 11, 208, 12, 48, 15, 240, 7, 224
db 1, 128, 1, 128, 1, 128, 1, 128
db 1, 128, 2, 64, 4, 32, 8, 16

; block at pixel position (0,80):

db 3, 240, 7, 248, 6, 216, 7, 248
db 5, 232, 6, 24, 7, 248, 3, 240
db 0, 192, 0, 192, 0, 192, 0, 192
db 0, 192, 1, 32, 2, 16, 4, 8

; block at pixel position (0,96):

db 1, 248, 3, 252, 3, 108, 3, 252
db 2, 244, 3, 12, 3, 252, 1, 248
db 0, 96, 0, 96, 0, 96, 0, 96
db 0, 96, 0, 144, 1, 8, 2, 4

; block at pixel position (0,112):

db 0, 252, 1, 254, 1, 182, 1, 254
db 1, 122, 1, 134, 1, 254, 0, 252
db 0, 48, 0, 48, 0, 48, 0, 48
db 0, 48, 0, 72, 0, 132, 1, 2
;

matofesi

  • *****
  • Wiadomości: 2073
  • Miejsce pobytu:
    Toruń/Poland
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #5 dnia: 2023.02.07, 10:42:10 »
Kod działa w RAMie co oznacza, że musisz go skompilować dodając loader. Najprościej na końcu kodu dodać linię "end 32768" a potem kompilować przez

pasmo --tapbas nazwa.asm nazwa.tap

I na koniec nazwa.tap załadować normalnie do emulatora albo na fizyczny sprzęt.

siudym

  • **
  • Wiadomości: 83
  • Miejsce pobytu:
    IŁAWA
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #6 dnia: 2023.02.07, 11:01:55 »
Dzięki, działa super. Jedynie nie odpala się na RetroVirtualMachine - niby robie wszystko poprawnie, robie load taśmy, wciskam PLAY, odpalają się jakieś dźwięki (pewnie aby oddać realizm ładowania) ale nie pojawia się nic na ekranie.

A gdyby ten kod chciałbym odpalić jako .ROM cartridge ? Zmiana na ORG 0 nic nie daje, próbowałem stworzyć plik .ROM 16KB ale próba załadowania nic nie powoduje. Rozumiem, że wtedy mamy wyłączony BIOS ROM i kod od tak sobie nie zadziała?

KWF

  • *****
  • Wiadomości: 7022
  • Miejsce pobytu:
    trzecia planeta od Słońca
  • "I co ja robię tu, u-u, co Ty tutaj robisz ..."
    • PCBway
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #7 dnia: 2023.02.07, 11:14:43 »
TAP wygenerowany w sposób w jaki podał @mat działa. GIF w załączniku.
KWF
-----
R Tape loading error 0:1
Moje zabawki: https://github.com/McKlaud76

siudym

  • **
  • Wiadomości: 83
  • Miejsce pobytu:
    IŁAWA
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #8 dnia: 2023.02.07, 12:12:10 »
Pod Spectaculator działa, ale mi pod RetroVirtualMachine już nie - no chyba, że tam nie ładuje się z automatu? :)

matofesi

  • *****
  • Wiadomości: 2073
  • Miejsce pobytu:
    Toruń/Poland
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #9 dnia: 2023.02.07, 12:21:13 »
Zmiana ORG na zero spowoduje zmianę adresów, ale nie spowoduje poprawnego działania - musiałbyś na początku dodać kod ustawiający stos, przerwania itp. Pod $38 ei/ret żeby przerwania działały itp. A na koniec skompilować jako --bin i podać do emulatora jako cart IF2.

Co do RetroVirtualMachine - ten emulator jest ładny, ale do praktycznego zastosowania (zwłaszcza "programistycznego") jest mocno taki sobie. Zostań raczej przy Spectaculatorze - tam zdaje się jest normalny debugger itp.

edit:Żeby twój kod działał w ROMie należałoby mu zrobić coś takiego na początku:
org 0
di
ld sp,$7fff
im 1
ld hl,16384
ld de,16385
ld bc,6144
ld (hl),l
ldir
ld (hl),56
ld bc,768
ldir
ld a,7
out(254),a
ei
jp main
ds 56-$
ei
ret

Do tego deklaracje zmiennych trzeba zmienić z DB na EQU do RAMu, np tak:
x_coordinate:   equ $5b00
y_coordinate:   equ $5b01

I jeszcze żeby emulator nie krzyczał, że cart jest za krótki bo chce 16 kilo w ostatniej linii dodać
ds 16384-$

Tak zmodyfikowany kod się kompiluje i wykonuje poprawnie po podpięciu jako cart IF2.
« Ostatnia zmiana: 2023.02.07, 12:41:03 wysłana przez matofesi »

siudym

  • **
  • Wiadomości: 83
  • Miejsce pobytu:
    IŁAWA
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #10 dnia: 2023.02.07, 14:01:55 »
Jak to uruchomić? "Cart IF2" to rodzaj cartridge? Nie wiem jak to odpalić w Spectaculator.

EDIT: Ok już wiem. Zapomniałem wywalić loader z .BAT podczas kompilacji.

ds 56-$
ei
ret

- to jakieś przerwanie?

EDIT2: Tak samo działa:

   org $0038
   EI
   RET
« Ostatnia zmiana: 2023.02.07, 14:16:34 wysłana przez siudym »

matofesi

  • *****
  • Wiadomości: 2073
  • Miejsce pobytu:
    Toruń/Poland
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #11 dnia: 2023.02.07, 14:16:45 »
ds 56-$ to padding - wypełnia zerami obszar od bieżącego adresu do 55. Od 56 zaczyna się standardowa obsługa przerwać w trybie IM1 - ei/ret przyjmuje przerwanie, włącza przerwania (w momencie przyjęcia są wyłączane) i wraca z obsługi - dzięki temu halt w pętli synchronizuje kod do ramki.

siudym

  • **
  • Wiadomości: 83
  • Miejsce pobytu:
    IŁAWA
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #12 dnia: 2023.02.12, 15:30:35 »
Fajnie to działa. Czy mógłbym jakiś przykładowy kod odczytu Joya lub podstawowe informacje dostać? Bo rozumiem nie ma lekko i są jakieś przystawki różne i zależnie jaka odczyt Joy'a jest inny?

Tygrys

  • Administrator
  • *****
  • Wiadomości: 4568
  • Miejsce pobytu:
    Warszawa
  • mistrz ceremonii
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #13 dnia: 2023.02.12, 15:48:33 »
Poczytaj mój artykuł o asm w 3 numerze Zin80. Tam opisywałem w jaki sposób obsłużyć joya typu Kempston.

Link: https://speccy.pl/archive/prod.php?id=566

siudym

  • **
  • Wiadomości: 83
  • Miejsce pobytu:
    IŁAWA
Odp: Asembler ZX Spectrum - Pytania na początek (Cartridge).
« Odpowiedź #14 dnia: 2023.02.13, 13:51:40 »
Dzieki.
Nie do końca rozumiem jak działa kodowanie koloru w Color Table czyli 768 Bajtów od $5800.
Mamy 1 Bajt na ustawienie koloru jednego znaku, ale nie czaje do końca jak to jest ustawione.
Rozumiem, że mamy tam po 3 Bity RGB dla Border, Paper oraz Ink i 1 Bit jako "Jasnosc" - ale nie wiem dokładnie jaki Bit za co odpowiada.