Po úspechu s húsenicou som sa rozhodol pokračovať v oprašovaní ZX Spectra s logickým pokračovaním v assembleri. Pre tieto pokusy použijem emulátor ZX Spin, ktorý obsahuje editor pre assembler.
Odskúšam kód z článku v prvom čísle časopisu Elektronika z roku 1990. Konkrétne článok od Pavla Vanouška o časovanom prepínaní okrajov. Poďme spraviť trik.
ZX Spectrum prišlo prvé v sérií Sinclair počítačov s farbami, na ich ovládanie v basicu sú použité INK, PAPER pre nastavenie písma a pozadia, BORDER na nastavenie farby okraju. Kým INK a PAPER majú limit na jednu kombináciu po znakoch (8x8 pixelov), BORDER ide nastaviť iba jeden na celý okraj obrazovky.
Avšak, ako iné 8bity, aj Spectrum má voči 50Hz vykresľovaniu obrazovky dostatočne rýchly procesor pre zmeny farieb počas vykresľovania. Tak rýchly, že aj interpretovaný kód v basicu zvládne pár príkazov počas 1/50 sekundy (1 snímka).
1 REM ** Pavel Vanousek **
2 REM ** ELEKTRONIKA 1 90 **
4 FOR x=1 TO 21: PRINT x: NEXT x
6 BORDER 1: BORDER 2: BORDER 3: BORDER 4: BORDER 5: BORDER 6: BORDER 7: BORDER 0: PAUSE 1: GO TO 6
8 PRINT AT 9,0;"22";AT 9,0;11: GO TO 8
Príkaz "PAUSE 1" čaká na prvé prerušenie synchronizované s obrazovkou. Preto sú príkazy basicu vždy rovnako posunuté a obrazovka "drží" stabilné farby.
Tento trik funguje pre rôzne počty okrajov, ako vidieť jeden príkaz pre zmenu farby trvá približne 3 textové riadky.
Rovnaké prepínanie umožňuje aj priamo assembler, samozrejme tu sme na iných rýchlostiach a tak po každej zmene farby okraju budeme čakať nejaký počet cyklov, nech sa na obrazovke vykreslí pár riadkov.
; program 1
; spustenie RANDOMIZE USR 59000
; nakresli modry pruh, tenky biely, za nim zeleny
org 59000
ei ; povolenie prerusenia
zac: halt ; pause 1
ld a,1 ; border 1
out (254),a
ld a,7 ; border 7
ld b,10 ; vyckame 10 cyklov
wa: push bc
ld b,255
ww: djnz ww ; vnut cyklus cakania
pop bc
djnz wa ; vonk cyklus
out (254),a
ld a,4 ; border 4
ld b,130 ; kratke cakanie
we: djnz we
out (254),a
ld a,(23560) ; posledny klaves
cp 32 ; break?
jr nz,zac
ret
V emulátore ZX Spin otvoríme cez menu TOOLS poslednú položku Z80 assembler a tam vložíme kód. ORG 59000 určí, kam sa v pamäti daný kód začne ukladať.
Stručne popíšem niektoré inštrukcie:
halt - zastaví program až do vyvolania prerušenia (1/50 sekundy)
ld a,1 - naplní (load) do registra "a" (8bit pamäť v procesore, niečo ako premenná pre číslo 0-255)
out (254),a - na port 254 nastaví hodnotu registra a, v tomto prípade "1", port 254 v Spectrum hardware používa na nastavenie okraja (BORDER) a vyššie bity tohto portu pre výstup na pásku (zvuk všeobecne)
push bc - odloží "bc" teda 2 registre b,c do zásobníka
pop bc - vráti registre zo zásobníka, táto kombinácia je dobrá na uchovanie pôvodných hodnôt, pretože registrov je v procesore len malý počet voči všetkým hodnotám ktoré program potrebuje
djnz ww - špeciálna inštrukcia, "d" znamená decrement, zníženie "b" registra o 1, "jnz" znamená jump if not zero, teda skočí ak "b" ešte nieje 0 na adresu návestia "ww"
ld a,(23560) - načíta posledný stlačený kláves zo systémových premenných Spectra
ret - return, návrat či už z podprogramu (call), alebo z celého programu (do basicu)
Po zápise kódu do assembler okna ho preložíme a uložíme do pamäte cez menu FILE a položku assemble. Dole v message okne vypíše koľko bajtov výsledok zaberá a či je bez chýb. Následne z okna emulátora basicu zavoláme RANDOMIZE USR 59000.
Je vidieť, že napriek čakaniu 130 cyklov je vykreslený zmenenou farbou pásik o šírke len zhruba 1 riadku (medzi modrou a zelenou).
Keďže assembler je omnoho rýchlejší, môžeme meniť počas zobrazovania aj PAPER a INK hodnoty vrámci jedného znaku.
; program 2
; spustenie RANDOMIZE USER 59034
; vykresli jeden znak s modrym a zltym pozadim
ei
zas: halt ;pause 1
call cak1
ld hl,22528 ; adresa atributu
ld (hl),3*8 ; paper 3, ink 0
inc hl
ld (hl),4*8 ; paper 3, ink 0
dec hl
call cak2 ; cakaj aby presla 1/3
ld (hl),6*8+128 ; paper 6, ink 0, bright
inc hl
ld (hl),5*8+64 ; paper 5, ink 0, flash
dec hl
call cak2 ; cakaj aby presla 1/3
ld (hl),1*8+5 ; paper 1, ink 5
inc hl
ld (hl),7*8 ; paper 7, ink 0
dec hl
ld a,(23560) ; klavesa
cp 32 ; break?
jr nz, zas
cak1: ld b,20 ; dlzka cakania
c1: push bc
ld b,48
c2: djnz c2
pop bc
djnz c1
ret
cak2: ld b,50
cc2: djnz cc2
ret
Ak program dáme za prvý, bude začínať na adrese 59034. Pre lepší efekt najskôr niečo vypíšeme na prvé dva znaky až potom ho spustíme:
10 PRINT AT 0,0;"ZX": RANDOMIZE USR 59034
Jediná novinka voči predchádzajúcemu programu je tu adresovanie PAPER,INK atribútov prvého a druhého znaku. Nachádza sa na adrese 22528 a 22529 (používam inc hl a dec hl pre posun medzi nimi).
Na obrázku to nevidieť, ale prostredná časť písmena "Z" bliká. Tá čierno-zelená. To zabezpečuje ULA, nie tento kód. Ten len zapína blikanie v 1/3 vykresľovania a potom zas vypína.
Na záver, tým že port 254 okrem okraju zabezpečuje aj zvuk / magnetofón, dá sa jedným OUT príkazom robiť efekt ako zvukový tak grafický. Napríklad pri hrách pri streľbe alebo zásahu. Veľmi šikovné. Uvádzam jednoduchý cyklus, žiadny zvláštny zvukový efekt nevytvorí, len akýsi šum.
; program 3
; efekty s okrajom a zvukom
; randomize usr 59075
ld de,38970 ; dlzka trvania
ld hl,0
lopk: ld a,h
out (254),a ; spodne 3 bity border
inc hl ; ale 4,5 bit je zvuk
dec de
ld a,d
cp 0
jp nz,lopk
ret
R.I.P. Sir Clive Sinclair 16.9.2021
Žiadne komentáre:
Zverejnenie komentára