PISZEMY DEMOW poniższym artykule postaramy się zakończyć rozważania nad ANTIC'em. DmactlBity 0-1 określają szerokość obrazu na ekranie: 00 - brak obrazu 01 - obraz wąski (szerokość: 192 punkty) 10 - obraz normalny (szerokość: 320 punktów) 11 - obraz szeroki (szerokość: 384 punkty) Bity 2-4 dotyczą PMG (Player/Missile Graphics - grafika graczy i pocisków). Grafiką tą zajmiemy się w przyszłości przy omawianiu układu GTIA. Bit 5 określa czy DMA dla programu ANTIC'a jest włączony (bit ustawiony) czy wyłączony (bit skasowany). DMA (Direct Memory Access) to bezpośredni dostęp do pamięci bez pośrednictwa procesora. Bity 6-7 pozostają niewykorzystane. Po włączeniu komputera Dmactls przyjmuje wartość $22 (obraz normalny, włączony DMA). Przy otwieraniu trybu graficznego lub tekstowego przez system operacyjny Dmactls ustawiane jest zawsze na tę wartość. Obraz szeroki umożliwia osiągnięcie 384 punktów w jednej linii. Niestety na niektórych monitorach lub telewizorach większość danych będzie niewidoczna (poza ekranem). Dlatego też producent podaje największą rozdzielczość jako 320x192, mimo że możliwe jest osiągnięcie rozdzielczości nawet 384x216. Zestawy znakówWygląd każdego znaku w zestawie zajmuje osiem bajtów. Każdy znak zawiera się w matrycy 8x8 punktów. Jeden bajt definiuje osiem poziomych punktów znaku. Bit ustawiony oznacza, że punkt ma być zapalony. Aby odnaleźć adres danych określających wygląd znaku należy posłużyć się wzorem: adres_zestawu + nr_znaku * 8 UWAGA: Znaki numerowane są według IOCODE. Pełny zestaw zawiera dane dla 128 znaków, połówka zestawu - dane dla 64 znaków. Dlatego też w trybach $02 i $03 ANTIC-a bit 7 decyduje o inwersie znaku, a trybach $06 i $07 ANTIC-a bity 6-7 określają kolor znaku. Bity te nie biorą udziału w określaniu adresu danych definiujących znak. W trybie $03 ANTIC'a tworzenie znaków na ekranie jest nieco inne. Po wyświetleniu znaku o kodzie $00-$5F ANTIC dodaje dwie linie, co powoduje, że znak ma wielkość 8x10. Znaki o kodach $60-$7F tworzone są w inny sposób: ANTIC pozostawia u góry znaku dwie linie, natomiast dwa pierwsze bajty wyglądu znaku umieszczane są w dwóch ostatnich liniach. Ze względu na takie ułożenie danych na ekranie możliwe jest utworzenie czytelnego tekstu po odpowiednim zaprojektowaniu zestawu znaków. Z trybu tego korzystają różne edytory tekstów. Standardowo Chbas wskazuje na zestaw umieszczony w ROM'ie komputera - Charset1 o adresie $E000. Ponadto w ROM'ie znajduje się jeszcze jeden zestaw zawierający definicję znaków międzynarodowych - Charset2 o adresie $CC00. A teraz kilka przykładów. Program 1
Procedure Equ $8800
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Charset1 Equ $E000
Chbas Equ $02F4
Clrscr Equ $F420
Crsinh Equ $02F0
Kbcodes Equ $02FC
Rtclok Equ $0012
Zestaw Equ $9000
Opt List_err+Code_mem
Org Procedure
Lda #$01
Sta Crsinh
Jsr Clrscr
Lda >Zestaw
Sta Chbas
Ldx #$00
L1 Txa
Pha
Lda Pomoc_tab,x
Tax
Ldy #$00
L2 Lda Znaki,x
Sta Zestaw,y
Inx
Iny
Cpy #$08
Bne L2
Ldx #$04
Jsr Wait
Pla
Tax
Inx
Cpx #$06
Bne L3
Ldx #$00
L3 Lda Kbcodes
Cmp #$FF
Beq L1
Rts
Znaki Equ *
Dta B($7E),B($81),B($81)
Dta B($81),B($81),B($81)
Dta B($81),B($7E)
Dta B($00),B($3C),B($42)
Dta B($42),B($42),B($42)
Dta B($3C),B($00)
Dta B($00),B($00),B($18)
Dta B($24),B($24),B($18)
Dta B($00),B($00)
Dta B($00),B($00),B($00)
Dta B($18),B($18),B($00)
Dta B($00),B($00)
Pomoc_tab Equ *
Dta B($00),B($08),B($10)
Dta B($18),B($10),B($08)
End of file
Na początku wyłączamy kursor (poprzez umieszczenie wartości $01 w rejestrze Crsinh) i czyścimy ekran (procedura systemowa Clrscr). Następnie rejestr Chbas ustawiamy na wolny obszar w RAM'ie ($9000). Ponieważ będziemy modyfikować tylko znak spacji, a inne znaki nie będą widoczne, dlatego też nie ma potrzeby przepisywać z ROM'u (lub definiować) całego zestawu.Tablica Znaki zawiera cztery kolejne fazy zmniejszania się okręgu, natomiast Pomoc_tab zawiera kolejność faz (co ile bajtów znajduje się nowa faza w tablicy Znaki). Program główny to dwie pętle. Pętla wewnętrzna przepisuje osiem bajtów definiujących wygląd okręgu w odpowiednie miejsce w zestawie, druga zlicza fazy. Program można przerwać, naciskając dowolny klawisz. UWAGA: W przykładzie korzystamy ze znanej nam procedury Wait. Program 2
Procedure Equ $8800
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Charset1 Equ $E000
Chbas Equ $02F4
Kbcodes Equ $02FC
Rtclok Equ $0012
Savmsc Equ $0058
Pomoc Equ $00F0
Zestaw Equ $9000
Opt List_err+Code_mem
Org Procedure
Lda >Zestaw
Sta Chbas
Ldx Savmsc
Ldy Savmsc+$01
Stx Pomoc
Sty Pomoc+$01
Ldx #$00
L1 Txa
Pha
Ldy #$00
Ldx #$00
L2 Txa
Sta (Pomoc),y
Inx
Iny
Cpy #$06
Bne L2
Clc
Lda Pomoc
Adc #$06
Sta Pomoc
Bcc L3
Inc Pomoc+$01
L3 Pla
Tax
Inx
Cpx #$A0
Bne L1
L4 Ldy #$00
L5 Tya
Lsr @
Lsr @
Lsr @
Tax
Lda Pomoc_tab,x
Tax
L6 Lda Znaki,x
Sta Zestaw,y
Inx
Iny
Tya
And #$07
Bne L6
Cpy #$30
Bne L5
Ldx #$00
Lda Pomoc_tab
Pha
L7 Lda Pomoc_tab+$01,x
Sta Pomoc_tab,x
Inx
Cpx #$05
Bne L7
Pla
Sta Pomoc_tab+$05
Ldx #$03
Jsr Wait
Lda Kbcodes
Cmp #$FF
Beq L4
Rts
Znaki Equ *
Dta B($7E),B($81),B($81)
Dta B($81),B($81),B($81)
Dta B($81),B($7E)
Dta B($00),B($3C),B($42)
Dta B($42),B($42),B($42)
Dta B($3C),B($00)
Dta B($00),B($00),B($18)
Dta B($24),B($24),B($18)
Dta B($00),B($00)
Dta B($00),B($00),B($00)
Dta B($18),B($18),B($00)
Dta B($00),B($00)
Dta B($00),B($00),B($18)
Dta B($24),B($24),B($18)
Dta B($00),B($00)
Dta B($00),B($3C),B($42)
Dta B($42),B($42),B($42)
Dta B($3C),B($00)
Pomoc_tab Equ *
Dta B($00),B($08),B($10)
Dta B($18),B($20),B($28)
End of file
Jak poprzednio, rejestr Chbas ustawiany jest na wolny obszar w RAM'ie. Następnie pętla przepisuje kolejne sześć znaków w pamięć ekranu aż do jego całkowitego zapełnienia. Od etykiety L4 zaczyna się animacja: pierwsza pętla przepisuje odpowiednio poukładane fazy (kolejność zapisana w tablicy Pomoc_tab) w pierwsze sześć znaków zestawu. Pętla druga natomiast zmienia kolejność faz. Następnie wywoływana jest procedura opóźniająca i jeśli nie został naciśnięty żaden klawisz wszystko powtarza się od nowa.Program 3
Procedure Equ $8800
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Charset1 Equ $E000
Chbas Equ $02F4
Clrscr Equ $F420
Kbcodes Equ $02FC
Rtclok Equ $0012
Savmsc Equ $0058
Zestaw Equ $9000
Opt List_err+Code_mem
Org Procedure
Jsr Clrscr
Ldx #$00
L1 Lda Charset1+$80,x
Sta Znaki,x
Cpx #$07
Bcs L2
Sta Znaki+$50,x
L2 Inx
Cpx #$50
Bne L1
Ldy #$01
L3 Tya
Dey
Sta (Savmsc),y
Iny
Iny
Cpy #$04
Bne L3
Tya
Eor #$80
Dey
Sta (Savmsc),y
L4 Ldy #$00
Ldx #$00
L5 Txa
Pha
Lda Licznik,x
Tax
L6 Lda Znaki,x
Sta Zestaw+$08,y
Inx
Iny
Tya
And #$07
Bne L6
Pla
Tax
Inx
Cpx #$04
Bne L5
Ldx #$03
L7 Inc Licznik,x
Lda Licznik,x
Cmp #$49
Bcc L9
Cmp #$50
Bne L8
Lda #$00
Sta Licznik,x
L8 Dex
Bpl L7
L9 Ldx #$02
Jsr Wait
Lda Kbcodes
Cmp #$FF
Beq L4
Rts
Licznik Equ *
Dta B($00),B($00),B($00)
Dta B($00)
Znaki Org *+$58
End of file
Program czyści ekran, następnie przepisuje z zestawu znaków w ROM'ie 10 znaków (wygląd cyfr). Znaki układane są w kolejności od 0 do 9 i po 9 występuje jeszcze jeden znak - zero. Następna pętla umieszcza na ekranie cztery znaki (cyfry licznika), przy czym ostatni jest w inwersie. Cztery bajty od etykiety Licznik zawierają pozycje, od których pobierane będą dane z tablicy znaków (Znaki) dla kolejnych cyfr licznika.Pętla od etykiety L4 wykonywana przy każdym "obrocie" licznika przepisuje dane dla czterech cyfr z tablicy znaki w zestaw. Następna pętla modyfikuje cztery bajty od etykiety Licznik. Jeżeli jedna z pozycji osiągnie wartość większą lub równą $49 oznacza to, że wyświetlana jest cyfra 9 na pozycji licznika określanej przez rejestr X procesora i konieczne jest przesunięcie kolejne cyfry licznika. Jeśli jedna z pozycji osiągnie wartość $50 (wskazanie licznika równe zero) jest ona zerowana. Program wykonywany jest dopóki nie zostanie naciśnięty klawisz. Program 5
Procedure Equ $880
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Charsetl Equ $E000
Chbas Equ $02F4
Kbcodes Equ $02FC
Ramtop Equ $006A
Random Equ $D20A
Savmsc Equ $0058
Pomoc Equ $00F0
Zestaw Equ $9000
Opt List_err+Code_mem
Org Procedure
Lda >Zestaw
Sta Chbas
Rob_kasze Ldx
Cały program składa się z dwóch pętli. Pierwsza wypełnia obszar pamięci przeznaczony na zestaw znaków losowymi wartościami pobieranymi z rejestru Random ($D20A). Pętla druga natomiast wypełnia ekran losowymi znakami, co tworzy żądany efekt.Program 5
Procedure Equ $880
List_mem Equ %00000110
List_err Equ %00000101
Code_mem Equ %00010000
Code_dsk Equ %00100000
Cdtma2 Equ $0228
Cdtmv2 Equ $021A
Charsetl Equ $E000
Chbas Equ $02F4
Pomoc Equ $00F0
Pomoc2 Equ $00F2
Zestaw Equ $9000
Opt List_err+Code_mem
Org Procedure
Jsr Przepisz
Lda >Zestaw
Sta Chbas
Ldx
W programie głównym przepisywany jest zestaw znaków z ROM'u do RAM'u (procedura Przepisz). Ponadto wektor Pomoc wskazuje na zestaw znaków zawarty w RAM'ie. Będzie on ustawiany na znak, który ma się obracać. Następnie uaktywniane jest przerwanie...Timer 2Tyle na razie o przerwaniu Timer 2. W przyszłości wrócimy do przerwań i omówimy rejestry kontrolujące je. Wróćmy do naszego programu. W procedurze przerwania (etykieta Przerw) wywoływane są trzy procedury. Procedury O_prawo i O_lewo obracają znak wskazywany przez wektor Pomoc o 90 stopni w odpowiednim kierunku przy użyciu dodatkowej tablicy Tablica. Po każdym wywołaniu procedury O_prawo i O_lewo wykonywana jest procedura Dodaj, która zwiększa wektor Pomoc o 8 bajtów, tak aby wskazywał on na następny znak. Jeśli skończy się zestaw znaków, wektor Pomoc otrzyma adres jego początku. Procedury O_lewo i O_prawo korzystają z podprocedury Przep2 tworzącej kopię wyglądu znaku w pomocniczej tablicy. Uważamy, że zastosowane przez nas procedury obrotu znaku są najkrótsze, szczególnie wtedy, gdy program główny wymieniałby dwa rozkazy (ASL na LSR i ROR na ROL). Krótsze lub ciekawsze rozwiązania tego problemu jak i zawartego w poprzednim artykule problemu najkrótszej tęczy pracującej na przerwaniu Display List będą mile widziane i opublikowane na łamach TA. W następnym artykule przejdziemy do GTIA. Rafał Bielecki
Tomasz Bielak Dziś pytanie - dziś odpowiedź
O_prawo Ldy #7
L1 Lda (Pomoc),y
Ldx #7
L2 Lsr @
Rol Tablica,x
Dex
Bpl L2
Dey
Bpl L1
Bmi Przep_2 (Jmp)
O_lewo Ldy #$07
L3 Lda (Pomoc),y
Ldx #7
L4 Asl @
Ror Tablica,x
Dex
Bpl L4
Dey
Bpl L3
Przep_2 Ldy #$07
L5 Lda Tablica,y
Sta (Pomoc),y
Dey
Bpl L5
Rts
Zastosowałem te same nazwy, aby można było wymienić odnośny fragment.Istnieje teoria, która mówi, że KAŻDY program można skrócić, nie zdziwię się więc, gdy ktoś nadeśle jeszcze krótszą metodę. Janusz B. Wiśniewski
|