Autor Thema: VESA-Mode - Initialisiert und jetzt?  (Gelesen 15088 mal)

Scorpion

  • Beiträge: 57
    • Profil anzeigen
Gespeichert
« am: 06. March 2005, 18:08 »
Hi Leute,
ich habe mir das super Tutorial über den VGA-Modus durchgelesen und bin begeistert. Ich kann jetzt in den Vesa-Mode schalten, sowohl in Windows als auch in meinem (ASM-)Kernel. Leider bleiben noch folgende Fragen offen:

- wie kann ich einzelne Pixel "anmalen"
- wie schreibe ich Text?
- wie portiere ich folgenden (nach dem Vesa-Tutorail erstellten) Asm-Code in C / C++?


VbeInfoBlock:
        VbeSignature            db      'VBE2'          ; 4 Bytes
        VbeVersion              db      0, 0
        VbeOEMStringPtr         db      0, 0, 0, 0
        VbeCapabilities         db      0, 0, 0, 0
        VbeVideoModePtr         db      0, 0, 0, 0
        VbeTotalMemory          db      0, 0
        VbeOEMSoftwareRev       db      0, 0
        VbeOEMVendorNamePtr     db      0, 0, 0, 0
        VbeOEMProductNamePtr    db      0, 0, 0, 0
        VbeOEMProductRevPtr     db      0, 0, 0, 0
        VbeReserved times 222   db 0
        VbeOEMData times 256    db 0

VbeModeInfoBlock:
        VbeModeModeAttributes           db      0, 0
        VbeModeWinAAttributes           db      0
        VbeModeWinBAttributes           db      0
        VbeModeWinGranularity           db      0, 0
        VbeModeWinSize                  db      0, 0
        VbeModeWinASegment              db      0, 0
        VbeModeWinBSegment              db      0, 0
        VbeModeWinFuncPtr               db      0, 0, 0, 0
        VbeModeBytesPerScanLine         db      0, 0
        VbeModeXResolution              db      0, 0
        VbeModeYResolution              db      0, 0
        VbeModeXCharSize                db      0
        VbeModeYCharSize                db      0
        VbeModeNumberOfPlanes           db      0
        VbeModeBitsPerPixel             db      0
        VbeModeNumberOfBanks            db      0
        VbeModeMemoryModel              db      0
        VbeModeBankSize                 db      0
        VbeModeNumberOfImagePages       db      0
        VbeModeReserved_page            db      0
        VbeModeRedMaskSize              db      0
        VbeModeRedMaskPos               db      0
        VbeModeGreenMaskSize            db      0
        VbeModeGreenMaskPos             db      0
        VbeModeBlueMaskSize             db      0
        VbeModeBlueMaskPos              db      0
        VbeModeReservedMaskSize         db      0
        VbeModeReservedMaskPos          db      0
        VbeModeDirectColorModeInfo      db      0
        VbeModePhysBasePtr              db      0, 0, 0, 0
        VbeModeOffScreenMemOffset       db      0, 0, 0, 0
        VbeModeOffScreenMemSize         db      0, 0
        VbeModeLinBytesPerScanLine      db      0, 0
        VbeModeBnkNumberOfPages         db      0
        VbeModeLinNumberOfPages         db      0
        VbeModeLinRedMaskSize           db      0
        VbeModeLinRedFieldPos           db      0
        VbeModeLinGreenMaskSize         db      0
        VbeModeLinGreenFieldPos         db      0
        VbeModeLinBlueMaskSize          db      0
        VbeModeLinBlueFieldPos          db      0
        VbeModeLinRsvdMaskSize          db      0
        VbeModeLinRsvdFieldPos          db      0
        VbeModeMaxPixelClock            db      0, 0, 0, 0
        VbeModeReserved db 0 times 190       db      0

mov     ax,     0x4F00
mov     di,     VbeInfoBlock
int     0x10
mov     ax,     0x4F01
mov     di,     VbeModeInfoBlock
mov     cx,     0x4105
and     cx,     0xFFF
int     0x10
mov     ax,     0x4F02
mov     bx,     0x4101
int     0x10
mov     edi,    [VbeModePhysBasePtr]
mov     ecx,    640 * 480
mov     eax,    0xCC
rep     stosd



Danke im Voraus.

MfG, Scorpion!

Homix

  • Beiträge: 138
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 06. March 2005, 19:10 »
hi,
um einzelne Pixel "anzumalen" musst du den LFB (Linear Frame Buffer) benutzen !
die Startadresse vom LFB steht in VbeModePhysBasePtr !
Bei 8-Bit Frabtiefe ist jeder Pixel 1 Byte lang (bei 16-Bit ist er 2 Byte,...)
Adresse:                              Pixelposition (von rechts oben aus gesehen)
[VbeModePhysBasePtr]      = X: 0  Y: 0
[VbeModePhysBasePtr]+1  = X: 1  Y: 0
... usw ...
[VbeModePhysBasePtr]+640 = X: 0 Y: 1
...

