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

    Nicky



  • 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 haben

    Zeilen 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 🙂