Notery - część 1 część 2
1. Notatka od środka.
Jak wspominałem w części poprzedniej aby było możliwe odczytanie notatki, potrzebny jest program (który jest integralną częścią każdej gotowej notki) który wyświetli ją w odpowiedni sposób na ekranie. Poniżej prezentuję asemblerowy kod takiego programu (otrzymuje się go przez komendę d810 w monitorze - czyli desasembluj kod od adresu - w tym przypadku - $0810). Zakładam też znajomość podstawowych komend asemblera - jeśli ich nie znasz, to polecam odpowiednie artykuły na C64 Power.
Co jeszcze jest ważne?
- muzyka znajduje się w bloku $1000 - $2000 ($1000 INIT, $1003 PLAY)
- tekst notatki znajduje się w pamięci począwszy od $2800; jedna strona to $1e0 znaków czyli w dziesiętnym 480 znaków, adres początku kolejnej strony to $2800 + (n-1)*$1e0 (n-numer strony).
Od $0a0c zapisane są kolory dla efektu znikania tekstu, od $0a1d kolory dla efektu pojawiania się tekstu
Jeśli nie wierzysz, sprawdź!
2. Kod.
(komentarze odnoszą się do bloku kodu powyżej)
.C:0810 20 81 FF JSR $FF81
.C:0813 20 8A FF JSR $FF8A
.C:0816 20 84 FF JSR $FF84
skok do funkcji kernala - inicjacja urządzeń i wektorów
.C:0819 A9 2E LDA #$2E
.C:081b 8D 18 03 STA $0318
.C:081e A9 0A LDA #$0A
.C:0820 8D 19 03 STA $0319
ustawiany jest wektor dla przerwania niemaskowalnego na adres $0A2E
$0A i $2E w komórkach $0319 (starszy) i $0318 (mlodszy) bajt
.C:0823 A9 18 LDA #$18
.C:0825 8D 18 D0 STA $D018
ustawiany rejestr VIC (układ odpowiadający za grafikę)
.C:0828 A9 00 LDA #$00
.C:082a 8D 30 0A STA $0A30
do komórki pamięci $0a30 wpisywana jest wartość $00
.C:082d A9 00 LDA #$00
.C:082f 85 04 STA $04
.C:0831 A9 28 LDA #$28
.C:0833 85 05 STA $05
w komórkach $05, $04 ustawiany jest adres $2800 - czyli pierwszej strony z tekstem!
.C:0835 A2 00 LDX #$00
.C:0837 8E 20 D0 STX $D020
.C:083a 8E 21 D0 STX $D021
czarny kolor tła i ramki ekranu
.C:083d 8A TXA
.C:083e 9D 00 D8 STA $D800,X
.C:0841 9D 00 D9 STA $D900,X
.C:0844 9D 00 DA STA $DA00,X
.C:0847 9D 00 DB STA $DB00,X
.C:084a E8 INX
.C:084b D0 F1 BNE $083E
pętla wypełniająca pamięć kolorów od $d800 do $dbff
.C:084d 20 DC 09 JSR $09DC
skok do podprogramu
.C:0850 78 SEI
.C:0851 A2 00 LDX #$00
.C:0853 8E 0E DC STX $DC0E
ustawienie rejestru CIA
.C:0856 86 C6 STX $C6
.C:0858 E8 INX
.C:0859 8E 32 0A STX $0A32
.C:085c 8E 1A D0 STX $D01A
.C:085f A9 1B LDA #$1B
.C:0861 8D 12 D0 STA $D012
.C:0864 8D 11 D0 STA $D011
ustawienie rejestrów VIC
.C:0867 A9 7E LDA #$7E
.C:0869 8D 14 03 STA $0314
.C:086c A9 09 LDA #$09
.C:086e 8D 15 03 STA $0315
ustawienie wektora dla procedury przerwań IRQ na adres $097E - to główna "pętla" programu odpowiadająca za odtwarzanie muzyki, oczekiwanie na naciśnięcie klawisza
.C:0871 58 CLI
.C:0872 20 26 09 JSR $0926
.C:0875 20 C5 08 JSR $08C5
skoki do podprogramów
->.C:0878 AD 01 DC LDA $DC01
.C:087b C9 7F CMP #$7F
.C:087d D0 03 BNE $0882
skok niżej, jeżeli zmiana strony
.C:087f 4C D1 09 JMP $09D1
skok do podprogramu - tam krótkie działanie i powrót do $0878
.C:0882 29 10 AND #$10
.C:0884 D0 F2 BNE $0878
.C:0886 20 92 08 JSR $0892
.C:0889 20 F8 08 JSR $08F8
.C:088c 20 C5 08 JSR $08C5
.C:088f 4C 78 08 JMP $0878
tu program się zapętla - wszędzie odbywają się skoki do $0878
*** podprogram ***
tu realizowany jest efekt znikania tekstu
.C:0892 A2 00 LDX #$00
.C:0894 A9 F8 LDA #$F8
.C:0896 CD 12 D0 CMP $D012
.C:0899 D0 FB BNE $0896
oczekuj, aż równe
.C:089b BD 0C 0A LDA $0A0C,X
.C:089e 30 24 BMI $08C4
powrót z podprogramu
.C:08a0 8D 21 D0 STA $D021
.C:08a3 8D 27 D0 STA $D027
.C:08a6 8D 28 D0 STA $D028
.C:08a9 8D 29 D0 STA $D029
.C:08ac 8D 2A D0 STA $D02A
.C:08af 8D 2B D0 STA $D02B
.C:08b2 8D 2C D0 STA $D02C
.C:08b5 8D 2D D0 STA $D02D
.C:08b8 8D 2E D0 STA $D02E
zmiana kolorów sprite'ów
.C:08bb A0 32 LDY #$32
.C:08bd 88 DEY
.C:08be D0 FD BNE $08BD
.C:08c0 E8 INX
.C:08c1 4C 94 08 JMP $0894
tu podprogram się zapętla
.C:08c4 60 RTS
*** koniec podprogramu ***
*** podprogram ***
tu realizowany jest efekt pojawiania sie tekstu
.C:08c5 A2 00 LDX #$00
.C:08c7 A9 F8 LDA #$F8
.C:08c9 CD 12 D0 CMP $D012
.C:08cc D0 FB BNE $08C9
skok do $08c9 jezeli nie równe - czekaj, aż równe
.C:08ce BD 1D 0A LDA $0A1D,X
.C:08d1 30 24 BMI $08F7
skocz na koniec podprogramu
.C:08d3 8D 21 D0 STA $D021
.C:08d6 8D 27 D0 STA $D027
.C:08d9 8D 28 D0 STA $D028
.C:08dc 8D 29 D0 STA $D029
.C:08df 8D 2A D0 STA $D02A
.C:08e2 8D 2B D0 STA $D02B
.C:08e5 8D 2C D0 STA $D02C
.C:08e8 8D 2D D0 STA $D02D
.C:08eb 8D 2E D0 STA $D02E
ustawia kolory 8 sprite'ów w VIC
.C:08ee A0 32 LDY #$32
.C:08f0 88 DEY
.C:08f1 D0 FD BNE $08F0
oczekuj, az równe
.C:08f3 E8 INX
.C:08f4 4C C7 08 JMP $08C7
zapętla podprogram - jedyne wyjście w $08d1
.C:08f7 60 RTS
*** koniec podprogramu ***
*** podprogram ***
zmiana wyswietlanej strony
.C:08f8 AD 30 0A LDA $0A30
.C:08fb 18 CLC
.C:08fc 69 01 ADC #$01
.C:08fe 8D 30 0A STA $0A30
.C:0901 CD 2F 0A CMP $0A2F
.C:0904 D0 10 BNE $0916
jesli nie równe, skok niżej
.C:0906 A9 00 LDA #$00
.C:0908 85 04 STA $04
.C:090a A9 28 LDA #$28
.C:090c 85 05 STA $05
do $04 - $05 wpisany adres $2800
.C:090e A9 00 LDA #$00
.C:0910 8D 30 0A STA $0A30
.C:0913 4C 26 09 JMP $0926
skok do podprogramu wyświetlającego tekst
.C:0916 A5 04 LDA $04
.C:0918 18 CLC
.C:0919 69 E0 ADC #$E0
.C:091b 85 04 STA $04
.C:091d A5 05 LDA $05
.C:091f 69 01 ADC #$01
.C:0921 85 05 STA $05
jeżeli ma wyświetlić kolejną stronę - zwiększa odpowiednio adresy, skąd pobierany jest tekst i niżej skok do procedury wyświetlania
.C:0923 4C 26 09 JMP $0926
*** koniec podprogramu ***
*** podprogram ***
wyświetlanie tekstu
.C:0926 A9 00 LDA #$00
.C:0928 85 02 STA $02
.C:092a A9 04 LDA #$04
.C:092c 85 03 STA $03
.C:092e A9 28 LDA #$28
.C:0930 85 06 STA $06
.C:0932 A9 04 LDA #$04
.C:0934 85 07 STA $07
w $02 - $03 zapisany zostaje adres $0400 (początek pamięci ekranu) w $06 - $07 zapisany zostaje adres $0428 (początek pamięci ekranu + $28 czyli 40 dziesiętnie, czyli jedna linia tekstu na ekranie :)
.C:0936 A5 04 LDA $04
.C:0938 48 PHA
.C:0939 A5 05 LDA $05
.C:093b 48 PHA
adres z $04 - $05 zostaje zapisany na stos
.C:093c A2 00 LDX #$00
|->.C:093e A0 00 LDY #$00
|
| zerowanie rejestrów x i y
|
| |->.C:0940 B1 04 LDA ($04),Y
| | .C:0942 91 02 STA ($02),Y
| | .C:0944 09 80 ORA #$80
| | .C:0946 91 06 STA ($06),Y
| | .C:0948 C8 INY
| | .C:0949 C0 28 CPY #$28
| |->.C:094b D0 F3 BNE $0940
pętla, wczytywanie znaków z pierwszej strony notki
.C:094d A5 04 LDA $04
.C:094f 18 CLC
.C:0950 69 28 ADC #$28
.C:0952 85 04 STA $04
.C:0954 A5 05 LDA $05
.C:0956 69 00 ADC #$00
.C:0958 85 05 STA $05
.C:095a A5 02 LDA $02
.C:095c 69 50 ADC #$50
.C:095e 85 02 STA $02
.C:0960 A5 03 LDA $03
.C:0962 69 00 ADC #$00
.C:0964 85 03 STA $03
.C:0966 A5 06 LDA $06
.C:0968 69 50 ADC #$50
.C:096a 85 06 STA $06
.C:096c A5 07 LDA $07
.C:096e 69 00 ADC #$00
| .C:0970 85 07 STA $07
| .C:0972 E8 INX
| .C:0973 E0 0C CPX #$0C
|->.C:0975 D0 C7 BNE $093E
kolejna pętla, kolejne operacje na ekranie..
.C:0977 68 PLA
.C:0978 85 05 STA $05
.C:097a 68 PLA
.C:097b 85 04 STA $04
przywrócenie poprzednich wartości do $04 - $05 (ze stosu)
.C:097d 60 RTS
*** koniec podprogramu ***
*** obsługa przerwania ***
.C:097e A9 18 LDA #$18
.C:0980 8D 18 D0 STA $D018
ustawienie rejestru VIC
.C:0983 AD 32 0A LDA $0A32
.C:0986 F0 43 BEQ $09CB
.C:0988 A5 FB LDA $FB
.C:098a 48 PHA
.C:098b A5 FC LDA $FC
.C:098d 48 PHA
.C:098e A5 FD LDA $FD
.C:0990 48 PHA
.C:0991 A5 FE LDA $FE
.C:0993 48 PHA
zapis wartości powyższych komórek pamięci na stos
.C:0994 AD 34 0A LDA $0A34
.C:0997 85 FB STA $FB
.C:0999 AD 33 0A LDA $0A33
.C:099c 85 FC STA $FC
.C:099e AD 35 0A LDA $0A35
.C:09a1 85 FD STA $FD
.C:09a3 AD 36 0A LDA $0A36
.C:09a6 85 FE STA $FE
wpisanie nowych wartości z pamięci
.C:09a8 20 03 10 JSR $1003
odgrywaj muzykę
.C:09ab A5 FB LDA $FB
.C:09ad 8D 34 0A STA $0A34
.C:09b0 A5 FC LDA $FC
.C:09b2 8D 33 0A STA $0A33
.C:09b5 A5 FD LDA $FD
.C:09b7 8D 35 0A STA $0A35
.C:09ba A5 FE LDA $FE
.C:09bc 8D 36 0A STA $0A36
zapis do pamięci (to, co wyżej, tylko w drugą stronę)
.C:09bf 68 PLA
.C:09c0 85 FE STA $FE
.C:09c2 68 PLA
.C:09c3 85 FD STA $FD
.C:09c5 68 PLA
.C:09c6 85 FC STA $FC
.C:09c8 68 PLA
.C:09c9 85 FB STA $FB
przywrócenie poprzednich wartości komórek ze stosu
.C:09cb EE 19 D0 INC $D019
.C:09ce 4C 31 EA JMP $EA31
standardowa obsługa przerwania
*** koniec obsługi przerwania ***
*** podprogram ***
.C:09d1 AD 31 0A LDA $0A31
.C:09d4 D0 03 BNE $09D9
.C:09d6 4C 00 8D JMP $8D00
.C:09d9 4C 78 08 JMP $0878
*** koniec podprogramu ***
*** podprogram ***
ustawienia muzyki
.C:09dc 78 SEI
.C:09dd A9 00 LDA #$00
.C:09df 8D 32 0A STA $0A32
wstawia $00 do $0a32
.C:09e2 AD 39 0A LDA $0A39
.C:09e5 8D A9 09 STA $09A9
.C:09e8 8D 10 9C STA $9C10
.C:09eb AD 3A 0A LDA $0A3A
.C:09ee 8D AA 09 STA $09AA
.C:09f1 8D 11 9C STA $9C11
.C:09f4 AD 37 0A LDA $0A37
.C:09f7 8D 03 0A STA $0A03
.C:09fa AD 38 0A LDA $0A38
.C:09fd 8D 04 0A STA $0A04
.C:0a00 A9 00 LDA #$00
Ustawia w programie adresy Init i Play dla muzyki - te adresy mogą być zmieniane i w notce są zapisane w komórkach pamięci:
$0a37 - $0a38 Init
$0a39 - $0a3a Play
Adres w ponizszym rozkazie jest modyfikowany w poprzednich dwóch liniach właśnie na podstawie tych zapisanych danych.
.C:0a02 20 00 10 JSR $1000
inicjacja muzyki
.C:0a05 A9 01 LDA #$01
.C:0a07 8D 32 0A STA $0A32
.C:0a0a 58 CLI
.C:0a0b 60 RTS
** koniec podprogramu **
Jeżeli nie rozumiesz wszystkiego - eksperymentuj! Zachęcam do zmian - np. sprawdzenia, co się stanie (co przestanie działać ;) po zastąpieniu skoku do jakiegoś podprogramu instrukcjami NOP (nie rób nic). Ten kod naprawdę nie jest taki trudny!
Komentarze, uwagi - tomko1@wp.pl
|