Tajemnice ATARI

Piszemy DEMO


    W 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 file
   Pierwszy 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 file
   Procedura 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

Powrót na start | Powrót do spisu treści | Powrót na stronę główną

Pixel 2001