text:
Oberon/ETH Oberon/2.3.7/DisplayMach64.Mod

(* ETH Oberon, Copyright 1990-2003 Computer Systems Institute, ETH Zurich, CH-8092 Zurich. Refer to the license.txt file provided with this distribution. *) MODULE DisplayMach64;	(* pjm *) IMPORT SYSTEM, AosDisplays := Displays, Kernel; CONST BusCntl = 28H*4; GenTestCntl = 34H*4; DstOffPitch = 40H*4; (*DstX = 41H*4;*) (*DstY = 42H*4;*) DstYX = 43H*4; (*DstWidth = 44H*4;*) DstHeight = 45H*4; DstHeightWidth = 46H*4; DstBresErr = 49H*4; DstBresInc = 4AH*4; DstBresDec = 4BH*4; DstCntl = 4CH*4; SrcOffPitch = 60H*4; SrcYX = 63H*4; SrcWidth1 = 64H*4; SrcHeight1Width1 = 66H*4; SrcYXStart = 69H*4; SrcCntl = 6DH*4; SrcHeight2Width2 = 6CH*4; HostData0 = 80H*4; HostData15 = 8FH*4; HostCntl = 90H*4; PatReg0 = 0A0H*4; PatReg1 = 0A1H*4; PatCntl = 0A2H*4; ScLeft = 0A8H*4; ScRight = 0A9H*4; ScTop = 0ABH*4; ScBottom = 0ACH*4; DpBkgdClr = 0B0H*4; DpFrgdClr = 0B1H*4; DpWriteMsk = 0B2H*4; DpChainMsk = 0B3H*4; DpPixWidth = 0B4H*4; DpMix = 0B5H*4; DpSrc = 0B6H*4; DstXY = 0BAH*4; (*DstWidthHeight = 0BBH*4;*) ClrCmpClr = 0C0H*4; ClrCmpMsk = 0C1H*4; ClrCmpCntl = 0C2H*4; FifoStat = 0C4H*4; ContextMsk = 0C8H*4; GuiTrajCntl = 0CCH*4; GuiStat = 0CEH*4; VAR d: Display; base0, truecol: LONGINT; TYPE Display* = OBJECT (AosDisplays.Display) PROCEDURE ReplConst*(col, x, y, w, h: LONGINT); BEGIN IF (w > 0) & (h > 0) & (col >= 0) THEN	(* opaque or invert *) IF ASH(col, 1) >= 0 THEN WaitFIFO(4); SYSTEM.PUT(base0+DpFrgdClr, TransColor(col)); SYSTEM.PUT(base0+DpSrc, {8}); SYSTEM.PUT(base0+DstXY, ASH(y, 16) + x MOD 10000H); SYSTEM.PUT(base0+DstHeightWidth, ASH(w, 16) + h MOD 10000H) ELSE	(* invert *) WaitFIFO(6); SYSTEM.PUT(base0+DpFrgdClr, TransColor(col)); SYSTEM.PUT(base0+DpMix, {0, 1, 16, 18});	(* DST xor SRC / DST *) SYSTEM.PUT(base0+DpSrc, {8}); SYSTEM.PUT(base0+DstXY, ASH(y, 16) + x MOD 10000H); SYSTEM.PUT(base0+DstHeightWidth, ASH(w, 16) + h MOD 10000H); SYSTEM.PUT(base0+DpMix, {0, 1, 16, 17, 18})	(* SRC / DST *) END END END ReplConst; PROCEDURE Dot*(col, x, y: LONGINT); BEGIN IF col >= 0 THEN	(* opaque or invert *) IF ASH(col, 1) >= 0 THEN WaitFIFO(4); SYSTEM.PUT(base0+DpFrgdClr, TransColor(col)); SYSTEM.PUT(base0+DpSrc, {8}); SYSTEM.PUT(base0+DstXY, ASH(y, 16) + x MOD 10000H); SYSTEM.PUT(base0+DstHeightWidth, SYSTEM.VAL(LONGINT, 10001H)) ELSE	(* invert *) WaitFIFO(6); SYSTEM.PUT(base0+DpFrgdClr, TransColor(col)); SYSTEM.PUT(base0+DpMix, {0, 1, 16, 18});	(* DST xor SRC / DST *) SYSTEM.PUT(base0+DpSrc, {8}); SYSTEM.PUT(base0+DstXY, ASH(y, 16) + x MOD 10000H); SYSTEM.PUT(base0+DstHeightWidth, SYSTEM.VAL(LONGINT, 10001H)); SYSTEM.PUT(base0+DpMix, {0, 1, 16, 17, 18})	(* SRC / DST *) END END END Dot; PROCEDURE CopyBlock*(sx, sy, w, h, dx, dy: LONGINT); VAR s: SET; BEGIN IF (w > 0) & (h > 0) THEN IF sy >= dy THEN s := {1} ELSE s := {}; INC(sy, h-1); INC(dy, h-1) END; IF sx >= dx THEN INCL(s, 0) ELSE INC(sx, w-1); INC(dx, w-1) END; WaitFIFO(8); SYSTEM.PUT(base0+DstCntl, s); SYSTEM.PUT(base0+DpSrc, {8, 9});	(* BLIT / BG *) SYSTEM.PUT(base0+SrcYX, ASH(sx, 16) + sy MOD 10000H); SYSTEM.PUT(base0+SrcWidth1, w); SYSTEM.PUT(base0+DstYX, ASH(dx, 16) + dy MOD 10000H); SYSTEM.PUT(base0+DstHeightWidth, ASH(w, 16) + h MOD 10000H); SYSTEM.PUT(base0+DpSrc, {8});	(* FG / BG *) SYSTEM.PUT(base0+DstCntl, {0, 1, 5}) ;WaitIdle END END CopyBlock; PROCEDURE PaintMask*(VAR buf: ARRAY OF CHAR; bitofs, stride, fg, bg, x, y, w, h: LONGINT); VAR p, i, j, out: LONGINT; ch: CHAR; BEGIN IF (w > 0) & (h > 0) THEN WaitFIFO(7); IF stride < 0 THEN INC(y, h-1); INC(bitofs, (h-1)*stride*8); stride := -stride; SYSTEM.PUT(base0+GuiTrajCntl, {0, 5})	(* left-to-right, bottom-to-top *) ELSE SYSTEM.PUT(base0+GuiTrajCntl, {0, 1, 5})	(* left-to-right, top-to-bottom *) END; p := SYSTEM.ADR(buf[0]) + bitofs DIV 8; bitofs := bitofs MOD 8; CASE format OF 					1: SYSTEM.PUT(base0+DpPixWidth, {1, 29}) |2: SYSTEM.PUT(base0+DpPixWidth, {2, 30}) |4: SYSTEM.PUT(base0+DpPixWidth, {1, 2, 29, 30}) END; SYSTEM.PUT(base0+DpSrc, {8, 17});	(* FG / BG / Mono Host *) SYSTEM.PUT(base0+DpFrgdClr, TransColor(fg)); SYSTEM.PUT(base0+DpBkgdClr, TransColor(bg)); SYSTEM.PUT(base0+DstYX, ASH(x, 16) + y MOD 10000H); SYSTEM.PUT(base0+DstHeightWidth, ASH(w, 16) + h MOD 10000H); j := 0; out := 0; LOOP FOR i := 0 TO (w-1) DIV 8 DO 						SYSTEM.GET(p+i, ch); out := ASH(out, -8) + ASH(ORD(ch), 24); INC(j); IF j MOD 4 = 0 THEN WaitFIFO(1); SYSTEM.PUT(base0+HostData0, out); out := 0 END END; DEC(h); IF h = 0 THEN EXIT END; INC(p, stride) END; IF j MOD 4 # 0 THEN REPEAT out := ASH(out, -8); INC(j) UNTIL j MOD 4 = 0; WaitFIFO(1); SYSTEM.PUT(base0+HostData0, out) END; WaitFIFO(3); SYSTEM.PUT(base0+DpSrc, {8});	(* FG / BG *) SYSTEM.PUT(base0+GuiTrajCntl, {0, 1, 5});	(* left-to-right, top-to-bottom *) CASE format OF 					1: SYSTEM.PUT(base0+DpPixWidth, {1, 9, 17, 29}) |2: SYSTEM.PUT(base0+DpPixWidth, {2, 10, 18, 30}) |4: SYSTEM.PUT(base0+DpPixWidth, {1, 2, 9, 10, 17, 18, 29, 30}) END END END PaintMask; PROCEDURE Transfer*(VAR buf: ARRAY OF CHAR; ofs, stride, x, y, w, h, op: LONGINT); VAR bufadr, w0, dw: LONGINT; ch: CHAR; BEGIN WaitIdle; Transfer^(buf, ofs, stride, x, y, w, h, op) (* 			IF op = AosDisplays.set THEN 				IF (w > 0) & (h > 0) THEN 					bufadr := SYSTEM.ADR(buf[ofs]); 					WaitFIFO(4); 					SYSTEM.PUT(base0+DpSrc, {9});	(* HOST / BG *) 					SYSTEM.PUT(base0+GuiTrajCntl, {0, 1, 5});	(* left-to-right, top-to-bottom *) 					SYSTEM.PUT(base0+DstYX, ASH(x, 16) + y MOD 10000H); 					SYSTEM.PUT(base0+DstHeightWidth, ASH(w, 16) + h MOD 10000H); 					w := w * format;	(* convert to bytes *) 					REPEAT 						w0 := w; 						WHILE w0 >= 16*4 DO 							WaitFIFO(16); 							SYSTEM.MOVE(bufadr, base0+HostData0, 16*4); 							DEC(w0, 16*4); INC(bufadr, 16*4) 						END; 						IF w0 >= 4 THEN 							WaitFIFO(w0 DIV 4); 							REPEAT 								SYSTEM.GET(bufadr, dw); 								SYSTEM.PUT(base0+HostData0, dw); 								DEC(w0, 4); INC(bufadr, 4) 							UNTIL w0 < 4 						END; 						IF w0 > 0 THEN 							WaitFIFO(w0); 							REPEAT 								SYSTEM.GET(bufadr, ch); 								SYSTEM.PUT(base0+HostData0, ch); DEC(w0); INC(bufadr) UNTIL w0 = 0 END; INC(bufadr, stride-w); DEC(h) UNTIL h = 0; WaitFIFO(1); SYSTEM.PUT(base0+DpSrc, {8})	(* FG / BG *) END ELSE WaitIdle; TransferBlock^(buf, ofs, stride, x, y, w, h, op) END *) 		END Transfer; 	END Display; PROCEDURE WaitFIFO(n: LONGINT); VAR x: LONGINT; BEGIN 	REPEAT SYSTEM.GET(base0+FifoStat, x) UNTIL x MOD 10000H <= ASH(8000H, -n) END WaitFIFO; PROCEDURE WaitIdle; VAR s: SET; BEGIN 	WaitFIFO(16); 	REPEAT SYSTEM.GET(base0+GuiStat, s) UNTIL ~(0 IN s) END WaitIdle; (* Translate a Color value to display format. *) PROCEDURE TransColor(col: LONGINT): LONGINT; BEGIN 	CASE truecol OF 		0:	(* 8-bit indexed *) 			IF 30 IN SYSTEM.VAL(SET, col) THEN 				col := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ASH(col, 7-23)) * {5..7} + SYSTEM.VAL(SET, ASH(col, 4-15)) * {2..4} + SYSTEM.VAL(SET, ASH(col, 1-7)) * {0..1}); 				IF col # 0 THEN RETURN col ELSE RETURN 15 END 			ELSE 				RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ASH(col, 7-23)) * {5..7} + SYSTEM.VAL(SET, ASH(col, 4-15)) * {2..4} + SYSTEM.VAL(SET, ASH(col, 1-7)) * {0..1}) 			END 		|1:	(* 16-bit hicolor *) 			IF SYSTEM.VAL(SET, col) * {0..23,30} = {30} THEN 				RETURN 0FFFFH 			ELSE 				RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ASH(col, 15-23)) * {11..15} + SYSTEM.VAL(SET, ASH(col, 10-15)) * {5..10} + SYSTEM.VAL(SET, ASH(col, 4-7)) * {0..4}) 			END 		|2:	(* 24/32-bit truecolor *) 			IF SYSTEM.VAL(SET, col) * {0..23,30} = {30} THEN 				RETURN 0FFFFFFH 			ELSE 				RETURN col MOD 1000000H 			END 	END END TransColor; PROCEDURE GetVal(str: ARRAY OF CHAR; default: LONGINT): LONGINT; VAR i: SHORTINT;  v: LONGINT;  s: ARRAY 10 OF CHAR; BEGIN 	Kernel.GetConfig(str, s); 	IF s[0] = 0X THEN 		v := default 	ELSE 		v := 0;  i := 0; 		WHILE s[i] # 0X DO v := v*10+(ORD(s[i])-48); INC(i) END 	END; 	RETURN v END GetVal; PROCEDURE InitPalette; VAR col: LONGINT; ch: CHAR; BEGIN 	SYSTEM.PORTIN(3DAH, ch); 	SYSTEM.PORTOUT(3C0H, 11X); 	SYSTEM.PORTOUT(3C0H, 0X);	(* palette entry 0 is black *) 	SYSTEM.PORTOUT(3C0H, 20X); 	FOR col := 0 TO 255 DO 		SYSTEM.PORTOUT(3C8H, CHR(col)); 		SYSTEM.PORTOUT(3C9H, CHR(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, col) * {5..7}) DIV 4)); 		SYSTEM.PORTOUT(3C9H, CHR(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ASH(col, 7-4)) * {5..7}) DIV 4)); SYSTEM.PORTOUT(3C9H, CHR(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ASH(col, 7-1)) * {6..7}) DIV 4)) END END InitPalette; PROCEDURE Init; VAR w, h, f, mem, adr: LONGINT; s: SET; BEGIN w := GetVal("DWidth", 1024);	(* assume 1024 if not specified *) h := GetVal("DHeight", 768);	(* assume 768 if not specified *) f := GetVal("DDepth", 8) DIV 8; truecol := f DIV 2; mem := GetVal("DMem", 0)*1024; IF mem = 0 THEN	(* compute default *) mem := 512*1024; WHILE w*h*f >= mem DO mem := mem*2 END END; Kernel.GetInit(1, adr); Kernel.MapPhysical(adr, 800000H, adr); ASSERT(adr # 0); base0 := adr + 7FFC00H; NEW(d); d.width := w; d.height := h; d.offscreen := mem DIV (w*f) - h; 	d.format := f; d.unit := 10000; d.InitFrameBuffer(adr, mem); IF f = 1 THEN InitPalette END; SYSTEM.GET(base0+38H*4, s); Kernel.WriteString("ConfigChipID="); Kernel.WriteHex(SYSTEM.VAL(LONGINT, s), 8); Kernel.WriteLn; (* reset the FIFO *) SYSTEM.GET(base0+GenTestCntl, s); SYSTEM.PUT(base0+GenTestCntl, s - {8}); SYSTEM.GET(base0+GenTestCntl, s); SYSTEM.PUT(base0+GenTestCntl, s + {8}); SYSTEM.GET(base0+BusCntl, s); SYSTEM.PUT(base0+BusCntl, s + {23}); (* initialize the engine (sec. 5.5.1) *) 	WaitFIFO(14); SYSTEM.PUT(base0+ContextMsk, {0..31}); SYSTEM.PUT(base0+DstOffPitch, ASH(w, 22-3)); SYSTEM.PUT(base0+DstYX, {}); SYSTEM.PUT(base0+DstHeight, {}); SYSTEM.PUT(base0+DstBresErr, {}); SYSTEM.PUT(base0+DstBresInc, {}); SYSTEM.PUT(base0+DstBresDec, {}); SYSTEM.PUT(base0+DstCntl, {0, 1, 5}); SYSTEM.PUT(base0+SrcOffPitch, ASH(w, 22-3)); SYSTEM.PUT(base0+SrcYX, {}); SYSTEM.PUT(base0+SrcHeight1Width1, {0, 16}); SYSTEM.PUT(base0+SrcYXStart, {}); SYSTEM.PUT(base0+SrcHeight2Width2, {0, 16}); SYSTEM.PUT(base0+SrcCntl, {}); WaitFIFO(13); SYSTEM.PUT(base0+HostCntl, {});	(* no byte align *) SYSTEM.PUT(base0+PatReg0, {}); SYSTEM.PUT(base0+PatReg1, {}); SYSTEM.PUT(base0+PatCntl, {}); SYSTEM.PUT(base0+ScLeft, {}); SYSTEM.PUT(base0+ScTop, {}); SYSTEM.PUT(base0+ScBottom, (h+d.offscreen)-1); SYSTEM.PUT(base0+ScRight, w-1); SYSTEM.PUT(base0+DpBkgdClr, {}); SYSTEM.PUT(base0+DpFrgdClr, {0..31}); SYSTEM.PUT(base0+DpWriteMsk, {0..31}); SYSTEM.PUT(base0+DpMix, {0, 1, 16, 17, 18});	(* SRC / DST *) SYSTEM.PUT(base0+DpSrc, {8});	(* FG / BG *) WaitFIFO(5); SYSTEM.PUT(base0+ClrCmpClr, {}); SYSTEM.PUT(base0+ClrCmpMsk, {0..31}); SYSTEM.PUT(base0+ClrCmpCntl, {}); CASE f OF 		1: SYSTEM.PUT(base0+DpPixWidth, {1, 9, 17, 29}); SYSTEM.PUT(base0+DpChainMsk, SYSTEM.VAL(LONGINT, 8080H)) |2: SYSTEM.PUT(base0+DpPixWidth, {2, 10, 18, 30}); SYSTEM.PUT(base0+DpChainMsk, SYSTEM.VAL(LONGINT, 4210H)) |4: SYSTEM.PUT(base0+DpPixWidth, {1, 2, 9, 10, 17, 18, 29, 30}); SYSTEM.PUT(base0+DpChainMsk, SYSTEM.VAL(LONGINT, 8080H)) END; WaitIdle END Init; PROCEDURE Install*; BEGIN IF d # NIL THEN AosDisplays.main := d END END Install; BEGIN Init; Install END DisplayMach64. DisplayTools.TryDriver DisplayMach64.Install 0 ~ DisplayTools.Restore System.Free DisplayMach64 ~ (* to do: 1 map register aperture *)


