C128 wechselt seine Farben

[RUN, September 1986 & 64er, Januar 1987, bisher unveröffentlicht]

"Farbreigen" - ein Programm bringt die Farben des C 128 zum Rotieren!

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: [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
 
 

[Seitenanfang] [Artikel] [Info] [Links] [Download] [Home]
Erstellt von WTE, am 19. Februar 2006; überarbeitet am 21. Februar 2006