home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1986-12-23 | 27.6 KB | 774 lines |
- IMPLEMENTATION MODULE LowEGA;
- (*
- Title : LowEGA
-
- Low Level EGA Facilities
- Supplies useful workarounds to the BIOS and
- extensions thereto such as split screen.
- LastEdit: July 14, 1986
- Author : John T. Cockerham, M.D.
- Syatem : LOGITECH MODULA-2/86
- *)
- (* This is a low level module *)
- FROM SYSTEM IMPORT INBYTE, OUTBYTE, OUTWORD, AX, BX, CX, DX, ES,
- ADR, BP, GETREG, SETREG, SWI, ADDRESS, CODE, BYTE, WORD;
- FROM PointLib IMPORT Point, MakePoint;
- FROM Opcodes IMPORT PushBP, PopBP;
- TYPE
- Register = RECORD CASE BOOLEAN OF TRUE : X : CARDINAL;
- | FALSE : L, H : CHAR; END; END;
- ByteADRType = RECORD
- CASE BOOLEAN OF TRUE : adr : POINTER TO CHAR;
- | FALSE : off, seg : CARDINAL; END; END;
-
- CONST
- TotalScanLinesEnhanced = 349;
- VIDEO = 10H;
- SetPageBiosCall = 005H;
- SetPaletteCall = 010H;
- CharacterGeneratorFunction = 011H;
- WriteTTY = 00EH;
- SetCPos = 002H;
- AlphaPageSize = 2048;
- BottomOfScreen = 01FFH;
-
- (* This is the bit layout for Info And Info3 -- EGA
- information bytes found the BIOS page *)
- CursorEmulateBit = 0; MonoAttachedBit = 1;
- WaitForEnableBit = 2; EGAIsActiveBit = 3;
- MemoryBit1 = 5; MemoryBit2 = 6;
- ModeSetClearBit = 7;
-
- VerticalRetraceBit = 3;
-
- (* These are EGA I/O Registers *)
- Graph1 = 03CCh; Graph2 = 03CAh;
- Graph12 = 03CEh; MiscOut = 03C2h;
- Status0 = 03C3h; Sequencer = 03C4h;
- AttributeCntrl = 03C0h; GraphData = 03CFh;
- StatusRegisterOffset = 6;
- (* These are the names of the EGA indices *)
- (* Sequencer controller first *)
- SequenceReset = 0; SequenceClockMode = 1;
- SequenceMapMask = 2; SequenceCharMap = 3;
- SequenceMemMode = 4;
- (* CRT controller registers *)
- CRTHorizTotal = 00h; CRTHorizEnd = 01h;
- CRTHorizblStart = 02h; CRTHorizBlEnd = 03h;
- CRTHorizRetStart = 04h; CRTHorizRetEnd = 05h;
- CRTVertTotal = 06h; CRTOvflo = 07h;
- CRTPreRowScan = 08h; CRTMaxScanLine = 09h;
- CRTCursorStart = 0Ah; CRTCursorEnd = 0Bh;
- CRTStartAddHi = 0Ch; CRTStartAddLo = 0Dh;
- CRTCursLocHi = 0Eh; CRTCursLocLo = 0Fh;
- CRTVertRetSt = 10h; CRTLightPenHi = 10h;
- CRTVertRetEnd = 11h; CRTLightPenLo = 11h;
- CRTVertDisEnd = 12h; CRTOffset = 13h;
- CRTUnderLoc = 14h; CRTVertBlSt = 15h;
- CRTVertBlEnd = 16h; CRTModeControl = 17h;
- CRTLineCompare = 18h;
- (* Graphics Controller indices *)
- GraphReset = 00h; GraphEnable = 01h;
- GraphColorComp = 02h; GraphDataRotate = 03h;
- GraphReadMapSel = 04h; GraphModeReg = 05h;
- GraphMisc = 06h; GraphColorDC = 07h;
- GraphBitMask = 08h;
- (* Memory Mapping mode values *)
- A000x128K = 00h; A000x64K = 04h;
- B000x32K = 02h; B800x32K = 0Ch;
- GraphicsModeBit = 01h; ChainEvenToOdd = 02h;
- (* Attribute Controller indices *)
- AttrModeControl = 10h; AttrOverscan = 11h;
- AttrColorPlane = 12h; AttrHorizPelPan = 13h;
- PaletteOn = 20h;
-
- VAR
- VIDEORAM : ByteADRType;
- bitmasks : ARRAY [0..7] OF CARDINAL;
- Cursors : ARRAY [0..7] OF Point;
- ActivePageOffsets : ARRAY [0..7] OF CARDINAL;
- i : CARDINAL;
- CRTCOverflowRegister : BITSET;
- PelScrollColumn : INTEGER;
- VerticalScrollRow : INTEGER;
- SplitScreenLine : CARDINAL;
- EGA6845 : CARDINAL;
-
- (*$S-*)(*$T-*)(*$R- Turn off Stack Checking for performance
- and reentrancy reasons *)
- PROCEDURE EGAOutWord(EGAPort, DeviceRegister, Value : CARDINAL);
- (* Output two bytes to the EGA at two Successive I/O addresses *)
- VAR A : Register;
- BEGIN
- A.L := CHR(DeviceRegister); A.H := CHR(Value);
- OUTWORD(EGAPort, A.X);
- END EGAOutWord;
- PROCEDURE WaitForVerticalRetrace;
- (* Wait in a tight loop for vertical retrace *)
- VAR InputStatusRegister1 : BITSET;
- BEGIN
- REPEAT
- INBYTE(EGA6845 + StatusRegisterOffset, InputStatusRegister1);
- UNTIL NOT (VerticalRetraceBit IN InputStatusRegister1);
- END WaitForVerticalRetrace;
- PROCEDURE WaitForVerticalDisplay;
- (* Wait in a tight loop for vertical display active *)
- VAR InputStatusRegister1 : BITSET;
- BEGIN
- REPEAT
- INBYTE(EGA6845 + StatusRegisterOffset, InputStatusRegister1);
- UNTIL NOT (VerticalRetraceBit IN InputStatusRegister1);
- END WaitForVerticalDisplay;
- PROCEDURE SetPageOffset(where : CARDINAL);
- (* Instruct the CRTC where the page starts after retrace *)
- VAR A : Register;
- BEGIN
- A.X := ActivePageOffset;
- EGAOutWord(EGA6845, CRTStartAddHi, ORD(A.H));
- EGAOutWord(EGA6845, CRTStartAddLo, ORD(A.L));
- END SetPageOffset;
-
- PROCEDURE SetActiveFonts(FontA, FontB : CARDINAL);
- (* This routine changes the active character map for
- text modes. It is written as a reentrant procedure *)
- VAR x : CARDINAL;
- BEGIN
- x := FontA * 2 + FontB;
- WaitForVerticalRetrace;
- EGAOutWord(Sequencer, SequenceCharMap, x);
- END SetActiveFonts;
- (*$S+*)(*$T+*)(*$R+ Turn run time services back on *)
-
- PROCEDURE InitEGA(EGAMonitor : MonitorType) : BOOLEAN;
- (* This routine sets up the EGA for alpha Mode 3 *)
- BEGIN
- SetUpAlpha; MemoryInstalled := 0;
- IF MemoryBit2 IN EGABiosParams.InfoAndInfo3
- THEN MemoryInstalled := 2 END;
- IF MemoryBit1 IN EGABiosParams.InfoAndInfo3
- THEN INC(MemoryInstalled) END;
- IF EGAMonitor = Monochrome THEN
- IF MonoAttachedBit IN EGABiosParams.InfoAndInfo3 THEN
- EGA6845 := 03B4H;
- ELSE
- RETURN FALSE;
- END;
- ELSE
- IF NOT (MonoAttachedBit IN EGABiosParams.InfoAndInfo3) THEN
- EGA6845 := 03D4H;
- ELSE
- RETURN FALSE;
- END;
- RETURN TRUE;
- END;
- END InitEGA;
-
- PROCEDURE SetUpAlpha;
- (* This is a non standard set up to the EGA to Alpha
- 80x25 on the graphics page (A000). Assertion that EGA
- is already in mode 3 and EGA is comfigured with 256K RAM *)
- VAR
- a, b : Register;
- BEGIN
- EGAOutWord(Graph12, GraphMisc,
- A000x64K + ChainEvenToOdd); (* Map to the A000 map *)
- EGAOutWord(EGA6845, CRTOvflo, 01FH);
- CRTCOverflowRegister := {4, 3, 2, 1, 0};
- END SetUpAlpha;
-
- PROCEDURE SetUpHiRes;
- (* This routine changes the EGA operating mode to HiRes color
- Graphics. All of these register settings are from the
- boards' documentation *)
- BEGIN
- WaitForVerticalRetrace;
- EGAOutWord(Sequencer, SequenceMapMask, 00FH);
- EGAOutWord(Sequencer, SequenceMemMode, 006H);
- EGAOutWord(EGA6845, CRTHorizRetStart, 052H);
- EGAOutWord(EGA6845, CRTHorizRetEnd, 000H);
- EGAOutWord(EGA6845, CRTOvflo, 01FH);
- CRTCOverflowRegister := {4, 3, 2, 1, 0};
- ResetVerticalScroll;
- ResetSplitScreen;
- EGAOutWord(EGA6845, CRTMaxScanLine, 000H);
- EGAOutWord(EGA6845, CRTCursorStart, 01FH); (*Turn off cursor*)
- EGAOutWord(EGA6845, CRTCursorEnd, 000H);
- EGAOutWord(EGA6845, CRTVertBlSt, 05FH);
- EGAOutWord(EGA6845, CRTModeControl, 0E3H); (*Byte Mode *)
- EGAOutWord(EGA6845, CRTLineCompare, 0FFH);
- EGAOutWord(Graph12, GraphModeReg, 000H);
- EGAOutWord(Graph12, GraphMisc, A000x64K + GraphicsModeBit);
- EGAOutWord(Graph12, GraphColorDC, 00FH);
- EGAOutWord(AttributeCntrl, AttrModeControl+PaletteOn, 001H);
- ResetHorizScroll;
- (* We are in writing mode 0 with all maps on this will
- clear out the display buffer *)
- FOR i := 0 TO 65500 DO DisplayBuffer[i] := 0C; END;
- END SetUpHiRes;
- (*----------------------------------------------------*)
- (* Position fiddling procedures *)
- (* Warning for these routines: *)
- (* Knowledge of exact mode *)
- (* specifications including word/byte *)
- (* count by 2 etc is essential to using *)
- (* these routines *)
- (*----------------------------------------------------*)
-
- PROCEDURE SetLogicalRowSize(RowSizeInWords : CARDINAL);
- (* This routine sets the offset register of the CTRC. Word/byte
- issues play a role in its setting *)
- BEGIN
- EGAOutWord(EGA6845, CRTOffset, RowSizeInWords);
- END SetLogicalRowSize;
-
- PROCEDURE SetUnderlineLocation(UnderlineScanLine : CARDINAL);
- (* Set the CRTC's scan line for underlining *)
- BEGIN
- EGAOutWord(EGA6845, CRTUnderLoc, UnderlineScanLine);
- END SetUnderlineLocation;
-
- (*----------------------------------------------------*)
- (* Mode Switching routines between the monitors *)
- (* Warning -- Two monitor systems only *)
- (* Bad results can happen if on mono *)
- (* systems only! *)
- (*----------------------------------------------------*)
-
- VAR
- EquipFlag [0:410H] : BITSET;
-
- PROCEDURE SwitchToMonoBios;
- (* Adjust the Equiptment Flag to indicate a Monochrome System *)
- BEGIN
- EquipFlag := EquipFlag + {4, 5};
- END SwitchToMonoBios;
-
- PROCEDURE SwitchToColorBios;
- (* Adjust the Equiptmant Flag to indicate Color system *)
- BEGIN
- EquipFlag := EquipFlag - {4} + {5};
- END SwitchToColorBios;
-
- PROCEDURE ColorBiosMode() : BOOLEAN;
- (* Return the status of the Flag. False = monochrome,
- true = Color. *)
- BEGIN
- RETURN (NOT ((5 IN EquipFlag) AND (4 IN EquipFlag)));
- END ColorBiosMode;
- (*----------------------------------------------------*)
- (* Cursor Routines *)
- (*----------------------------------------------------*)
-
- PROCEDURE SetCursor(Page : CARDINAL);
- (* Set the Cursor to display for the given page *)
- VAR Off : Register;
- BEGIN
- Off.X := CursorOffset(Page) DIV 2;
- EGAOutWord(EGA6845, CRTCursLocHi, ORD(Off.H));
- EGAOutWord(EGA6845, CRTCursLocLo, ORD(Off.L));
- END SetCursor;
-
- PROCEDURE CursorOffset(Page : CARDINAL) : CARDINAL;
- (* Calculate cursor offset for CPU mappings: which is doubled
- accouting for the attribute byte *)
- BEGIN
- RETURN ((ActivePageOffsets[Page] +
- CARDINAL(Cursors[Page].y) * ORD(BiosCRTParams.CRTCols) +
- CARDINAL(Cursors[Page].x)) * 2);
- END CursorOffset;
-
- PROCEDURE BumpCursor(Page : CARDINAL);
- (* Increment the cursor in the X direction one unit. If the cursor
- falls off the row, reset to beginning of the next row. Rows
- wrap around to the start of the screen *)
- BEGIN
- INC(Cursors[Page].x);
- IF Cursors[Page].x >= INTEGER(BiosCRTParams.CRTCols) THEN
- Cursors[Page].x := 0;
- INC(Cursors[Page].y);
- IF ORD(Cursors[Page].y) > ORD(RowsOnScreen) THEN
- Cursors[Page].y := 0;
- END;
- END;
- IF Page = ActivePage THEN SetCursor(Page); END;
- END BumpCursor;
-
- PROCEDURE SetCursorPoint(Page : CARDINAL; p : Point);
- (* Set the cursor to point 'p'. Don't allow it to fall off
- either edge of the display *)
- BEGIN
- IF p.x < INTEGER(BiosCRTParams.CRTCols) THEN
- Cursors[Page].x := p.x;
- ELSE
- Cursors[Page].x := INTEGER(BiosCRTParams.CRTCols) - 1;
- END;
- IF p.y <= INTEGER(ORD(RowsOnScreen)) THEN
- Cursors[Page].y := p.y;
- ELSE
- Cursors[Page].y := ORD(RowsOnScreen);
- END;
- IF Page = ActivePage THEN SetCursor(Page); END;
- END SetCursorPoint;
-
- PROCEDURE GetCursorPoint(VAR p : Point; Page : CARDINAL);
- (* Return the cursor position for the given page *)
- BEGIN
- p := Cursors[Page];
- END GetCursorPoint;
-
-
- (*--------------------------------------------------*)
- (* Alpha mode write routines *)
- (*--------------------------------------------------*)
-
- PROCEDURE Write(Page : CARDINAL; ch : CHAR; color : INTEGER);
- (* Place one character into the display buffer at the
- cursor. The cursor is moved to the next column.
- Color represents the attribute byte *)
- VAR x : CARDINAL;
- BEGIN
- x := CursorOffset(Page);
- DisplayBuffer[x] := ch;
- DisplayBuffer[x+1] := CHR(color);
- BumpCursor(Page);
- END Write;
-
- PROCEDURE WriteString(Page : CARDINAL; s : ARRAY OF CHAR;
- c : CARDINAL);
- (* Place a string into the display buffer at the cursor.
- The string is written one character at a time with
- the attribute byte of c *)
- VAR i : CARDINAL;
- BEGIN
- i := 0;
- WHILE i <= HIGH(s) DO
- Write(Page, s[i], c);
- INC(i);
- END;
- END WriteString;
-
- (*--------------------------------------------------*)
- (* Virtual page manipulation routines *)
- (*--------------------------------------------------*)
-
- PROCEDURE SetActivePage(page : CARDINAL);
- (* Set the active display page to 'page' resetting
- any scrolling etc. *)
- BEGIN
- ActivePage := page;
- ResetHorizScroll;
- ResetVerticalScroll;
- IF page <= MaxVideoPages THEN
- ActivePageOffset := ActivePageOffsets[page];
- SetPageOffset(ActivePageOffset);
- SetCursor(page);
- END;
- END SetActivePage;
-
- PROCEDURE MakeSecondGraphicsPage;
- (* This routine abitrarily set the offset to the
- second hi res graphics page *)
- BEGIN
- ActivePageOffset := 8000H;
- SetPageOffset(ActivePageOffset);
- SetBiosPage(1);
- END MakeSecondGraphicsPage;
-
- PROCEDURE ResetVideoPage;
- (* This routine resets the current video page, and
- get rid of any scrolling and split screens, etc. *)
- BEGIN
- SetActivePage(ActivePage);
- ResetSplitScreen;
- END ResetVideoPage;
- (*--------------------------------------------------*)
- (* Attribute manipulation routines *)
- (*--------------------------------------------------*)
-
- PROCEDURE SetPalette(Palette, Color : CARDINAL);
- (* This routine sets up the palette RAM in the
- attribute controller with the patern in Color *)
- BEGIN
- WaitForVerticalRetrace;
- EGAOutWord(AttributeCntrl, Palette, Color);
- EGAOutWord(AttributeCntrl, AttrColorPlane+PaletteOn, 0FH);
- END SetPalette;
-
- PROCEDURE SetOverscan(Color : CARDINAL);
- (* This routine sets up the overscan color for a border
- with the patteren in Color *)
- BEGIN
- WaitForVerticalRetrace;
- EGAOutWord(AttributeCntrl, AttrOverscan, Color);
- EGAOutWord(AttributeCntrl, AttrColorPlane+PaletteOn, 0FH);
- END SetOverscan;
-
- PROCEDURE TurnOnBlinking;
- BEGIN
- EGAOutWord(AttributeCntrl, AttrModeControl+PaletteOn, 09H);
- END TurnOnBlinking;
-
- PROCEDURE TurnOffBlinking;
- BEGIN
- EGAOutWord(AttributeCntrl, AttrModeControl+PaletteOn, 01H);
- END TurnOffBlinking;
- (*--------------------------------------------------*)
- (* Horizontal scrolling routines *)
- (*--------------------------------------------------*)
-
- PROCEDURE HorScrollLeft;
- (* Horizontal scrolling left means advancing the page offset
- when falling off the pixel box. The routine is specific
- for 8 pixens per byte *)
- BEGIN
- INC(PelScrollColumn);
- WaitForVerticalDisplay;
- IF PelScrollColumn > 7 THEN
- PelScrollColumn := 0;
- INC(ActivePageOffset);
- SetPageOffset(ActivePageOffset); (* Does a Wait already *)
- EGAOutWord(AttributeCntrl, AttrHorizPelPan+PaletteOn,
- PelScrollColumn);
- ELSE
- WaitForVerticalDisplay;
- EGAOutWord(AttributeCntrl, AttrHorizPelPan+PaletteOn,
- PelScrollColumn);
- END;
- END HorScrollLeft;
-
- PROCEDURE HorScrollRight;
- BEGIN
- DEC(PelScrollColumn);
- WaitForVerticalDisplay;
- IF PelScrollColumn < 0 THEN
- PelScrollColumn := 7;
- DEC(ActivePageOffset);
- SetPageOffset(ActivePageOffset);
- EGAOutWord(AttributeCntrl, AttrHorizPelPan+PaletteOn,
- PelScrollColumn);
- ELSE
- WaitForVerticalDisplay;
- EGAOutWord(AttributeCntrl, AttrHorizPelPan+PaletteOn,
- PelScrollColumn);
- END;
- END HorScrollRight;
-
- PROCEDURE HorizScroll(pixels : INTEGER);
- VAR i : INTEGER;
- BEGIN
- IF pixels = 0 THEN RETURN; END;
- IF pixels > 0 THEN
- FOR i := 1 TO pixels DO HorScrollLeft; END;
- ELSE
- FOR i := -1 TO pixels BY -1 DO HorScrollRight; END;
- END;
- END HorizScroll;
-
- PROCEDURE ResetHorizScroll;
- BEGIN
- PelScrollColumn :=0;
- WaitForVerticalRetrace;
- EGAOutWord(AttributeCntrl, AttrHorizPelPan+PaletteOn, 0);
- END ResetHorizScroll;
-
- (*-----------------------------------------------*)
- (* Vertical Scrolling *)
- (* only has meaning in alpha mode *)
- (*-----------------------------------------------*)
-
- PROCEDURE VerticalScrollUp;
- (* Smooth vertical scroll uses the preset row scan regiater
- in the CRTC. When the row is completely scrolled,
- the offset pointer is advanced by one row size *)
- BEGIN
- INC(VerticalScrollRow); WaitForVerticalDisplay;
- IF VerticalScrollRow >= INTEGER(BytesPerChar) THEN
- ActivePageOffset := ActivePageOffset + BiosCRTParams.CRTCols;
- VerticalScrollRow := 0;
- SetPageOffset(ActivePageOffset);
- EGAOutWord(EGA6845, CRTPreRowScan, VerticalScrollRow);
- ELSE
- WaitForVerticalRetrace;
- EGAOutWord(EGA6845, CRTPreRowScan, VerticalScrollRow);
- END;
- END VerticalScrollUp;
-
- PROCEDURE VerticalScrollDown;
- (* Vertical scrolling down is the same as up except the row
- changes backward, each character row is brought down a line
- at a time by setting the preset row scan register to the
- high value and decrementing it. *)
- BEGIN
- DEC(VerticalScrollRow); WaitForVerticalDisplay;
- IF VerticalScrollRow < 0 THEN
- ActivePageOffset := ActivePageOffset - BiosCRTParams.CRTCols;
- VerticalScrollRow := BytesPerChar - 1;
- SetPageOffset(ActivePageOffset);
- EGAOutWord(EGA6845, CRTPreRowScan, VerticalScrollRow);
- ELSE
- WaitForVerticalRetrace;
- EGAOutWord(EGA6845, CRTPreRowScan, VerticalScrollRow);
- END;
- END VerticalScrollDown;
-
- PROCEDURE ResetVerticalScroll;
- BEGIN
- WaitForVerticalRetrace;
- EGAOutWord(EGA6845, CRTPreRowScan, 0);
- VerticalScrollRow := 0;
- END ResetVerticalScroll;
- (*--------------------------------------------------*)
- (* Split screen routines *)
- (* The split screen starts at offset in the *)
- (* display buffer *)
- (*--------------------------------------------------*)
-
- PROCEDURE SplitScreenAt(ScanLine : CARDINAL);
- (* Splitting the screen uses the Line Compare Register of
- the CRTC. The overflow for the 9th bit is placed in the
- CRTC's overflow register. The screen splits when the
- current video scan line equals the designated value
- in those two registers *)
- VAR Line : Register;
- BEGIN
- Line.X := ScanLine;
- IF Line.H <> 0C THEN
- CRTCOverflowRegister := CRTCOverflowRegister + {4};
- ELSE
- CRTCOverflowRegister := CRTCOverflowRegister - {4}; END;
- WaitForVerticalDisplay; WaitForVerticalRetrace;
- EGAOutWord(EGA6845, CRTLineCompare, ORD(Line.L));
- EGAOutWord(EGA6845, CRTOvflo,
- CARDINAL(CRTCOverflowRegister));
- SplitScreenLine := ScanLine;
- END SplitScreenAt;
-
- PROCEDURE RollSplitScreenUp(SplitSizeLines : CARDINAL);
- (* Smoothly bring up the split screen with a delay between
- each line as it is brought up. *)
- VAR Line : CARDINAL;
- BEGIN
- Line := TotalVerticalScanLines - 1;
- WHILE Line > TotalVerticalScanLines - SplitSizeLines DO
- SplitScreenAt(Line);
- DEC(Line);
- WaitForVerticalRetrace;
- END;
- END RollSplitScreenUp;
-
- PROCEDURE RollSplitScreenDown;
- (* This routine smoothly rolls the split screen back down *)
- VAR Line : CARDINAL;
- BEGIN
- Line := TotalVerticalScanLines + 1;
- WHILE Line < TotalVerticalScanLines DO
- SplitScreenAt(Line);
- INC(Line);
- WaitForVerticalRetrace;
- END;
- END RollSplitScreenDown;
- PROCEDURE ResetSplitScreen;
- (* This routine pops the split screen back down, no scrolling
- is performed. *)
- BEGIN
- SplitScreenAt(BottomOfScreen);
- END ResetSplitScreen;
-
- (*--------------------------------------------------*)
- (* Graphics routines *)
- (*--------------------------------------------------*)
-
- PROCEDURE FillGraphicsPage(Color : CARDINAL);
- (* Modify to use writing mode 2: Set every bit in bit plane N
- Equal to Bit N of the data bytes. Useful for rapid flooding
- of the display ram with a particular palette. *)
- VAR x1, y1 : CARDINAL;
- BEGIN
- EGAOutWord(Graph12, GraphModeReg, 2);
- FOR x1 := 0 TO BiosCRTParams.CRTCols -1 DO
- FOR y1 := 0 TO 349 DO
- DisplayBuffer[ActivePageOffset + x1 +
- BiosCRTParams.CRTCols * y1] := CHR(Color);
- END;
- END;
- EGAOutWord(Graph12, GraphModeReg, 0);
- END FillGraphicsPage;
-
- PROCEDURE DrawPointTutorial(p : Point; color : CARDINAL);
- (* This procedure demonstrates the method for turning on
- one pixel. A faster version is below with key parts reduced
- to machine level code *)
- (* Turn on a dot at 'p', setting its 'color'. *)
- VAR rowbyte, bitmask, byteoffset : CARDINAL;
- Temp : CHAR;
- BEGIN
- (* Here compute the address of the pixel byte to change,
- and its bit offset within the byte. *)
- rowbyte := p.x DIV 8; bitmask := p.x MOD 8;
- bitmask := bitmasks[bitmask];
- byteoffset := CARDINAL(p.y) * BiosCRTParams.CRTCols + rowbyte
- + ActivePageOffset;
- VIDEORAM.off := byteoffset;
- (* Select Graphics Bit Mask Register to mask
- out all but the desired pixel *)
- EGAOutWord(Graph12, GraphBitMask, bitmask);
- (* Select sequencer map mask to enable all four
- maps and latches aven if 2 are present *)
- EGAOutWord(Sequencer, SequenceMapMask, 0FH);
- (* Now read the character to latch it in to the 4 EGA plane
- latches. The value read is of no importance *)
- Temp := VIDEORAM.adr^;
- (* Now blank out the all bytes, to clear out the desired
- pixel. Remember the other bits are still latched in, and
- will be preserved during this operation. *)
- VIDEORAM.adr^ := 0c;
- (* Select sequencer Map Mask to enable only writing to those
- bit planes with bits corresponding to the selected palette *)
- EGAOutWord(Sequencer, SequenceMapMask, color);
- (* Now write all bits out in parallel. The sequencer map
- mask and the board latches preserve all pixels except
- that to be set. *)
- VIDEORAM.adr^ := CHR(0FFH);
- (* Normalize the enviroment, by resetting the masks and
- the data rotation redister *)
- EGAOutWord(Sequencer, SequenceMapMask, 0FH);
- EGAOutWord(Graph12, GraphDataRotate, 0);
- EGAOutWord(Graph12, GraphBitMask, 0FFH);
- END DrawPointTutorial;
-
- (*$R-*)(*$S-*)(*$T-*) (* Turn off overhead for calls to speed *)
-
- PROCEDURE DrawPoint(p : Point; color : CARDINAL);
- (* Turn on a dot at 'p', with setting color *)
- VAR
- A : Register;
- rowbyte, bitmask, byteoffset : CARDINAL;
- BEGIN
- rowbyte := p.x DIV 8; (* After a divide dx has modulus *)
- GETREG(DX, bitmask);
- bitmask := bitmasks[bitmask];
- byteoffset := CARDINAL(p.y) * BiosCRTParams.CRTCols + rowbyte
- + ActivePageOffset;
- SETREG(ES, VIDEORAM.seg); SETREG(BX, byteoffset);
- SETREG(CX, color); SETREG(AX, bitmask);
- CODE ( 88h, 0c4h, 0b0h, 08h, 0bah, 0ceh, 03h, 0efh, 0b8h, 02h,
- 0ffh, 0b2h, 0c4h, 0efh, 26h, 08ah, 2fh, 26h, 0c6h, 07h,
- 00h, 88h, 0cch, 0efh, 026h, 0c6h, 07h, 0ffh, 0b4h, 0ffh,
- 0efh, 0b2h, 0ceh, 0b8h, 03h, 00h, 0efh, 0b8h, 08h, 0ffh,
- 0efh);
- END DrawPoint;
-
- (*$R+*)(*$S+*)(*$T+*)
-
- (*--------------------------------------------------*)
- (* BIOS Interface Routines *)
- (*--------------------------------------------------*)
-
- PROCEDURE LoadBiosFont(Font : FontType; ResetFlag : BOOLEAN;
- Block : CARDINAL);
- VAR A : Register;
- BEGIN
- A.H := CHR(CharacterGeneratorFunction);
- A.L := CHR(ORD(Font));
- IF ResetFlag THEN A.L := CHR(ORD(A.L) + 011H);
- ELSE A.L := CHR(ORD(A.L) + 01H) END;
- SETREG(AX, A.X);
- SETREG(BX, Block);
- SWI(VIDEO);
- END LoadBiosFont;
-
- PROCEDURE LoadUserFont(VAR Font : ARRAY OF CHAR; ResetFlag : BOOLEAN;
- Block, Count, Points : CARDINAL);
- VAR A, B : Register;
- f : ADDRESS;
- BEGIN
- A.H := CHR(CharacterGeneratorFunction);
- IF ResetFlag THEN A.L := CHR(010H);
- ELSE A.L := CHR(00H) END;
- B.H := CHR(Points); B.L := CHR(Block);
- SETREG(CX, Count); SETREG(BX, B.X);
- SETREG(AX, A.X); CODE(PushBP); (*Save out BP *)
- SETREG(ES, f.SEGMENT); SETREG(DX, f.OFFSET);
- CODE(89h, 0d5h); (* MOV bp, dx ;Set BP to point at font *)
- SETREG(DX, 0); SWI(VIDEO);
- CODE(PopBP); (*Restore the BP *)
- END LoadUserFont;
-
- PROCEDURE GetAlternatePrintScreen;
- BEGIN
- SETREG(AX, 01200H); SETREG(BX, 0020H);
- SWI(VIDEO);
- END GetAlternatePrintScreen;
-
- PROCEDURE SetBiosPage(Page : CARDINAL);
- VAR A : Register;
- BEGIN
- A.H := CHR(SetPageBiosCall); A.L := CHR(Page);
- SETREG(AX, A.X); SWI(VIDEO);
- END SetBiosPage;
-
- PROCEDURE SetBiosPalette(Palette, Color : CARDINAL);
- VAR A, B : Register;
- BEGIN
- A.H := CHR(SetPaletteCall); A.L := 0C;
- B.H := CHR(Color); B.L := CHR(Palette);
- SETREG(BX, B.X); SETREG(AX, A.X);
- SWI(VIDEO);
- END SetBiosPalette;
-
- PROCEDURE SetModeBios(Mode : CARDINAL);
- BEGIN
- SETREG(AX, Mode);
- SWI(VIDEO);
- END SetModeBios;
-
- PROCEDURE SetBiosCursorPoint(Page : CARDINAL; p : Point);
- VAR A, B, D : Register;
- BEGIN
- A.H := CHR(SetCPos); A.L := 0C;
- A.H := CHR(Page); B.L := 0C;
- D.H := CHR(p.y); D.L := CHR(p.x);
- SETREG(DX, D.X); SETREG(BX, B.X);
- SETREG(AX, A.X); SWI(VIDEO);
- END SetBiosCursorPoint;
-
- PROCEDURE WriteBios(c : CHAR; color : CARDINAL);
- VAR A, B : Register;
- BEGIN
- A.H := CHR(WriteTTY); A.L := c;
- B.H := 0C; B.L := CHR(color);
- SETREG(BX, B.X); SETREG(AX, A.X);
- SWI(VIDEO);
- END WriteBios;
-
- PROCEDURE WriteBiosString(msg : ARRAY OF CHAR; color : CARDINAL);
- VAR i : CARDINAL;
- BEGIN
- i := 0;
- WHILE i <= HIGH(msg) DO
- WriteBios(msg[i], color);
- INC(i);
- END;
- END WriteBiosString;
-
- PROCEDURE PrintScreen;
- BEGIN
- SWI(05H);
- END PrintScreen;
-
-
- BEGIN
- VIDEORAM.seg := 0a000H; VIDEORAM.off := 0;
- bitmasks[7] := 1; bitmasks[6] := 2;
- bitmasks[5] := 4; bitmasks[4] := 8;
- bitmasks[3] := 16; bitmasks[2] := 32;
- bitmasks[1] := 64; bitmasks[0] := 128;
- MakePoint(Cursors[0], 0, 0);
- FOR i := 1 TO MaxVideoPages DO Cursors[i] := Cursors[0]; END;
- FOR i := 0 TO MaxVideoPages DO
- ActivePageOffsets[i] := i * AlphaPageSize; END;
- PelScrollColumn := 0; VerticalScrollRow := 0;
- TotalVerticalScanLines := TotalScanLinesEnhanced;
- ActivePage := 0;
- END LowEGA.