Autor Thema: Byte aus speicher lesen, bit verändern und Byte wieder im speicher ablegen  (Gelesen 8198 mal)

Tbex

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
Zuerst mal Danke für die Aktivierung meines Accounts in diesem Forum :)

wie im Titel schon beschrieben möchte ich ein bit in einem Byte maskieren.
Ich möchte nämlich den vga modus 12 benuzten, der im Planar modus ist.
Ich schaff es den Modus zu ändern wie auch den ganzen Bildschirm schon mit einer Farbe zu füllen.
Wenn ich aber ein Pixel ändere möchte, muss ich 4 bits ändern die alle auf der gleichen Adresse liegen. mit outportw kann ich in diesen Planes switchen.

Hier der Code:
Code: ("c") [Auswählen]
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

    //ä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
  }

Irgendwie kann aber k_memcpy das Byte nicht aus dem speicher lesen und in den string schreiben....
Kann mir jemand helfen oder zeigen wie ich das machen kann?

Vielen Dank im voraus

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
Auch hier nochmal herzlich willkommen im Forum, falls du die PN noch nicht gelesen hast. ;)

Wenn du sagst, dass k_memcpy() die Daten nicht richtig liest, heißt das, dass du das Zwischenergebnis nach dem Holen der Bytes ausgegeben hast und schon das nicht stimmt? Dann müssen wir uns den Rest nämlich gar nicht erst anschauen.

Theoretisch denkbar ist, dass dein k_memcpy() nicht richtig funktioniert, kannst du es mal posten? Ansonsten wäre es wahrscheinlich, dass VGA doch nicht so funktioniert wie du denkst. Wie das genau geht, weiß ich aber auch nicht auswendig und müsste es erstmal nachlesen.

Und dann wäre natürlich noch die Frage, wieso du dir überhaupt Modus 12 antust, wenn es heute vernünftige Auflösungen mit genug Farben gibt. :D
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Tbex

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
wenn ich im standart textmodus diesen code benutzte:
    USHORT* vidmem = (USHORT*) 0xb8000;
    char Ausgabe[10];
    set_cursor(0,0);
    save_cursor();
    k_clear_screen();
    printformat("hallo");
    k_memcpy(Ausgabe,vidmem, 10);
    printformat("\n%s",Ausgabe);
    sleepSeconds(100);
kommt auch beim 2. printformat das Hallo, davon gehe ich aus, dass die funktion geht.
hier k_memcpy:
void* k_memcpy(void* dest, const void* src, size_t count)
{
    const char *sp = (const char *)src;
    char *dp = (char *)dest;
    for(; count != 0; count--) *dp++ = *sp++;
    return dest;
}

mir geht es nicht darum den besten Farbmodus zu haben, ich möchte nur meine Programmierfähigkeiten verbessern und dazulernen.
hier das einzige gute dokument was ich zu den vga modis gefunden habe:
http://webpages.charter.net/danrollins/techhelp/0089.HTM
« Letzte Änderung: 09. March 2016, 11:50 von Tbex »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
Hier gibt es ein bisschen mehr Doku: http://www.osdever.net/FreeVGA/vga/vga.htm

Bist du dir sicher, dass es eine gute Idee ist, Adress- und Datenregister gleichzeitig mit einem outw zu setzen statt erst die Adresse und dann die Daten jeweils mit outb?

