' VESA-Demonstration: Demonstriert die Verwendung der SuperVGA-Grafikmodi ' aus QuickBASIC heraus unter Zuhilfsnahme der VESA-Schnittstelle ' (c) 2000 by Andreas Meile, CH-8242 Hofen SH ' e-Mail: andreas@hofen.ch WWW: http://www.hofen.ch/~andreas/ ' $INCLUDE: 'qb.bi' DECLARE SUB PrintText (y%, x%, VFar%, HFar%, t$) DECLARE FUNCTION FuehrNull$ (w%, b%) DECLARE SUB VesaPset (x%, y%, Farb&) DECLARE FUNCTION Pot2& (e%) DECLARE FUNCTION Farbe& (r%, g%, b%) DECLARE FUNCTION PeekWord% (Adr%) DECLARE FUNCTION FormatHex$ (w%, b%) DECLARE SUB VesaPsetPlanar (x%, y%, Farb%) ' Strukturen wie in einem C-Programm verwenden => macht den Code lesbarer :-) ' Hinweis: Es wird nur nach VESA-Spezifikation 1.2 gearbeitet. TYPE VgaInfoBlock VESASignatur AS STRING * 4 VESAVersionMinor AS STRING * 1 VESAVersionMajor AS STRING * 1 OEMStringOffs AS INTEGER OEMStringSeg AS INTEGER Faehigkeiten AS LONG VideoModeListeOffs AS INTEGER VideoModeListeSeg AS INTEGER TotalSpeicher AS INTEGER Reserviert AS STRING * 236 END TYPE TYPE ModeInfoBlock ModusAttribute AS INTEGER FenstAAttr AS STRING * 1 FenstBAttr AS STRING * 1 FenstGranularitaet AS INTEGER FenstGroesse AS INTEGER FenstASeg AS INTEGER FenstBSeg AS INTEGER FenstFktPtrOffs AS INTEGER FenstFktPtrSeg AS INTEGER ByteProPixelZeile AS INTEGER ' ab hier die frher einmal noch freiwilligen Felder xAufl AS INTEGER YAufl AS INTEGER XZeiGroe AS STRING * 1 YZeiGroe AS STRING * 1 AnzBitPlanes AS STRING * 1 AnzBitProPixel AS STRING * 1 AnzSpeiBaenke AS STRING * 1 SpeiModell AS STRING * 1 BankGroesse AS STRING * 1 AnzBildSeiten AS STRING * 1 Reserviert1 AS STRING * 1 ' ab hier die seit VESA 1.2 eingefhrten Farbfelder RotMaskenGroesse AS STRING * 1 RotFeldPos AS STRING * 1 GruenMaskenGroesse AS STRING * 1 GruenFeldPos AS STRING * 1 BlauMaskenGroesse AS STRING * 1 BlauFeldPos AS STRING * 1 ReservMaskenGroesse AS STRING * 1 ReservFeldPos AS STRING * 1 DirektFarbInfo AS STRING * 1 Reserviert AS STRING * 216 END TYPE DIM dosIntEin AS RegTypeX, dosIntAus AS RegTypeX DIM infBlk AS VgaInfoBlock DIM vModBesch AS ModeInfoBlock DIM vModes%(100) ' fr Farbberechnung verwendet DIM SHARED rPos&, gPos&, bPos& DIM SHARED rDiv%, gDiv%, bDiv% ' fr VesaPset()-Unterprogramm verwendet DIM SHARED AktFenst%, xSpr%, ySpr&, yJmp&, yInterleav%, FenstGroe&, GranSpr% DIM SHARED xAufl%, YAufl%, SchrFenst%, LeseFenst% ' Ersatz fr shl-Operator DIM SHARED XPot%(7) w% = 128 FOR i% = 0 TO 7 XPot%(i%) = w% w% = w% \ 2 NEXT i% PRINT "VESA-Demonstration aus QuickBASIC heraus" PRINT "(c) 2000 by Andreas Meile, CH-8242 Hofen SH" PRINT "e-Mail: andreas@hofen.ch WWW: http://www.hofen.ch/~andreas/" PRINT ' Demo 1: Ermittlung der Eigenschaften der Grafikkarte PRINT "Details zu dieser Grafikkarte:" PRINT "------------------------------" dosIntEin.ax = &H4F00 ' Funktion 4fh (VESA-BIOS), Unterfunktion 00h ' (SuperVGA-Informationen zurckliefern) dosIntEin.es = VARSEG(infBlk) dosIntEin.di = VARPTR(infBlk) CALL INTERRUPTX(&H10, dosIntEin, dosIntAus) IF dosIntAus.ax <> &H4F THEN ' AL=4Fh und AH=00h? PRINT "Fehler: Keine VESA-f„hige Grafikkarte vorhanden!" PRINT "Laden Sie das VESA-TSR noch nach. Sie k”nnen dieses auf der" PRINT "WWW-Site des Grafikkarten-Herstellers downloaden" END END IF ' In InfoPuffer% befindet sich jetzt die VgaInfoBlock-Struktur ' VESA-Signatur prfen IF infBlk.VESASignatur <> "VESA" THEN PRINT "Keine gltige VESA-Signatur" END IF PRINT "VESA-Version: V"; ASC(infBlk.VESAVersionMajor); "."; ASC(infBlk.VESAVersionMinor) DEF SEG = infBlk.OEMStringSeg i% = infBlk.OEMStringOffs OEMString$ = "" WHILE PEEK(i%) <> 0 OEMString$ = OEMString$ + CHR$(PEEK(i%)) i% = i% + 1 WEND PRINT "Herstellerkennung: "; OEMString$ PRINT "F„higkeiten: Schaltbarer DAC: "; IF infBlk.Faehigkeiten AND 1& THEN PRINT "Ja" ELSE PRINT "Nein" END IF DEF SEG = infBlk.VideoModeListeSeg i% = infBlk.VideoModeListeOffs PRINT "Liste untersttzter Videomodi:"; nModes% = 0 WHILE PeekWord%(i%) <> -1 vModes%(nModes%) = PeekWord%(i%) PRINT " " + FormatHex$(vModes%(nModes%), 4) + "h"; i% = i% + 2 nModes% = nModes% + 1 WEND PRINT PRINT "Installierter Speicher:"; CLNG(infBlk.TotalSpeicher) * 64&; "KB" PRINT ' Version prfen ma% = ASC(infBlk.VESAVersionMajor) mi% = ASC(infBlk.VESAVersionMinor) IF ma% < 1 OR ma% = 1 AND mi% < 2 THEN PRINT "Es wird im Minimum VESA Version 1.2 ben”tigt!" PRINT "Bitte im WWW nach einem BIOS-Update fr die Grafikkarte oder" PRINT "neueren VESA-TSR-Programmversion nachschauen" END END IF PRINT "Fortsetzung mit Taste => Analyse der Modi mit Grafikdemo" dummy$ = INPUT$(1) FOR i% = 1 TO nModes% PRINT "Modus"; i%; "von"; nModes%; ": "; FormatHex$(vModes%(i% - 1), 4); "h" PRINT "====================================" dosIntEin.ax = &H4F01 ' Funktion SuperVGA-Modus zurckliefern dosIntEin.cx = vModes%(i% - 1) dosIntEin.es = VARSEG(vModBesch) dosIntEin.di = VARPTR(vModBesch) CALL INTERRUPTX(&H10, dosIntEin, dosIntAus) IF dosIntAus.ax <> &H4F THEN COLOR 30 PRINT "Fehler: Nicht untersttzt" COLOR 7 ELSE PRINT "Modus-Attribute: Hardware-Support: "; IF vModBesch.ModusAttribute AND 1 THEN PRINT "Ja"; ELSE PRINT "Nein"; END IF PRINT " BIOS-Ausgabe: "; IF vModBesch.ModusAttribute AND 4 THEN PRINT "Ja" ELSE PRINT "Nein" END IF PRINT "Modusart: "; IF vModBesch.ModusAttribute AND 8 THEN PRINT "farbiger "; ELSE PRINT "monochromer "; END IF IF vModBesch.ModusAttribute AND 16 THEN PRINT "Grafikmodus" ELSE PRINT "Textmodus" END IF PRINT "Untersttzung Fenster A: "; IF ASC(vModBesch.FenstAAttr) AND 1 THEN PRINT "Ja"; ELSE PRINT "Nein"; END IF PRINT " Operationen:"; IF ASC(vModBesch.FenstAAttr) AND 2 THEN PRINT " Lesen"; END IF IF ASC(vModBesch.FenstAAttr) AND 4 THEN PRINT " Schreiben" ELSE PRINT END IF PRINT "Untersttzung Fenster B: "; IF ASC(vModBesch.FenstBAttr) AND 1 THEN PRINT "Ja"; ELSE PRINT "Nein"; END IF PRINT " Operationen:"; IF ASC(vModBesch.FenstBAttr) AND 2 THEN PRINT " Lesen"; END IF IF ASC(vModBesch.FenstBAttr) AND 4 THEN PRINT " Schreiben" ELSE PRINT END IF PRINT "kleinster Fenstersetzschritt:"; vModBesch.FenstGranularitaet; "KB" PRINT "Fenstergr”sse:"; vModBesch.FenstGroesse; "KB" PRINT "Fenster A @ Seg. "; FormatHex$(vModBesch.FenstASeg, 4); " Fenster B @ Seg. "; FormatHex$(vModBesch.FenstBSeg, 4) PRINT "Fenstersetz-Funktion @ "; FormatHex$(vModBesch.FenstFktPtrSeg, 4); ":"; FormatHex$(vModBesch.FenstFktPtrOffs, 4) PRINT "# Bytes pro Pixelzeile:"; vModBesch.ByteProPixelZeile PRINT "Aufl”sung:"; vModBesch.xAufl; "x"; vModBesch.YAufl; IF vModBesch.ModusAttribute AND 16 THEN PRINT "Pixel" ELSE PRINT "Textzeichen" END IF PRINT "Zeichengr”sse"; ASC(vModBesch.XZeiGroe); "x"; ASC(vModBesch.YZeiGroe); "Pixel" PRINT "# Bitebenen:"; ASC(vModBesch.AnzBitPlanes); PRINT " # Bit pro Pixel"; ASC(vModBesch.AnzBitProPixel); PRINT " # Speicherb„nke"; ASC(vModBesch.AnzSpeiBaenke) PRINT "Speichermodell: "; SELECT CASE ASC(vModBesch.SpeiModell) CASE &H0 PRINT "Textmodus" CASE &H1 PRINT "CGA-Grafikmodus" CASE &H2 PRINT "Hercules" CASE &H3 PRINT "planar, 4 Bitebenen" CASE &H4 PRINT "Gepackte Pixel" CASE &H5 PRINT "ungekettet 4, 256 Farben" CASE &H6 PRINT "Direkte Farben" CASE &H7 PRINT "YUV" CASE ELSE PRINT "Nicht bekannte Art: "; FormatHex$(ASC(vModBesch.SpeiModell), 2); "h" END SELECT PRINT "Bankgr”sse:"; ASC(vModBesch.BankGroesse); "KB" PRINT "# zus„tzliche Bildseiten:"; ASC(vModBesch.AnzBildSeiten) COLOR 12 PRINT "Rot-Maskengr”sse:"; ASC(vModBesch.RotMaskenGroesse); "Position:"; ASC(vModBesch.RotFeldPos) COLOR 10 PRINT "Grn-Maskengr”sse:"; ASC(vModBesch.GruenMaskenGroesse); "Position:"; ASC(vModBesch.GruenFeldPos) COLOR 9 PRINT "Blau-Maskengr”sse:"; ASC(vModBesch.BlauMaskenGroesse); "Position:"; ASC(vModBesch.BlauFeldPos) COLOR 7 PRINT "Reservierte Maske:"; ASC(vModBesch.ReservMaskenGroesse); "Position:"; ASC(vModBesch.ReservFeldPos) PRINT "Direktfarb-Eigenschaften: Anstiegsprofil:"; IF ASC(vModBesch.DirektFarbInfo) AND 1 THEN PRINT " frei programmierbar" ELSE PRINT " fest" END IF PRINT "Bits im Reserviert-Feld:"; IF ASC(vModBesch.DirektFarbInfo) AND 2 THEN PRINT " frei verwendbar fr Anwendungen" ELSE PRINT " reserviert" END IF dummy$ = INPUT$(1) ' Demo erzeugen ' Zuerst alter Modus sichern dosIntEin.ax = &H4F03 ' SuperVGA-Modus zurckliefern CALL INTERRUPTX(&H10, dosIntEin, dosIntAus) IF dosIntAus.ax <> &H4F THEN PRINT "Fehler bei Videomodus lesen" END END IF AlterModus% = dosIntAus.bx ' Modus setzen dosIntEin.ax = &H4F02 ' SuperVGA-Modus setzen dosIntEin.bx = vModes%(i% - 1) CALL INTERRUPTX(&H10, dosIntEin, dosIntAus) IF dosIntAus.ax <> &H4F THEN PRINT "Fehler bei Videomodus setzen: ax="; FormatHex$(dosIntAus.ax, 4); "h" ELSE ' Werte fr VESA-"PSET()" vorbereiten: Suche nach dem Schreibfenster IF (ASC(vModBesch.FenstAAttr) AND 5) = 5 THEN SchrFenst% = 0 DEF SEG = vModBesch.FenstASeg ELSEIF (ASC(vModBesch.FenstBAttr) AND 5) = 5 THEN SchrFenst% = 1 DEF SEG = vModBesch.FenstBSeg ELSE SchrFenst% = -1 ' Kein Fenster END IF IF (ASC(vModBesch.FenstAAttr) AND 3) = 3 THEN LeseFenst% = 0 ELSEIF (ASC(vModBesch.FenstBAttr) AND 3) = 3 THEN LeseFenst% = 1 ELSE LeseFenst% = -1 ' Kein Fenster END IF ' In der Demo wird jedoch kein separates Schreib-/Lese- ' Speicherfenster ben”tigt dosIntEin.ax = &H4F05 dosIntEin.bx = SchrFenst% OR 256 CALL INTERRUPTX(&H10, dosIntEin, dosIntAus) AktFenst% = dosIntAus.dx IF LeseFenst% <> SchrFenst% THEN ' separates Lese- und Schreibfenster: Sind beide identisch? dosIntEin.ax = &H4F05 dosIntEin.bx = LeseFenst% OR 256 CALL INTERRUPTX(&H10, dosIntEin, dosIntAus) IF dosIntAus.dx <> AktFenst% THEN ' Nein => auf gleichen Wert setzen dosIntEin.ax = &H4F05 dosIntEin.bx = LeseFenst% dosIntEin.dx = AktFenst% CALL INTERRUPTX(&H10, dosIntEin, dosIntAus) END IF END IF xSpr% = (ASC(vModBesch.AnzBitProPixel) + 7) \ 8 ySpr& = CLNG(vModBesch.ByteProPixelZeile) yJmp& = CLNG(ASC(vModBesch.BankGroesse)) * 1024& yInterleav% = ASC(vModBesch.AnzSpeiBaenke) FenstGroe& = CLNG(vModBesch.FenstGroesse) * 1024& GranSpr% = vModBesch.FenstGroesse \ vModBesch.FenstGranularitaet xAufl% = vModBesch.xAufl YAufl% = vModBesch.YAufl rPos& = Pot2&(ASC(vModBesch.RotFeldPos)) rDiv% = CINT(Pot2&(8 - ASC(vModBesch.RotMaskenGroesse))) gPos& = Pot2&(ASC(vModBesch.GruenFeldPos)) gDiv% = CINT(Pot2&(8 - ASC(vModBesch.GruenMaskenGroesse))) bPos& = Pot2&(ASC(vModBesch.BlauFeldPos)) bDiv% = CINT(Pot2&(8 - ASC(vModBesch.BlauMaskenGroesse))) keinDemo% = 0 SELECT CASE ASC(vModBesch.SpeiModell) CASE &H0 ' Textdemo FOR y% = 1 TO YAufl% PrintText y%, 1, 1, 2, FuehrNull$(y%, 3) NEXT y% FOR x% = 4 TO xAufl% h% = x% FOR y% = 3 TO 1 STEP -1 PrintText y%, x%, 13, 0, CHR$(48 + h% MOD 10) h% = h% \ 10 NEXT y% NEXT x% PrintText 5, 5, 12, 0, "Zeichenvorrat:" PrintText 5, 22, 3, 0, "Farben:" FOR y% = 0 TO 15 FOR x% = 0 TO 15 PrintText 6 + y%, 5 + x%, 7, 0, CHR$(16 * y% + x%) PrintText 6 + y%, 22 + x%, x%, y%, "A" NEXT x% NEXT y% CASE &H3 ' Sequenz aus initPlanar(), um den sog. Write Mode auf 2 zu setzen OUT &H3C4, &H2 OUT &H3C5, &HF OUT &H3CE, &H3 OUT &H3CF, &H0 OUT &H3CE, &H5 OUT &H3CF, &H2 FOR y% = 0 TO YAufl% - 1 FOR x% = 0 TO xAufl% - 1 VesaPsetPlanar x%, y%, (x% + y%) \ 20 AND 15 NEXT x% NEXT y% ' Wieder auf BIOS-Vorgabewerte setzen gem„ss setWriteMode0() OUT &H3CE, &H8 OUT &H3CF, &HFF OUT &H3CE, &H5 OUT &H3CF, &H0 CASE &H6 FOR y% = 0 TO YAufl% - 1 FOR x% = 0 TO xAufl% - 1 VesaPset x%, y%, Farbe&(y% AND 255, x% AND 255, 133) NEXT x% NEXT y% CASE &H4 FOR y% = 0 TO YAufl% - 1 FOR x% = 0 TO xAufl% - 1 VesaPset x%, y%, CLNG((x% \ 5 AND 15) + 16 * (y% \ 5 AND 15)) NEXT x% NEXT y% CASE ELSE keinDemo% = -1 END SELECT dummy$ = INPUT$(1) ' Wieder in den Textmodus zurckgehen dosIntEin.ax = &H4F02 ' SuperVGA-Modus setzen dosIntEin.bx = AlterModus% CALL INTERRUPTX(&H10, dosIntEin, dosIntAus) IF dosIntAus.ax <> &H4F THEN PRINT "Fehler bei Videomodus setzen" END END IF END IF IF keinDemo% THEN PRINT "Kein Demo fr diese Modusart m”glich!" dummy$ = INPUT$(1) END IF END IF NEXT i% FUNCTION Farbe& (r%, g%, b%) Farbe& = rPos& * CLNG(r% \ rDiv%) OR gPos& * CLNG(g% \ gDiv%) OR bPos& * CLNG(b% \ bDiv%) END FUNCTION FUNCTION FormatHex$ (w%, b%) h$ = HEX$(w%) FormatHex$ = STRING$(b% - LEN(h$), "0") + h$ END FUNCTION FUNCTION FuehrNull$ (w%, b%) h$ = MID$(STR$(w%), 2) FuehrNull$ = STRING$(b% - LEN(h$), "0") + h$ END FUNCTION FUNCTION PeekWord% (Adr%) PeekWord% = CVI(CHR$(PEEK(Adr%)) + CHR$(PEEK(Adr% + 1))) END FUNCTION FUNCTION Pot2& (e%) h& = 1& FOR i% = 1 TO e% h& = h& * 2 NEXT i% Pot2& = h& END FUNCTION SUB PrintText (y%, x%, VFar%, HFar%, t$) ' Diese Routine l„uft auch ohne BIOS-Untersttzung Adr% = (y% - 1) * CINT(ySpr&) + 2 * (x% - 1) fa% = 16 * HFar% OR VFar% FOR i% = 1 TO LEN(t$) POKE Adr%, ASC(MID$(t$, i%, 1)) POKE Adr% + 1, fa% Adr% = Adr% + 2 NEXT i% END SUB SUB VesaPset (x%, y%, Farb&) DIM dosIntEin1 AS RegType, dosIntAus1 AS RegType IF x% >= 0 AND y% >= 0 AND x% < xAufl% AND y% < YAufl% THEN AbsAdr& = CLNG(x% * xSpr%) + CLNG(y% \ yInterleav%) * ySpr& + yJmp& * (y% MOD yInterleav%) f1& = Farb& FOR i% = 1 TO xSpr% NeuFenst% = CINT(AbsAdr& \ FenstGroe&) * GranSpr% IF AktFenst% <> NeuFenst% THEN dosIntEin1.ax = &H4F05 dosIntEin1.bx = SchrFenst% dosIntEin1.dx = NeuFenst% CALL INTERRUPT(&H10, dosIntEin1, dosIntAus1) AktFenst% = NeuFenst% END IF POKE AbsAdr& MOD FenstGroe&, CINT(f1& AND 255&) AbsAdr& = AbsAdr& + 1 f1& = f1& \ 256& NEXT i% END IF END SUB SUB VesaPsetPlanar (x%, y%, Farb%) DIM dosIntEin1 AS RegType, dosIntAus1 AS RegType IF x% >= 0 AND y% >= 0 AND x% < xAufl% AND y% < YAufl% THEN AbsAdr& = CLNG(x% \ 8) + CLNG(y% \ yInterleav%) * ySpr& + yJmp& * (y% MOD yInterleav%) NeuFenst% = CINT(AbsAdr& \ FenstGroe&) * GranSpr% IF AktFenst% <> NeuFenst% THEN dosIntEin1.ax = &H4F05 dosIntEin1.bx = SchrFenst% dosIntEin1.dx = NeuFenst% CALL INTERRUPT(&H10, dosIntEin1, dosIntAus1) IF SchrFenst% <> LeseFenst% THEN ' Separates Schreib- und Lesefenster => Lesefenster auch setzen dosIntEin1.ax = &H4F05 dosIntEin1.bx = LeseFenst% dosIntEin1.dx = NeuFenst% CALL INTERRUPT(&H10, dosIntEin1, dosIntAus1) END IF AktFenst% = NeuFenst% END IF OUT &H3CE, 8 OUT &H3CF, XPot%(x% AND 7) dummy% = PEEK(AbsAdr& MOD FenstGroe&) POKE AbsAdr& MOD FenstGroe&, Farb% END IF END SUB