Notery - część 1 część 2

Tomek "Scrap" Michniewicz
tomko1@wp.pl

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

 © 1999-2020 Wszystkie prawa zastrzeżone
 Webmaster: Mariusz "Flooder" Młynek