Bitmap

Aus C64-Wiki
Wechseln zu: Navigation, Suche

Speicherauszug, in dem festgehalten ist, ob in einer zugehörigen Grafik ein Punkt (Pixel) gesetzt ist oder nicht. Ein gesetztes Pixel wird durch ein 1-Bit repräsentiert und erhält im C64-Hires-Modus die Schreibfarbe zugewiesen (siehe auch HIRES). Nicht gesetzte Pixel entsprechen folglich der 0 und stellen die Hintergrundfarbe dar. Im Prinzip ist eine Bitmap jedoch attributlos (monochrom).

Eine komplette Bitmap ist 8000 Bytes lang und wird gebildet aus 1000 Kacheln zu je acht untereinander liegenden Bytes, die jeweils eine 8 Pixel breite Pixelzeile bilden. Nebeneinander liegen 40 dieser Kacheln, untereinander wiederum 25 solcher Kachelzeilen. 40 × 8 Bits ergeben 320 Pixel in der Waagerechten und 25 × 8 Bits sind senkrecht 200 Pixel. So erklärt sich die Auflösung von 320 × 200 Pixeln der Hires-Grafik.

Die Pixel in einer solchen Bitmap sind also nicht linear angeordnet, sondern müssen auf diese Kachel-Geometrie umgerechnet werden. Eine waagerechte Linie in der obersten Pixelzeile besteht deshalb aus 40 Einzelstücken, die jeweils acht Byte voneinander entfernt liegen, das sind alle obersten Bytes der ersten 40 Kacheln.

Der Anfang des Grafikspeichers

Eine Adresse x,y errechnet sich nun folgendermaßen
(z.B. für x = 100, y = 50, Grafikspeicher ab 8192):

Offset der zugehörigen Kachel im Grafikspeicher:
k = INT(x/8)*8 + INT(y/8) * 320
INT(x/8)*8 bewirkt, dass die niederwertigsten 3 Bits des x-Wertes gelöscht werden (das ist der nächstniedrige ganzzahlig durch 8 teilbare Wert). Diese 3 Bits der Pixelzeile, werden dann weiter unten benötigt.
⇒ Beispiel: k = 96 + 1920 = 2016

Offset des Bytes in dieser Kachel (0 bis 7):
pz = (y AND 7)
Das "AND" belässt hier als bit-orientiere Operation die niederwertigsten 3 Bits des y-Wertes. Die Maske ist die Summe der Bit-Wertigkeiten von Bit 0 bis Bit 2 (1+2+4).
⇒ Beispiel: pz = 2

Wert des angepeilten Bits in diesem Byte:
px = 2(7 - (x AND 7))
Das "AND" belässt hier als bit-orientiere Operation die niederwertigsten 3 Bits des x-Wertes. Die Maske ist die Summe der Bit-Wertigkeiten von Bit 0 bis Bit 2 (1+2+4).
⇒ Beispiel: px = 8 (das ist Bit 3 von rechts)

Byte-Adresse: ba = 8192+k+pz

Pixel setzen:
POKE ba, PEEK(ba) OR px

Pixel löschen:
POKE ba, PEEK(ba) AND NOT px


Beispiel für Pixel setzen und löschen:

POKE 10210, PEEK(10210) OR 8
POKE 10210, PEEK(10210) AND NOT 8


Jede Grafik, egal in welchem Modus sie angezeigt wird, enthält (zumindest) eine Bitmap.

Implementierung[Bearbeiten]

BASIC V2

Grafikverwendung nur mit Mitteln des BASIC V2.
Zur Beschleunigung werden

  • in Z() die Kachelzeilenadressen
  • in B() die Bit-Werte für eine Pixelzeile einer Kachel

vorberechnet.
Die Grafik wird liegt ab Adresse 8192 ($2000), die Farbinformationen im Bildschirmspeicher ab 1024 ($0400).
Mit Hilfe eines temporär angelegten Integer-Arrays A%(), das von BASIC mit Wert 0 initialisiert wird, erfolgt indirekt das Löschen der Bitmap, da das Array unmittelbar auf das Programm im Speicher folgt und rund 16000 Bytes belegt und damit den Speicher der Bitmap abdeckt.

Initialisierung:

 105 REM BITMAP MIT INTEGER-ARRAY LOESCHEN
 110 DIM A%(8000): CLR
 115 REM ARRAYS FUER PIXELZEILENMASKE, ZEILENANFANGSADRESSEN
 120 DIM B(7),Z(24)
 125 REM PIXELZEILENMASKENWERTE BERECHNEN
 130 W=1: FOR I=7 TO 0 STEP -1: B(I)=W: W=W+W: NEXT
 135 REM ZEILENANFANGSADRESSEN BERECHNEN
 140 FOR I=0 TO 24: Z(I)=8192+320*I: NEXT
 145 REM GRAFIKMODUS EIN, RAHMENFARBE GRAU
 140 POKE 53265,59: POKE 53272,24: POKE 53280,15
 145 REM ZEICHENFARBE, HINTERGRUND DER BITMAP: HELLGRUEN/SCHWARZ 
 140 F=13*16+0: FOR I=1024 TO 2023: POKE I,F: NEXT

Zeichnen:

 145 REM PUNKTIERTE LINIE ZEICHNEN
 150 FOR X=0 TO 99: Y=X+X
 155 REM PIXEL SETZEN
 160 GOSUB 200
 170 NEXT
 175 REM AUF TASTE WARTEN
 180 WAIT 198,1 

Grafik ausschalten:

 180 PRINT "{CLR}"
 190 POKE 53265,155: POKE 53272,21
 199 END

Unterprogramm zum Pixelsetzen:

 200 G=Z(Y/8) + (X AND 504) + (Y AND 7):POKE G, PEEK(G) OR B(X AND 7): RETURN

Das "AND 504" löscht hier als bit-orientiere Operation die niederwertigsten 3 Bits des x-Wertes, entspricht also dem INT(x/8)*8. Die Maske ist die Summe der Bit-Wertigkeiten von Bit 3 bis Bit 8 (8+16+32+64+128+256).