Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

Oberon/ETH Oberon/2.3.7/DisplayTool.Mod

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

(* ETH Oberon, Copyright 1990-2003 Computer Systems Institute, ETH Zurich, CH-8092 Zurich. Refer to the license.txt file provided with this distribution. *) MODULE DisplayTool; IMPORT V86, SYSTEM, MathL, Kernel (*, Log, Texts, Oberon, In *); CONST textsDebug = TRUE; CONST GTFLockVF = 1; (* Lock to vertical frequency *) GTFLockHF = 2; (* Lock to horizontal frequency *) GTFLockPF = 3; (* Lock to pixel clock frequency *) TYPE GTFConstants = RECORD margin: LONGREAL; (* Margin size as percentage of display *) cellGran: LONGREAL; (* Character cell granularity *) minPorch: LONGREAL; (* Minimum front porch in lines/chars *) vSyncRqd: LONGREAL; (* Width of V sync in lines *) hSync: LONGREAL; (* Width of H sync as percent of total *) minVSyncBP: LONGREAL; (* Minimum vertical sync + back porch (us) *) m: LONGREAL; (* Blanking formula gradient *) c: LONGREAL; (* Blanking formula offset *) k: LONGREAL; (* Blanking formula scaling factor *) j: LONGREAL; (* Blanking formula scaling factor weight *) END; GTFHCRTC = RECORD hTotal: LONGINT; (* Horizontal total *) hDisp: LONGINT; (* Horizontal displayed *) hSyncStart: LONGINT; (* Horizontal sync start *) hSyncEnd: LONGINT; (* Horizontal sync end *) hFrontPorch: LONGINT; (* Horizontal front porch *) hSyncWidth: LONGINT; (* Horizontal sync width *) hBackPorch: LONGINT; (* Horizontal back porch *) END; GTFVCRTC = RECORD vTotal: LONGINT; (* Vertical total *) vDisp: LONGINT; (* Vertical displayed *) vSyncStart: LONGINT; (* Vertical sync start *) vSyncEnd: LONGINT; (* Vertical sync end *) vFrontPorch: LONGINT; (* Vertical front porch *) vSyncWidth: LONGINT; (* Vertical sync width *) vBackPorch: LONGINT; (* Vertical back porch *) END; GTFTimings = RECORD h: GTFHCRTC; (* Horizontal CRTC paremeters *) v: GTFVCRTC; (* Vertical CRTC parameters *) hSyncPol: CHAR; (* Horizontal sync polarity *) vSyncPol: CHAR; (* Vertical sync polarity *) interlace: CHAR; (* 'I' for Interlace, 'N' for Non *) vFreq: LONGREAL; (* Vertical frequency (Hz) *) hFreq: LONGREAL; (* Horizontal frequency (KHz) *) dotClock: LONGREAL; (* Pixel clock (Mhz) *) END; VAR GC: GTFConstants; TYPE VBEString = ARRAY 32 OF CHAR; VideoMode = POINTER TO VideoModeDesc; VideoModeDesc = RECORD modeNr: LONGINT; (* mandatory for all VBE revisions *) modeAttr, winAAttr, winBAttr: SET; winGranularity, winSize, winASeg, winBSeg, bytesPerScanLine: LONGINT; winFuncPtr: LONGINT; (* mandatory for VBE 1.2 and above *) xRes, yRes, xCharSize, yCharSize, nrOfPlanes, bitsPerPixel, nrOfBanks: LONGINT; memoryModel, bankSize, nrOfImgPages: LONGINT; (* direct color fields (for direct/6 and YUV/7) *) redMaskSize, redFieldPos: LONGINT; greenMaskSize, greenFieldPos: LONGINT; blueMaskSize, blueFieldPos: LONGINT; rsvdMaskSize, rsvdFieldPos: LONGINT; directColorModeInfo: SET; (* mandatory for VBE 2.0 and above *) physBasePtr: LONGINT; (* mandatory for VBE 3.0 and above *) linBytesPerScanLine, bnkNrOfImgPages, linNrOfImgPages: LONGINT; linRedMaskSize, linRedFieldPos: LONGINT; linGreenMaskSize, linGreenFieldPos: LONGINT; linBlueMaskSize, linBlueFieldPos: LONGINT; linRsvdMaskSize, linRsvdFieldPos, maxPixelClock: LONGINT; next: VideoMode END; VBEControllerInfo = RECORD sig: ARRAY 5 OF CHAR; version, oemSoftwareRev, totalMem: LONGINT; oemString, oemVendor, oemProductName, oemProductRev: VBEString; dac8, vga, extDac, stereo, stereoEVC, available: BOOLEAN; vmodes: VideoMode END; VAR Width*, Height*, Depth*, Hz*: LONGINT; HSyncStart, HSyncEnd, VSyncStart, VSyncEnd: LONGINT; vbe: VBEControllerInfo; (* W: Texts.Writer; T: Texts.Text; *) PROCEDURE LogStr(s: ARRAY OF CHAR); BEGIN (* IF textsDebug THEN Texts.WriteString(W, s); Texts.Append(T, W.buf) ELSE Log.Str(s) END *) END LogStr; PROCEDURE LogHex(x: LONGINT); BEGIN (* IF textsDebug THEN Texts.WriteHex(W, x); Texts.Append(T, W.buf) ELSE Log.Hex(x) END *) END LogHex; PROCEDURE LogInt(x: LONGINT); BEGIN (* IF textsDebug THEN Texts.WriteInt(W, x, 0); Texts.Append(T, W.buf) ELSE Log.Int(x) END *) END LogInt; PROCEDURE LogLn; BEGIN (* IF textsDebug THEN Texts.WriteLn(W); Texts.Append(T, W.buf) ELSE Log.Ln END *) END LogLn; (* GTF *) PROCEDURE pow(x: LONGREAL; n: LONGINT): LONGREAL; VAR s: LONGREAL; BEGIN s := 1; WHILE n > 0 DO s := s * x; DEC(n) END; RETURN s END pow; PROCEDURE Round(v: LONGREAL): LONGREAL; BEGIN RETURN ENTIER(v + 0.5) END Round; PROCEDURE GetInternalConstants(VAR c: GTFConstants); BEGIN c.margin := GC.margin; c.cellGran := Round(GC.cellGran); c.minPorch := Round(GC.minPorch); c.vSyncRqd := Round(GC.vSyncRqd); c.hSync := GC.hSync; c.minVSyncBP := GC.minVSyncBP; IF GC.k = 0 THEN c.k := 0.001 ELSE c.k := GC.k END; c.m := (c.k / 256) * GC.m; c.c := (GC.c - GC.j) * (c.k / 256) + GC.j; c.j := GC.j; END GetInternalConstants; (**************************************************************************** * * Function: GTF_calcTimings * Parameters: hPixels - X resolution * vLines - Y resolution * freq - Frequency (Hz, KHz or MHz depending on type) * type - 1 - vertical, 2 - horizontal, 3 - dot clock * margins - True if margins should be generated * interlace - True if interlaced timings to be generated * t - Place to store the resulting timings * * Description: Calculates a set of GTF timing parameters given a specified * resolution and vertical frequency. The horizontal frequency * and dot clock will be automatically generated by this * routines. * * For interlaced modes the CRTC parameters are calculated for * a single field, so will be half what would be used in * a non-interlaced mode. * ****************************************************************************) PROCEDURE GTFCalcTimings(hPixels, vLines, freq: LONGREAL; type: LONGINT; wantMargins, wantInterlace: BOOLEAN; VAR t: GTFTimings); VAR interlace,vFieldRate,hPeriod: LONGREAL; topMarginLines,botMarginLines: LONGREAL; leftMarginPixels,rightMarginPixels: LONGREAL; hPeriodEst,vSyncBP,vBackPorch: LONGREAL; vTotalLines,vFieldRateEst: LONGREAL; hTotalPixels,hTotalActivePixels,hBlankPixels: LONGREAL; idealDutyCycle,hSyncWidth,hSyncBP,hBackPorch: LONGREAL; idealHPeriod: LONGREAL; vFreq,hFreq,dotClock: LONGREAL; c: GTFConstants; BEGIN GetInternalConstants(c); vFreq := freq; hFreq := freq; dotClock := freq; (* Round pixels to character cell granularity *) hPixels := Round(hPixels / c.cellGran) * c.cellGran; (* For interlaced mode halve the vertical parameters, and double the required field refresh rate. *) IF wantInterlace THEN vLines := Round(vLines / 2); vFieldRate := vFreq * 2; dotClock := dotClock * 2; interlace := 0.5; ELSE vFieldRate := vFreq; interlace := 0 END; (* Determine the lines for margins *) IF wantMargins THEN topMarginLines := Round(c.margin / 100 * vLines); botMarginLines := Round(c.margin / 100 * vLines) ELSE topMarginLines := 0; botMarginLines := 0 END; IF type # GTFLockPF THEN IF type = GTFLockVF THEN (* Estimate the horizontal period *) hPeriodEst := ((1/vFieldRate)-(c.minVSyncBP/1000000))/ (vLines+(2*topMarginLines)+c.minPorch+interlace)*1000000; (* Find the number of lines in vSync + back porch *) vSyncBP := Round(c.minVSyncBP / hPeriodEst); ELSIF type = GTFLockHF THEN (* Find the number of lines in vSync + back porch *) vSyncBP := Round((c.minVSyncBP * hFreq) / 1000); END; (* Find the number of lines in the V back porch alone *) vBackPorch := vSyncBP - c.vSyncRqd; (* Find the total number of lines in the vertical period *) vTotalLines := vLines + topMarginLines + botMarginLines + vSyncBP + interlace + c.minPorch; IF type = GTFLockVF THEN (* Estimate the vertical frequency *) vFieldRateEst := 1000000 / (hPeriodEst * vTotalLines); (* Find the actual horizontal period *) hPeriod := (hPeriodEst * vFieldRateEst) / vFieldRate; (* Find the actual vertical field frequency *) vFieldRate := 1000000 / (hPeriod * vTotalLines); ELSIF type = GTFLockHF THEN (* Find the actual vertical field frequency *) vFieldRate := (hFreq / vTotalLines) * 1000; END END; (* Find the number of pixels in the left and right margins *) IF wantMargins THEN leftMarginPixels := Round(hPixels * c.margin) / (100 * c.cellGran); rightMarginPixels := Round(hPixels * c.margin) / (100 * c.cellGran); ELSE leftMarginPixels := 0; rightMarginPixels := 0 END; (* Find the total number of active pixels in image + margins *) hTotalActivePixels := hPixels + leftMarginPixels + rightMarginPixels; IF type = GTFLockVF THEN (* Find the ideal blanking duty cycle *) idealDutyCycle := c.c - ((c.m * hPeriod) / 1000) ELSIF type = GTFLockHF THEN (* Find the ideal blanking duty cycle *) idealDutyCycle := c.c - (c.m / hFreq); ELSIF type = GTFLockPF THEN (* Find ideal horizontal period from blanking duty cycle formula *) idealHPeriod := (((c.c - 100) + (MathL.sqrt((pow(100-c.c,2)) + (0.4 * c.m * (hTotalActivePixels + rightMarginPixels + leftMarginPixels) / dotClock)))) / (2 * c.m)) * 1000; (* Find the ideal blanking duty cycle *) idealDutyCycle := c.c - ((c.m * idealHPeriod) / 1000); END; (* Find the number of pixels in blanking time *) hBlankPixels := Round((hTotalActivePixels * idealDutyCycle) / ((100 - idealDutyCycle) * c.cellGran)) * c.cellGran; (* Find the total number of pixels *) hTotalPixels := hTotalActivePixels + hBlankPixels; (* Find the horizontal back porch *) hBackPorch := Round((hBlankPixels / 2) / c.cellGran) * c.cellGran; (* Find the horizontal sync width *) hSyncWidth := Round(((c.hSync/100) * hTotalPixels) / c.cellGran) * c.cellGran; (* Find the horizontal sync + back porch *) hSyncBP := hBackPorch + hSyncWidth; IF type = GTFLockPF THEN (* Find the horizontal frequency *) hFreq := (dotClock / hTotalPixels) * 1000; (* Find the number of lines in vSync + back porch *) vSyncBP := Round((c.minVSyncBP * hFreq) / 1000); (* Find the number of lines in the V back porch alone *) vBackPorch := vSyncBP - c.vSyncRqd; (* Find the total number of lines in the vertical period *) vTotalLines := vLines + topMarginLines + botMarginLines + vSyncBP + interlace + c.minPorch; (* Find the actual vertical field frequency *) vFieldRate := (hFreq / vTotalLines) * 1000; ELSE IF type = GTFLockVF THEN (* Find the horizontal frequency *) hFreq := 1000 / hPeriod; ELSIF type = GTFLockHF THEN (* Find the horizontal frequency *) hPeriod := 1000 / hFreq; END; (* Find the pixel clock frequency *) dotClock := hTotalPixels / hPeriod; END; (* Find the vertical frame frequency *) IF wantInterlace THEN vFreq := vFieldRate / 2; dotClock := dotClock / 2; ELSE vFreq := vFieldRate END; (* Return the computed frequencies *) t.vFreq := vFreq; t.hFreq := hFreq; t.dotClock := dotClock; (* Determine the vertical timing parameters *) t.h.hTotal := ENTIER(hTotalPixels); t.h.hDisp := ENTIER(hTotalActivePixels); t.h.hSyncStart := ENTIER(t.h.hTotal - hSyncBP); t.h.hSyncEnd := ENTIER(t.h.hTotal - hBackPorch); t.h.hFrontPorch := t.h.hSyncStart - t.h.hDisp; t.h.hSyncWidth := ENTIER(hSyncWidth); t.h.hBackPorch := ENTIER(hBackPorch); (* Determine the vertical timing parameters *) t.v.vTotal := ENTIER(vTotalLines); t.v.vDisp := ENTIER(vLines); t.v.vSyncStart := ENTIER(t.v.vTotal - vSyncBP); t.v.vSyncEnd := ENTIER(t.v.vTotal - vBackPorch); t.v.vFrontPorch := t.v.vSyncStart - t.v.vDisp; t.v.vSyncWidth := ENTIER(c.vSyncRqd); t.v.vBackPorch := ENTIER(vBackPorch); (* Mark as GTF timing using the sync polarities *) IF wantInterlace THEN t.interlace := 'I' ELSE t.interlace := 'N' END; t.hSyncPol := '-'; t.vSyncPol := '+'; END GTFCalcTimings; (* VBE *) PROCEDURE CopyVBEString(adr: LONGINT; VAR s: ARRAY OF CHAR); VAR adr0, i: LONGINT; adr1: INTEGER; BEGIN SYSTEM.GET(adr+2, adr1); adr0 := LONG(adr1) * 16; SYSTEM.GET(adr, adr1); adr0 := adr0+adr1; i := -1; REPEAT INC(i); SYSTEM.GET(adr0, s[i]); INC(adr0) UNTIL s[i] = 0X END CopyVBEString; PROCEDURE UpDown*; BEGIN END UpDown; PROCEDURE LeftRight*; BEGIN END LeftRight; PROCEDURE ChangeHz*; BEGIN END ChangeHz; PROCEDURE Set*; BEGIN END Set; PROCEDURE SetVideoMode*(modeNr, vFreq: LONGINT; blank, linear: BOOLEAN; VAR res: LONGINT); VAR vmem, adr: LONGINT; flags: SET; p: VideoMode; regs: V86.Regs; t: GTFTimings; BEGIN modeNr := modeNr MOD 200H; res := 0; Kernel.NewDMA(256, adr, vmem); (* allocate DMA buffer *) ASSERT(vmem MOD 16 = 0); ASSERT(vmem < 100000H); (* sanity *) ASSERT(adr = vmem); (* implementation restriction *) p := vbe.vmodes; WHILE (p # NIL) & (p.modeNr # modeNr) DO p := p.next END; IF p # NIL THEN IF (vbe.version >= 300H) & (vFreq > 0) THEN GTFCalcTimings(p.xRes, p.yRes, vFreq, GTFLockVF, FALSE, FALSE, t); regs.EAX := 4F0BH; regs.EBX := 0; regs.ECX := vFreq*t.h.hTotal*t.v.vTotal; regs.EDX := modeNr; V86.Video(regs); ASSERT(regs.EAX = 4FH, 100); SYSTEM.PUT(vmem, SYSTEM.VAL(INTEGER, t.h.hTotal)); SYSTEM.PUT(vmem+2, SYSTEM.VAL(INTEGER, t.h.hSyncStart)); SYSTEM.PUT(vmem+4, SYSTEM.VAL(INTEGER, t.h.hSyncEnd)); SYSTEM.PUT(vmem+6, SYSTEM.VAL(INTEGER, t.v.vTotal)); SYSTEM.PUT(vmem+8, SYSTEM.VAL(INTEGER, t.v.vSyncStart)); SYSTEM.PUT(vmem+10, SYSTEM.VAL(INTEGER, t.v.vSyncEnd)); flags := {}; IF t.interlace = "I" THEN INCL(flags, 1) END; IF t.hSyncPol = "-" THEN INCL(flags, 2) END; IF t.vSyncPol = "-" THEN INCL(flags, 3) END; SYSTEM.PUT(vmem+12, SYSTEM.VAL(CHAR, flags)); SYSTEM.PUT(vmem+13, regs.ECX); SYSTEM.PUT(vmem+17, SYSTEM.VAL(INTEGER, vFreq*100)); regs.EBX := 800H ELSE regs.EBX := 0 END; regs.EAX := 4F02H; INC(regs.EBX, modeNr); IF ~blank THEN INC(regs.EBX, 8000H) END; IF linear THEN INC(regs.EBX, 4000H) END; regs.ES := SHORT(vmem DIV 16); regs.EDI := 0; V86.Video(regs); ASSERT(regs.EAX MOD 10000H= 4FH, 101); ELSE res := 1 END; Kernel.DisposeDMA(256, vmem); (* deallocate DMA buffer *) END SetVideoMode; PROCEDURE GetFrameBuffer*(modeNr: LONGINT; VAR physAdr, size: LONGINT); VAR p: VideoMode; BEGIN modeNr := modeNr MOD 200H; p := vbe.vmodes; WHILE (p # NIL) & (p.modeNr # modeNr) DO p := p.next END; IF p = NIL THEN physAdr := -1; size := 0 ELSE physAdr := p.physBasePtr; size := vbe.totalMem END END GetFrameBuffer; PROCEDURE SearchVideoMode*(width, height, depth: LONGINT): LONGINT; VAR modeNr: LONGINT; p: VideoMode; BEGIN p := vbe.vmodes; WHILE (p # NIL) & ((p.xRes # width) OR (p.yRes # height) OR (p.bitsPerPixel # depth)) DO p := p.next END; IF p # NIL THEN modeNr := p.modeNr ELSE modeNr := 0 END; RETURN modeNr; END SearchVideoMode; PROCEDURE GetCurrentVideoMode*(): LONGINT; VAR regs: V86.Regs; BEGIN regs.EAX := 4F03H; V86.Video(regs); RETURN regs.EBX END GetCurrentVideoMode; PROCEDURE ShowVideoModes; VAR p: VideoMode; BEGIN LogStr("VideoModes"); LogLn; p := vbe.vmodes; WHILE p # NIL DO LogStr("Mode: "); LogHex(p.modeNr); LogLn; LogStr("mode attributes: "); LogLn; LogStr(" "); IF ~(0 IN p.modeAttr) THEN LogStr("no ") END; LogStr("HW support"); LogLn; LogStr(" "); IF ~(2 IN p.modeAttr) THEN LogStr("no ") END; LogStr("TTY output support"); LogLn; LogStr(" "); IF 3 IN p.modeAttr THEN LogStr("color") ELSE LogStr("monochrome") END; LogLn; LogStr(" "); IF 4 IN p.modeAttr THEN LogStr("graphics") ELSE LogStr("text") END; LogLn; LogStr(" "); IF ~(5 IN p.modeAttr) THEN LogStr("not ") END; LogStr("VGA compatible"); LogLn; LogStr(" "); IF 6 IN p.modeAttr THEN LogStr("no ") END; LogStr("VGA comp. windowing"); LogLn; LogStr(" "); IF ~(7 IN p.modeAttr) THEN LogStr("no ") END; LogStr("linear frame buffer available"); LogLn; LogStr(" "); IF ~(8 IN p.modeAttr) THEN LogStr("no ") END; LogStr("double scanning available"); LogLn; LogStr(" "); IF ~(9 IN p.modeAttr) THEN LogStr("no ") END; LogStr("interlacing available"); LogLn; LogStr(" "); IF ~(10 IN p.modeAttr) THEN LogStr("no ") END; LogStr("HW triple buffering support"); LogLn; LogStr(" "); IF ~(11 IN p.modeAttr) THEN LogStr("no ") END; LogStr("HW stereoscopic support"); LogLn; LogStr(" "); IF ~(12 IN p.modeAttr) THEN LogStr("no ") END; LogStr("dual display start address support"); LogLn; LogStr("window A attributes: "); LogLn; IF 0 IN p.winAAttr THEN LogStr(" relocatable window") ELSE LogStr(" single non-relocatable window") END; LogLn; LogStr(" Window "); IF ~(1 IN p.winAAttr) THEN LogStr("not ") END; LogStr("readable"); LogLn; LogStr(" Window "); IF ~(2 IN p.winAAttr) THEN LogStr("not ") END; LogStr("writeable"); LogLn; LogStr("window B attributes: "); LogLn; IF 0 IN p.winBAttr THEN LogStr(" relocatable window") ELSE LogStr(" single non-relocatable window") END; LogLn; LogStr(" Window "); IF ~(1 IN p.winBAttr) THEN LogStr("not ") END; LogStr("readable"); LogLn; LogStr(" Window "); IF ~(2 IN p.winBAttr) THEN LogStr("not ") END; LogStr("writeable"); LogLn; LogStr("window granularity in KB: "); LogInt(p.winGranularity); LogLn; LogStr("window size: "); LogInt(p.winSize); LogLn; LogStr("window A start segment: "); LogHex(p.winASeg); LogLn; LogStr("window B start segment: "); LogHex(p.winBSeg); LogLn; LogStr("real mode pointer to window function: "); LogHex(p.winFuncPtr); LogLn; LogStr("bytes per scan line: "); LogInt(p.bytesPerScanLine); LogLn; IF vbe.version >= 102H THEN (* VBE 1.2 and above *) LogStr("horizontal resolution: "); LogInt(p.xRes); LogLn; LogStr("vertical resolution: "); LogInt(p.yRes); LogLn; LogStr("character cell width: "); LogInt(p.xCharSize); LogLn; LogStr("character cell height: "); LogInt(p.yCharSize); LogLn; LogStr("planes: "); LogInt(p.nrOfPlanes); LogLn; LogStr("bits per pixel: "); LogInt(p.bitsPerPixel); LogLn; LogStr("number of banks: "); LogInt(p.nrOfBanks); LogLn; LogStr("memory model: "); LogInt(p.memoryModel); LogStr(", "); CASE p.memoryModel OF 0: LogStr("text mode") | 1: LogStr("CGA graphics") | 2: LogStr("Hercules graphics") | 3: LogStr("planar") | 4: LogStr("packed pixel") | 5: LogStr("non-chain 4, 256 color") | 6: LogStr("direct color") | 7: LogStr("YUV") | 8..0FH: LogStr("reserverd (VESA)") ELSE LogStr("OEM defined") END; LogLn; LogStr("bank size: "); LogInt(p.bankSize); LogLn; LogStr("number of images: "); LogInt(p.nrOfImgPages); LogLn; IF (p.memoryModel = 6) OR (p.memoryModel = 7) THEN LogStr("red mask size: "); LogInt(p.redMaskSize); LogLn; LogStr("red field position: "); LogInt(p.redFieldPos); LogLn; LogStr("green mask size: "); LogInt(p.greenMaskSize); LogLn; LogStr("green field position: "); LogInt(p.greenFieldPos); LogLn; LogStr("blue mask size: "); LogInt(p.blueMaskSize); LogLn; LogStr("blue field position: "); LogInt(p.blueFieldPos); LogLn; LogStr("reserved mask size: "); LogInt(p.rsvdMaskSize); LogLn; LogStr("reserved field position: "); LogInt(p.rsvdFieldPos); LogLn; LogStr("direct color mode information: "); LogLn; LogStr(" color ramp "); IF 0 IN p.directColorModeInfo THEN LogStr("programmable") ELSE LogStr("fixed") END; LogLn; LogStr(" reserved field "); IF 1 IN p.directColorModeInfo THEN LogStr("usable") ELSE LogStr("reserved") END; LogLn END END; IF vbe.version >= 200H THEN LogStr("start address of linear frame buffer: "); LogHex(p.physBasePtr); LogLn END; IF vbe.version >= 300H THEN LogStr("linear bytes per scan line: "); LogInt(p.linBytesPerScanLine); LogLn; LogStr("# images for banked modes: "); LogInt(p.bnkNrOfImgPages); LogLn; LogStr("# images for linear modes: "); LogInt(p.linNrOfImgPages); LogLn; LogStr("linear red mask size: "); LogInt(p.linRedMaskSize); LogLn; LogStr("linear red field position: "); LogInt(p.linRedFieldPos); LogLn; LogStr("linear green mask size: "); LogInt(p.linGreenMaskSize); LogLn; LogStr("linear green field position: "); LogInt(p.linGreenFieldPos); LogLn; LogStr("linear blue mask size: "); LogInt(p.linBlueMaskSize); LogLn; LogStr("linear blue field position: "); LogInt(p.linBlueFieldPos); LogLn; LogStr("linear reserved mask size: "); LogInt(p.linRsvdMaskSize); LogLn; LogStr("linear reserved field position: "); LogInt(p.linRsvdFieldPos); LogLn; LogStr("maximum pixel clock (Hz): "); LogInt(p.maxPixelClock); LogLn END; p := p.next END END ShowVideoModes; PROCEDURE ShowVesaInfo*; BEGIN LogStr("VESA signature: "); LogStr(vbe.sig); LogLn; LogStr("version: "); LogHex(vbe.version); LogLn; LogStr("OEM: "); LogStr(vbe.oemString); LogLn; LogStr("OEM vendor: "); LogStr(vbe.oemVendor); LogLn; LogStr("OEM product: "); LogStr(vbe.oemProductName); LogLn; LogStr("OEM product revision: "); LogStr(vbe.oemProductRev); LogLn; LogStr("OEM software revision: "); LogHex(vbe.oemSoftwareRev); LogLn; LogStr("total memory (MB): "); LogInt(vbe.totalMem DIV (1024 * 1024)); LogLn; LogStr("Capabilities: "); IF vbe.dac8 THEN LogStr("8-bit DAC") ELSE LogStr("6-bit DAC") END; LogStr(", "); IF ~vbe.vga THEN LogStr("not VGA comp") ELSE LogStr("VGA comp") END; LogStr(", "); IF vbe.extDac THEN LogStr("extended RAMDAC") ELSE LogStr("normal RAMDAC") END; LogStr(", "); IF vbe.stereo THEN LogStr("stereoscopic support") ELSE LogStr("no stereoscopic support") END; LogStr(", "); IF vbe.stereoEVC THEN LogStr("stereo. over VESA EVC") ELSE LogStr("stereo. over external VESA conn.") END; LogLn; ShowVideoModes END ShowVesaInfo; PROCEDURE GetModeInfo(p: VideoMode); VAR adr, vmem: LONGINT; regs: V86.Regs; vali: INTEGER; valc: CHAR; BEGIN Kernel.NewDMA(256, adr, vmem); (* allocate DMA buffer *) ASSERT(vmem MOD 16 = 0); ASSERT(vmem < 100000H); (* sanity *) ASSERT(adr = vmem); (* implementation restriction *) regs.EAX := 4F01H; regs.ECX := p.modeNr; regs.ES := SHORT(vmem DIV 16); regs.EDI := 0; V86.Video(regs); SYSTEM.GET(vmem, vali); p.modeAttr := SYSTEM.VAL(SET, vali); SYSTEM.GET(vmem+2, valc); p.winAAttr := SYSTEM.VAL(SET, valc); SYSTEM.GET(vmem+3, valc); p.winBAttr := SYSTEM.VAL(SET, valc); SYSTEM.GET(vmem+4, vali); p.winGranularity := vali; SYSTEM.GET(vmem+6, vali); p.winSize := vali; SYSTEM.GET(vmem+8, vali); p.winASeg := vali; SYSTEM.GET(vmem+10, vali); p.winBSeg := vali; SYSTEM.GET(vmem+12, p.winFuncPtr); SYSTEM.GET(vmem+16, vali); p.bytesPerScanLine := vali; SYSTEM.GET(vmem+18, vali); p.xRes := vali; SYSTEM.GET(vmem+20, vali); p.yRes := vali; SYSTEM.GET(vmem+22, valc); p.xCharSize := ORD(valc); SYSTEM.GET(vmem+23, valc); p.yCharSize := ORD(valc); SYSTEM.GET(vmem+24, valc); p.nrOfPlanes := ORD(valc); SYSTEM.GET(vmem+25, valc); p.bitsPerPixel := ORD(valc); SYSTEM.GET(vmem+26, valc); p.nrOfBanks := ORD(valc); SYSTEM.GET(vmem+27, valc); p.memoryModel := ORD(valc); SYSTEM.GET(vmem+28, valc); p.bankSize := ORD(valc); SYSTEM.GET(vmem+29, valc); p.nrOfImgPages := ORD(valc); SYSTEM.GET(vmem+31, valc); p.redMaskSize := ORD(valc); SYSTEM.GET(vmem+32, valc); p.redFieldPos := ORD(valc); SYSTEM.GET(vmem+33, valc); p.greenMaskSize := ORD(valc); SYSTEM.GET(vmem+34, valc); p.greenFieldPos := ORD(valc); SYSTEM.GET(vmem+35, valc); p.blueMaskSize := ORD(valc); SYSTEM.GET(vmem+36, valc); p.blueFieldPos := ORD(valc); SYSTEM.GET(vmem+37, valc); p.rsvdMaskSize := ORD(valc); SYSTEM.GET(vmem+38, valc); p.rsvdFieldPos := ORD(valc); SYSTEM.GET(vmem+39, valc); p.directColorModeInfo := SYSTEM.VAL(SET, valc); SYSTEM.GET(vmem+40, p.physBasePtr); SYSTEM.GET(vmem+50, vali); p.linBytesPerScanLine := vali; SYSTEM.GET(vmem+52, valc); p.bnkNrOfImgPages := ORD(valc); SYSTEM.GET(vmem+53, valc); p.linNrOfImgPages := ORD(valc); SYSTEM.GET(vmem+54, valc); p.linRedMaskSize := ORD(valc); SYSTEM.GET(vmem+55, valc); p.linRedFieldPos := ORD(valc); SYSTEM.GET(vmem+56, valc); p.linGreenMaskSize := ORD(valc); SYSTEM.GET(vmem+57, valc); p.linGreenFieldPos := ORD(valc); SYSTEM.GET(vmem+58, valc); p.linBlueMaskSize := ORD(valc); SYSTEM.GET(vmem+59, valc); p.linBlueFieldPos := ORD(valc); SYSTEM.GET(vmem+60, valc); p.linRsvdMaskSize := ORD(valc); SYSTEM.GET(vmem+61, valc); p.linRsvdFieldPos := ORD(valc); SYSTEM.GET(vmem+62, p.maxPixelClock); Kernel.DisposeDMA(256, vmem); (* deallocate DMA buffer *) END GetModeInfo; PROCEDURE GetVideoModes(adr: LONGINT; VAR vmode: VideoMode); VAR adr0: LONGINT; adr1, vali: INTEGER; p: VideoMode; BEGIN SYSTEM.GET(adr+2, adr1); adr0 := LONG(adr1) * 16; SYSTEM.GET(adr, adr1); adr0 := adr0+adr1; LOOP SYSTEM.GET(adr0, vali); IF vali = -1 THEN EXIT END; NEW(p); p.next := vmode; vmode := p; p.modeNr := vali; GetModeInfo(p); INC(adr0, 2) END END GetVideoModes; PROCEDURE GetVBEControllerInfo; VAR adr, vmem: LONGINT; regs: V86.Regs; vali: INTEGER; vals: SET; BEGIN vbe.vmodes := NIL; Kernel.NewDMA(512, adr, vmem); (* allocate DMA buffer *) ASSERT(vmem MOD 16 = 0); ASSERT(vmem < 100000H); (* sanity *) ASSERT(adr = vmem); (* implementation restriction *) SYSTEM.MOVE(SYSTEM.ADR("VBE2"), vmem, 4); regs.EAX := 4F00H; regs.ES := SHORT(vmem DIV 16); regs.EDI := 0; V86.Video(regs); vbe.available := regs.EAX = 4FH; IF vbe.available THEN SYSTEM.MOVE(vmem, SYSTEM.ADR(vbe.sig), 4); vbe.sig[4] := 0X; SYSTEM.GET(vmem+4, vali); vbe.version := vali; CopyVBEString(vmem+6, vbe.oemString); SYSTEM.GET(vmem+10, vals); vbe.dac8 := 0 IN vals; vbe.vga := ~(1 IN vals); vbe.extDac := 2 IN vals; vbe.stereo := 3 IN vals; vbe.stereoEVC := 4 IN vals; GetVideoModes(vmem+14, vbe.vmodes); SYSTEM.GET(vmem+18, vali); vbe.totalMem := LONG(vali)*64*1024; SYSTEM.GET(vmem+20, vali); vbe.oemSoftwareRev := vali; CopyVBEString(vmem+22, vbe.oemVendor); CopyVBEString(vmem+26, vbe.oemProductName); CopyVBEString(vmem+30, vbe.oemProductRev) END; Kernel.DisposeDMA(512, vmem); (* deallocate DMA buffer *) END GetVBEControllerInfo; PROCEDURE GetVideoBios; BEGIN GetVBEControllerInfo END GetVideoBios; PROCEDURE InitGtf; BEGIN GC.margin := 1.8; GC.cellGran := 8; GC.minPorch := 1; GC.vSyncRqd := 3; GC.hSync := 8; GC.minVSyncBP := 550; GC.m := 600; GC.c := 40; GC.k := 128; GC.j := 20 END InitGtf; PROCEDURE Init; BEGIN (* IF textsDebug THEN NEW(T); Texts.Open(T, ""); Oberon.OpenText("", T, 400, 200); Texts.OpenWriter(W) END; *) InitGtf; GetVideoBios END Init; (* PROCEDURE DoSearch*; VAR w, h, d, modeNr: LONGINT; BEGIN In.Open; In.LongInt(w); In.LongInt(h); In.LongInt(d); IF In.Done THEN modeNr := SearchVideoMode(w, h, d); LogStr("Mode Nr: "); LogHex(modeNr); LogLn END END DoSearch; PROCEDURE DoGetCurrentVideoMode*; VAR modeNr: LONGINT; BEGIN modeNr := GetCurrentVideoMode(); LogStr("Mode Nr: "); LogHex(modeNr); LogLn END DoGetCurrentVideoMode; PROCEDURE DoSetVideoMode*; VAR modeNr, res, w, h, d, vFreq: LONGINT; BEGIN In.Open; In.LongInt(w); In.LongInt(h); In.LongInt(d); In.LongInt(vFreq); IF In.Done THEN modeNr := SearchVideoMode(w, h, d); ASSERT(modeNr # 0, 100); SetVideoMode(modeNr, vFreq, FALSE, TRUE, res); ASSERT(res = 0, 101) END END DoSetVideoMode; *) BEGIN Init END DisplayTool. DisplayTool.ShowVesaInfo DisplayTool.DoSearch 1024 768 32 DisplayTool.DoGetCurrentVideoMode DisplayTool.DoSetVideoMode 1024 768 32 105 DisplayTool.DoSetVideoMode 1024 768 32 100 DisplayTool.DoSetVideoMode 1600 1200 16 74 DisplayTool.DoSetVideoMode 1600 1200 16 60