Text kannst du nicht direkt draufzeichnen ! du musst die Pixel halt so zeichnen! normalerweise wird das über Fonts gemacht !

cu,
stefan2005

Scorpion

  • Beiträge: 57
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 06. March 2005, 19:14 »
hätte dazu jemand mal ein beispiel, denn ich blick da leider kaum durch!

MfG, Scorpion!

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #3 am: 06. March 2005, 19:57 »
die formeln lauten so:

ZielAdresse = PhysBasePtr + ((X + Y*PixelProZeile)*BitsPerPixel)/8

so, und das formst du nun entweder in C mit den passenden variablen um, oder aber du baust dir den dazu passenden ASM-Code. dann musste nurnoch an die adresse in ZielAdresse den Farbwert schreiben und schon is der Punkt angemalt. davor kannst/musste noch checken, ob der ausgewählte bereich inerhalb des anzeigebereichs is, sonst könnte jemand das ausnutzen (bufferoverflow!). und darauf kannste dann das zeichensetzen bauen, da brauchste ne font, die dir zeigt, weile pixel für z.B. ein A gesetzt werden müssen und eine passende routine, die die einzellnen werte abtastet und die punkte setzt, wenns angegeben is.

mfg

J!N
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #4 am: 06. March 2005, 20:00 »
ich dachte links oben sei x: 0 y: 0...?

@scorpion:

ich mach das so. ich schreibe die beiden blöcke (VbeModeInfo... ) linear an irgend eine unbenutzte adresse und schalte in den modues. später im pm und in c greife ich so drauf zu:
unsigned long *VbeModeInfoBlock = (unsigned long *) 0x7e00;
unsigned char *VideoMem;

unsigned long ScrWidth, ScrHeight;

unsigned long BGColor = 0x02A8C6;

void SetupVideo()
{
ScrWidth = VbeModeInfoBlock[4] & 0xFFFF; //extract high word from double
ScrHeight= VbeModeInfoBlock[4] >> 0xF; //extract low word from double

VideoMem = (unsigned char *)(VbeModeInfoBlock[10]);

ClearScreen();
};

void ClearScreen ()
{
unsigned char BGR = (BGColor & 0xFF0000) >> 16;
unsigned char BGG = (BGColor & 0x00FF00) >> 8;
unsigned char BGB = (BGColor & 0x0000FF);

unsigned long i = 2;
for (;i < (ScrWidth * ScrHeight)*3; i++)
{
VideoMem[i] = BGR;
i++;
VideoMem[i] = BGG;
i++;
VideoMem[i] = BGB;
};

};


leider stimmt aber die farbe nicht mit der überein die ich eigendlich beabsichtigt habe...

aber villeicht hilft dir das was..

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #5 am: 06. March 2005, 20:05 »
dein problem ist, dass du nicht auf die anzahl der bits per pixel achtest, zacK!

