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 1Procedure 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 fileNa 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 2Procedure 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 fileJak 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 3Procedure 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 fileProgram 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 5Procedure 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 LdxCał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 5Procedure 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 LdxW 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 RtsZastosował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
|