VGA Mode 12 (Planar)
-
Hallo Zusammen
Ich habe ein kleines Problem mit k_memcpy.
Zuerst mal den code:void int32_setpixel_0x12(int x, int y, char farbe) { char Plane0[2]; char Plane1[2]; char Plane2[2]; char Plane3[2]; int getPosPixel = (y*640) + x;//wieviele pixel von oben links gesehen int BytePos = getPosPixel /8;//welches byte anwählen int modulo = getPosPixel % 8;//welches bit im byte anwählen char* vidmem = (char*) 0xA0000; //holle byte das verändert werden muss(4x wegen planes) outportw(0x3CE,0x0005);//setup plane masking outportw(0x3c4,0x0102);//plane 0 k_memcpy(Plane0,(vidmem + BytePos), 1); outportw(0x3c4,0x0202);//plane 1 k_memcpy(Plane1,(vidmem + BytePos), 1); outportw(0x3c4,0x0402);//plane 2 k_memcpy(Plane2,(vidmem + BytePos), 1); outportw(0x3c4,0x0802);//plane 3 k_memcpy(Plane3,(vidmem + BytePos), 1); outportw(0x3c4,0x0F02);//restore normal plane mask a = Plane0[0]; b = Plane1[0]; c = Plane2[0]; d = Plane3[0]; //ändere bits switch(modulo) { case(0): { if((farbe & 0x1) == 0x1){Plane0[0] |= 0x80;}//1000'0000 else{Plane0[0] &= 0x7F;}//0111'1111 if((farbe & 0x2) == 0x2){Plane1[0] |= 0x80;} else{Plane1[0] &= 0x7F;} if((farbe & 0x4) == 0x4){Plane2[0] |= 0x80;} else{Plane2[0] &= 0x7F;} if((farbe & 0x8) == 0x8){Plane3[0] |= 0x80;} else{Plane3[0] &= 0x7F;} break; } } //byte zurück in video speicher outportw(0x3CE,0x0005);//setup plane masking outportw(0x3c4,0x0102);//plane 0 k_memset((vidmem + BytePos), Plane0[0], 1); outportw(0x3c4,0x0202);//plane 1 k_memset((vidmem + BytePos), Plane1[0], 1); outportw(0x3c4,0x0402);//plane 2 k_memset((vidmem + BytePos), Plane2[0], 1); outportw(0x3c4,0x0802);//plane 3 k_memset((vidmem + BytePos), Plane3[0], 1); outportw(0x3c4,0x0F02);//restore normal plane mask }
Da dieser VGA modus nicht normal ist muss ich eine eigene Funktion schreiben um pixel zu zeichen. Mein problem ist, das memcpy den wert aus dem video speicher nicht in die variable planex[0] abspeichert. um ein pixel zu zeichen muss ich in 4 Bytes je nur 1 bit ändern(maskieren). Kann mir jemand helfen?(a-d sind nur varablen die ich spähter wieder im texmodus abfrage um zu testen ob der video speicher überhaupt ausgelessen wurde.)
-
Hallo,
es gibt noch ein Register mit dem du genau 1 Pixel (Bit) ändern kannst.
Schau dir mal das Bit Mask Register (Index 08h) an.Pixel zeichnen:
char *offset; //Bitmaske mit dem zu ändernden Pixel erstellen offset = (char*)0xA0000 + y * 640 + x / 8; bitmask = 0x80 >> (x & 7); //die Farbe schreibst du in das Set/Reset Register outportb(0x3CE,0x0); //Index 0 outportb(0x3CF,color); //Farbe eintragen //Alle Ebenen öffnen im Set/Reset Enable Register outportb(0x3CE,0x1); //Index 1 outportb(0x3CF,0xF); //Bit 0 bis 3 setzen //Im Bit Mask Register nur das berechnete Bit setzen! outportb(0x3CE,0x8); //Index 8 outportb(0x3CF,bitmask); //Bit setzen bei welchem die Farbe geändert werden soll //beliebigen Wert an die Adresse schreiben *offset--; //Register wieder herstellen
SVGA ist aber viel einfacher.
Nicky
-
und wo bestimme ich die Adresse?
Ich verstehe dein Code nicht zu 100%
-
Hallo,
die Adresse des Grafikspeichers im Modus 12h beginnt immer bei 0xA0000.
Der offset wird dann einfach dazu addiert.
X und Y sind die Koordinaten des zu zeichnenden Pixels.Nicky
-
also einfach wie ich das oben gemacht habe mit k_memset auf die 4 planes?
-
Warum willst du denn erst die 4 Planes auslesen, ändern und dann wieder
schreiben?Zum setzen eines Pixels genügen diese paar Zeilen Code.
Wenn du dich schon quälen willst schau mal nach diesem Buch
VGA- und Super- VGA- Karten programmieren | ISBN: 3772370136Nicky
-
ich meine in deinem Code wo du geschrieben hast steht nur *offset--.
nirgends wird der Offset an einen Port/register geschrieben wie z.b farbe/bitmask, und das verwiert mich gerade
dein code verstehe ich zu 100% aber wo die Adresse deviniert wird krieg ich nicht raus.
adrian
-
Hallo Adrian,
nirgends wird der Offset an einen Port/register geschrieben wie z.b farbe/bitmask, und das verwiert mich gerade
Was bei mir in Zeile 4 steht, steht bei dir in den Zeilen 7+8
Ich addiere dann noch den Beginn des Videospeichers dazu 0xA0000.Offset ist ein Zeiger zum lesen/schreiben eines Bytes in den RAM.
Und zwar in das Byte in dem dein Pixel gesetzt werden soll.Deine Daten oder Farben die du zeichnen möchtest nimmt die Graka aber
aus den Registern die wir zuvor gesetzt habenZeilen 8 bis 17
zum Schluss genügt ein Schreibzugriff auf die Speicherstelle.
*offset--;
würde das Byte an der Speicherstelle um 1 verringern, also Arbeit gemacht.
Du kannst aber auch*offset = 0xFF;
schreiben. Nur einfach irgendwas.
Nicky
-
zum Schluss genügt ein Schreibzugriff auf die Speicherstelle.
*offset--;
würde das Byte an der Speicherstelle um 1 verringern, also Arbeit gemacht.
Das stimmt nicht.
*offset--;
verringert offset um 1, tut aber sonst nichts. Die Speicherzelle, auf die offset zeigt, wird nicht verändert.
(*offset)--;
würde die Speicherzelle verändern.
-
danke für eure antworten aber irgendwie geht der code immer noch nicht
void int32_test() { char *offset; char color = RED; // red = 0xC int x = 320; int y = 320; char bitmask; //Bitmaske mit dem zu ändernden Pixel erstellen offset = (char*)0xA0000 + y * 640 + x / 8; bitmask = 0x80 >> (x & 7); //die Farbe schreibst du in das Set/Reset Register outportb(0x3CE,0x0); //Index 0 outportb(0x3CF,color); //Farbe eintragen //Alle Ebenen öffnen im Set/Reset Enable Register outportb(0x3CE,0x1); //Index 1 outportb(0x3CF,0xF); //Bit 0 bis 3 setzen //Im Bit Mask Register nur das berechnete Bit setzen! outportb(0x3CE,0x8); //Index 8 outportb(0x3CF,bitmask); //Bit setzen bei welchem die Farbe geändert werden soll //beliebigen Wert an die Adresse schreiben *offset = 0xFF; //(*offset)--; egal welches >> gleiches ergebnis = keine änderung des diplsays :/ //Register wieder herstellen }
(*offset)--; hab ich noch nirgend gesehen aber gut zu wissen
-
(char*)0xA0000 + y * 640 + x / 8;
sollte es nicht
(char*)0xA0000 + y*(640/8) + x/8;
heißen?
-
nein da y die vertikale linie bestimmt und x das bit im byte bestimmt