ich inite das zeug im bootloader, dazu check ich die modi 0x118 und 0x115 mit LFB und setze erstgenannten, falls es geht, sonst den 2. und wenn der net geht keinen. die werte übergebe ich meinem kernel, der berechnet daraus die passenden werte (maxX, maxY, LFBSize) und speichert die. und beim zeichenen checkt die routine dann auf maxX usw und auf bitsperpixel und setzt dann entsprechend die werte. und es geht :) alles in asm gemacht.
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #6 am: 06. March 2005, 20:11 »
ich kapiere das nicht ganz. eigendlich schalte ich in den 1024*768*32. aber die farben muss ich anscheinend gleich ich 24 bit speichern... :(

bei meinem echten pc komt viollet heraus. und bei bochs ist es ein grün. eigendlich wollte ich ein helles blau... :(

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #7 am: 06. March 2005, 20:35 »
eben. bochs benutzt 24bit pro pixel, was man auch braucht. real benutzt oft (aber leider nicht immer, sondern eher 50:50) 32bit, weil schnellerer speicherzugriff durch 1 dword als durch 1 word + 1 byte erfolgt. deshalb musst du das mit einbeziehen, also wenn du 24bit hast das X+Y*PixelProZeile nur mal 3, bei 32bit mal 4 multiplizieren, um an die adresse zu kommen...
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 09. March 2005, 17:40 »
In der Regeln reichen auch 16 Bit aus, da duerftest du die Sorgen nicht haben, vermute ich mal.
16 Bit ist schon sehr viel, damit ist auch Fotobearbeitung gut möglich. 32 Bit ist bei manchen Treibern, die direkt arbeiten, schon ein Geschwindigkeitsverlust... hab ich gehört (kann es selbst nicht beurteilen; messen muesstet ihr selbst)

Mvh Svenska

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #9 am: 10. March 2005, 09:13 »
16Bit ist aber wieder komplizierter zu zerlegen, bei 32/24 kann man einfach die Bytes nehmen, bei 16 müsste man etwas komplizierter mit shift & and arbeiten wenn man die einzelnen Farben extrahieren will. Naja aber so wirklich viel ist 16 Bit nich, "nur" 65k Farben im Gegensatz zu 16Millionen, das macht schon einen Unterschied, nur ist dummerweise das menschliche Auge zu dumm den zu bemerken^^
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 10. March 2005, 11:23 »
Also ... hab Praktikerfahrung  gleich null. Aber sind 16 Bit nicht gleich 2 Byte? Duerfte doch theoretisch ganz einfach sein, da ran zu kommen, Wert nach EAX und AX auslesen.
Mir gefällt immernoch die Angabe von 48 Bit Farbtiefe bei Scannern, weil das ist definitiv ueber dem Vermögen des Auges. Ich glaube, das Auge schafft nur 12-16 Bit und bei begabten Leuten sinds dann schonmal 20 Bit ... oder?
Ich fände es glaube ich einfacher, 16 Bit zu schreiben anstatt immer zu ueberlegen "nehm ich jetzt 24 oder 32 Bit?" ... aber wie gesagt, bei mir läuft eh noch nix. Ich schaffe es nichteinmal, ein Stringvariable in C in eine andere zu kopieren... :(

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #11 am: 10. March 2005, 14:18 »
Zitat von: Svenska
Also ... hab Praktikerfahrung  gleich null. Aber sind 16 Bit nicht gleich 2 Byte? Duerfte doch theoretisch ganz einfach sein, da ran zu kommen, Wert nach EAX und AX auslesen.
Mir gefällt immernoch die Angabe von 48 Bit Farbtiefe bei Scannern, weil das ist definitiv ueber dem Vermögen des Auges. Ich glaube, das Auge schafft nur 12-16 Bit und bei begabten Leuten sinds dann schonmal 20 Bit ... oder?
Ich fände es glaube ich einfacher, 16 Bit zu schreiben anstatt immer zu ueberlegen "nehm ich jetzt 24 oder 32 Bit?" ... aber wie gesagt, bei mir läuft eh noch nix. Ich schaffe es nichteinmal, ein Stringvariable in C in eine andere zu kopieren... :(


ja, aber diese 3 farbwerte (RGB) in 16 bits zu bekommen is schwer, weil das net aufgeht. (16%3!=0) deswegen muss man das dann zerlegen. während bei 32 oder 24bit ist das einfach nur 1 byte für jedes (24bit) oder aber 1 nullbyte und dann die RGBs...
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #12 am: 10. March 2005, 15:50 »
ich habe da auch ein problem....

mein vesa treiber spuckt die falschen farben aus...
aus 0x123456 gibt bochs die farbe 0x005634 aus...

und mein real-pc gibt wieder andere farben aus...

ausserdem fehlt beim echten pc in der mitte ein grosser streiffen der einfach schwarz ist... bochs färb alles ein...

hat das problem schon jemand gehabt?

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #13 am: 10. March 2005, 17:52 »
ja, ich. du scheinst einen zahlendreher zu haben. wie ich dir in meiner email schon geschrieben habe, rate ich dir, einfach mal ein bisschen mit der reihenfolge auszuprobieren. und was den echten PC angeht: der wird wohl 32bit haben und deine routine hat nen fehler, dass sie da net geht, ich denke da an den zahlendreher.
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #14 am: 10. March 2005, 20:41 »
ne, auch wenn ich die zahlen fest einschreiben also gleich

VideoMem[pos_für_rot] = 0x20 // angenommen VideoMem ist unsigned char *


auch dann ist rot 0x00... :(

und wenn ich die zahlen für die farbe ändere dann ändert sich das bild so wie ich es möchte in bochs, aber im realpc nicht...

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #15 am: 11. March 2005, 07:43 »
hier mein code:
/*
;
;---------------------------------------------------------------+
;       .__               __                           ¦
;______ |__|___________ _/  |_            ____  ______ ¦
;\____ \|  \_  __ \__  \\   __\  ______  /  _ \/  ___/ ¦
;|  |_> >  ||  | \// __ \|  |   /_____/ (  <_> )___ \ ¦
;|   __/|__||__|  (____  /__|            \____/____  > ¦
;|__|                  \/                          \/ ¦
;---------------------------------------------------------------+
;
;[1] Informations
;
; Last Modified: 25. Januar 2005
; Begin: 15. Juni 2004
; Version: 0.000
; Coder: z4ck
;
;
;[2] Tasks
;
; Task Done Coder
;----------------------------------------------------------------
; -                   [  0%] z4ck
;----------------------------------------------------------------
; TOTAL [  0%] z4ck
;================================================================
*/

#include <video.h>

#define VesaMode 0x118

unsigned long *VbeModeInfoBlock = (unsigned long *) 0x7e00; // This one ist set in kernel16.asm @ setvesa...
unsigned char *VideoMem; // saved in the VbeModeInfoBlock

/********************************************/
/* Screen Settings                          */
/********************************************/
unsigned long ScrWidth, ScrHeight;
unsigned char BitsPerPixel;


/********************************************/
/* COLORS                                   */
/********************************************/
unsigned long BGColor = 0x0011A8C6;
unsigned long FontColor = 0x00FFFFFF;
unsigned long FontShadowColor = 0x00EEEEEE;
/********************************************/


/********************************************/
/* Init the video                           */
/********************************************/
void SetupVideo()
{
ScrWidth  =  VbeModeInfoBlock[4] & 0xFFFF; //extract high word from double
ScrHeight  =  VbeModeInfoBlock[4] >> 0x10; //extract low word from double
BitsPerPixel  = (VbeModeInfoBlock[6] & 0xFF00) >> 0x8;

VideoMem  = (unsigned char *)(VbeModeInfoBlock[10]);

ClearScreen(); //Result: Color 0x00c6a8

DrawPixel(0, 0, 0x202020); //Result: Color 0x002020
VideoMem[(1*BitsPerPixel/8)]=0x11; //Result: COlor 0xc6a811
VideoMem[(1*BitsPerPixel/8)+1]=0xA8;
VideoMem[(1*BitsPerPixel/8)+2]=0xc6;
};


/********************************************/
/* Clear Screen whit BGColor                */
/********************************************/
void ClearScreen ()
{
unsigned long i = 0;
for (;i < ScrHeight; i++)
{
unsigned long u = 0;
for (; u < ScrWidth; u++)
DrawPixel(u, i, BGColor);
};

};


void printf (char *_string, long _color)
{

};

void printc (char _character, long _color)
{

};

void Num2String(int _number)
{

};


/********************************************/
/* Draw a Pixel                             */
/********************************************/
void DrawPixel (unsigned long _x, unsigned long _y, unsigned long _RGB)
{
unsigned char A   =  _RGB >> 0x18; //Alpha
unsigned char R   = (_RGB & 0x00FF0000) >> 0x10; //Red
unsigned char G   = (_RGB & 0x0000FF00) >> 0x08; //Green
unsigned char B   = (_RGB & 0x000000FF); //Blue
unsigned long pos = ((_y*ScrWidth)+_x)*(BitsPerPixel/8);

if (pos > (ScrWidth*ScrHeight*BitsPerPixel/8)) return;

switch(BitsPerPixel)
{
case 8:
case 16:
break;

case 24:
VideoMem[pos]   = R;
VideoMem[pos++] = G;
VideoMem[pos++] = B;
break;

case 32:
VideoMem[pos] = A;
VideoMem[pos++] = R;
VideoMem[pos++] = G;
VideoMem[pos++] = B;
break;
};
};


/*
void DrawBMP (File *_file, int _x, int _y)
{

};

*/


Scorpion

  • Beiträge: 57
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 11. March 2005, 12:55 »
danke, das hilft mir schon mehr weiter!

MfG, Scorpion!

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #17 am: 11. March 2005, 13:40 »
@zacK: eben, das meine ich. vll. stimmt die position nicht richtig, oder aber C und soweiter bekommt was mit fett und schmalspur endian nicht gebacken oder so. ändere einfach mal die reihenfolge ein bisschen und schau, wann das richtige byte an der richigen stelle ist. dann ändere die anderen noch und fertig... (und ergebniss bitte posten, interessiert mich, warums net ging!)
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #18 am: 11. March 2005, 14:00 »
wenn ich die position verändere, dann stimmt es vll in bochs, aber beim echten pc nicht mehr. ausser dem bleibt der rot-anteil immer auf 0x00 ausser ich schreibe es mit :
VideoMem[(1*BitsPerPixel/8)]=0x11;

also habe ich da noch ein bug...
:(

könnte es sein das die position der einzelnen farbwerte im ram irgendwie noch z.B von VbeModeLinRedFieldPos abhängt (sprich irgend einem eintrag im VbeModeInfoBlock)?

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #19 am: 11. March 2005, 14:42 »
ja, aber es ist zu 99,999 % standardisiert (RGB oder ARGB), deswegen beachte ich das nichtmehr...
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

 

Einloggen