forum speccy.pl
ZX Spectrum => PROGRAMOWANIE => Wątek zaczęty przez: Abrimaal w 2012.03.25, 23:45:57
-
Poszukuję scrollera, może być najprostszy, byleby działał.
Mam kod z jakiejś gazety z 1988, ale nie wyświetla nic.
Na tyle ile potrafię, szukałem błędów, jednak 20 lat bez programowania w asm udzieliło się.
Może ktoś będzie na tyle chętny pomóc.
Powienien przewijać w dolnej linii text zaczynający się od 40000 i zakończony Enter (CHR$ 13),
o jeden pixel w lewo i wracać tam skąd został wywołany.
ORG 36200
L1 LD HL,39999
PUSH HL
PUSH HL
S1 POP HL
POP HL
INC HL
LD A, (HL)
CP 13
JR Z, L1
PUSH HL
CP 144
JR NC, L2
LD HL, (23606)
JR L3
L2 LD HL, (23675)
SUB 144
L3 LD D,0
LD E,A
LD B,8
L4 ADD HL, DE
DJNZ L4
PUSH HL
LD D,128
L10 POP IX
PUSH IX
LD HL,20735
LD E,8
L7 LD A,D
AND (IX+0)
JR Z, L5
SCF
L5 PUSH HL
LD B,32
L6 LD A,(HL)
RLA
LD (HL),A
DEC HL
DJNZ L6
INC IX
POP HL
INC H
DEC E
JR NZ, L7
L9 RRA
JR NZ, L10
POP HL
POP HL
EI
RET
-
Nie wiem, czy dokładnie czegoś takiego oczekiwałeś, ale masz... W załączniku tap z działającym przykładem. A kod jest taki:
org 32768
main_loop:
halt
call one_scroll
ld bc,$7ffe
in a,(c)
and 1
jr nz, main_loop
ret
one_scroll:
di
ld a,(bpos)
or a
jr nz,skip_text
ld a,7
ld (bpos),a
text_adr: equ $+1
ld hl,text
ld a,(hl)
inc hl
ld (text_adr),hl
cp 13
jr nz,get_char
ld hl,text
ld a,(hl)
inc hl
ld (text_adr),hl
get_char:
ld h,0
ld l,a
add hl,hl
add hl,hl
add hl,hl
ld de,15360
add hl,de
ld de,buf
rept 8
ldi
endm
jr do_scroll
skip_text:
dec a
ld (bpos),a
do_scroll:
ld hl,20704+31
ld de,buf
ld b,8
loop1:
push hl
ld c,32
ld a,(de)
rla
ld (de),a
loop2:
ld a,(hl)
rla
ld (hl),a
dec hl
dec c
jr nz,loop2
inc de
pop hl
inc h
djnz loop1
ei
ret
buf: ds 8
bpos: db 0
text: defm "Tekst scrollera... wpisany jako parametr dla defm albo "
defm "w dowolne miejsce w pamieci a wtedy zamiast text: defm "
defm "nalezy uzyc text: equ adres_tekstu "
db 13
end 32768
Na początku jest pętla odpalająca jako test - możesz ją usunąć i zassemblować sobie pod potrzebny adres tylko samą procedurę "one_scroll" i ją wołać z BASICa co ramkę (sprawdziłem - też działa). Tekst masz wpisany w defm na końcu, ale jeśli chcesz go mieć w innym miejscu to defm zamieniasz na odpowiednie equ. Procedura - za wyjątkiem zmiennych (buf, bpos i text_adr) jest relokowalna. Zmienne można przerzucić na przykład do bufora drukarki albo w ekran po przysłonięciu atrybutami i wtedy będzie całkowicie relokowalna, ale to już zostawiam jako pracę domową ;)
Cały kod oczywiście używa składni pasmo i przy jego użyciu testowy tap generuje się tak:
pasmo --name srol --tapbas sroll.asm sroll.tap
-
A tu jeszcze jedno o co pytałeś - na szybko zmontowany kursor graficzny.
Kod jest taki sobie, ale działa.
Procedura na starcie czyta współrzędne strzałki z 23296 (x) i 23297 (y) (nie będzie więc działać w trybie 128 - tam trzeba gdzieś przenieść zmienne). Po wywołaniu wyświetla strzałkę, której bitmapa znajduje się na końcu kodu (16x16 pikseli przesunięte 8 razy - każda klatka ma 48 bajtów) nakładając (bez maskowania, choć to powinno się dać dość łatwo dorobić) na istniejący obraz ale bez ruszania atrybutów. Następnie czeka na klawisze - obsługa przesuwania to procedura move_arrow - ją trzeba by zmodyfikować, żeby zmienić sterowanie - teraz jest QAOP. Strzałka jest przesuwana z buforowaniem - nie psuje zawartości ekranu. Po wciśnięciu spacji albo 1 (obsługa tego jest już w głównej pętli i tam trzeba zmieniać obsługę) strzałka jest kasowana i procedura wraca do BASICa zostawiając w 23296 i 23297 współrzędne a dodatkowo w 23298 jest 1 jeśli wciśnięto spację lub 0 jeśli wciśnięto 1 (rozróżnienie select/cancel).
Na podstawie współrzędnych można wykonać jakieś działanie a potem wywołać procedurę jeszcze raz, co przywróci strzałkę w to samo miejsce i pozwoli na dalszy wybór.
Żeby sobie uprościć pisanie strzałka nie dochodzi całkiem do lewego brzegu - maksymalna zwracana współrzędna to 238x190.
Kod oczywiście jak zwykle dla pasmo.
org 32768
ld a,(23296)
ld (pos_x),a
ld a,(23297)
ld (pos_y),a
call buffer_it
main_loop:
halt
call restore_it
call move_arrow
call buffer_it
call put_arrow
ld e,0
ld bc,$f7fe
in a,(c)
and 1
jr z,exit_loop
ld e,1
ld bc,$7ffe
in a,(c)
and 1
jr nz,main_loop
exit_loop:
push de
call restore_it
pop de
ld a,(pos_x)
ld (23296),a
ld a,(pos_y)
ld (23297),a
ld a,e
ld (23298),a
ret
buffer_it:
ld a,(pos_x)
ld c,a
ld a,(pos_y)
ld b,a
call pixel_address
ld de,buf
ld b,16
ld a,(pos_y)
cp 175
jr c,buffer_it1
ld b,a
ld a,192
sub b
ld b,a
buffer_it1:
push hl
ld a,(hl)
ld (de),a
inc l
inc de
ld a,(hl)
ld (de),a
inc l
inc de
ld a,(hl)
ld (de),a
inc de
pop hl
call next_hl
djnz buffer_it1
ret
restore_it:
ld a,(pos_x)
ld c,a
ld a,(pos_y)
ld b,a
call pixel_address
ld de,buf
ld b,16
ld a,(pos_y)
cp 175
jr c,restore_it1
ld b,a
ld a,192
sub b
ld b,a
restore_it1:
push hl
ld a,(de)
ld (hl),a
inc l
inc de
ld a,(de)
ld (hl),a
inc l
inc de
ld a,(de)
ld (hl),a
inc de
pop hl
call next_hl
djnz restore_it1
ret
put_arrow:
ld a,(pos_x)
ld c,a
ld a,(pos_y)
ld b,a
call pixel_address
push hl
ld h,0
ld l,a
add hl,hl
add hl,hl
add hl,hl
add hl,hl
push hl
pop de
add hl,hl
add hl,de
ld de,arrow
add hl,de
pop de
ex de,hl
ld b,16
ld a,(pos_y)
cp 175
jr c,put_arrow1
ld b,a
ld a,192
sub b
ld b,a
put_arrow1:
push hl
ld a,(de)
or (hl)
ld (hl),a
inc l
inc de
ld a,(de)
or (hl)
ld (hl),a
inc l
inc de
ld a,(de)
or (hl)
ld (hl),a
inc l
inc de
pop hl
call next_hl
djnz put_arrow1
ret
next_hl:
inc h
ld a,h
and 7
jp nz,next_hl_skip
ld a,l
add a,32
ld l,a
jp c,next_hl_skip
ld a,h
sub 8
ld h,a
next_hl_skip:
ret
pixel_address:
ld a,b
and a
rra
scf
rra
and a
rra
xor b
and $f8
xor b
ld h,a
ld a,c
rlca
rlca
rlca
xor b
and $c7
xor b
rlca
rlca
ld l,a
ld a,c
and 7
ret
move_arrow:
; O/P
ld bc,$dffe
in a,(c)
ld e,0
bit 0,a
jr nz,move_arrow1
ld e,1
move_arrow1:
bit 1,a
jr nz,move_arrow2
ld e,-1
move_arrow2:
ld d,0
; Q
ld bc,$fbfe
in a,(c)
and 1
jr nz,move_arrow3
ld d,-1
move_arrow3:
; A
ld bc,$fdfe
in a,(c)
and 1
jr nz,move_arrow4
ld d,1
move_arrow4:
ld a,(pos_x)
add a,e
cp 239
jr nc,move_arrow5
ld (pos_x),a
move_arrow5:
ld a,(pos_y)
add a,d
cp 191
ret nc
ld (pos_y),a
ret
pos_x: db 0
pos_y: db 191
buf: ds 48
arrow:
db %00000000, %00000000, %00000000
db %01111111, %10000000, %00000000
db %01111111, %00000000, %00000000
db %01111110, %00000000, %00000000
db %01111100, %00000000, %00000000
db %01110100, %00000000, %00000000
db %01100010, %00000000, %00000000
db %01000001, %00000000, %00000000
db %00000000, %10000000, %00000000
db %00000000, %01000000, %00000000
db %00000000, %00100000, %00000000
db %00000000, %00010000, %00000000
db %00000000, %00001000, %00000000
db %00000000, %00000100, %00000000
db %00000000, %00000010, %00000000
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00111111, %11000000, %00000000
db %00111111, %10000000, %00000000
db %00111111, %00000000, %00000000
db %00111110, %00000000, %00000000
db %00111010, %00000000, %00000000
db %00110001, %00000000, %00000000
db %00100000, %10000000, %00000000
db %00000000, %01000000, %00000000
db %00000000, %00100000, %00000000
db %00000000, %00010000, %00000000
db %00000000, %00001000, %00000000
db %00000000, %00000100, %00000000
db %00000000, %00000010, %00000000
db %00000000, %00000001, %00000000
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00011111, %11100000, %00000000
db %00011111, %11000000, %00000000
db %00011111, %10000000, %00000000
db %00011111, %00000000, %00000000
db %00011101, %00000000, %00000000
db %00011000, %10000000, %00000000
db %00010000, %01000000, %00000000
db %00000000, %00100000, %00000000
db %00000000, %00010000, %00000000
db %00000000, %00001000, %00000000
db %00000000, %00000100, %00000000
db %00000000, %00000010, %00000000
db %00000000, %00000001, %00000000
db %00000000, %00000000, %10000000
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00001111, %11110000, %00000000
db %00001111, %11100000, %00000000
db %00001111, %11000000, %00000000
db %00001111, %10000000, %00000000
db %00001110, %10000000, %00000000
db %00001100, %01000000, %00000000
db %00001000, %00100000, %00000000
db %00000000, %00010000, %00000000
db %00000000, %00001000, %00000000
db %00000000, %00000100, %00000000
db %00000000, %00000010, %00000000
db %00000000, %00000001, %00000000
db %00000000, %00000000, %10000000
db %00000000, %00000000, %01000000
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000111, %11111000, %00000000
db %00000111, %11110000, %00000000
db %00000111, %11100000, %00000000
db %00000111, %11000000, %00000000
db %00000111, %01000000, %00000000
db %00000110, %00100000, %00000000
db %00000100, %00010000, %00000000
db %00000000, %00001000, %00000000
db %00000000, %00000100, %00000000
db %00000000, %00000010, %00000000
db %00000000, %00000001, %00000000
db %00000000, %00000000, %10000000
db %00000000, %00000000, %01000000
db %00000000, %00000000, %00100000
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000011, %11111100, %00000000
db %00000011, %11111000, %00000000
db %00000011, %11110000, %00000000
db %00000011, %11100000, %00000000
db %00000011, %10100000, %00000000
db %00000011, %00010000, %00000000
db %00000010, %00001000, %00000000
db %00000000, %00000100, %00000000
db %00000000, %00000010, %00000000
db %00000000, %00000001, %00000000
db %00000000, %00000000, %10000000
db %00000000, %00000000, %01000000
db %00000000, %00000000, %00100000
db %00000000, %00000000, %00010000
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000001, %11111110, %00000000
db %00000001, %11111100, %00000000
db %00000001, %11111000, %00000000
db %00000001, %11110000, %00000000
db %00000001, %11010000, %00000000
db %00000001, %10001000, %00000000
db %00000001, %00000100, %00000000
db %00000000, %00000010, %00000000
db %00000000, %00000001, %00000000
db %00000000, %00000000, %10000000
db %00000000, %00000000, %01000000
db %00000000, %00000000, %00100000
db %00000000, %00000000, %00010000
db %00000000, %00000000, %00001000
db %00000000, %00000000, %00000000
db %00000000, %00000000, %00000000
db %00000000, %11111111, %00000000
db %00000000, %11111110, %00000000
db %00000000, %11111100, %00000000
db %00000000, %11111000, %00000000
db %00000000, %11101000, %00000000
db %00000000, %11000100, %00000000
db %00000000, %10000010, %00000000
db %00000000, %00000001, %00000000
db %00000000, %00000000, %10000000
db %00000000, %00000000, %01000000
db %00000000, %00000000, %00100000
db %00000000, %00000000, %00010000
db %00000000, %00000000, %00001000
db %00000000, %00000000, %00000100
db %00000000, %00000000, %00000000
end 32768
-
Mat, scroller działa wspaniale, lecz to trochę za mało dla mnie, wiem tylko jak przestawić generator znaków.
Czy da się w nim zmienić linię, w której jest wyświetlany (chciałbym uruchomić 2 scrollery).
I jak zmienić kolor tekstu?
-
Pozycję scrollera na ekranie określa parametr instrukcji
ld hl,20704+31
Żeby go przesunąć musisz sobie wyliczyć początek odpowiedniej ośmiopikselowej linii ekranu - 20704 to trzecia tercja ekranu (pierwsza to 16384, druga 18432, trzecia to 20480) a w niej siódmy (licząc od zera) wiersz ekranu czyli 7*32=224, 224+20480=20704. Dodanie 31 ustawia wskaźnik na ostatni bajt linii bo przewijanie robione jest od prawej do lewej.
Żeby uruchomić dwa scrollery na raz musiałbyś tak na prawdę przepisać procedurę dwa razy zmieniając nazwy etykiet i dodając stosowne bufory itp. i oczywiście adres na ekranie.
Ustawienie koloru tekstu to zupełnie inna bajka - scroller dotyka tylko części bitmapowej. Żeby ustawić kolor musisz po prostu zapisać odpowiednie dane do pamięci atrybutów w miejscu w którym scroller będzie wyświetlany.
W powyższym przykładzie dla adresu bitmapy 20704 adres atrybutów to 22528+23*32=23264 a ustawienie żółtego INKa z czarnym PAPERem w linii scrollera to na przykład taki kawałek kodu:
ld hl,23264
ld de,23265
ld bc,31
ld (hl),6
ldir
A w ogóle jeśli chodzi o scrollery i zrozumienie tego jak się je robi to zapraszam tutaj: http://www.speccy.pl/articles.php?article_id=11 - przykładowy kod jest dokładnie opisany ;)
-
To już wczoraj testowałem, zmieniałem adres i do wszystkich nazw etykiet i zmiennych dodałem 2, to pewnie coś przegapiłem, choć pasmo zassemblował "podwójny" kod bez błędów. Popróbuję jeszcze.
-
Nie wiem co ci nie poszło... Podwójny kod z ustawianiem kolorów wygląda tak:
org 32768
ld hl,23232
ld de,23233
ld bc,32
ld (hl),57
ldir
ld bc,31
ld (hl),58
ldir
main_loop:
halt
call one_scroll1
call one_scroll2
ld bc,$7ffe
in a,(c)
and 1
jr nz, main_loop
ret
one_scroll1:
di
ld a,(bpos1)
or a
jr nz,skip_text1
ld a,7
ld (bpos1),a
text_adr1: equ $+1
ld hl,text1
ld a,(hl)
inc hl
ld (text_adr1),hl
cp 13
jr nz,get_char1
ld hl,text1
ld a,(hl)
inc hl
ld (text_adr1),hl
get_char1:
ld h,0
ld l,a
add hl,hl
add hl,hl
add hl,hl
ld de,15360
add hl,de
ld de,buf1
rept 8
ldi
endm
jr do_scroll1
skip_text1:
dec a
ld (bpos1),a
do_scroll1:
ld hl,20704+31
ld de,buf1
ld b,8
loop11:
push hl
ld c,32
ld a,(de)
rla
ld (de),a
loop21:
ld a,(hl)
rla
ld (hl),a
dec hl
dec c
jr nz,loop21
inc de
pop hl
inc h
djnz loop11
ei
ret
buf1: ds 8
bpos1: db 0
text1: defm "Tekst scrollera... wpisany jako parametr dla defm albo "
defm "w dowolne miejsce w pamieci a wtedy zamiast text: defm "
defm "nalezy uzyc text: equ adres_tekstu "
db 13
one_scroll2:
di
ld a,(bpos2)
or a
jr nz,skip_text2
ld a,7
ld (bpos2),a
text_adr2: equ $+1
ld hl,text2
ld a,(hl)
inc hl
ld (text_adr2),hl
cp 13
jr nz,get_char2
ld hl,text2
ld a,(hl)
inc hl
ld (text_adr2),hl
get_char2:
ld h,0
ld l,a
add hl,hl
add hl,hl
add hl,hl
ld de,15360
add hl,de
ld de,buf2
rept 8
ldi
endm
jr do_scroll2
skip_text2:
dec a
ld (bpos2),a
do_scroll2:
ld hl,20704+31-32
ld de,buf2
ld b,8
loop12:
push hl
ld c,32
ld a,(de)
rla
ld (de),a
loop22:
ld a,(hl)
rla
ld (hl),a
dec hl
dec c
jr nz,loop22
inc de
pop hl
inc h
djnz loop12
ei
ret
buf2: ds 8
bpos2: db 0
text2: defm "Tekst drugiego scrollera wpisany dokladnie "
defm "tak samo jak tekst pierwszego scrollera... "
db 13
end 32768
Pierwszy scroller wyświetla się w najniższej linii ekranu na czerwono (one_scroll1), drugi w przedostatniej na niebiesko (one_scroll2).