Piszemy DEMOW poprzednim artykule, zakończyliśmy część teoretyczną naszego cyklu. W tym i kolejnych artykułach zamieścimy procedury przykładowej, trzyczęściowej demonstracji. Większość z nich będzie przygotowywana w dwóch wersjach: wersja przeznaczona do samodzielnego uruchomienia spod QA oraz wersja kompilowana na dysk, będąca częścią demonstracji. Przestrzegamy przed wprowadzaniem zmian w początkowych adresach procedur i w adresach komórek na stronie zerowej, gdyż wszystkie procedury powiązane są ze sobą i nierozsądne zmiany tego typu mogą prowadzić do błędnego działania demonstracji. W szczególności zalecamy dokładne przepisywanie (bez zmian) procedur kompilowanych na dysk oraz zapisywanie ich pod nazwami proponowanymi przez nas. W pierwszej części dema będzie: na górze ekranu - napis "Tajemnice Atari" odbity w lustrze, z lewej i z prawej strony tego napisu - dwa obracające się firmowe znaczki Atari; w środku ekranu - poruszający się obrazek, otoczony z czterech stron płynącymi napisami. Natomiast na dole ekranu - przepływający tekst o znakach wysokich na 64 fizyczne linie ekranu. Na tym tekście, w prawym dolnym rogu ekranu - wskaźniki poziomu głośności poszczególnych kanałów dźwiękowych. Przez cały czas działania demonstracji komputer będzie odgrywał muzykę. Programowanie pierwszej części zaczniemy od organizacji ekranu, czyli ułożenia programu dla ANTIC'a: Procedure Equ $9800 List_mem Equ %00000110 List_err Equ %00000101 Code_mem Equ %00010000 Code_dsk Equ %00100000 Dlptrs Equ $0230 Obrazek Equ $8000 Scroll Equ $7000 Scrol2 Equ $6600 Opt List_err+Code_mem Org Procedure Ldx <Dlist Ldy >Dlist Stx Dlptrs Sty Dlptrs+$01 Rts Text Dta D' TAJEMNICE ATARI ' Dlist Dta B($F0),B($70) Dta B($57) Dta A(Text) Dta B($00) Dta B($56) Dta A(Text) Dta B($F0) Dta B($52) Dta A(Scroll) Dta B($F0) Dta B($5E) Dta A(Obrazek) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($1E),B($1E),B($1E) Dta B($F0) Dta B($52) Dta A(Scroll) Dta B($E0) Dta B($00) Dta B($54),A(Scrol2) Dta B($54),A(Scrol2+$38) Dta B($54),A(Scrol2+$70) Dta B($54),A(Scrol2+$A8) Dta B($54),A(Scrol2+$E0) Dta B($54),A(Scrol2+$118) Dta B($54),A(Scrol2+$150) Dta B($54),A(Scrol2+$188) Dta B($41) Dta A(Dlist) End of filePierwszy rozkaz ANTIC'a uaktywnia pierwsze przerwanie Display List (i zarazem tworzy 8 pustych linii). W trakcie tworzenia ekranu przerwanie to wywoływane jest aż pięć razy. Ustawia ono kolory i pozycje obiektów oraz niektóre rejestry sprzętowe (np. HScrol). Dokładny opis poszczególnych wywołań tego przerwania zamieścimy w jednym z następnych odcinków. Kolejny rozkaz to następne osiem pustych linii, po których tworzone są dwie linie trybów tekstowych ANTIC'a (oddzielone jedną pustą linią). Jedna w trybie $07, druga - w $06. W nich umieszczony jest tekst "Tajemnice Atari". Dodatkowo ustawiony bit 4 (HSC) w rozkazach ANTIC'a umożliwia ustawienie na środku tego tekstu. Po kolejnych ośmiu pustych liniach ANTIC tworzy linię trybu $02, w której będzie płynął napis. Następna grupa rozkazów umożliwia pokazanie obrazka oddzielonego od płynącego napisu ośmioma pustymi liniami i identycznej linii z płynącym napisem, kak powyżej. Ostatnia grupa rozkazów to rozkazy tworzące osiem linii trybu $04, po których będzie przesuwał się "duży" tekst. Ostatni rozkaz to zakończenie programu ANTICa. Jak wynika z deklaracji etykiet, obrazek umieszczony będzie w pamięci od adresu $8000, tekst do dwóch małych płynących napisów - od adresu $7000, a pamięć ekranu dla dużego płynącego napisu - od adresu $6600. Powyższa procedura nadaje się zarówno do uruchomienia, jak i do ostatecznego skompilowania na dysk. Proponujemy zapisać ją pod nazwą "DLI.ASM". Drugą istotną procedurą do pierwszej części jest "PLAYER.ASM", uaktywniająca grafikę PMG: Procedure Equ $9B5B List_mem Equ %00000110 List_err Equ %00000101 Code_mem Equ %00010000 Code_dsk Equ %00100000 Dmactls Equ $022F Gtictls Equ $026F Pmcntl Equ $D01D Pmbase Equ $D407 Sizep0 Equ $D008 Sizep2 Equ $D00A Start_pl Equ $9000 Opt List_err+Code_dsk Org Procedure Jmp Init_pl IntProc Ldx #$00 L0 Lda Dane_pl,x Sta Start_pl+$416,x Sta Start_pl+$616,x Inx Cpx #$10 Bne L0 L1 Lda Dane_pl,x Sta Start_pl+$506,x Sta Start_pl+$706,x Inx Cpx #$20 Bne L1 Clc Lda L0+$01 Adc #$20 Sta L0+$01 Sta L1+$01 Lda L0+$02 Adc #$00 Sta L0+$02 Sta L1+$02 Inc Licznik Lda Licznik Cmp #$0A Bne Koniec Ldx #$00 Stx Licznik Ldx <Dane_pl Ldy >Dane_pl Stx L0+$01 Stx L1+$01 Sty L0+$02 Sty L1+$02 Koniec Rts Init_pl Ldy #$07 L2 Ldx #$00 Txa L3 Sta Start_pl,x Inx Bne L3 Inc L3+$02 Dey Bpl L2 Ldx #$07 L4 Lda Dane_2,x Sta Start_pl+$539,x Sta Start_pl+$59A,x Lda Dane_3,x Sta Start_pl+$739,x Sta Start_pl+$79A,x Dex Bpl L4 Ldx >Start_pl Stx Pmbase Ldx #$3E Stx Dmactls Ldx #$01 Stx Gtictls Ldx #$00 Stx Sizep0 Stx Sizep2 Ldx #$03 Stx Pmcntl Cdtma2 Equ $0228 Cdtmv2 Equ $021A Colpm0s Equ $02C0 Hposp0 Equ $D000 Hposp1 Equ $D001 Hposp2 Equ $D002 Hposp3 Equ $D003 Lda #$3D Sta Dmactl Lda #$30 Sta Hposp0 Lda #$38 Sta Hposp1 Lda #$C0 Sta Hposp2 Lda #$C8 Sta Hposp3 Ldx #$03 Lda #$0F L5 Sta Colpm0s,x Dex Bpl L5 Ldx <Timer2 Ldy >Timer2 Stx Cdtma2 Sty Cdtma2+$01 End Lda #$02 Sta Cdtmv2 Rts Timer2 Jsr IntProc Jmp End Licznik Dta B($00) Dane_pl Dta B($0D),B($0D),B($0D) Dta B($0D),B($0D),B($0D) Dta B($0D),B($0D),B($0D) Dta B($0D),B($0D),B($1D) Dta B($19),B($39),B($F1) Dta B($E1),B($B0),B($B0) Dta B($B0),B($B0),B($B0) Dta B($B0),B($B0),B($B0) Dta B($B0),B($B0),B($B0) Dta B($B8),B($98),B($9C) Dta B($8F),B($87),B($0D) Dta B($0D),B($0D),B($0D) Dta B($0D),B($0D),B($0D) Dta B($0D),B($0D),B($0D) Dta B($0D),B($1D),B($19) Dta B($39),B($71),B($61) Dta B($B0),B($B0),B($B0) Dta B($B0),B($B0),B($B0) Dta B($B0),B($B0),B($B0) Dta B($B0),B($B0),B($B8) Dta B($98),B($9C),B($8E) Dta B($86),B($06),B($06) Dta B($06),B($06),B($06) Dta B($06),B($06),B($06) Dta B($06),B($06),B($06) Dta B($0E),B($0C),B($1C) Dta B($38),B($30),B($E0) Dta B($E0),B($E0),B($E0) Dta B($E0),B($E0),B($E0) Dta B($E0),B($E0),B($E0) Dta B($E0),B($F0),B($B0) Dta B($B8),B($9C),B($8C) Dta B($06),B($06),B($06) Dta B($06),B($06),B($06) Dta B($06),B($06),B($06) Dta B($06),B($06),B($0E) Dta B($0C),B($0C),B($0C) Dta B($1C),B($E0),B($E0) Dta B($E0),B($E0),B($E0) Dta B($E0),B($E0),B($E0) Dta B($E0),B($E0),B($E0) Dta B($F0),B($B0),B($B0) Dta B($B0),B($B8),B($01) Dta B($01),B($01),B($01) Dta B($01),B($01),B($01) Dta B($01),B($01),B($01) Dta B($01),B($03),B($03) Dta B($03),B($03),B($07) Dta B($C0),B($C0),B($C0) Dta B($C0),B($C0),B($C0) Dta B($C0),B($C0),B($C0) Dta B($C0),B($C0),B($E0) Dta B($60),B($60),B($60) Dta B($70),B($01),B($01) Dta B($01),B($01),B($01) Dta B($01),B($01),B($01) Dta B($01),B($01),B($01) Dta B($01),B($01),B($01) Dta B($01),B($01),B($80) Dta B($80),B($80),B($80) Dta B($80),B($80),B($80) Dta B($80),B($80),B($80) Dta B($80),B($80),B($80) Dta B($80),B($80),B($80) Dta B($03),B($03),B($03) Dta B($03),B($03),B($03) Dta B($03),B($03),B($03) Dta B($03),B($03),B($07) Dta B($06),B($06),B($06) Dta B($0E),B($80),B($80) Dta B($80),B($80),B($80) Dta B($80),B($80),B($80) Dta B($80),B($80),B($80) Dta B($C0),B($C0),B($C0) Dta B($C0),B($E0),B($07) Dta B($07),B($07),B($07) Dta B($07),B($07),B($07) Dta B($07),B($07),B($07) Dta B($07),B($0F),B($0D) Dta B($0D),B($0D),B($1D) Dta B($60),B($60),B($60) Dta B($60),B($60),B($60) Dta B($60),B($60),B($60) Dta B($60),B($60),B($70) Dta B($30),B($30),B($30) Dta B($38),B($07),B($07) Dta B($07),B($07),B($07) Dta B($07),B($07),B($07) Dta B($07),B($07),B($07) Dta B($0F),B($0D),B($1D) Dta B($39),B($31),B($60) Dta B($60),B($60),B($60) Dta B($60),B($60),B($60) Dta B($60),B($60),B($60) Dta B($60),B($70),B($30) Dta B($38),B($1C),B($0C) Dta B($0D),B($0D),B($0D) Dta B($0D),B($0D),B($0D) Dta B($0D),B($0D),B($0D) Dta B($0D),B($0D),B($1D) Dta B($19),B($39),B($71) Dta B($61),B($B0),B($B0) Dta B($B0),B($B0),B($B0) Dta B($B0),B($B0),B($B0) Dta B($B0),B($B0),B($B0) Dta B($B8),B($98),B($9C) Dta B($8E),B($86) Dane_2 Dta B($FF),B($FE),B($FC) Dta B($F8),B($F0),B($E0) Dta B($C0) B($80) Dane_3 Dta B($01),B($03),B($07) Dta B($0F),B($1F),B($3F) Dta B($7F),B($FF) End of fileProcedura czyści obszar pamięci PMG, następnie tablice Dane_2 i Dane_3 przepisuje w odpowiednie miejsca pamięci. Są to ozdobne początki i zakończenia małych płynących napisów. Następnie inicjalizowana jest grafika PMG i ustawiany wektor przerwania Timer 2 na procedurę IntProc. Każdy ze znaczków Atari złożony jest z dwóch graczy PMG. Procedura przerwania IntProc, za każdym wywołaniem, przepisuje inną fazę obrotu znaczków Atari z tablicy Dane_pl. Jedna faza zajmuje $20 bajtów, po $10 bajtów na każdego gracza. Po przepisaniu program modyftkuje sam siebie, tak aby przy następnym obiegu przerwania przepisywać z innego miejsca tablicy Dane_pl. Faz jest dziesięć. Program przystosowany jest do samodzielnego uruchomienia. Aby utworzyć wersję, którą następnie skompilujemy na dysk należy wyrzucić fragment programu rozpoczynający się od etykiety Cdtma2 do rozkazu Jmp End włącznie. Ciąg dalszy w następnym numerze Tajemnic Atari. Tomasz Bielak
Rafał Bielecki |