(k_memcpy sieht okay aus. Nur das Textmodus-Testprogramm ist strenggenommen kaputt, weil Ausgabe nicht nullterminiert ist.)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Tbex

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
wie meinst du das: "Adress- und Datenregister gleichzeitig mit einem outw zu setzen"?
wenn es mit:
void int32_clear_screen_0x12(char farbe)
  {
    char Plane0, Plane1, Plane2, Plane3;


    if((farbe & 0x1) == 0x1){Plane0 = 0xFF;}
      else{Plane0 = 0x00;}

    if((farbe & 0x2) == 0x2){Plane1 = 0xFF;}
      else{Plane1 = 0x00;}

    if((farbe & 0x4) == 0x4){Plane2 = 0xFF;}
      else{Plane2 = 0x00;}

    if((farbe & 0x8) == 0x8){Plane3 = 0xFF;}
      else{Plane3 = 0x00;}

        outportw(0x3CE,0x0005);//setup plane masking
        outportw(0x3c4,0x0102);//plane 0
        k_memset((char*) 0xA0000,Plane0,38400);
        outportw(0x3c4,0x0202);//plane 1
        k_memset((char*) 0xA0000,Plane1,38400);
        outportw(0x3c4,0x0402);//plane 2
        k_memset((char*) 0xA0000,Plane2,38400);
        outportw(0x3c4,0x0802);//plane 3
        k_memset((char*) 0xA0000,Plane3,38400);
        outportw(0x3c4,0x0F02);//restore normal plane mask
  }
geht, sollte es ja auch mit einem byte gehen^^

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
wie meinst du das: "Adress- und Datenregister gleichzeitig mit einem outw zu setzen"?
Das hier:
outportw(0x3c4,0x0102);//plane 0Ich hätte da eher sowas erwartet:
outportb(0x3c4,0x02); // Adressregister auf Index von Map Mask Register setzen
outportb(0x3c5,0x01); // Mit Datenregister den Wert des MMR setzen

Zitat
wenn es mit: [...] geht, sollte es ja auch mit einem byte gehen^^
Du meinst, dein int32_clear_screen_0x12() funktioniert? Das hattest du bisher nicht erwähnt. :)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Tbex

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
ja diese Funktion geht einwandfrei :)
ich habe auch schon mit dieser Funktion den Bildschirm Komplet Weiß eingefärbt(alle byte mit 0xFF) und dann wieder in Textmodus gewechselt um dann wie vorher den Speicher abgefragt.
Leider ohne erfolg :/

ob ich outportb oder outportw benutzte macht auch kein unterschied....
Ich frage morgen in der Schule mal mein H&S Lehrer, auch wenn ich nicht viel von ihm erwarte kann^^

Krendor

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
Was für eine Ausgabe erwartest du denn? Wenn die ersten beiden Pixel schwarz sind, (Wert 0x00) dann enthält der String Ausgabe ja gleich ein Nullterminierungzeichen und somit wird nichts ausgegeben. Vielleicht solltest du den Wert noch in einen String umwandeln?

Tbex

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
Wie meinst du was ich als Ausgabe erwarte? ich erwarte beim Auslesen des Speichers ein 0xFF, weil der Bildschirm weiss ist/war.

Mein Lehrer weiss auch nichts wie erwartet.... :?

ich setzt mich heut Abend mal hin und mach ne asm Funktion die den Speicher auslesen soll.


Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
ob ich outportb oder outportw benutzte macht auch kein unterschied....
Das kann reale Hardware deutlich anders sehen als ein Emulator.

Tbex

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
Zitat
Das kann reale Hardware deutlich anders sehen als ein Emulator.

da geb ich dir recht aber das ist nicht mein problem^^
Irgendwie will k_memcpy den speicher nicht ausslesen und ich seh den fehler nicht :/

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
Wenn du gar nicht weiterkommst, kannst du mal deinen kompletten Code irgendwo online stellen, dass man das im Komplettzusammenhang sehen und evtl. auch damit spielen kann. Ich bin mir noch nicht sicher, ob ich Zeit habe, das für dich zu debuggen, aber vielleicht springt ja jemand anderes ein.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Tbex

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
https://www.dropbox.com/sh/8b08pga11m3ms9n/AABXrYM34vN_rKN5cLq6ZDhLa?dl=0

viel spass, sollte recht gut auskommentiert sein :)

die funktion die aufgeruffen wird heisst: int32_setpixel_0x12(320,320,GREEN); in ckernel.c zeile 112

die funktion ist ausgeschrieben in int32.c zeile 61


 

Einloggen