Piszemy DEMOArtykuł dotyczy procedur obsługi płynących napisów w pierwszej części naszego dema. Poniżej zamieszczone są trzy procedury, które należy skompilować na dysk i zachować, oraz dodatkowe dwie procedury pomocnicze. Procedura "HSCROLL.ASM" realizuje przesuw poziomy dwu najmniejszych płynących napisów. Oto jej tekst źródłowy:
Procedure Equ $9DA5
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
DList Equ $9800
HHScrol Equ $0089
Text Equ $7000
Opt List_err+Code_dsk
Org Procedure
Jmp InitScrl
IntProc Dec HHScrol
Lda HHScrol
Cmp #$0B
Bne L2
Lda #$0F
Sta HHScrol
Inc DList+$28
Inc DList+$78
Bne L1
Inc DList+$29
Inc DList+$79
L1 Lda DList+$28
Cmp #$E0
Bne L2
Lda DList+$29
Cmp #$71
Bne L2
Lda <Text
Sta DList+$28
Sta DList+$78
Lda >Text
Sta DList+$29
Sta DList+$79
L2 Rts
InitScrl Lda #$0F
Sta HHScrol
Rts
Procedura odwołuje się do zamieszczanych w poprzednich artykułach procedur: "DLI.ASM", "DLIV.ASM" oraz korzysta z tekstu umieszczonego w pamięci od adresu $7000. Uruchomienie procedury powoduje wykonanie jedynie jej fragmentu od etykiety InitScrl - ustawienie zmiennej HHScrol. Dla przypomnienia podajemy, że zmienna ta przechowuje wartość rejestru Hscrol dla płynących napisów i jest przepisywana do Hscrol'a podczas przerwania Display List. Właściwy przesuw napisu wykonuje dopiero główna część procedury (od etykiety IntProc), która jest wywoływana co 1/50 sekundy przez przerwanie Timer'a 2. W każdym obiegu tego przerwania zmniejszana jest wartość HHScrol, co powoduje delikatne przesuwanie napisów. W przypadku gdy HHScrol osiągnie wartość $OB, oba napisy trzeba przesunąć zgrubnie poprzez zwiększenie adresów pamięci ekranu w Display List i ustawienie HHScroll'a na początkową wartość. Gdy tekst się skończy, należy puścić go od początku.Druga procedura to "VSCROLL.ASM". Obsługuje ona dwa pionowe napisy w grafice PMG.
Procedure Equ $9D49
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Pomoc Equ $0080
Start_pl Equ $9000
Text Equ $6E00
VText Equ $0084
Znak Equ $9A92
Opt List_err+Code_dsk
Org Procedure
Jmp Init_Scrl
IntProc Lda Licznik
Bne L3
Ldy #$00
Lda (VText),y
Inc VText
Bne L1
Inc VText+$01
Ldx VText+$01
Cpx #$70
Bne L1
Ldx >Text
Stx VText+$01
L1 Jsr Znak
Ldy #$00
Ldx #$00
L2 Lda (Pomoc),y
Sta Start_pl+$04A2,x
Sta Start_pl+$04A3,x
Iny
Inx
Inx
Cpy #$08
Bne L2
L3 Ldx #$00
L4 Lda Start_pl+$0432,x
Sta Start_pl+$0431,x
Sta Start_pl+$0631,x
Inx
Cpx #$80
Bne L4
Inc Licznik
Lda Licznik
Cmp #$10
Bne L5
Lda #$00
Sta Licznik
L5 Rts
Init_Scrl Ldx <Text
Ldy >Text
Stx VText
Sty VText+$01
Rts
Licznik Dta B($00)
Podobnie jak poprzednia, ta procedura korzysta z tekstu, tym razem umieszczonego od adresu $6E00. Obszar grafiki PMG wskazywany jest przez etykietę Start_pl. Wykorzystywane są również dwubajtowe zmienne umieszczone na stronie zerowej: Pomoc (zmienna pomocnicza) oraz VText (wskazująca na kolejną literę tekstu).Jak poprzednio, wywołanie procedury inicjuje tylko odpowiednie zmienne (VText). Część główna procedury rozpoczyna się od etykiety IntProc. Na początku sprawdzana jest wartość Licznika (zmienna, która przyjmuje wartości od $OO do $00. Jeśli Licznik jest różny od zera, to wystarczy tylko przepisać dane w obszarze pamięci PMG o jeden bajt w górę, co spowoduje przesunięcie tekstu. Gdy Licznik równy jest zero, oznacza to, że napis został przesunięty o całą literę i trzeba pobrać kolejny znak z tekstu (wskazuje na nią zmienna VText) i wywołać procedurę Znak ze znakiem w akumulatorze. Procedura ta zwraca w zmiennej Pomoc adres znaku w zestawie znaków:
Procedure Equ $9A92
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Zestaw Equ $E000
Pomoc Equ $0080
Opt List_err+Code_dsk
Org Procedure
Pha
And #$60
Lsr @
Lsr @
Lsr @
Lsr @
Lsr @
Clc
Adc >Zestaw
Sta Pomoc+$01
Pla
And #$1F
Asl @
Asl @
Asl @
Sta Pomoc
Rts
Powyższa procedura korzysta ze standardowego zestawu znaków Atari, umieszczonego od adresu $E000. Proponujemy skompilowanie wersji tej procedury ze zmienionym adresem zestawu znaków na $8C00, gdyż w przyszłości w tym miejscu pamięci będzie się znajdował zestaw znaków ze zdefiniowanymi przez nas polskimi literami.Wróćmy do opisu procedury "VSCROLL.ASM". Po odnalezieniu adresu znaku w zestawie należy przepisać wygląd znaku w pamięć PMG. Ostatnia procedura przesuwu napisu w pierwszej części dema to "BSCROLL.ASM". Procedura ta tworzy płynący napis o szerokości i wysokości ośmiu znaków trybu $02 Antic'a:
Procedure Equ $9DE6
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
BHScrol Equ $0088
BText Equ $0086
Dlist Equ $9800
Pomoc Equ $0080
Pomoc2 Equ $0082
Scrol2 Equ $6600
Text Equ $7200
Znak Equ $9A92
Opt List_err+Code_dsk
Org Procedure
Jmp Init_Scrl
IntProc Lda BHScrol
Eor #$02
Sta BHScrol
Cmp #$0F
Bne L8
Ldx #$15
L1 Inc Dlist+$7D,x
Dex
Dex
Dex
Bpl L1
Lda Dlist+$7D
Cmp #$08
Bne L8
Ldx #$15
Ldy #$07
L2 Lda Tab,y
Sta Dlist+$7D,x
Dex
Dex
Dex
Dey
Bpl L2
Ldx <Scrol2
Ldy >Scrol2
Stx Pomoc2
Sty Pomoc2+$01
Ldy #$00
Lda (BText),y
Jsr Znak
Ldy #$00
L3 Tya
Pha
Lda (Pomoc),y
Pha
Ldx #$2F
L4 Ldy #$08
Lda (Pomoc2),y
Ldy #$00
Sta (Pomoc2),y
Inc Pomoc2
Bne L5
Inc Pomoc2+$01
L5 Dex
Bpl L4
Pla
Ldx #$00
L6 Ldy #$00
Asl @
Bcc L7
Ldy #$03
L7 Pha
Tya
Ldy #$00
Sta (Pomoc2),y
Inc Pomoc2
Pla
Inx
Cpx #$08
Bne L6
Pla
Tay
Iny
Cpy #$08
Bne L8
Inc BText
Bne L8
Inc BText+$01
Lda BText+$01
Cmp #$74
Bne L8
Lda >Text
Sta BText+$01
L8 Rts
Init_Scrl Ldx <Text
Ldy >Text
Stx BText
Sty BText+$01
Lda #$0F
Sta BHScrol
Rts
Tab Dta B($00),B($38),B($70)
Dta B($A8),B($E0),B($18)
Dta B($50),B($88)
"BSCROLL.ASM" wykorzystuje zmienną BHScroll, przechowującą wartość HScrol'a tego napisu (podobnie jak w procedurze HHScroll) oraz znane procedury Dlist i Źnak Dwubajtowa zmienna BText wskazuje na kolejny znak tekstu, którego początek wskazuje stała Text ($7200). Stała Scrol2 określa adres początku pamięci ekranu dla pierwszej linii płynącego napisu.Po uruchomieniu procedury inicjowane są wartości zmiennych BText i BHScrol. W każdym obiegu przerwania wykonuje się główna cześć procedury (od etykiety IntProc). Na początku modyfikujemy wartość BHScrol'a, co powoduje delikatny przesuw tekstu. Gdy BHScrol osiągnie wartość $Of, robiony jest zgrabny przesuw kolejnych linii ekranu (pętla L1). Gdy przesunięcie zgrubne zostanie wykonane osiem razy, to najpierw przywracane są początkowe wartości adresów kolejnych linii pamięci ekranu (pętla L2) na podstawie tabeli Tab zażerającej młodsze bajty tych adresów. Potem zmienna Pomoc2 przyjmuje wartość stałej Scrol2 i pobierany jest następny znak z tekstu. Rozpoczyna się główna pętla (etykieta L3). Instrukcje w niej zawarte wykonywane są osiem razy. W trakcie każdego obiegu tej pętli modyfikowana jest kolejna linia ekranu. Pobierany jest każdy bajt wyglądu znaku i odkładany na stos. Potem w wewnętrznej pętli L4 przesuwane są kolejne bajty pamięci ekranu o osiem w lewo, co daje przesunięcie części dużej litery o jeden znak. W następnej pętli wewnętrzej (etykieta L6) bajt pobrany ze stosu rozkładany jest na bity i w ten sposób tworzony jest wygląd części kolejnego dużego znaku. Jeśli bit znaku jest ustawiony, to w pamięć ekranu wpisywana jest wartość $03, w przeciwnym wypadku - zero. Każda część dużego znaku zawiera się w jednej linii ekranu, czyli operacja przesunięcia i tworzenia nowego znaku jest wykonywana odrębnie dla każdej linii. Gdy tekst się skończy, to zmienna BText przyjmuje początkową wartość. Na zakończenie tego artykułu prezentujemy program, który pozwala oglądnąć efekty dotychczasowej pracy. Program należy nagrać na dysk i skompilować. Aby uruchomić całość, należy załadować zbiory: DLI.OBJ, DLIV.OBJ, PLAYER.OBJ, ZNAK.OBJ, BSCROLL.OBJ, HSCROLL.OBJ, VSCROLL.OBJ, RUN1.0BJ i zbiór z tekstem z poprzedniego artykułu utworzony przy pomocy Zgrywusa. "Mini-Demo" uruchamia się zleceniem RUN 600.
Procedure Equ $0600
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Cdtma2 Equ $0228
Cdtmv2 Equ $021A
BScroll Equ $9DE6
Dli Equ $9800
Dliv Equ $9897
HScroll Equ $9DA5
Player Equ $9B5B
VScroll Equ $9D49
Opt List_err+Code_dsk
Org Procedure
Jsr Dli
Jsr Dliv
Jsr Player
Jsr BScroll
Jsr HScroll
Jsr VScroll
Ldx <Timer_2
Ldy >Timer_2
Stx Cdtma2
Sty Cdtma2+$01
Koniec Lda #$01
Sta Cdtmv2
Rts
Timer_2 Lda Licznik
Eor #$01
Sta Licznik
Bne L1
Jsr Player+$03
L1 Jsr HScroll+$03
Jsr VScroll+$03
Jsr BScroll+$03
Jmp Koniec
Licznik Dta B($00)
End of File
Program inicjuje wszystkie procedury oraz przerwanie Timer'a 2, w którym wywoływane są kolejno procedury płynących napisów, i - co drugi obieg przerwania - procedurę "PLAYER.ASM".
Tomasz Bielak
Rafał Bielecki |