Das hier vorgestellte Programm,
das interruptgesteuert (IRQ) abläuft, tauscht gezielt einzelne
Farben im Hires- und Multicolor-Graphicmodus (40-Zeichen VIC-Graphik) aus. Dabei ist es egal, in welchem Typ
Farbspeicher die auszuwechselnde Farbe liegt. Die Service-Diskette
enthält ein kleines Demoprogramm,
das eigentliche Maschinenprogramm "FARBREIGEN .OBJ", ein Graphic-File
für Demonstrationszwecke und den Assemblerquellcode
"FARBREIGEN
Q" (erstellt mit dem Basiceditor für einen CBM
4001/8001-Series 2-Pass-Assembler).
Farbreigen
Das Programm "Farbreigen" ermöglicht
für die VIC-Graphic des C 128 das programmgesteuerte
Verändern der Farben im Hires- und Multicolormodus. Die
Veränderungen werden direkt im Farb-RAM bei $01C00-$01FFF und
bei Multicolor auch in $FD800-$FDFFF vorgenommen. Dabei muß
beachtet werden, daß der C 128, wegen der Splitscreens, zwei
unabhängige Farb-RAM bei $FD8000 besitzt. Natürlich
lassen sich solche zeitkritischen Routinen nur in Maschinensprache
realisieren, doch auch dabei gibt es noch Zeitprobleme!
Da
die Farbänderungen im Normalfall interruptgesteuert (es geht
auch 'ganz normal') ablaufen, können während des
Programmablaufes Bewegungen simuliert werden. Beispiel: Ein Wasserfall
aus den Farben Blau, Hellblau und Weiß. Durch
ständige Farbvertauschung entsteht ein
'fließ'-Effekt. (Vergleiche mit der Amiga-Graphic sind
allerdings pure Blasphemie.)
Wird
die Routine in den Interrupt eingebunden, so muß beachtet
werden, daß dadurch die normale Programmverarbeitung sehr
langsam werden kann (je nachdem wieviel die Routine arbeiten
muß). Auch können Schwierigkeiten bei der Eingabe
von der Tastatur auftreten ('der IRQ hat andere Sorgen') und vor allem
geht die Software-Uhr (TI, TI$) nach dem Mond! Im Verzweifelungsfall
hilft immer ein 'Ausstieg' mit [RUN/STOP] & [RESTORE].
Die
Möglichkeiten dieser Routine, sie läuft nur im
128er-Modus der C 128, sind vielfältig und können
deshalb am leichtesten bei der Parameterbeschreibung des
Programmaufrufes erklärt werden:
SYNTAX:
SYS DEC ("1300"),
A, X, Y [[, P, R$]]
Die
in eckigen Klammern angegebenen Parameter sind optional und werden
nicht immer benötigt. $01300 ist die Programmstartadresse, das
Programm belegt den Adressbereich von $01300 bis $014CF.
A: |
Farbrammodus |
|
0 = |
IRQ-Steuerung
aus (keine weiteren Parameter nötig). Mit diesem Befehl wird
der IRQ auf $FA65 (Standard) zurückgesetzt. |
1 = |
Die
Farbgebung des graphischen Vordergrunds (COLOR 1) wird
geändert; |
2 = |
dito
für Multicolor 1 (COLOR 2); |
4 = |
dito
für Multicolor 2 (COLOR 3); |
8 = |
dito
für Hintergrundfarbe im Multicolor- UND Textmodus (COLOR 0). |
|
|
Alle
Bitkombinationen sind möglich! Es können so die
Farben verschiedener Ebenen gleichzeitig geändert werden. |
X: |
Farbwechselmodus |
|
1 = |
Alle
Farbwerte werden um eins erhöht
(aus Schwarz wird Weiß, aus Weiß wird Rot... und
aus Hellgrau wieder Schwarz). |
2 = |
Dieser
Modus benötigt die
Informationen aus dem String R$. Die im String codierten Farbwerte
(s.u.) werden 'rotiert', das bedeutet, daß der erste Farbwert
in den zweiten, der zweite in den dritten gewandelt wird... und der
letzte wieder in den ersten. So können einer oder auch mehrere
Farbzyklen erstellt werden. |
3 = |
Alle
Farbwerte werden um eins erniedrigt
(siehe 1). |
|
|
Werte
ungleich 1 ,2 oder 3 ergeben einen Illegal Quantity Error. |
Y: |
Zeitkonstante |
|
0 = |
Einmaliger
Farbwechsel ohne eine Aktivierung
der IRQ-Routine bzw. mit Deaktivierung. |
X = |
Alle
Werte von 1 bis 255 geben die Häufigkeit des Aufrufs der
Farbwandel-Routine an. Eine Eins bedeutet einen Aufruf bei jedem
zweiten IRQ, eine 255 einen Aufruf bei jedem 256sten IRQ. |
|
P: |
Unbenutzter
Parameter. Bei Farbwechselmodus 2 (benötigt
String-Daten) auslassen, aber das zugehörige Komma nicht
vergessen! |
R$: |
Farbcodestring
für den Farbwechselmodus 2. Die Hexziffern 0
bis F stehen für die Farben 1 bis 16. Alle anderen Zeichen
gelten als Trennsymbole zwischen verschiedenen Farbzyklen. Die Maximale
Stringlänge beträgt 24 Zeichen. |
Beispiel: R$="3E6.D75"
Der erste Farbzyklus ("3E6")
lautet:
Türkis - Hellblau - Blau -
Türkis...
Der zweite Farbzyklus ("D75")
lautet:
Hellgrün - Gelb - Grün
- Hellgrün...
Beide Farbvertauschungen laufen gleichzeitig ab! Bei mehreren
Farbzyklen muß besonders beachtet werden, daß jede
Farbe nur einmal auftaucht!
Das
Maschinenprogramm gliedert sich in zwei logische Teilprogramme. Das
erste wertet den SYS-Aufruf aus, ordnet die Parameter zu und speichert
den String nach $14AD. Der zweite Teil ist das eigentliche Programm,
das in den IRQ eingehängt wird. Der Einsprung erfolgt bei
$1361. Hier wird zuerst geprüft, ob die
Farbänderroutine aufgerufen werden soll oder die
Zeitverzögerung noch aktiv ist. Anschließend wird je
nach gesetzter Bitkombination des Farbramwechselflags mit den
entsprechenden Parametern in die CCOLOR-Routine bei $13E2 gesprungen.
Diese holt jedes einzelne Byte aus dem angewählten Farb-RAM,
modifiziert es, wandelt es entsprechend dem aktivierten
Farbwechselmodus und speichert es wieder ab.
Einige
Programmvariable sind im Bereich von $14C5 bis $14CF abgelegt. Die
Variablen für die zeitkritische IRQ-Routine liegen bei $FA bis
$FE in der Zeropage. Von $149D bis $14AC liegen in einer Tabelle die
CHR$-Codes für die Stringauswertung.
Reinhard Kratzberg
Download:
- Demoprogramm: "reigen
demo.bas"
- Demo-Grafik: "garten bild.vic"
- Farbreigen (Maschinenprogramm): "farbreigen
.obj"
- Original* Maschinenprogramm: "farbreigen m"
- Original* Quellcode: "farbreigen
q"
*
Der Quellcode wurde auf einem CBM 4008 erstellt (im BASIC-Editor) und
auch dort mit einem Disk-orientierten 2-Pass-Assembler assembliert. Die
Files "farbreigen .obj" und "farbreigen m" sind
inhaltlich identisch.
Das
Demoprogramm zeigt eine Anwendung von "Farbreigen" |
100 rem *** mini demo zum
farbreigen ***
110 graphic3
120 color3,7:scnclr:color0,8
130 bload"garten bild.vic"
140 bload"farbreigen .obj"
150 do
160 fori=1to4
170 onigoto200,210,180,190
180 sys dec("1300"),1,2,0,,"57.d5":goto220
190 sys dec("1300"),1,2,0,,"72.57":goto220
200 sys dec("1300"),1,2,0,,"21.7f":goto220
210 sys dec("1300"),1,2,0,,"15.fd":goto220
220 sys dec("1300"),10,2,0,,"d571"
230 sys dec("1300"),4,2,30,,"63"
240 sleep3:next
250 get a$:ifa$=chr$(32)then exit
260 loop |
|
|
Quelltext
für CBM Assembler |
1000 ";-------------------------------
1010 "; *** f a r b r e i g e n ***
1020 ";
1030 "; dieses programm ermoeglicht
1040 "; im vic-graphicmodus (auch in
1050 "; multicolor) das veraendern
1060 "; der farben. da dieses inter-
1070 "; ruptgesteuert erfolgt, koen-
1080 "; nen waehrend des programmab-
1090 "; laufes bewegungen simuliert
1100 "; werden. es muss beachtet wer-
1110 "; den, dass durch die erhebli-
1120 "; che zeitverzoegerung im in-
1130 "; terrupt die normale programm-
1140 "; verarbeitung sehr langsam
1150 "; werden kann, und schwierigkei-
1160 "; ten bei der tastatureingabe
1170 "; auftreten koennen (der irq
1180 "; wird seltener bedient).
1190 ";
1200 "; dieses programm laeuft auf
1210 "; dem c 128 im 128er modus.
1220 ";
1230 "; syntax:
1240 "; sys dec("1300"),a,x,y,[p,b$]
1250 ";
1260 "; a:= farbram-modus
1261 ";
1270 "; 0=irq-steuerung aus
1280 "; 1=color 1, vordergrund
1290 "; 2=color 2, multicolor1
1300 "; 4=color 3, multicolor2
1310 "; 8=color 0, hintergrund
1320 "; alle bitkombinationen
1330 "; sind moeglich.
1340 ";
1350 "; x:= farbwechsel-modus
1360 ";
1370 "; 1=aendere farbwerte -1
1380 "; 2=rot. farben aus
string
1390 "; 3=aendere farbwerte +1
1400 ";
1410 "; y:= zeitkonstante fuer irq-
1420 "; gesteuerte farbwechsel.
1430 ";
1440 "; 0=einmaliger
farbwechsel
1450
";
ohne aktivierung der
1460
";
irq-routine.
1470 "; sonst (1-255):
zeitkonst.
1480 ";
1490 "; p:= unbenutzter parameter. bei
1500 "; farbwechsel-modus 2 (be-
1510 "; noetigt string)
auslassen.
1520 ";
1530 "; b$= farbstring fuer farbwech-
1540 "; sel-modus 2. die
hexziffern
1550 "; 0 bis f stehen fuer die
1560 "; farben 1 bis 16. alle
ande-
1570 "; ren zeichen gelten als
1580 "; trennsymbole zwischen
ver-
1590 "; schiedenen farbzyclen.
die
1600 "; maximale stringlaenge:
24
1610 "; zeichen.
1620 ";
1630 "; beispiel: b$='3e6.d75'
1640 ";
1650 "; der erste farbzyclus lautet:
1660 "; tuerkis - hellblau - blau
1670 "; der zweite farbzyclus lautet:
1680 "; hellgruen - gelb - gruen
1690 "; beide laufen gleichzeitig ab!
1700 ";
1710 ";--------------------------------
1720 ";
1730 ".opt t8
1740 ";
1750 "*=$1300;startadresse
1760 ";
1770 ";labels & variable
1780 ";
1790 "irqvec:=$0314;irq-vector
1800 "chrgot:=$0386;char aus basictext
1810 "ladb1:=$03b7;zeichen aus bank 1
1820 "bank0:=$03bd;nach rts ram bank 0
1830 "hilfjs:=$03e4;ermoeg. jsr strpar
1840 "frmevl:=$77ef;variable auswerten
1850 "chkom:=$795c;testet auf komma
1860 "iqerr:=$7d28;ill. quantity error
1870 "strpar:=$866e;holt stringadresse
1871 "sterr:=$a5ed;string to long error
1880 "goirq:=$fa65;irq fortsetzen
1890 ";
1900 "halb1:=$fa;maske1
1910 "halb2:=$fb;maske2
1920 "wmod:=$fc;fabwechsel-mod.flag
1930 "oldcol:=$fd;zwischenspeicher
1940 "blkanf:=$fe;zwischenspeicher
1950 ";
1960 ";--- programmstart
1970 ";
1980 "sta $ff03;ram 0 ein
1990 "sta data+7;farbram-modus
2000 "sty data+6;zeitkonstante
2010 "sei;irq sperren und
2020 "lda #<goirq;ruecksetzen
2030 "sta irqvec
2040 "lda #>goirq
2050 "sta irqvec+1
2060 "cli;irq freigeben
2070 "lda data+7;wenn nicht null
2080 "bne ok1;dann weiter
2090 "rts;irq ist aus -- ende
2100 "ok1:txa;farbwechselmod.test
2110 "beq error1
2120 "cmp #$04
2130 "bcs error1
2140 "dex
2150 "dex
2160 "stx data+5;speichere fw-mod
2170 "bne hupf;modus 1 oder 3!
2180 ";--- bei modus 2 lese string ein
2190 "jsr chrgot
2200 "jsr chkom
2210 "jsr frmevl;wertet variable aus
2220 "ldy #$05;kopiert up hilf
2230 "loop0:lda hilf,y
2240 "sta hilfjs,y
2250 "dey
2260 "bpl loop0
2270 "jsr hilfjs
2280 "sta $26;stringlaenge
2290 "cmp #$00;leerstring verboten
2300 "beq error1
2310 "cmp #25;string zu lang ?
2320 "bcc ok2
2330 "error2:jmp sterr;fehlermeldung
2331 "error1:jmp iqerr;fehlermeldung
2340 "ok2:jsr copyst;copy string in bank0
2350 "hupf:sei;sperrt irq
2360 "ldy data+6;farbwechsel?
2370 "beq noirq;nur einmal
2380 "jmp irqon;set irq-farbwechsel
2390 ";--- nur einmal farbwechsel
2400 "noirq:jsr change;farbwechsel
2410 "cli;irq frei
2420 "rts;ende
2421 ";
2430 ";--- exirq einsprung
2431 ";
2440 "exirq:jsr goex
2450 "jmp goirq
2460 ";--- extra irq-routine
2470 "goex:dec data+4;zeittest ob farb-
2480 "beq ok3;wechsel folgt
2490 "rts;zurueck zum irq
2500 "ok3:lda data+6;zeitkonstante
2510 "sta data+4;init zaehler
2519 ";
2520 ";--- farbwechsel
2521 ";
2530 "change:lda $8c;rette pointer
2540 "pha
2550 "lda $8d
2560 "pha
2570 "lda data+5;fw-modus flag in
2580 "sta wmod;zeropage kopieren
2590 "lda data+7;farbram-modus
2600 "pha
2610 "and #$01;test ob color 1
2620 "beq col2
2630 "lda #$f0;oberes halbbyte
2640 "ldy #$1c;ram adr.high
2650 "jsr ccolor
2660 "col2:pla
2670 "pha
2680 "and #$02;test ob color 2
2690 "beq col3
2700 "lda #$0f;unteres halbbyte
2710 "ldy #$1c;ram adr.high
2720 "jsr ccolor
2730 "col3:pla
2740 "pha
2750 "and #$04;test ob color 3
2760 "beq col0
2770 "jsr $a845;bank 0 und rom ein
2780 "lda $01
2790 "pha;rettet port-zustand
2800 "and #$fe
2810 "sta $01;farbram ein
2820 "lda #$0f;unteres halbbyte
2830 "ldy #$d8;ram adr.high
2840 "jsr ccolor
2850 "pla
2860 "sta $01;alter port-zustand
2870 "col0:pla
2880 "and #$08;test ob hintergrund
2890 "beq end
2900 "jsr $a845;bank0 und rom ein
2910 "lda $d021;farbe alt
2920 "and #$0f
2930 "tax
2940 "lda wmod;test auf fw modus
2950 "bne addsub
2960 "jsr rot;rot. mit stringdaten
2970 "bcc fneu;farbe gefunden
2980 "bcs end;farbe nicht gefunden
2990 "addsub:bpl add1
3000 "dex;farbe-1
3010 "dex
3020 "add1:inx;farbe+1
3030 "fneu:stx $d021;farbe neu
3040 ";--- ende von exirq
3050 "end:pla;holt alten pointer
3060 "sta $8d
3070 "pla
3080 "sta $8c
3090 "rts
3100 ";
3110 ";--- up hilf (wird umkopiert)
3120 "hilf:jsr strpar;stringadr.holen
3130 "jmp $03ce;reaktiviere bank 0
3140 ";
3150 ";--- unterprogramm farbwechsel
3160 ";
3170 "ccolor:sty $8d;ram high
3180 "ldy #$00
3190 "sty $8c;ram low
3200 "sta halb1
3210 "eor #$ff;invertieren
3220 "sta halb2
3230 "lda #$04;anzahl der bloecke
3240 "sta data+3;blockzaehler
3250 "loop1:lda ($8c),y;holt farbwert
3260 "pha
3270 "and halb2;unveraendertes
3280 "sta oldcol;halbbyte retten
3290 "pla
3300 "ldx halb1;halbyte test
3310 "php
3320 "bpl lo1;--> unteres halbbyte
3330 "lsr a
3340 "lsr a
3350 "lsr a
3360 "lsr a
3370 "lo1:and #$0f
3380 "tax;rettet farbwert
3390 "lda wmod;test auf fw modus
3400 "beq rotup;rot. mit stringdaten
3410 "bpl add0
3420 "dex;farbe-1
3430 "dex
3440 "add0:inx;farbe+1
3450 "loop5:txa;geaenderter farbwert
3460 "and #$0f;halbbyte ausblenden
3470 "plp;habbyte test
3480 "bpl lo2;--> unteres halbbyte
3490 "asl a
3500 "asl a
3510 "asl a
3520 "asl a
3530 "lo2:ora oldcol
3540 "sta ($8c),y;setzt neue farbe
3550 "loop4:dey
3560 "bne loop1;schleife 0-255
3570 "inc $8d;erhoehe ram-zeiger
3580 "dec data+3
3590 "bne loop1;schleife 1-4
3600 "rts;ruecksprung in exirq
3610 ";--- farben aus string daten
3620 ";--- rotieren lassen
3630 "rotup:jsr rot
3640 "bcc loop5;farbe gefunden
3650 "pla
3660 "bcs loop4;farbe nicht gefunden
3670 ";--- rotier-routine
3680 "rot:tya
3690 "pha;rettet schleifenzaehler
3700 "inx;farbe+1
3710 "ldy #$00
3720 "loop2:sty blkanf;init blkanfang
3730 "dey
3740 "loop3:txa;farbe in accu
3750 "iny
3760 "cmp string,y;vergl.mit stringdaten
3770 "beq find
3780 "lda string,y;lade stringdaten
3790 "beq neublk;blocktrenner gefunden
3800 "bpl loop3;anderes farbzeichen
3810 "pla;stringende erreicht
3820 "tay
3830 "sec;flag keine farbaenderung
3840 "rts
3850 "neublk:iny
3860 "bne loop2;neuer blkanfang
3870 "find:iny;farbwert gefunden
3880 "loop6:lda string,y;neuer farbwert+1
3890 "tax
3900 "dex;farbe-1
3910 "bpl ok4;farbe ok
3920 "ldy blkanf;alter blkanfang
3930 "bpl loop6;immer
3940 "ok4:pla;holt schleifenzaehler
3950 "tay
3960 "clc;flag setze farbe in ram
3970 "rts
3980 ";
3990 ";--- hole und bearbeite string
4000 ";
4010 "copyst:sei;sperre irq
4020 "lda #$03;preconf - bank0
4030 "sta bank0
4040 "ldy #$00;init zaehler
4050 "loop8:cpy $26;vergl.stringlaenge
4060 "beq ok6;stringende erreicht
4070 "jsr ladb1;hole char aus string
4080 "ldx #$10;zaehler fuer tabelle
4090 "loop7:cmp table-1,x;vergl.mit 0-f
4100 "beq ok5;schleifen ende
4110 "dex
4120 "bne loop7;naechster tab.wert
4130 "ok5:txa;setze farbcode+1
4140 "sta string,y;oder 0 fuer blkend
4150 "iny
4160 "bne loop8;naechstes stringbyte
4170 "ok6:lda #$ff
4180 "sta string,y;string-end kennung
4190 "lda #$04;preconf - bank1
4200 "sta bank0
4210 "cli;irq frei
4220 "rts;auswertung fortsetzen
4230 ";
4240 ";--- irq vektor umsetzen
4250 ";
4260 "irqon:iny
4270 "sty data+6;zeitkonstante
4280 "sty data+4;init zaehler
4290 "lda #<exirq
4300 "sta irqvec
4310 "lda #>exirq
4320 "sta irqvec+1
4330 "cli;irq frei
4340 "rts;ende
4350 ";
4360 ";tabelle der asc-codes, die in
4370 ";farbcodes+1 gewandelt werden
4380 ";
4390 "table:.byt '01'
4400 ".byt '234'
4410 ".byt '567'
4420 ".byt '89a'
4430 ".byt 'bcd'
4440 ".byt 'ef'
4450 ";
4460 ";string speicher freiraum
4470 ";
4480 "string:.byt 0,0,0,0,0,0,0,0
4490 ".byt 0,0,0,0,0,0,0,0
4491 ".byt 0,0,0,0,0,0,0,0
4500 ";
4510 ";variable
4520 ";
4530 "data:.byt 0,0,0,0,0
4531 ".byt 0,0,0,0,0
4540 ".end
|
|