text:
Oberon/ETH Oberon/2.3.7/DisplayTool.Mod

(* 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

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

title: Oberon/ETH Oberon/2.3.7/DisplayTool.Mod


text:
Oberon/ETH Oberon/2.3.7/DisplayVGA4.Mod

(* ETH Oberon, Copyright 1990-2003 Computer Systems Institute, ETH Zurich, CH-8092 Zurich. Refer to the license.txt file provided with this distribution. *) MODULE DisplayVGA4;	(* pjm *) (* 16-color VGA display driver for Native Oberon with virtual truecolor. Config strings: 	Display="Displays." 	DDriver="DisplayVGA4" 	Init="b81200cd10" *) IMPORT SYSTEM, Kernel, CLUTs, Displays; CONST Width = 640; Height = 480; VAR d: Display; base: LONGINT; clut: POINTER TO CLUTs.CLUT; pal: ARRAY 16 OF LONGINT; shadow: POINTER TO ARRAY OF CHAR; pelmask: LONGINT;	(* trace *) TYPE Display* = OBJECT (Displays.Display) PROCEDURE Transfer*(VAR buf: ARRAY OF CHAR; ofs, stride, x, y, w, h, op: LONGINT); VAR bufadr, buflow, bufhigh, dispadr, scradr: LONGINT; BEGIN IF w > 0 THEN bufadr := SYSTEM.ADR(buf[ofs]); IF op = Displays.set THEN buflow := SYSTEM.ADR(shadow[0]); bufhigh := buflow + LEN(shadow^); dispadr := SYSTEM.ADR(shadow[0]) + ((y*Width)+x); scradr := base + (x DIV 8 + y*(Width DIV 8)) MOD 10000H; WHILE h > 0 DO 						ASSERT((dispadr >= buflow) & (dispadr+w <= bufhigh));	(* index check *) SYSTEM.MOVE(bufadr, dispadr, w); CopyLineTo(bufadr, scradr, x, w); INC(bufadr, stride); INC(dispadr, Width); INC(scradr, Width DIV 8); DEC(h) END ELSIF op = Displays.get THEN buflow := SYSTEM.ADR(buf[0]); bufhigh := buflow + LEN(buf); dispadr := SYSTEM.ADR(shadow[0]) + ((y*Width)+x); WHILE h > 0 DO 						ASSERT((bufadr >= buflow) & (bufadr+w <= bufhigh));	(* index check *) SYSTEM.MOVE(dispadr, bufadr, w); INC(bufadr, stride); INC(dispadr, Width); DEC(h) END ELSE (* skip *) END END END Transfer; (* 		PROCEDURE Dot*(col, x, y: LONGINT); 		VAR ch: CHAR; 		BEGIN 			y := base + (x + y*Width) DIV 8 MOD 10000H; 			SYSTEM.PORTOUT(3CEH, SYSTEM.VAL(INTEGER, 8 + ASH(100H, 7-x MOD 8))); 			IF ASH(col, 1) >= 0 THEN	(* replace *) 				SYSTEM.GET(y, ch); 				SYSTEM.PUT(y, CHR(CLUTs.Match(clut^, col))) 			ELSE	(* invert *) 				SYSTEM.PORTOUT(3CEH, SYSTEM.VAL(INTEGER, 1803H)); 				SYSTEM.GET(y, ch); 				SYSTEM.PUT(y, CHR(CLUTs.Match(clut^, col))); 				SYSTEM.PORTOUT(3CEH, SYSTEM.VAL(INTEGER, 0003H)) 			END 		END Dot; *) PROCEDURE ColorToIndex*(col: LONGINT): LONGINT; BEGIN RETURN CLUTs.Match(clut^, col) END ColorToIndex; PROCEDURE IndexToColor*(index: LONGINT): LONGINT; BEGIN RETURN pal[index MOD 16] END IndexToColor; END Display; (* Copy a line of pixels to the display. *) PROCEDURE CopyLineTo(src, dst, x, w: LONGINT); CODE {SYSTEM.i386} MOV ESI, src[EBP] MOV EDI, dst[EBP] MOV EBX, x[EBP] MOV EDX, 3CEH MOV AL, 8 new: MOV CH, [ESI]	; CH = current pixel color MOV AH, 80H	; AH = mask for current pixels (at left of byte) MOV CL, BL 	AND CL, 7	; CL = offset to shift mask right JMP loop same: SAR AH, 1 loop: DEC w[EBP] JZ done INC EBX INC ESI TEST BL, 7 JZ edge CMP CH, [ESI] JE same diff: SHR AH, CL 	OUT DX, AX 	MOV CL, [EDI] MOV [EDI], CH 	JMP new edge: SHR AH, CL	; adjust mask OUT DX, AX	; set mask MOV CL, [EDI]	; latch MOV [EDI], CH	; output color INC EDI JMP new done: SHR AH, CL 	OUT DX, AX 	MOV CL, [EDI] MOV [EDI], CH end: END CopyLineTo; PROCEDURE Install*; BEGIN IF d # NIL THEN Displays.main := d END END Install; PROCEDURE InitPalette; VAR i, col: LONGINT; ch: CHAR; BEGIN (* standard Oberon colours *) pal[0] := 0; pal[1] := 0FF0000H; pal[2] := 000FF00H; pal[3] := 00000FFH; pal[4] := 0FF00FFH; pal[5] := 0FFFF00H; pal[6] := 000FFFFH; pal[7] := 0AA0000H; pal[9] := 000009AH; pal[10] := 0A6CBF3H; pal[11] := 0008282H; pal[12] := 08A8A8AH; pal[13] := 0BEBEBEH; pal[14] := 0DFDFDFH; pal[15] := 0FFFFFFH; (* set attribute controller registers *) SYSTEM.PORTIN(3DAH, ch);	(* clear flip/flop *) FOR i := 0 TO 0FH DO 		SYSTEM.PORTOUT(3C0H, CHR(i));	(* EGA palette register i *) SYSTEM.PORTOUT(3C0H, CHR(i))	(* maps to VGA palette i *) END; SYSTEM.PORTOUT(3C0H, 11X);	(* overscan color *) SYSTEM.PORTOUT(3C0H, 0X);	(* black/EGA palette 0/VGA palette 0 *) SYSTEM.PORTOUT(3C0H, 12X);	(* color plane enable *) SYSTEM.PORTOUT(3C0H, 0FX);	(* enable all planes *) SYSTEM.PORTOUT(3C0H, 14X);	(* color select *) SYSTEM.PORTOUT(3C0H, 0X);	(* use first 16 colors in VGA palette *) SYSTEM.PORTOUT(3C0H, 20X);	(* enable display to use palette again *) (* set up VGA palette and reverse lookup table *) NEW(clut); SYSTEM.PORTOUT(3C8H, 0X);	(* select index 0 *) FOR i := 0 TO 15 DO 		col := pal[i]; CLUTs.Set(clut^, i, col); SYSTEM.PORTOUT(3C9H, CHR(col DIV 10000H MOD 100H DIV 4)); SYSTEM.PORTOUT(3C9H, CHR(col DIV 100H MOD 100H DIV 4)); SYSTEM.PORTOUT(3C9H, CHR(col MOD 100H DIV 4)) END; FOR i := 16 TO 255 DO 		SYSTEM.PORTOUT(3C9H, 0X); SYSTEM.PORTOUT(3C9H, 0X); SYSTEM.PORTOUT(3C9H, 0X) END; CLUTs.Init(clut^, 16, 3); SYSTEM.PORTIN(3C6H, ch); pelmask := ORD(ch) END InitPalette; (* 		IF i = 6 THEN j := 14H 		ELSIF i > 7 THEN j := i+30H 		ELSE j := i 		END; *) PROCEDURE Init; BEGIN NEW(d); d.width := Width; d.height := Height; d.offscreen := 0; d.format := Displays.index8; d.unit := 10000; Kernel.MapPhysical(0A0000H, 10000H, base); NEW(shadow, Width*Height); (* data rotate 0 *) SYSTEM.PORTOUT(3CEH, SYSTEM.VAL(INTEGER, 0003H)); (* write mode 2 *) SYSTEM.PORTOUT(3CEH, SYSTEM.VAL(INTEGER, 0205H)); (* set/reset disabled *) SYSTEM.PORTOUT(3CEH, SYSTEM.VAL(INTEGER, 0001H)); (* no set/reset *) SYSTEM.PORTOUT(3CEH, SYSTEM.VAL(INTEGER, 0000H)); (* map mask enable all planes *) SYSTEM.PORTOUT(3C4H, SYSTEM.VAL(INTEGER, 0F02H)); InitPalette END Init; BEGIN Init; Install END DisplayVGA4. (* to do: 1 fix for Mach64 1 remove shadow (read from real display) 1 offscreen *)

title: Oberon/ETH Oberon/2.3.7/DisplayVGA4.Mod


text:
Oberon/ETH Oberon/2.3.7/S3TrioC.Display.Mod

(* ETH Oberon, Copyright 1990-2003 Computer Systems Institute, ETH Zurich, CH-8092 Zurich. Refer to the license.txt file provided with this distribution. *) MODULE Display; (* Type: S3Trio (ard, pjm, Peter Matthias) *) IMPORT Kernel, SYSTEM, Objects, V86; CONST BG* = 0; FG* = 15; (*background, foreground*) replace* = 0; paint* = 1; invert* = 2; (*operation modes*) remove* = 0; suspend* = 1; restore* = 2; newprinter* = 3; (*ControlMsg id*) reduce* = 0; extend* = 1; move* = 2; (*ModifyMsg id*) display* = 0; state* = 1; (*ModifyMsg mode*) screen* = 0; printer* = 1; (* DisplayMsg device *) full* = 0; area* = 1; contents* = 2; (* DisplayMsg id. *) get* = 0; set* = 1; reset* = 2; (*SelectMsg id*) drop* = 0; integrate* = 1; (*ConsumeMsg id*) unknown* = 0; index8* = 8; color555* = 16; color565* = 17; color664* = 18; color888* = 24; color8888* = 32; (* S3 Constants, packed MMIO *) curY= 0A8100H;		curX= 0A8102H; axStep= 0A8108H;		diaStep= 0A810AH; errTerm= 0A8110H; cmd= 0A8118H; shortStroke= 0A811CH; BGcol= 0A8120H; FGcol= 0A8124H; wrtMask= 0A8128H; rdMask= 0A812CH; ColorCMP= 0A8130H; BGmix= 0A8134H;	FGmix= 0A8136H;	AltMix= 0A8134H; ScissorsT= 0A8138H;	ScissorsL= 0A813AH;	(* clippint top, left *) ScissorsB= 0A813CH;	ScissorsR= 0A813EH;	(* clipping bottom, right *) PixCntl= 0A8140H;	MultMisc2= 0A8142H; MultMisc= 0A8144H;	ReadSel= 0A8146H; MinAxis= 0A8148H;	MajAxis= 0A814AH; pixTrans = 0AE2E8H; TYPE Color* = LONGINT; Pattern* = LONGINT; PatternPtr = POINTER TO RECORD w, h: CHAR; pixmap: ARRAY 8192 OF CHAR END; List = POINTER TO ListDesc; ListDesc = RECORD next: List; pat: PatternPtr END; Frame* = POINTER TO FrameDesc; FrameDesc* = RECORD (Objects.ObjDesc) next*, dsc*: Frame; X*, Y*, W*, H*: INTEGER END; FrameMsg* = RECORD (Objects.ObjMsg) F*: Frame; (*target*) x*, y*, res*: INTEGER END; ControlMsg* = RECORD (FrameMsg) id*: INTEGER END; ModifyMsg* = RECORD (FrameMsg) id*, mode*: INTEGER; dX*, dY*, dW*, dH*: INTEGER; X*, Y*, W*, H*: INTEGER END; DisplayMsg* = RECORD (FrameMsg) device*: INTEGER; id*: INTEGER; u*, v*, w*, h*: INTEGER END; LocateMsg* = RECORD (FrameMsg) loc*: Frame; X*, Y*, u*, v*: INTEGER END; SelectMsg* = RECORD (FrameMsg) id*: INTEGER; time*: LONGINT; sel*: Frame; obj*: Objects.Object END; ConsumeMsg* = RECORD (FrameMsg) id*: INTEGER; u*, v*: INTEGER; obj*: Objects.Object END; MsgProc* = PROCEDURE (VAR M: FrameMsg); VAR Unit*: LONGINT; (* RasterUnit = Unit/36000 mm *) Left*, (* left margin of black-and-white maps *) ColLeft*, (* left margin of color maps *) Bottom*, (* bottom of primary map *) UBottom*, (* bottom of secondary map *) Width*, (* map width *) Height*: INTEGER; (* map height *) arrow*, star*, cross*, downArrow*, hook*, grey0*, grey1*, grey2*, ticks*, solid*: Pattern; Broadcast*: MsgProc; Pat: List; dmem, base: LONGINT; clipx, clipy, clipright, cliptop: LONGINT;	(* clipping variables *) depth: INTEGER; truecol: LONGINT; colmap, palette: ARRAY 256 OF LONGINT; PROCEDURE Wait; VAR wait: INTEGER; BEGIN REPEAT SYSTEM.GET( cmd, wait) UNTIL ~ODD( ASH( wait, -9)); END Wait; PROCEDURE Map*(x: LONGINT): LONGINT; BEGIN RETURN base		(* of linear framebuffer *) END Map; PROCEDURE AdjustClip*(x, y, w, h: LONGINT); VAR right, top, left, bottom: LONGINT; BEGIN right := x + w; 	IF x > clipx THEN clipx:= x END; IF right < clipright THEN clipright:= right END; left:= clipx; IF left < 0 THEN left := 0 ELSIF left > Width THEN left := Width-1 END; right := clipright-1; IF right < 0 THEN right := 0 ELSIF right > Width THEN right := Width-1 END; top := y + h; 	IF y> clipy THEN clipy:= y END; IF top< cliptop THEN cliptop:= top END; top := cliptop-1; IF top < 0 THEN top := 0 ELSIF top >= Height THEN top := Height-1 END; bottom := clipy; IF bottom < 0 THEN bottom := 0 ELSIF bottom > Height THEN bottom := Height-1 END; SYSTEM.PUT( ScissorsT, SYSTEM.VAL(INTEGER, 1000H+ Height-1-top));	(* top *) SYSTEM.PUT( ScissorsL, SYSTEM.VAL(INTEGER, 2000H+ left)); 	(* left *) SYSTEM.PUT( ScissorsB, SYSTEM.VAL(INTEGER, 3000H+ Height-1-bottom));	(* bottom *) SYSTEM.PUT( ScissorsR, SYSTEM.VAL(INTEGER, 4000H+ right))	(* right *) END AdjustClip; PROCEDURE GetDim*(pat: Pattern; VAR w, h: INTEGER); VAR p: PatternPtr; BEGIN p:= SYSTEM.VAL( PatternPtr, pat); w:= ORD(p^.w); h:= ORD(p^.h) END GetDim; PROCEDURE ResetClip*; BEGIN clipx := 0; clipy := UBottom; clipright := Width; cliptop := Height; SYSTEM.PUT( ScissorsT, SYSTEM.VAL(INTEGER, 1000H));	(* top *) SYSTEM.PUT( ScissorsL, SYSTEM.VAL(INTEGER, 2000H));	(* left *) SYSTEM.PUT( ScissorsB, SYSTEM.VAL(INTEGER, 3000H+ Height-1-UBottom));	(* bottom *) SYSTEM.PUT( ScissorsR, SYSTEM.VAL(INTEGER, 4000H+ Width-1))	(* right *) END ResetClip; PROCEDURE SetClip*(x, y, w, h: LONGINT); BEGIN clipright := x+w; cliptop := y+h; clipy := y; clipx := x; 	SYSTEM.PUT( ScissorsT, SYSTEM.VAL(INTEGER, 1000H + Height-cliptop));	(* top *) SYSTEM.PUT( ScissorsL, SYSTEM.VAL(INTEGER, 2000H + clipx));	(* left *) SYSTEM.PUT( ScissorsB, SYSTEM.VAL(INTEGER, 3000H + Height-1-clipy));	(* bottom *) SYSTEM.PUT( ScissorsR, SYSTEM.VAL(INTEGER, 4000H + clipright-1)); 		 (* right *) END SetClip; PROCEDURE GetClip*(VAR x, y, w, h: INTEGER); BEGIN x := SHORT(clipx); y := SHORT(clipy); w := SHORT(clipright - clipx); h := SHORT(cliptop - clipy); END GetClip; PROCEDURE SetColor*(col: Color; red, green, blue: LONGINT);	(* 0 <= col, red, green, blue < 256 *) VAR ch: CHAR; BEGIN palette[col] := ASH(ASH(red, 8) + green, 8) + blue; CASE truecol OF 		0:	(* indexed *) colmap[col] := col; IF (col = 0) OR (col = 15) THEN	(* either 0 or 15 must be black. set the border to black. *) (* note: the S3 uses the palette for the border colour too *) SYSTEM.PORTIN(3DAH, ch); SYSTEM.PORTOUT(3C0H, 11X); IF (red = 0) & (green = 0) & (blue = 0) THEN SYSTEM.PORTOUT(3C0H, CHR(col)) ELSE SYSTEM.PORTOUT(3C0H, CHR(15-col)) END; SYSTEM.PORTOUT(3C0H, 20X) END; SYSTEM.PORTOUT(3C8H, CHR(col)); SYSTEM.PORTOUT(3C9H, CHR(red DIV 4)); SYSTEM.PORTOUT(3C9H, CHR(green DIV 4)); SYSTEM.PORTOUT(3C9H, CHR(blue DIV 4)) |1:	(* 565 hicolor *) colmap[col] := ASH(ASH(ASH(red, -3), 6) + ASH(green, -2), 5) + ASH(blue, -3) |2:	(* 888 truecolor *) colmap[col] := ASH(ASH(red, 8) + green, 8) + blue END END SetColor; PROCEDURE GetColor*(col: Color; VAR red, green, blue: INTEGER); BEGIN IF col >= 0 THEN col := palette[col] END; red := SHORT(ASH(col, -16) MOD 256); green := SHORT(ASH(col, -8) MOD 256); blue := SHORT(col MOD 256) END GetColor; PROCEDURE RGB*(red, green, blue: LONGINT): Color; BEGIN RETURN MIN(LONGINT) + ASH(red, 16) + ASH(green, 8) + blue END RGB; (* Translate a Color value 	col >= 0 => index through colmap 	col < 0 & truecol = 0 => undefined 	col < 0 & truecol = 1 => translate 888 to 565 	col < 0 & truecol = 2 => keep lower 24 bits *) PROCEDURE -TransColor(col: Color): LONGINT; CODE {SYSTEM.i386} POP EAX CMP EAX, 0 JGE index AND EAX, 0FFFFFFH CMP truecol, 1 JNE end MOV EBX, EAX MOV ECX, EAX SHR EAX, 8	; 23..19 -> 15..11 SHR EBX, 5	; 15..10 -> 10..5 SHR ECX, 3	; 7..3 -> 4..0 AND EAX, 0F800H	; 15..11 AND EBX, 007E0H	; 10..5 AND ECX, 0001FH	; 4..0 OR EAX, EBX OR EAX, ECX JMP end index: AND EAX, 0FFH LEA EBX, colmap MOV EAX, [EBX][EAX*4] end: END TransColor; PROCEDURE Dot*(col: Color; x, y, mode: LONGINT); BEGIN IF mode = invert THEN IF (truecol # 0) & (col = FG) THEN col := 0FFFFFFH END; SYSTEM.PUT(FGmix, LONG(25H)) (*ELSIF mode= paint THEN 		 SYSTEM.PUT( FGmix, LONG(2BH))*) ELSE SYSTEM.PUT(FGmix, LONG(27H)) END; SYSTEM.PUT(FGcol, TransColor(col)); SYSTEM.PUT(PixCntl, LONG( 0)); SYSTEM.PUT(curX, SHORT(x)); SYSTEM.PUT(curY, SHORT(Height-1-y)); Wait; SYSTEM.PUT(cmd, 121BH); SYSTEM.PUT(shortStroke, LONG(10H)) END Dot; PROCEDURE CopyBlock*(sx, sy, w, h, dx, dy, mode: LONGINT); VAR comd: INTEGER; BEGIN IF (w > 0) & (h > 0) THEN comd := SYSTEM.VAL(INTEGER, 0C073H); IF sy <= dy THEN INC(sy, h-1); INC(dy, h-1); INC(comd, 128); IF sx < dx THEN INC(sx, w-1); INC(dx, w-1); DEC(comd, 32) END END; IF mode = invert THEN SYSTEM.PUT(FGmix, LONG(65H)) ELSE SYSTEM.PUT(FGmix, LONG(67H)) END; SYSTEM.PUT(PixCntl, LONG(0)); SYSTEM.PUT(curX, SHORT(sx)); SYSTEM.PUT(curY, SHORT(Height - 1 - sy)); SYSTEM.PUT(diaStep, SHORT(dx)); SYSTEM.PUT(axStep, SHORT(Height -1 - dy)); SYSTEM.PUT(MajAxis, SHORT(w-1)); SYSTEM.PUT(MinAxis, SHORT(h-1)); Wait; SYSTEM.PUT(cmd, comd) END END CopyBlock; PROCEDURE SetMode*(x: LONGINT; s: SET); VAR mode: LONGINT; BEGIN IF s # {} THEN mode := SYSTEM.VAL(LONGINT, s); InitMode(mode); truecol := x; 		(*Kernel.WriteString("SetMode "); Kernel.WriteInt(truecol, 1);  Kernel.WriteHex(mode, 9);  Kernel.WriteLn;*) InitS3(FALSE); ResetClip END END SetMode; PROCEDURE CopyPattern*(col: Color; pat: Pattern; x, y, mode: LONGINT); VAR wth, pwidth, pos: LONGINT; p: PatternPtr; BEGIN p:= SYSTEM.VAL( PatternPtr, pat); wth:=(ORD(p.w)+7) DIV 8; INC(x, wth*8-1); y := Height-y-ORD(p.h); IF mode= invert THEN IF (truecol # 0) & (col = FG) THEN col := 0FFFFFFH END; SYSTEM.PUT(AltMix, 250003H) ELSIF mode= replace THEN SYSTEM.PUT(AltMix, 270001H) ELSE SYSTEM.PUT(AltMix, 270003H) END; SYSTEM.PUT(FGcol, TransColor(col)); SYSTEM.PUT(PixCntl, ORD( 80X)); SYSTEM.PUT(MajAxis, SHORT( wth*8-1)); pos:= wth*ORD(p.h); WHILE pos>0 DO 		SYSTEM.PUT(curX, SHORT(x)); SYSTEM.PUT(curY, SHORT(y)); Wait; SYSTEM.PUT(cmd, 219BH); pwidth:= wth; REPEAT DEC( pos); DEC( pwidth); SYSTEM.PUT( pixTrans, p.pixmap[ pos]); UNTIL (pwidth<=0); INC( y) 	END END CopyPattern; PROCEDURE ReplConst*(col: Color; x, y, w, h, mode: LONGINT); BEGIN IF (w > 0) & (h > 0) THEN IF mode = invert THEN IF (truecol # 0) & (col = FG) THEN col := 0FFFFFFH END; SYSTEM.PUT(FGmix, LONG(25H)) (*ELSIF mode= paint THEN 			SYSTEM.PUT( FGmix, LONG(2BH))*) ELSE SYSTEM.PUT(FGmix, LONG(27H)) END; SYSTEM.PUT(FGcol, TransColor(col)); SYSTEM.PUT(PixCntl, LONG( 0)); SYSTEM.PUT(curX, SHORT(x)); SYSTEM.PUT(curY, SHORT(Height-1-y)); SYSTEM.PUT(MajAxis, SHORT(w-1)); SYSTEM.PUT(MinAxis, SHORT(h-1)); Wait; SYSTEM.PUT(cmd, 4073H) END END ReplConst; PROCEDURE FillPattern*(col: Color; pat: Pattern; px, py, x, y, w, h, mode: LONGINT); VAR bit16: INTEGER; pat0, bit32, yo, hgt, wdt: LONGINT;  p: PatternPtr; BEGIN IF (w > 0) & (h > 0) THEN p:= SYSTEM.VAL( PatternPtr, pat); INC(pat, 2); INC(x, w-1); yo:= (y + py) MOD ORD(p.h); y := Height-1-y; IF mode= invert THEN IF (truecol # 0) & (col = FG) THEN col := 0FFFFFFH END; SYSTEM.PUT( AltMix, 250003H) ELSIF mode= replace THEN SYSTEM.PUT( AltMix, 270001H) ELSE SYSTEM.PUT( AltMix, 270003H) END; SYSTEM.PUT(FGcol, TransColor(col)); SYSTEM.PUT(PixCntl, ORD( 80X)); SYSTEM.PUT(MajAxis, SHORT(w-1)); pat0 := pat+ ORD(p.w) DIV 8 * yo; hgt := ORD(p.h) - yo; WHILE h > 0 DO 			wdt:= ( w + 7 ) DIV 8; IF ORD(p.w) = 16 THEN SYSTEM.GET(pat0, bit16); INC(pat0, 2); bit32:= LONG( bit16)* 10000H+ LONG( bit16) MOD 10000H ELSIF ORD(p.w) = 32 THEN SYSTEM.GET(pat0, bit32); INC(pat0, 4) END; bit32 := SYSTEM.ROT(bit32, px-x);	(* SYSTEM.ROT(bit32, pX-X0+16) ?? *) SYSTEM.PUT(curX, SHORT(x)); SYSTEM.PUT(curY, SHORT(y)); Wait; SYSTEM.PUT(cmd, 239BH); WHILE wdt >0 DO 				SYSTEM.PUT(pixTrans, bit32); DEC( wdt,4) END; DEC(y); DEC(h); DEC(hgt); IF hgt <= 0 THEN hgt := ORD(p.h); pat0 := pat END END END END FillPattern; PROCEDURE ReplPattern*(col: Color; pat: Pattern; x, y, w, h, mode: LONGINT); BEGIN FillPattern(col, pat, 0, 0, x, y, w, h, mode) END ReplPattern; PROCEDURE NewPattern*(w, h: LONGINT; VAR image: ARRAY OF SET): Pattern; VAR len, src, dest, i: LONGINT; p: PatternPtr; pl: List; BEGIN len := (w+7) DIV 8; SYSTEM.NEW(p, 4+len*h); p.w := CHR(w); p.h := CHR(h); src := SYSTEM.ADR(image); dest := SYSTEM.ADR(p.pixmap); i := 0; WHILE i < h DO SYSTEM.MOVE(src, dest, len); INC(src, 4); INC(dest, len); INC(i) END; NEW(pl); pl.pat := p;  pl.next := Pat;  Pat := pl;	(* put in list to avoid GC *) RETURN SYSTEM.ADR(p.w) END NewPattern; PROCEDURE CreatePatterns; VAR image: ARRAY 16 OF SET; BEGIN image[0] := {13}; image[1] := {12..14}; image[2] := {11..13}; image[3] := {10..12}; image[4] := {9..11}; image[5] := {8..10}; image[6] := {7..9}; image[7] := {0, 6..8}; image[8] := {0, 1, 5..7}; image[9] := {0..2, 4..6}; image[10] := {0..5}; image[11] := {0..4}; image[12] := {0..5}; image[13] := {0..6}; image[14] := {0..7}; arrow := NewPattern(15, 15, image); image[0] := {0, 10}; image[1] := {1, 9}; image[2] := {2, 8}; image[3] := {3, 7}; image[4] := {4, 6}; image[5] := {}; image[6] := {4, 6}; image[7] := {3, 7}; image[8] := {2, 8}; image[9] := {1, 9}; image[10] := {0, 10}; cross := NewPattern(11, 11, image); image[0] := {6}; image[1] := {5..7}; image[2] := {4..8}; image[3] := {3..9}; image[4] := {2..10}; image[5] := {5..7}; image[6] := {5..7}; image[7] := {5..7}; image[8] := {5..7}; image[9] := {5..7}; image[10] := {5..7}; image[11] := {5..7}; image[12] := {5..7}; image[13] := {5..7}; image[14] := {}; downArrow := NewPattern(15, 15, image); image[0] := {0, 4, 8, 12}; image[1] := {}; image[2] := {2, 6, 10, 14}; image[3] := {}; image[4] := {0, 4, 8, 12}; image[5] := {}; image[6] := {2, 6, 10, 14}; image[7] := {}; image[8] := {0, 4, 8, 12}; image[9] := {}; image[10] := {2, 6, 10, 14}; image[11] := {}; image[12] := {0, 4, 8, 12}; image[13] := {}; image[14] := {2, 6, 10, 14}; image[15] := {}; grey0 := NewPattern(16, 16, image); image[0] := {0, 2, 4, 6, 8, 10, 12, 14}; image[1] := {1, 3, 5, 7, 9, 11, 13, 15}; image[2] := {0, 2, 4, 6, 8, 10, 12, 14}; image[3] := {1, 3, 5, 7, 9, 11, 13, 15}; image[4] := {0, 2, 4, 6, 8, 10, 12, 14}; image[5] := {1, 3, 5, 7, 9, 11, 13, 15}; image[6] := {0, 2, 4, 6, 8, 10, 12, 14}; image[7] := {1, 3, 5, 7, 9, 11, 13, 15}; image[8] := {0, 2, 4, 6, 8, 10, 12, 14}; image[9] := {1, 3, 5, 7, 9, 11, 13, 15}; image[10] := {0, 2, 4, 6, 8, 10, 12, 14}; image[11] := {1, 3, 5, 7, 9, 11, 13, 15}; image[12] := {0, 2, 4, 6, 8, 10, 12, 14}; image[13] := {1, 3, 5, 7, 9, 11, 13, 15}; image[14] := {0, 2, 4, 6, 8, 10, 12, 14}; image[15] := {1, 3, 5, 7, 9, 11, 13, 15}; grey1 := NewPattern(16, 16, image); image[0] := {0, 1, 4, 5, 8, 9, 12, 13}; image[1] := {0, 1, 4, 5, 8, 9, 12, 13}; image[2] := {2, 3, 6, 7, 10, 11, 14, 15}; image[3] := {2, 3, 6, 7, 10, 11, 14, 15}; image[4] := {0, 1, 4, 5, 8, 9, 12, 13}; image[5] := {0, 1, 4, 5, 8, 9, 12, 13}; image[6] := {2, 3, 6, 7, 10, 11, 14, 15}; image[7] := {2, 3, 6, 7, 10, 11, 14, 15}; image[8] := {0, 1, 4, 5, 8, 9, 12, 13}; image[9] := {0, 1, 4, 5, 8, 9, 12, 13}; image[10] := {2, 3, 6, 7, 10, 11, 14, 15}; image[11] := {2, 3, 6, 7, 10, 11, 14, 15}; image[12] := {0, 1, 4, 5, 8, 9, 12, 13}; image[13] := {0, 1, 4, 5, 8, 9, 12, 13}; image[14] := {2, 3, 6, 7, 10, 11, 14, 15}; image[15] := {2, 3, 6, 7, 10, 11, 14, 15}; grey2 := NewPattern(16, 16, image); image[0] := {0..2, 8..11}; image[1] := {0..2, 7..10}; image[2] := {0..2, 6..9}; image[3] := {0..2, 5..8}; image[4] := {0..2, 4..7}; image[5] := {0..6}; image[6] := {0..5}; image[7] := {0..4}; image[8] := {0..3}; image[9] := {0..2}; image[10] := {0, 1}; image[11] := {0}; hook := NewPattern(12, 12, image); image[0] := {7}; image[1] := {7}; image[2] := {2, 7, 12}; image[3] := {3, 7, 11}; image[4] := {4, 7, 10}; image[5] := {5, 7, 9}; image[6] := {6..8}; image[7] := {0..6, 8..14}; image[8] := {6..8}; image[9] := {5, 7, 9}; image[10] := {4, 7, 10}; image[11] := {3, 7, 11}; image[12] := {2, 7, 12}; image[13] := {7}; image[14] := {7}; star := NewPattern(15, 15, image); image[0] := {}; image[1] := {}; image[2] := {0}; image[3] := {}; image[4] := {}; image[5] := {}; image[6] := {}; image[7] := {}; image[8] := {}; image[9] := {}; image[10] := {}; image[11] := {}; image[12] := {}; image[13] := {}; image[14] := {}; image[15] := {}; ticks := NewPattern(16, 16, image); image[0] := -{}; image[1] := -{}; image[2] := -{}; image[3] := -{}; image[4] := -{}; image[5] := -{}; image[6] := -{}; image[7] := -{}; solid := NewPattern(16, 8, image) END CreatePatterns; PROCEDURE Depth*(x: LONGINT): INTEGER; BEGIN RETURN depth END Depth; PROCEDURE TrueColor*(x: LONGINT): BOOLEAN; BEGIN RETURN truecol > 0 END TrueColor; PROCEDURE DB0( adr, bw, wdt, h: LONGINT); CODE {SYSTEM.i386} MOV ESI, adr[ EBP] MOV EAX, bw[ EBP] MOV EBX, wdt[ EBP] ADD EBX, 3 AND EBX, 0FFFFFFFCH SUB EAX, EBX SHR EBX, 2 MOV EDX, h[ EBP] CLD labY: MOV EDI, 0A0000H MOV ECX, EBX REP MOVSD ADD ESI, EAX DEC EDX JNZ labY END DB0; PROCEDURE DB1(adr, bw, wdt, h: LONGINT); CODE {SYSTEM.i386} MOV ESI, adr[EBP] MOV ECX, wdt[EBP] INC ECX AND ECX, 0FFFFFFFEH SUB bw[EBP], ECX SHR ECX, 1 MOV wdt[EBP], ECX LEA EDX, colmap CLD labY: MOV EDI, 0A0000H MOV ECX, wdt[EBP] loop: LODSW MOV EBX, EAX AND EAX, 0FFH SHR EBX, 8 MOV EAX, [EDX][EAX*4] AND EBX, 0FFH MOV EBX, [EDX][EBX*4] SHL EBX, 16 OR EAX, EBX STOSD LOOP loop ADD ESI, bw[EBP] DEC h[EBP] JNZ labY END DB1; PROCEDURE DB2(adr, bw, wdt, h: LONGINT); CODE {SYSTEM.i386} MOV ESI, adr[EBP] MOV ECX, wdt[EBP] SUB bw[EBP], ECX LEA EDX, colmap CLD labY: MOV EDI, 0A0000H MOV ECX, wdt[EBP] loop: LODSB AND EAX, 0FFH MOV EAX, [EDX][EAX*4] STOSD LOOP loop ADD ESI, bw[EBP] DEC h[EBP] JNZ labY END DB2; (* PROCEDURE DBobn( adr, bw, wdt, h: LONGINT); VAR i, j: LONGINT; BEGIN 	WHILE h>0 DO 		FOR i:=0 TO wdt BY 4 DO 			SYSTEM.GET( adr+i, j); 			SYSTEM.PUT( pixTrans, j);		(* pixTrans or 0A0000H..0A7FFCH *) 		END;			 		INC( adr, bw); 		DEC( h); 	END; END DBobn; *) PROCEDURE DisplayBlock*(adr, dx, dy, w, h, sx, sy, mode: LONGINT); VAR width, blockadr: LONGINT; BEGIN SYSTEM.GET(adr+8, width); SYSTEM.GET(adr+12, blockadr); sy := Height-1-sy; IF mode # invert THEN SYSTEM.PUT(FGmix, SYSTEM.VAL(INTEGER, 47H))	(* replace, paint *) ELSE SYSTEM.PUT(FGmix, SYSTEM.VAL(INTEGER, 45H))	(* invert *) END; SYSTEM.PUT(PixCntl, SYSTEM.VAL(INTEGER, 0A000H)); SYSTEM.PUT(curX, SHORT(sx)); SYSTEM.PUT(curY, SHORT(sy)); SYSTEM.PUT(MajAxis, SHORT(w-1)); SYSTEM.PUT(MinAxis, SHORT(h-1)); Wait; SYSTEM.PUT(cmd, SYSTEM.VAL(INTEGER, 5531H)); CASE truecol OF 		0: DB0(blockadr + width*dy + dx, width, w, h) 		|1: DB1(blockadr + width*dy + dx, width, w, h) 		|2: DB2(blockadr + width*dy + dx, width, w, h) 	END END DisplayBlock; PROCEDURE TransferFormat*(x: LONGINT): LONGINT; BEGIN CASE truecol OF 		0: x := index8 |1: x := color565 |2: x := color8888 END; RETURN x END TransferFormat; PROCEDURE TransferBlock*(VAR buf: ARRAY OF CHAR; ofs, stride, x, y, w, h, mode: LONGINT); BEGIN IF mode = set THEN y := Height-1-y; SYSTEM.PUT(FGmix, 47H); SYSTEM.PUT(PixCntl, LONG( 0H)); SYSTEM.PUT(curX, SHORT(x)); SYSTEM.PUT(curY, SHORT(y)); SYSTEM.PUT(MajAxis, SHORT(w-1)); SYSTEM.PUT(MinAxis, SHORT(h-1)); Wait; SYSTEM.PUT(cmd, 5531H); DB0(SYSTEM.ADR(buf[ofs]), stride, ASH(w, truecol), h) 	END END TransferBlock; PROCEDURE GetVal(str: ARRAY OF CHAR; default: LONGINT): LONGINT; VAR i: SHORTINT; v: LONGINT;  s: ARRAY 10 OF CHAR; BEGIN Kernel.GetConfig(str, s); IF s[0] = 0X THEN v := default ELSE v := 0; i := 0; WHILE s[i] # 0X DO v := v*10+(ORD(s[i])-48); INC(i) END END; RETURN v END GetVal; PROCEDURE InitMode(mode: LONGINT); VAR vreg: V86.Regs; BEGIN vreg.EAX := 4F02H; vreg.EBX := mode; V86.Video(vreg) END InitMode; PROCEDURE InitS3(first: BOOLEAN); VAR ch: CHAR; mask, i, mode: LONGINT; BEGIN FOR i := 0 TO 255 DO colmap[i] := i END; IF first THEN truecol := GetVal("DColor", 0); mode := GetVal("Color", 1);	(* assume 1 if not specified *) IF mode = 0 THEN depth := 1 ELSE IF truecol = 0 THEN depth := 8 ELSE depth := 24 END END; Width := SHORT(GetVal("DWidth", 1024));	(* assume 1024 if not specified *) Height := SHORT(GetVal("DHeight", 768));	(* assume 768 if not specified *) dmem := GetVal("DMem", 1024)*1024;	(* assume 1Mb if not specified *) mode := -1; IF Width = 640 THEN CASE truecol OF 				1: mode := 111H |2: mode := 112H ELSE (* skip *) END ELSIF Width = 800 THEN CASE truecol OF 				0: mode := 103H |1: mode := 114H |2: mode := 115H ELSE (* skip *) END ELSIF Width = 1024 THEN CASE truecol OF 				0: mode := 105H |1: mode := 117H |2: mode := 118H ELSE (* skip *) END ELSIF Width = 1280 THEN CASE truecol OF 				0: mode := 107H |1: mode := 11AH ELSE (* skip *) END ELSE (* skip *) END; IF mode # -1 THEN InitMode(mode) END END; SYSTEM.PORTOUT( 3D4H, 2DH); SYSTEM.PORTIN( 3D5H, ch); IF ch= 88X THEN SYSTEM.PORTOUT( 3D4H, 2EH); SYSTEM.PORTIN( 3D5H, ch); IF ch= 11X THEN																(*	Trio found	*) Width:=0; Height:=0; SYSTEM.PORTOUT( 3D4H, 5DH);								(* get Width *) SYSTEM.PORTIN( 3D5H, ch); IF ODD( ORD( ch) DIV 2) THEN Width:= 256*8 END; SYSTEM.PORTOUT( 3D4H, 1); SYSTEM.PORTIN( 3D5H, ch); INC( Width, ( ORD( ch)+1)*8); IF truecol = 1 THEN Width := Width DIV 2 END; SYSTEM.PORTOUT( 3D4H, 5EH);									(* get Height *) SYSTEM.PORTIN( 3D5H, ch); IF ODD( ORD( ch) DIV 2) THEN Height:= 1024 END; SYSTEM.PORTOUT( 3D4H, 7); SYSTEM.PORTIN( 3D5H, ch); IF ODD( ORD( ch) DIV 2) THEN INC( Height, 256) END; IF ODD( ORD( ch) DIV 64) THEN INC( Height, 512) END; SYSTEM.PORTOUT( 3D4H, 12H); SYSTEM.PORTIN( 3D5H, ch); INC( Height, ORD( ch)+1); SYSTEM.PORTOUT( 3D4H, 36H);									(* get MemSize *) SYSTEM.PORTIN( 3D5H, ch); mask:= ASH( ORD( ch), -5); IF mask= 0 THEN dmem:= 4096*1024; ELSIF mask= 4 THEN dmem:= 2048*1024; ELSE dmem:= 1024*1024; END; END; END; UBottom := Height - SHORT((dmem-4096) DIV Width) + 1;	(* Space for 4 Sprites reserved *) SYSTEM.PORTOUT( 3D4H, 1053H);	(*	10H: enable old MMIO 18H: old & new MMIO	*) mask:= -1; SYSTEM.PUT(wrtMask, mask);				(* Write mask *) SYSTEM.PUT(rdMask, mask);					(* Read mask *) Kernel.MapPhysical(0E0000000H, dmem, base); IF base # 0 THEN										(* enable lfb *) SYSTEM.PORTOUT( 3D4H, 0831H);		(* CR31 bit 3: enhanced mode mapping*) IF dmem<=1024*1024 THEN SYSTEM.PORTOUT( 3D4H, 1158H); ELSIF dmem<=2024*1024 THEN SYSTEM.PORTOUT( 3D4H, 1258H); ELSE SYSTEM.PORTOUT( 3D4H, 1358H);		(* bit 4: enable lfb, bit 0,1: size: 0= 64k, 1=1MB, 2= 2MB, 3= 4MB *) END; SYSTEM.PORTOUT( 3D4H, 59H);			(* set base adr for lfb *) SYSTEM.PORTOUT( 3D5H, CHR( ASH( base, -24) )); SYSTEM.PORTOUT( 3D4H, 5AH); SYSTEM.PORTOUT( 3D5H, CHR( ASH( base, -16) )); (* 		SYSTEM.PORTOUT( 3D4H, 33H);			(* disable border *) 		SYSTEM.PORTIN( 3D5H, ch); 		SYSTEM.PORTOUT( 3D5H, SYSTEM.VAL( CHAR, SYSTEM.VAL( SET, ch)+{5})); *) END; SYSTEM.PORTOUT( 3C4H, SYSTEM.VAL( INTEGER, 8009H));		(* disable programmed I/O *) Kernel.WriteString("S3TrioC: "); Kernel.WriteInt(Width, 1); Kernel.WriteChar("x"); Kernel.WriteInt(Height, 1); Kernel.WriteChar("x"); Kernel.WriteInt(depth, 1); CASE truecol OF 		0: Kernel.WriteString(" 8-bit indexed") |1: Kernel.WriteString(" 5,6,5-bit RGB") |2: Kernel.WriteString(" 8,8,8-bit RGB") END; Kernel.WriteString(" (+"); Kernel.WriteInt(-UBottom, 1); 	Kernel.WriteString(" offscreen)"); Kernel.WriteLn END InitS3; BEGIN Left:= 0; ColLeft:= 0; Bottom:= 0; truecol := -1; Pat := NIL; IF Kernel.tspeed < 0 THEN Kernel.tspeed := 0 END;	(* switch off screen tracing *) InitS3(TRUE); ResetClip; CreatePatterns; Unit := 10000 END Display. (* #     0103   800  600  256  P8   0 *) (* Compiler.Compile S3TrioC.Display.Mod\X ~ *)
 * 1) Trio64 Display settings
 * 1)      0205  1024  768  256  P8   0
 * 2)      0107  1280 1024  256  P8   0
 * 3)      0211   640  480  64k  P16  1
 * 4)      0111   640  480  64k  P16  1
 * 5)      0114   800  600  64k  P16  1
 * 6)      0117  1024  768  64k  P16  1
 * 7)      011A  1280 1024  64k  P16  1
 * 8)      0212   640  480  16m  P24  2
 * 9)      0112   640  480  16m  P32  2
 * 10)      0115   800  600  16m  P32  2
 * 11)      0118  1024  768  16m  P32  2