{ This file is part of the Free Pascal run time library. Copyright (c) 2010, 2011 by Nikolay Nikolov (nickysn@users.sourceforge.net) Copyright (c) 2007 by Daniel Mantione member of the Free Pascal development team This file implements the PTC support for the graph unit See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} unit ptcgraph; {//$define logging} {$define FPC_GRAPH_SUPPORTS_TRUECOLOR} {$modeswitch DEFAULTPARAMETERS+} {******************************************************************************} interface {******************************************************************************} uses ptc, ptcwrapper; {$ifdef VER2_6} type CodePointer = Pointer; {$endif} {$i graphh.inc} {Driver number for PTC.} const _PTC=22; // CGA = 1; // MCGA = 2; // EGA = 3; // EGA64 = 4; // EGAMono = 5; IBM8514 = 6; // HercMono = 7; ATT400 = 8; // VGA = 9; PC3270 = 10; LastDriverNum = 10; // CGAC0 = 0; // CGAC1 = 1; // CGAC2 = 2; // CGAC3 = 3; // CGAHi = 4; // MCGAC0 = 0; // MCGAC1 = 1; // MCGAC2 = 2; // MCGAC3 = 3; // MCGAMed = 4; // MCGAHi = 5; // EGALo = 0; // EGAHi = 1; // EGA64Lo = 0; // EGA64Hi = 1; // EGAMonoHi = 3; IBM8514Lo = 0; IBM8514Hi = 1; // HercMonoHi = 0; ATT400C0 = 0; ATT400C1 = 1; ATT400C2 = 2; ATT400C3 = 3; ATT400Med = 4; ATT400Hi = 5; // VGALo = 0; // VGAMed = 1; // VGAHi = 2; m640x200x16 = VGALo; m640x400x16 = VGAMed; m640x480x16 = VGAHi; { VESA Specific video modes. } m320x200x32k = $10D; m320x200x64k = $10E; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} m320x200x16m = $10F; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} m640x400x256 = $100; m640x480x256 = $101; m640x480x32k = $110; m640x480x64k = $111; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} m640x480x16m = $112; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} m800x600x16 = $102; m800x600x256 = $103; m800x600x32k = $113; m800x600x64k = $114; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} m800x600x16m = $115; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} m1024x768x16 = $104; m1024x768x256 = $105; m1024x768x32k = $116; m1024x768x64k = $117; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} m1024x768x16m = $118; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} m1280x1024x16 = $106; m1280x1024x256 = $107; m1280x1024x32k = $119; m1280x1024x64k = $11A; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} m1280x1024x16m = $11B; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} const FullscreenGraph: Boolean = False; var WindowTitle: AnsiString; PTCWrapperObject: TPTCWrapperThread; function InstallUserMode(Width, Height: SmallInt; Colors: LongInt; HardwarePages: SmallInt = 1; XAspect: Word = 10000; YAspect: Word = 10000): smallint; {******************************************************************************} implementation {******************************************************************************} const InternalDriverName = 'PTCPas'; FirstNonStandardModeNumber = $200; NonStandardModeNumberMaxLimit = $7FFF; var Has320x200: Boolean; Has320x240: Boolean; charmessagehandler: Pointer; { dummy, for compatibility with graph.inc, which initializes this to nil under win32 } hasVesa: Boolean = false; { dummy, for compatibility with graph.inc, which checks it in its ExitProc under go32v2 } VesaInfo: record { dummy, for compatibility with graph.inc under go32v2 } ModeList: PInteger; end; NextNonStandardModeNumber: LongInt; {$i graph.inc} type PByte = ^Byte; PLongInt = ^LongInt; PByteArray = ^TByteArray; TByteArray = array [0..MAXINT - 1] of Byte; TEGAPalette = array [0..15] of 0..63; TVGAPalette = array [0..255, 0..2] of 0..63; { --------------------------------------------------------------------- SVGA bindings. ---------------------------------------------------------------------} const DefaultEGAPalette: TEGAPalette = (0, 1, 2, 3, 4, 5, 20, 7, 56, 57, 58, 59, 60, 61, 62, 63); { default EGA palette for modes 0Dh and 0Eh } DefaultEGAPalette_200: TEGAPalette = (0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23); { default VGA palette for modes 04h, 05h, 06h, 0Dh and 0Eh } DefaultVGA16Palette_CGAEmu: TVGAPalette = ((0,0,0),(0,0,42),(0,42,0),(0,42,42),(42,0,0),(42,0,42),(42,21,0),(42,42,42), (0,0,0),(0,0,42),(0,42,0),(0,42,42),(42,0,0),(42,0,42),(42,21,0),(42,42,42), (21,21,21),(21,21,63),(21,63,21),(21,63,63),(63,21,21),(63,21,63),(63,63,21),(63,63,63), (21,21,21),(21,21,63),(21,63,21),(21,63,63),(63,21,21),(63,21,63),(63,63,21),(63,63,63), (0,0,0),(0,0,42),(0,42,0),(0,42,42),(42,0,0),(42,0,42),(42,21,0),(42,42,42), (0,0,0),(0,0,42),(0,42,0),(0,42,42),(42,0,0),(42,0,42),(42,21,0),(42,42,42), (21,21,21),(21,21,63),(21,63,21),(21,63,63),(63,21,21),(63,21,63),(63,63,21),(63,63,63), (21,21,21),(21,21,63),(21,63,21),(21,63,63),(63,21,21),(63,21,63),(63,63,21),(63,63,63), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0)); { default VGA palette for modes 00h, 01h, 02h, 03h, 10h, 11h, 12h } DefaultVGA16Palette: TVGAPalette = ((0,0,0),(0,0,42),(0,42,0),(0,42,42),(42,0,0),(42,0,42),(42,42,0),(42,42,42), (0,0,21),(0,0,63),(0,42,21),(0,42,63),(42,0,21),(42,0,63),(42,42,21),(42,42,63), (0,21,0),(0,21,42),(0,63,0),(0,63,42),(42,21,0),(42,21,42),(42,63,0),(42,63,42), (0,21,21),(0,21,63),(0,63,21),(0,63,63),(42,21,21),(42,21,63),(42,63,21),(42,63,63), (21,0,0),(21,0,42),(21,42,0),(21,42,42),(63,0,0),(63,0,42),(63,42,0),(63,42,42), (21,0,21),(21,0,63),(21,42,21),(21,42,63),(63,0,21),(63,0,63),(63,42,21),(63,42,63), (21,21,0),(21,21,42),(21,63,0),(21,63,42),(63,21,0),(63,21,42),(63,63,0),(63,63,42), (21,21,21),(21,21,63),(21,63,21),(21,63,63),(63,21,21),(63,21,63),(63,63,21),(63,63,63), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0)); { default VGA palette for mode 13h } DefaultVGA256Palette: TVGAPalette = ((0,0,0),(0,0,42),(0,42,0),(0,42,42),(42,0,0),(42,0,42),(42,21,0),(42,42,42),(21,21,21),(21,21,63),(21,63,21),(21,63,63),(63,21,21), (63,21,63),(63,63,21),(63,63,63),(0,0,0),(5,5,5),(8,8,8),(11,11,11),(14,14,14),(17,17,17),(20,20,20),(24,24,24),(28,28,28),(32,32,32), (36,36,36),(40,40,40),(45,45,45),(50,50,50),(56,56,56),(63,63,63),(0,0,63),(16,0,63),(31,0,63),(47,0,63),(63,0,63),(63,0,47),(63,0,31), (63,0,16),(63,0,0),(63,16,0),(63,31,0),(63,47,0),(63,63,0),(47,63,0),(31,63,0),(16,63,0),(0,63,0),(0,63,16),(0,63,31),(0,63,47),(0,63,63), (0,47,63),(0,31,63),(0,16,63),(31,31,63),(39,31,63),(47,31,63),(55,31,63),(63,31,63),(63,31,55),(63,31,47),(63,31,39),(63,31,31),(63,39,31), (63,47,31),(63,55,31),(63,63,31),(55,63,31),(47,63,31),(39,63,31),(31,63,31),(31,63,39),(31,63,47),(31,63,55),(31,63,63),(31,55,63),(31,47,63), (31,39,63),(45,45,63),(49,45,63),(54,45,63),(58,45,63),(63,45,63),(63,45,58),(63,45,54),(63,45,49),(63,45,45),(63,49,45),(63,54,45),(63,58,45), (63,63,45),(58,63,45),(54,63,45),(49,63,45),(45,63,45),(45,63,49),(45,63,54),(45,63,58),(45,63,63),(45,58,63),(45,54,63),(45,49,63),(0,0,28), (7,0,28),(14,0,28),(21,0,28),(28,0,28),(28,0,21),(28,0,14),(28,0,7),(28,0,0),(28,7,0),(28,14,0),(28,21,0),(28,28,0),(21,28,0),(14,28,0),(7,28,0), (0,28,0),(0,28,7),(0,28,14),(0,28,21),(0,28,28),(0,21,28),(0,14,28),(0,7,28),(14,14,28),(17,14,28),(21,14,28),(24,14,28),(28,14,28),(28,14,24), (28,14,21),(28,14,17),(28,14,14),(28,17,14),(28,21,14),(28,24,14),(28,28,14),(24,28,14),(21,28,14),(17,28,14),(14,28,14),(14,28,17),(14,28,21), (14,28,24),(14,28,28),(14,24,28),(14,21,28),(14,17,28),(20,20,28),(22,20,28),(24,20,28),(26,20,28),(28,20,28),(28,20,26),(28,20,24),(28,20,22), (28,20,20),(28,22,20),(28,24,20),(28,26,20),(28,28,20),(26,28,20),(24,28,20),(22,28,20),(20,28,20),(20,28,22),(20,28,24),(20,28,26),(20,28,28), (20,26,28),(20,24,28),(20,22,28),(0,0,16),(4,0,16),(8,0,16),(12,0,16),(16,0,16),(16,0,12),(16,0,8),(16,0,4),(16,0,0),(16,4,0),(16,8,0),(16,12,0), (16,16,0),(12,16,0),(8,16,0),(4,16,0),(0,16,0),(0,16,4),(0,16,8),(0,16,12),(0,16,16),(0,12,16),(0,8,16),(0,4,16),(8,8,16),(10,8,16),(12,8,16), (14,8,16),(16,8,16),(16,8,14),(16,8,12),(16,8,10),(16,8,8),(16,10,8),(16,12,8),(16,14,8),(16,16,8),(14,16,8),(12,16,8),(10,16,8),(8,16,8), (8,16,10),(8,16,12),(8,16,14),(8,16,16),(8,14,16),(8,12,16),(8,10,16),(11,11,16),(12,11,16),(13,11,16),(15,11,16),(16,11,16),(16,11,15), (16,11,13),(16,11,12),(16,11,11),(16,12,11),(16,13,11),(16,15,11),(16,16,11),(15,16,11),(13,16,11),(12,16,11),(11,16,11),(11,16,12),(11,16,13), (11,16,15),(11,16,16),(11,15,16),(11,13,16),(11,12,16),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0)); { Text } WRITEMODE_OVERWRITE = 0; WRITEMODE_MASKED = 1; FONT_EXPANDED = 0; FONT_COMPRESSED = 2; { Types } type pvga_modeinfo = ^vga_modeinfo; vga_modeinfo = record width, height, bytesperpixel, colors, linewidth, { scanline width in bytes } maxlogicalwidth, { maximum logical scanline width } startaddressrange, { changeable bits set } maxpixels, { video memory / bytesperpixel } haveblit, { mask of blit functions available } flags: Longint; { other flags } { Extended fields: } chiptype, { Chiptype detected } memory, { videomemory in KB } linewidth_unit: Longint; { Use only a multiple of this as parameter for set_displaystart } linear_aperture: PChar; { points to mmap secondary mem aperture of card } aperture_size: Longint; { size of aperture in KB if size>=videomemory.} set_aperture_page: procedure (page: Longint); { if aperture_size nil then PTCWrapperObject.Close; end; function VGA6to8(dac6: Uint32): Uint32; begin VGA6to8 := dac6 shl 2; end; procedure ptc_InitPalette16(UseCGAEmuPalette: Boolean); var PaletteData: PUint32; I: Integer; r, g, b: Uint32; begin if UseCGAEmuPalette then begin VGAPalette := DefaultVGA16Palette_CGAEmu; EGAPalette := DefaultEGAPalette_200; end else begin VGAPalette := DefaultVGA16Palette; EGAPalette := DefaultEGAPalette; end; EGAPaletteEnabled := True; PaletteData := ptc_palette_lock; FillChar(PaletteData^, 256*4, 0); for I := 0 to 15 do begin r := VGA6to8(VGAPalette[EGAPalette[I], 0]); g := VGA6to8(VGAPalette[EGAPalette[I], 1]); b := VGA6to8(VGAPalette[EGAPalette[I], 2]); PaletteData[I] := (r shl 16) or (g shl 8) or b; end; ptc_palette_unlock; end; procedure ptc_InitPalette256; var PaletteData: PUint32; I: Integer; r, g, b: Uint32; begin EGAPaletteEnabled := False; VGAPalette := DefaultVGA256Palette; PaletteData := ptc_palette_lock; for I := 0 to 255 do begin r := VGA6to8(VGAPalette[I, 0]); g := VGA6to8(VGAPalette[I, 1]); b := VGA6to8(VGAPalette[I, 2]); PaletteData[I] := (r shl 16) or (g shl 8) or b; end; ptc_palette_unlock; end; procedure ptc_SetEGAPalette(ColorNum, Color: Integer); var PaletteData: PUint32; r, g, b: Uint32; begin if EGAPalette[ColorNum] <> Color then begin if (VGAPalette[EGAPalette[ColorNum], 0] <> VGAPalette[Color, 0]) or (VGAPalette[EGAPalette[ColorNum], 1] <> VGAPalette[Color, 1]) or (VGAPalette[EGAPalette[ColorNum], 2] <> VGAPalette[Color, 2]) then begin EGAPalette[ColorNum] := Color; r := VGA6to8(VGAPalette[Color, 0]); g := VGA6to8(VGAPalette[Color, 1]); b := VGA6to8(VGAPalette[Color, 2]); PaletteData := ptc_palette_lock; PaletteData[ColorNum] := (r shl 16) or (g shl 8) or b; ptc_palette_unlock; end else EGAPalette[ColorNum] := Color; end; end; procedure ptc_SetVGAPalette(ColorNum, ARed, AGreen, ABlue: Integer); var PaletteData: PUint32; I: Integer; begin if (VGAPalette[ColorNum, 0] <> ARed) or (VGAPalette[ColorNum, 1] <> AGreen) or (VGAPalette[ColorNum, 2] <> ABlue) then begin VGAPalette[ColorNum, 0] := ARed; VGAPalette[ColorNum, 1] := AGreen; VGAPalette[ColorNum, 2] := ABlue; if EGAPaletteEnabled then begin for I := 0 to 15 do if EGAPalette[I] = ColorNum then begin PaletteData := ptc_palette_lock; PaletteData[I] := (VGA6to8(ARed) shl 16) or (VGA6to8(AGreen) shl 8) or VGA6to8(ABlue); ptc_palette_unlock; end; end else begin PaletteData := ptc_palette_lock; PaletteData[ColorNum] := (VGA6to8(ARed) shl 16) or (VGA6to8(AGreen) shl 8) or VGA6to8(ABlue); ptc_palette_unlock; end; end; end; procedure ptc_InitPaletteCGA(CGAPalette: Integer); var PaletteData: PUint32; I: Integer; r, g, b: Uint32; begin VGAPalette := DefaultVGA16Palette_CGAEmu; FillChar(EGAPalette, SizeOf(EGAPalette), 0); EGAPaletteEnabled := True; case CGAPalette of 0: begin EGAPalette[1] := $12; EGAPalette[2] := $14; EGAPalette[3] := $16; end; 1: begin EGAPalette[1] := $13; EGAPalette[2] := $15; EGAPalette[3] := $17; end; 2: begin EGAPalette[1] := $02; EGAPalette[2] := $04; EGAPalette[3] := $06; end; 3: begin EGAPalette[1] := $03; EGAPalette[2] := $05; EGAPalette[3] := $07; end; end; PaletteData := ptc_palette_lock; FillChar(PaletteData^, 256*4, 0); for I := 0 to 3 do begin r := VGA6to8(VGAPalette[EGAPalette[I], 0]); g := VGA6to8(VGAPalette[EGAPalette[I], 1]); b := VGA6to8(VGAPalette[EGAPalette[I], 2]); PaletteData[I] := (r shl 16) or (g shl 8) or b; end; ptc_palette_unlock; CurrentCGABkColor := 0; end; procedure ptc_InitPaletteCGA2; var PaletteData: PUint32; I: Integer; r, g, b: Uint32; begin VGAPalette := DefaultVGA16Palette_CGAEmu; FillChar(EGAPalette, SizeOf(EGAPalette), 0); EGAPaletteEnabled := True; for I := 1 to 15 do EGAPalette[I] := 63; PaletteData := ptc_palette_lock; FillChar(PaletteData^, 256*4, 0); for I := 0 to 1 do begin r := VGA6to8(VGAPalette[EGAPalette[I], 0]); g := VGA6to8(VGAPalette[EGAPalette[I], 1]); b := VGA6to8(VGAPalette[EGAPalette[I], 2]); PaletteData[I] := (r shl 16) or (g shl 8) or b; end; ptc_palette_unlock; CurrentCGABkColor := 0; end; procedure ptc_InitPaletteMCGA2; var PaletteData: PUint32; I: Integer; r, g, b: Uint32; begin VGAPalette := DefaultVGA16Palette; FillChar(EGAPalette, SizeOf(EGAPalette), 0); EGAPaletteEnabled := True; for I := 1 to 15 do EGAPalette[I] := 63; PaletteData := ptc_palette_lock; FillChar(PaletteData^, 256*4, 0); for I := 0 to 1 do begin r := VGA6to8(VGAPalette[EGAPalette[I], 0]); g := VGA6to8(VGAPalette[EGAPalette[I], 1]); b := VGA6to8(VGAPalette[EGAPalette[I], 2]); PaletteData[I] := (r shl 16) or (g shl 8) or b; end; ptc_palette_unlock; CurrentCGABkColor := 0; end; procedure ptc_InternalOpen(const ATitle: string; AWidth, AHeight: Integer; AFormat: IPTCFormat; AVirtualPages: Integer); var ConsoleWidth, ConsoleHeight: Integer; begin ConsoleWidth := AWidth; ConsoleHeight := AHeight; if Double320x200 and (AWidth = 320) and (AHeight = 200) then begin ConsoleWidth := 640; ConsoleHeight := 400; end; if Double320x240 and (AWidth = 320) and (AHeight = 240) then begin ConsoleWidth := 640; ConsoleHeight := 480; end; if Double640x200 and (AWidth = 640) and (AHeight = 200) then begin ConsoleWidth := 640; ConsoleHeight := 400; end; if FullscreenGraph then PTCWrapperObject.Option('fullscreen output') else PTCWrapperObject.Option('windowed output'); PTCWrapperObject.Open(ATitle, AWidth, AHeight, ConsoleWidth, ConsoleHeight, AFormat, AVirtualPages, 0); end; procedure ptc_InternalInitMode16(XResolution, YResolution, Pages: LongInt; UseCGAEmuPalette: Boolean); begin {$IFDEF logging} LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 16 colours'); {$ENDIF logging} { open the console } ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, Pages); PTCWidth := XResolution; PTCHeight := YResolution; CurrentActivePage := 0; { create palette } ptc_InitPalette16(UseCGAEmuPalette); ColorMask := 15; end; procedure ptc_InitMode16(XResolution, YResolution, Pages: LongInt); begin ptc_InternalInitMode16(XResolution, YResolution, Pages, False); end; procedure ptc_InitMode16_CGAEmu(XResolution, YResolution, Pages: LongInt); begin ptc_InternalInitMode16(XResolution, YResolution, Pages, True); end; procedure ptc_InitMode256(XResolution, YResolution, Pages: LongInt); begin {$IFDEF logging} LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 256 colours'); {$ENDIF logging} { open the console } ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, Pages); PTCWidth := XResolution; PTCHeight := YResolution; CurrentActivePage := 0; { create palette } ptc_InitPalette256; ColorMask := 255; end; procedure ptc_InitModeCGA4(XResolution, YResolution, CGAPalette: LongInt); begin {$IFDEF logging} LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 4 colours, palette ' + strf(CGAPalette)); {$ENDIF logging} { open the console } ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, 1); PTCWidth := XResolution; PTCHeight := YResolution; CurrentActivePage := 0; { create palette } ptc_InitPaletteCGA(CGAPalette); ColorMask := 3; end; procedure ptc_InitModeCGA2(XResolution, YResolution, Pages: LongInt); begin {$IFDEF logging} LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 2 colours'); {$ENDIF logging} { open the console } ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, Pages); PTCWidth := XResolution; PTCHeight := YResolution; CurrentActivePage := 0; { create palette } ptc_InitPaletteCGA2; ColorMask := 1; end; procedure ptc_InitModeMCGA2(XResolution, YResolution, Pages: LongInt); begin {$IFDEF logging} LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 2 colours'); {$ENDIF logging} { open the console } ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, Pages); PTCWidth := XResolution; PTCHeight := YResolution; CurrentActivePage := 0; { create palette } ptc_InitPaletteMCGA2; ColorMask := 1; end; procedure ptc_InitMode32k(XResolution, YResolution, Pages: LongInt); begin {$IFDEF logging} LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 32768 colours'); {$ENDIF logging} { open the console } ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat15, Pages); PTCWidth := XResolution; PTCHeight := YResolution; CurrentActivePage := 0; ColorMask := 32767; end; procedure ptc_InitMode64k(XResolution, YResolution, Pages: LongInt); begin {$IFDEF logging} LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 65536 colours'); {$ENDIF logging} { open the console } ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat16, Pages); PTCWidth := XResolution; PTCHeight := YResolution; CurrentActivePage := 0; ColorMask := 65535; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_InitMode32bpp(XResolution, YResolution, Pages: LongInt); begin {$IFDEF logging} LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 16777216 colours (32bpp)'); {$ENDIF logging} { open the console } ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat32, Pages); PTCWidth := XResolution; PTCHeight := YResolution; CurrentActivePage := 0; ColorMask := 16777215; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_Init640x200x16; begin ptc_InitMode16_CGAEmu(640, 200, 4); end; procedure ptc_Init640x350x16; begin ptc_InitMode16(640, 350, 2); end; procedure ptc_Init640x480x16; begin ptc_InitMode16(640, 480, 1); end; procedure ptc_Init800x600x16; begin ptc_InitMode16(800, 600, 2); end; procedure ptc_Init1024x768x16; begin ptc_InitMode16(1024, 768, 2); end; procedure ptc_Init1280x1024x16; begin ptc_InitMode16(1280, 1024, 2); end; procedure ptc_Init320x200x4cgaC0; begin ptc_InitModeCGA4(320, 200, 0); end; procedure ptc_Init320x200x4cgaC1; begin ptc_InitModeCGA4(320, 200, 1); end; procedure ptc_Init320x200x4cgaC2; begin ptc_InitModeCGA4(320, 200, 2); end; procedure ptc_Init320x200x4cgaC3; begin ptc_InitModeCGA4(320, 200, 3); end; procedure ptc_Init640x200x2; begin ptc_InitModeCGA2(640, 200, 1); end; procedure ptc_Init640x480x2; begin ptc_InitModeMCGA2(640, 480, 1); end; procedure ptc_Init720x348x2; begin DummyHGCBkColor := 0; ptc_InitModeCGA2(720, 348, 2); end; procedure ptc_Init320x200x256; begin ptc_InitMode256(320, 200, 4); end; procedure ptc_Init640x400x256; begin ptc_InitMode256(640, 400, 2); end; procedure ptc_Init640x480x256; begin ptc_InitMode256(640, 480, 2); end; procedure ptc_Init800x600x256; begin ptc_InitMode256(800, 600, 2); end; procedure ptc_Init1024x768x256; begin ptc_InitMode256(1024, 768, 2); end; procedure ptc_Init1280x1024x256; begin ptc_InitMode256(1280, 1024, 2); end; procedure ptc_Init320x200x32k; begin ptc_InitMode32k(320, 200, 2); end; procedure ptc_Init640x480x32k; begin ptc_InitMode32k(640, 480, 2); end; procedure ptc_Init800x600x32k; begin ptc_InitMode32k(800, 600, 2); end; procedure ptc_Init1024x768x32k; begin ptc_InitMode32k(1024, 768, 2); end; procedure ptc_Init1280x1024x32k; begin ptc_InitMode32k(1280, 1024, 2); end; procedure ptc_Init320x200x64k; begin ptc_InitMode64k(320, 200, 2); end; procedure ptc_Init640x480x64k; begin ptc_InitMode64k(640, 480, 2); end; procedure ptc_Init800x600x64k; begin ptc_InitMode64k(800, 600, 2); end; procedure ptc_Init1024x768x64k; begin ptc_InitMode64k(1024, 768, 2); end; procedure ptc_Init1280x1024x64k; begin ptc_InitMode64k(1280, 1024, 2); end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_Init320x200x32bpp; begin ptc_InitMode32bpp(320, 200, 2); end; procedure ptc_Init640x480x32bpp; begin ptc_InitMode32bpp(640, 480, 2); end; procedure ptc_Init800x600x32bpp; begin ptc_InitMode32bpp(800, 600, 2); end; procedure ptc_Init1024x768x32bpp; begin ptc_InitMode32bpp(1024, 768, 2); end; procedure ptc_Init1280x1024x32bpp; begin ptc_InitMode32bpp(1280, 1024, 2); end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_InitNonStandard16; begin ptc_InitMode16(MaxX + 1, MaxY + 1, 2); end; procedure ptc_InitNonStandard256; begin ptc_InitMode256(MaxX + 1, MaxY + 1, 2); end; procedure ptc_InitNonStandard32k; begin ptc_InitMode32k(MaxX + 1, MaxY + 1, 2); end; procedure ptc_InitNonStandard64k; begin ptc_InitMode64k(MaxX + 1, MaxY + 1, 2); end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_InitNonStandard32bpp; begin ptc_InitMode32bpp(MaxX + 1, MaxY + 1, 2); end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_SetVisualPage(page: word); begin if page > HardwarePages then exit; PTCWrapperObject.SetVisualPage(page); end; procedure ptc_SetActivePage(page: word); begin if page > HardwarePages then exit; CurrentActivePage := page; end; { compatible with TP7's HERC.BGI } procedure SetBkColorHGC720(ColorNum: ColorType); begin if ColorNum > 15 then exit; DummyHGCBkColor := ColorNum; end; { compatible with TP7's HERC.BGI } function GetBkColorHGC720: ColorType; begin GetBkColorHGC720 := DummyHGCBkColor; end; procedure SetBkColorCGA320(ColorNum: ColorType); begin if ColorNum > 15 then exit; CurrentCGABkColor := ColorNum; ptc_SetEGAPalette(0, ((ColorNum shl 1) and $10) or (ColorNum and $07)); end; function GetBkColorCGA320: ColorType; begin GetBkColorCGA320 := CurrentCGABkColor; end; {yes, TP7 CGA.BGI behaves *exactly* like that} procedure SetBkColorCGA640(ColorNum: ColorType); begin if ColorNum > 15 then exit; CurrentCGABkColor := ColorNum; if ColorNum = 0 then exit; ptc_SetEGAPalette(1, ((ColorNum shl 1) and $10) or (ColorNum and $07)); end; function GetBkColorCGA640: ColorType; begin GetBkColorCGA640 := CurrentCGABkColor; end; { nickysn: VGA compatible implementation. I don't have a real MCGA to test if there's any difference with VGA } procedure SetBkColorMCGA640(ColorNum: ColorType); begin if ColorNum > 15 then exit; CurrentCGABkColor := ColorNum; ptc_SetEGAPalette(0, ((ColorNum shl 1) and $10) or (ColorNum and $07)); end; function GetBkColorMCGA640: ColorType; begin GetBkColorMCGA640 := CurrentCGABkColor; end; Function ClipCoords (Var X,Y : smallint) : Boolean; { Adapt to viewport, return TRUE if still in viewport, false if outside viewport} begin X:= X + StartXViewPort; Y:= Y + StartYViewPort; ClipCoords:=Not ClipPixels; if ClipPixels then Begin ClipCoords:=(X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)); ClipCoords:=ClipCoords or ((Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight))); ClipCoords:=Not ClipCoords; end; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_DirectPixelProc_32bpp(X,Y: smallint); var pixels:Plongword; begin // Writeln('ptc_DirectPixelProc_32bpp(', X, ', ', Y, ')'); pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] xor CurrentColor; end; OrPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] or CurrentColor; end; AndPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] and CurrentColor; end; NotPut: begin pixels[x+y*PTCWidth] := CurrentColor xor $FFFFFF; end else pixels[x+y*PTCWidth] := CurrentColor; end; ptc_surface_unlock; ptc_update; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_DirectPixelProc_16bpp(X,Y: smallint); var pixels:Pword; begin // Writeln('ptc_DirectPixelProc_16bpp(', X, ', ', Y, ')'); pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] xor CurrentColor; end; OrPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] or CurrentColor; end; AndPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] and CurrentColor; end; NotPut: begin pixels[x+y*PTCWidth] := CurrentColor xor $FFFF; end else pixels[x+y*PTCWidth] := CurrentColor; end; ptc_surface_unlock; ptc_update; end; procedure ptc_DirectPixelProc_8bpp(X,Y: smallint); var pixels:PByte; begin // Writeln('ptc_DirectPixelProc_8bpp(', X, ', ', Y, ')'); pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] xor (CurrentColor and ColorMask); end; OrPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] or (CurrentColor and ColorMask); end; AndPut: begin pixels[x+y*PTCWidth] := pixels[x+y*PTCWidth] and (CurrentColor and ColorMask); end; NotPut: begin pixels[x+y*PTCWidth] := CurrentColor xor ColorMask; end else pixels[x+y*PTCWidth] := CurrentColor and ColorMask; end; ptc_surface_unlock; ptc_update; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_putpixelproc_32bpp(X,Y:smallint;Color:ColorType); var pixels:Plongword; begin // Writeln('ptc_putpixelproc_32bpp(', X, ', ', Y, ', ', Color, ')'); if clipcoords(X,Y) then begin pixels := ptc_surface_lock; {Plot the pixel on the surface.} pixels[x+y*PTCWidth] := color; ptc_surface_unlock; ptc_update; end; end; function ptc_getpixelproc_32bpp(X,Y: smallint):ColorType; var pixels:Plongword; begin if clipcoords(X,Y) then begin pixels := ptc_surface_lock; {Get the pixel from the surface.} ptc_getpixelproc_32bpp:=pixels[x+y*PTCWidth]; ptc_surface_unlock; end; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_putpixelproc_16bpp(X,Y:smallint;Color:ColorType); var pixels:Pword; begin // Writeln('ptc_putpixelproc_16bpp(', X, ', ', Y, ', ', Color, ')'); if clipcoords(X,Y) then begin pixels := ptc_surface_lock; {Plot the pixel on the surface.} pixels[x+y*PTCWidth] := color; ptc_surface_unlock; ptc_update; end; end; function ptc_getpixelproc_16bpp(X,Y: smallint):ColorType; var pixels:Pword; begin if clipcoords(X,Y) then begin pixels := ptc_surface_lock; {Get the pixel from the surface.} ptc_getpixelproc_16bpp:=pixels[x+y*PTCWidth]; ptc_surface_unlock; end; end; procedure ptc_PutPixelProc_8bpp(X,Y:smallint;Color:ColorType); var pixels:PByte; begin // Writeln('ptc_PutPixelProc_8bpp(', X, ', ', Y, ', ', Color, ')'); if clipcoords(X,Y) then begin pixels := ptc_surface_lock; {Plot the pixel on the surface.} pixels[x+y*PTCWidth]:=color and ColorMask; ptc_surface_unlock; ptc_update; end; end; function ptc_GetPixelProc_8bpp(X,Y: smallint):ColorType; var pixels:PByte; begin if clipcoords(X,Y) then begin pixels := ptc_surface_lock; {Get the pixel from the surface.} ptc_GetPixelProc_8bpp:=pixels[x+y*PTCWidth] and ColorMask; ptc_surface_unlock; ptc_update; end; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_HLineProc_32bpp(x, x2,y : smallint); var pixels:Plongword; i:word; xtmp: smallint; begin // Writeln('ptc_HLineProc_32bpp(', x, ', ', x2, ', ', y, ')'); { must we swap the values? } if x >= x2 then begin xtmp := x2; x2 := x; x:= xtmp; end; inc(x,StartXViewPort); inc(x2,StartXViewPort); inc(y,StartYViewPort); if ClipPixels then begin if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; end; pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] xor CurrentColor; end; OrPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] or CurrentColor; end; AndPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] and CurrentColor; end; NotPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := CurrentColor xor $FFFFFF; end else for i:=x to x2 do pixels[i+y*PTCWidth] := CurrentColor; end; ptc_surface_unlock; ptc_update; end; procedure ptc_VLineProc_32bpp(x,y,y2 : smallint); var pixels:PLongWord; i:word; ytmp: smallint; begin if y >= y2 then begin ytmp := y2; y2 := y; y:= ytmp; end; inc(x,StartXViewPort); inc(y,StartYViewPort); inc(y2,StartYViewPort); if ClipPixels then begin if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; end; pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] xor CurrentColor; end; OrPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] or CurrentColor; end; AndPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] and CurrentColor; end; NotPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := CurrentColor xor $FFFFFF; end else for i:=y to y2 do pixels[x+i*PTCWidth] := CurrentColor; end; ptc_surface_unlock; ptc_update; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_HLineProc_16bpp(x, x2,y : smallint); var pixels:Pword; i:word; xtmp: smallint; begin // Writeln('ptc_HLineProc_16bpp(', x, ', ', x2, ', ', y, ')'); { must we swap the values? } if x >= x2 then begin xtmp := x2; x2 := x; x:= xtmp; end; inc(x,StartXViewPort); inc(x2,StartXViewPort); inc(y,StartYViewPort); if ClipPixels then begin if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; end; pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] xor CurrentColor; end; OrPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] or CurrentColor; end; AndPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] and CurrentColor; end; NotPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := CurrentColor xor $FFFF; end else for i:=x to x2 do pixels[i+y*PTCWidth] := CurrentColor; end; ptc_surface_unlock; ptc_update; end; procedure ptc_VLineProc_16bpp(x,y,y2 : smallint); var pixels:PWord; i:word; ytmp: smallint; begin if y >= y2 then begin ytmp := y2; y2 := y; y:= ytmp; end; inc(x,StartXViewPort); inc(y,StartYViewPort); inc(y2,StartYViewPort); if ClipPixels then begin if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; end; pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] xor CurrentColor; end; OrPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] or CurrentColor; end; AndPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] and CurrentColor; end; NotPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := CurrentColor xor $FFFF; end else for i:=y to y2 do pixels[x+i*PTCWidth] := CurrentColor; end; ptc_surface_unlock; ptc_update; end; procedure ptc_HLineProc_8bpp(x, x2,y : smallint); var pixels:PByte; i:word; xtmp: smallint; begin // Writeln('ptc_HLineProc_8bpp(', x, ', ', x2, ', ', y, ')'); { must we swap the values? } if x >= x2 then begin xtmp := x2; x2 := x; x:= xtmp; end; inc(x,StartXViewPort); inc(x2,StartXViewPort); inc(y,StartYViewPort); if ClipPixels then begin if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; end; pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] xor (CurrentColor and ColorMask); end; OrPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] or (CurrentColor and ColorMask); end; AndPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := pixels[i+y*PTCWidth] and (CurrentColor and ColorMask); end; NotPut: begin for i:=x to x2 do pixels[i+y*PTCWidth] := (CurrentColor and ColorMask) xor ColorMask; end else for i:=x to x2 do pixels[i+y*PTCWidth] := CurrentColor and ColorMask; end; ptc_surface_unlock; ptc_update; end; procedure ptc_VLineProc_8bpp(x,y,y2 : smallint); var pixels:PByte; i:word; ytmp: smallint; begin // Writeln('ptc_VLineProc_8bpp(', x, ', ', y, ', ', y2, ')'); { must we swap the values? } if y >= y2 then Begin ytmp := y2; y2 := y; y:= ytmp; end; inc(x,StartXViewPort); inc(y,StartYViewPort); inc(y2,StartYViewPort); if ClipPixels then begin if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; end; pixels := ptc_surface_lock; case CurrentWriteMode of XORPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] xor (CurrentColor and ColorMask); end; OrPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] or (CurrentColor and ColorMask); end; AndPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := pixels[x+i*PTCWidth] and (CurrentColor and ColorMask); end; NotPut: begin for i:=y to y2 do pixels[x+i*PTCWidth] := (CurrentColor and ColorMask) xor ColorMask; end else for i:=y to y2 do pixels[x+i*PTCWidth] := CurrentColor and ColorMask; end; ptc_surface_unlock; ptc_update; end; procedure ptc_PatternLineProc_8bpp(x1,x2,y: smallint); {********************************************************} { Draws a horizontal patterned line according to the } { current Fill Settings. } {********************************************************} { Important notes: } { - CurrentColor must be set correctly before entering } { this routine. } {********************************************************} var pixels: PByte; NrIterations: smallint; i : smallint; j : smallint; TmpFillPattern : byte; begin { convert to global coordinates ... } x1 := x1 + StartXViewPort; x2 := x2 + StartXViewPort; y := y + StartYViewPort; { if line was fully clipped then exit...} if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; { Get the current pattern } TmpFillPattern := FillPatternTable [FillSettings.Pattern][(y and $7)+1]; pixels := ptc_surface_lock; { number of times to go throuh the 8x8 pattern } NrIterations := abs(x2 - x1+8) div 8; for i := 0 to NrIterations do for j := 0 to 7 do begin { x1 mod 8 } if RevBitArray[x1 and 7] and TmpFillPattern <> 0 then pixels[x1+y*PTCWidth] := FillSettings.Color and ColorMask else pixels[x1+y*PTCWidth] := CurrentBkColor and ColorMask; Inc(x1); if x1 > x2 then begin ptc_surface_unlock; ptc_update; exit; end; end; ptc_surface_unlock; ptc_update; end; procedure ptc_PatternLineProc_16bpp(x1,x2,y: smallint); {********************************************************} { Draws a horizontal patterned line according to the } { current Fill Settings. } {********************************************************} { Important notes: } { - CurrentColor must be set correctly before entering } { this routine. } {********************************************************} var pixels: PWord; NrIterations: smallint; i : smallint; j : smallint; TmpFillPattern : byte; begin { convert to global coordinates ... } x1 := x1 + StartXViewPort; x2 := x2 + StartXViewPort; y := y + StartYViewPort; { if line was fully clipped then exit...} if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; { Get the current pattern } TmpFillPattern := FillPatternTable [FillSettings.Pattern][(y and $7)+1]; pixels := ptc_surface_lock; { number of times to go throuh the 8x8 pattern } NrIterations := abs(x2 - x1+8) div 8; for i := 0 to NrIterations do for j := 0 to 7 do begin { x1 mod 8 } if RevBitArray[x1 and 7] and TmpFillPattern <> 0 then pixels[x1+y*PTCWidth] := FillSettings.Color else pixels[x1+y*PTCWidth] := CurrentBkColor; Inc(x1); if x1 > x2 then begin ptc_surface_unlock; ptc_update; exit; end; end; ptc_surface_unlock; ptc_update; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_PatternLineProc_32bpp(x1,x2,y: smallint); {********************************************************} { Draws a horizontal patterned line according to the } { current Fill Settings. } {********************************************************} { Important notes: } { - CurrentColor must be set correctly before entering } { this routine. } {********************************************************} var pixels: PLongWord; NrIterations: smallint; i : smallint; j : smallint; TmpFillPattern : byte; begin { convert to global coordinates ... } x1 := x1 + StartXViewPort; x2 := x2 + StartXViewPort; y := y + StartYViewPort; { if line was fully clipped then exit...} if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort, StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then exit; { Get the current pattern } TmpFillPattern := FillPatternTable [FillSettings.Pattern][(y and $7)+1]; pixels := ptc_surface_lock; { number of times to go throuh the 8x8 pattern } NrIterations := abs(x2 - x1+8) div 8; for i := 0 to NrIterations do for j := 0 to 7 do begin { x1 mod 8 } if RevBitArray[x1 and 7] and TmpFillPattern <> 0 then pixels[x1+y*PTCWidth] := FillSettings.Color else pixels[x1+y*PTCWidth] := CurrentBkColor; Inc(x1); if x1 > x2 then begin ptc_surface_unlock; ptc_update; exit; end; end; ptc_surface_unlock; ptc_update; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure ptc_SetRGBAllPaletteProc(const Palette: PaletteType); begin {...} end; procedure ptc_setrgbpaletteproc(ColorNum, RedValue, GreenValue, BlueValue: smallint); begin { NOTE: this makes the function compatible to the go32v2 graph implementation, but *not* with TP7 } if EGAPaletteEnabled then ColorNum := DefaultEGAPalette[ColorNum and 15]; ptc_SetVGAPalette(ColorNum,RedValue shr 2,GreenValue shr 2,BlueValue shr 2); end; procedure ptc_getrgbpaletteproc (ColorNum: smallint; var RedValue, GreenValue, BlueValue: smallint); begin { NOTE: this makes the function compatible to the go32v2 graph implementation, but *not* with TP7 } if EGAPaletteEnabled then ColorNum := DefaultEGAPalette[ColorNum and 15]; RedValue := VGAPalette[ColorNum, 0] shl 2; GreenValue := VGAPalette[ColorNum, 1] shl 2; BlueValue := VGAPalette[ColorNum, 2] shl 2; end; {**********************************************************} { Procedure PutImage() } {----------------------------------------------------------} { Displays the image contained in a bitmap starting at X,Y } { the first 2 bytes of the bitmap structure define the } { width and height of the bitmap } { note: This optomized version does not use PutPixel } { Which would be checking the viewport for every pixel } { Instead it just does it's own viewport check once then } { puts all the pixels within the veiwport without further} { checking. Also instead of checking BitBlt every pixel } { it is only checked once before all the pixels are } { displayed at once (JMR) } {**********************************************************} Procedure ptc_PutImageproc_8bpp(X,Y: smallint; var Bitmap; BitBlt: Word); type pt = array[0..{$ifdef cpu16}16382{$else}$fffffff{$endif}] of word; ptw = array[0..2] of longint; var pixels:Pbyte; k: longint; i, j, y1, x1, deltaX, deltaX1, deltaY: smallint; JxW, I_JxW: Longword; Begin inc(x,startXViewPort); inc(y,startYViewPort); { width/height are 1-based, coordinates are zero based } x1 := ptw(Bitmap)[0]+x-1; { get width and adjust end coordinate accordingly } y1 := ptw(Bitmap)[1]+y-1; { get height and adjust end coordinate accordingly } deltaY := 0; deltaX := 0; deltaX1 := 0; k := 3 * sizeOf(Longint) div sizeOf(Word); { Three reserved longs at start of bitmap } { check which part of the image is in the viewport } if clipPixels then begin if y < startYViewPort then begin deltaY := startYViewPort - y; inc(k,(x1-x+1)*deltaY); y := startYViewPort; end; if y1 > startYViewPort+viewHeight then y1 := startYViewPort+viewHeight; if x < startXViewPort then begin deltaX := startXViewPort-x; x := startXViewPort; end; if x1 > startXViewPort + viewWidth then begin deltaX1 := x1 - (startXViewPort + viewWidth); x1 := startXViewPort + viewWidth; end; end; pixels := ptc_surface_lock; case BitBlt of XORPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] xor (pt(bitmap)[k] and ColorMask); inc(k); end; inc(k,deltaX1); End; End; ORPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] or (pt(bitmap)[k] and ColorMask); inc(k); end; inc(k,deltaX1); End; End; AndPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] and (pt(bitmap)[k] and ColorMask); inc(k); end; inc(k,deltaX1); End; End; NotPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin pixels[i+JxW] := (pt(bitmap)[k] and ColorMask) xor ColorMask; inc(k); end; inc(k,deltaX1); End; End; Else Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin pixels[i+JxW] := pt(bitmap)[k] and ColorMask; inc(k); end; inc(k,deltaX1); End; End; End; {case} ptc_surface_unlock; ptc_update; end; Procedure ptc_PutImageproc_16bpp(X,Y: smallint; var Bitmap; BitBlt: Word); type pt = array[0..{$ifdef cpu16}16382{$else}$fffffff{$endif}] of word; ptw = array[0..2] of longint; var pixels:Pword; k: longint; i, j, y1, x1, deltaX, deltaX1, deltaY: smallint; JxW, I_JxW: Longword; Begin inc(x,startXViewPort); inc(y,startYViewPort); { width/height are 1-based, coordinates are zero based } x1 := ptw(Bitmap)[0]+x-1; { get width and adjust end coordinate accordingly } y1 := ptw(Bitmap)[1]+y-1; { get height and adjust end coordinate accordingly } deltaY := 0; deltaX := 0; deltaX1 := 0; k := 3 * sizeOf(Longint) div sizeOf(Word); { Three reserved longs at start of bitmap } { check which part of the image is in the viewport } if clipPixels then begin if y < startYViewPort then begin deltaY := startYViewPort - y; inc(k,(x1-x+1)*deltaY); y := startYViewPort; end; if y1 > startYViewPort+viewHeight then y1 := startYViewPort+viewHeight; if x < startXViewPort then begin deltaX := startXViewPort-x; x := startXViewPort; end; if x1 > startXViewPort + viewWidth then begin deltaX1 := x1 - (startXViewPort + viewWidth); x1 := startXViewPort + viewWidth; end; end; pixels := ptc_surface_lock; case BitBlt of XORPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] xor pt(bitmap)[k]; inc(k); end; inc(k,deltaX1); End; End; ORPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] or pt(bitmap)[k]; inc(k); end; inc(k,deltaX1); End; End; AndPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] and pt(bitmap)[k]; inc(k); end; inc(k,deltaX1); End; End; NotPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin pixels[i+JxW] := pt(bitmap)[k] xor $FFFF; inc(k); end; inc(k,deltaX1); End; End; Else Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin pixels[i+JxW] := pt(bitmap)[k]; inc(k); end; inc(k,deltaX1); End; End; End; {case} ptc_surface_unlock; ptc_update; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} Procedure ptc_PutImageproc_32bpp(X,Y: smallint; var Bitmap; BitBlt: Word); type pt = array[0..{$ifdef cpu16}16382{$else}$fffffff{$endif}] of longword; ptw = array[0..2] of longint; var pixels:Plongword; k: longint; i, j, y1, x1, deltaX, deltaX1, deltaY: smallint; JxW, I_JxW: Longword; Begin inc(x,startXViewPort); inc(y,startYViewPort); { width/height are 1-based, coordinates are zero based } x1 := ptw(Bitmap)[0]+x-1; { get width and adjust end coordinate accordingly } y1 := ptw(Bitmap)[1]+y-1; { get height and adjust end coordinate accordingly } deltaY := 0; deltaX := 0; deltaX1 := 0; k := 3 * sizeOf(Longint) div sizeOf(LongWord); { Three reserved longs at start of bitmap } { check which part of the image is in the viewport } if clipPixels then begin if y < startYViewPort then begin deltaY := startYViewPort - y; inc(k,(x1-x+1)*deltaY); y := startYViewPort; end; if y1 > startYViewPort+viewHeight then y1 := startYViewPort+viewHeight; if x < startXViewPort then begin deltaX := startXViewPort-x; x := startXViewPort; end; if x1 > startXViewPort + viewWidth then begin deltaX1 := x1 - (startXViewPort + viewWidth); x1 := startXViewPort + viewWidth; end; end; pixels := ptc_surface_lock; case BitBlt of XORPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] xor pt(bitmap)[k]; inc(k); end; inc(k,deltaX1); End; End; ORPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] or pt(bitmap)[k]; inc(k); end; inc(k,deltaX1); End; End; AndPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin I_JxW:=i+JxW; pixels[I_JxW] := pixels[I_JxW] and pt(bitmap)[k]; inc(k); end; inc(k,deltaX1); End; End; NotPut: Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin pixels[i+JxW] := pt(bitmap)[k] xor $FFFFFF; inc(k); end; inc(k,deltaX1); End; End; Else Begin for j:=Y to Y1 do Begin JxW:=j*PTCWidth; inc(k,deltaX); for i:=X to X1 do begin pixels[i+JxW] := pt(bitmap)[k]; inc(k); end; inc(k,deltaX1); End; End; End; {case} ptc_surface_unlock; ptc_update; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} {**********************************************************} { Procedure GetScanLine() } {----------------------------------------------------------} { Returns the full scanline of the video line of the Y } { coordinate. The values are returned in a WORD array } { each WORD representing a pixel of the specified scanline } { note: we only need the pixels inside the ViewPort! (JM) } { note2: extended so you can specify start and end X coord } { so it is usable for GetImage too (JM) } { note3: This optomized version does not use GetPixel, } { Whcih would be checking the viewport for every pixel. } { Instead it just does it's own viewport check once then } { gets all the pixels on the scan line without further } { checking (JMR) } {**********************************************************} Procedure PTC_GetScanlineProc_8bpp (X1, X2, Y : smallint; Var Data); Var pixels : Pbyte; x,vpx1,vpx2 : smallint; Begin vpx1:=X1+StartXViewPort; vpx2:=X2+StartXViewPort; Y:=Y+StartYViewPort; { constrain to the part of the scanline that is in the viewport } if clipPixels then begin if vpx1 < startXViewPort then vpx1 := startXViewPort; if vpx2 > startXViewPort + viewWidth then vpx2 := startXViewPort + viewWidth; end; { constrain to the part of the scanline that is on the screen } if vpx1 < 0 then vpx1 := 0; if vpx2 >= PTCwidth then vpx2 := PTCwidth-1; If (ClipPixels AND (y <= startYViewPort+viewHeight) and (y >= startYViewPort) and (y>=0) and (y startXViewPort + viewWidth then vpx2 := startXViewPort + viewWidth; end; { constrain to the part of the scanline that is on the screen } if vpx1 < 0 then vpx1 := 0; if vpx2 >= PTCwidth then vpx2 := PTCwidth-1; If (ClipPixels AND (y <= startYViewPort+viewHeight) and (y >= startYViewPort) and (y>=0) and (y startXViewPort + viewWidth then vpx2 := startXViewPort + viewWidth; end; { constrain to the part of the scanline that is on the screen } if vpx1 < 0 then vpx1 := 0; if vpx2 >= PTCwidth then vpx2 := PTCwidth-1; If (ClipPixels AND (y <= startYViewPort+viewHeight) and (y >= startYViewPort) and (y>=0) and (y startXViewPort + viewWidth then vpx2 := startXViewPort + viewWidth; if vpy1 < startYViewPort then vpy1 := startYViewPort; if vpy2 > startYViewPort+viewHeight then vpy2 := startYViewPort+viewHeight; end; { check if coordinates are on the screen} if vpx1 < 0 then vpx1 := 0; if vpx2 >= PTCwidth then vpx2 := PTCwidth-1; if vpy1 < 0 then vpy1 := 0; if vpy2 >= PTCheight then vpy2 := PTCheight-1; i := (x2 - x1 + 1); j := i * (vpy1 - StartYViewPort - y1); inc(k,j); pixels := ptc_surface_lock; for y:=vpy1 to vpy2 do Begin For x:=vpx1 to vpx2 Do pt(Bitmap)[k+(x-StartXViewPort-x1)]:=pixels[x+y*PTCWidth] and ColorMask; inc(k,i); end; ptc_surface_unlock; end; Procedure PTC_GetImageProc_16bpp(X1,Y1,X2,Y2: smallint; Var Bitmap); type pt = array[0..{$ifdef cpu16}16382{$else}$fffffff{$endif}] of word; ptw = array[0..2] of longint; var pixels : Pword; x,y,i,j,vpx1,vpx2,vpy1,vpy2 : smallint; k : longint; Begin ptw(Bitmap)[0] := X2-X1+1; { First longint is width } ptw(Bitmap)[1] := Y2-Y1+1; { Second longint is height } ptw(bitmap)[2] := 0; { Third longint is reserved} k:= 3 * Sizeof(longint) div sizeof(word); { Three reserved longs at start of bitmap } vpx1:=x1+StartXViewPort; vpx2:=x2+StartXViewPort; vpy1:=y1+StartYViewPort; vpy2:=y2+StartYViewPort; { check which part of the image is in the viewport } if clipPixels then begin if vpx1 < startXViewPort then vpx1 := startXViewPort; if vpx2 > startXViewPort + viewWidth then vpx2 := startXViewPort + viewWidth; if vpy1 < startYViewPort then vpy1 := startYViewPort; if vpy2 > startYViewPort+viewHeight then vpy2 := startYViewPort+viewHeight; end; { check if coordinates are on the screen} if vpx1 < 0 then vpx1 := 0; if vpx2 >= PTCwidth then vpx2 := PTCwidth-1; if vpy1 < 0 then vpy1 := 0; if vpy2 >= PTCheight then vpy2 := PTCheight-1; i := (x2 - x1 + 1); j := i * (vpy1 - StartYViewPort - y1); inc(k,j); pixels := ptc_surface_lock; for y:=vpy1 to vpy2 do Begin For x:=vpx1 to vpx2 Do pt(Bitmap)[k+(x-StartXViewPort-x1)]:=pixels[x+y*PTCWidth]; inc(k,i); end; ptc_surface_unlock; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} Procedure PTC_GetImageProc_32bpp(X1,Y1,X2,Y2: smallint; Var Bitmap); type pt = array[0..{$ifdef cpu16}16382{$else}$fffffff{$endif}] of longword; ptw = array[0..2] of longint; var pixels : Plongword; x,y,i,j,vpx1,vpx2,vpy1,vpy2 : smallint; k : longint; Begin ptw(Bitmap)[0] := X2-X1+1; { First longint is width } ptw(Bitmap)[1] := Y2-Y1+1; { Second longint is height } ptw(bitmap)[2] := 0; { Third longint is reserved} k:= 3 * Sizeof(longint) div sizeof(longword); { Three reserved longs at start of bitmap } vpx1:=x1+StartXViewPort; vpx2:=x2+StartXViewPort; vpy1:=y1+StartYViewPort; vpy2:=y2+StartYViewPort; { check which part of the image is in the viewport } if clipPixels then begin if vpx1 < startXViewPort then vpx1 := startXViewPort; if vpx2 > startXViewPort + viewWidth then vpx2 := startXViewPort + viewWidth; if vpy1 < startYViewPort then vpy1 := startYViewPort; if vpy2 > startYViewPort+viewHeight then vpy2 := startYViewPort+viewHeight; end; { check if coordinates are on the screen} if vpx1 < 0 then vpx1 := 0; if vpx2 >= PTCwidth then vpx2 := PTCwidth-1; if vpy1 < 0 then vpy1 := 0; if vpy2 >= PTCheight then vpy2 := PTCheight-1; i := (x2 - x1 + 1); j := i * (vpy1 - StartYViewPort - y1); inc(k,j); pixels := ptc_surface_lock; for y:=vpy1 to vpy2 do Begin For x:=vpx1 to vpx2 Do pt(Bitmap)[k+(x-StartXViewPort-x1)]:=pixels[x+y*PTCWidth]; inc(k,i); end; ptc_surface_unlock; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} {************************************************************************} {* General routines *} {************************************************************************} procedure CloseGraph; Begin If not isgraphmode then begin _graphresult := grnoinitgraph; exit end; RestoreVideoState; isgraphmode := false; end; procedure FillCommonVESA16(var mode: TModeInfo); begin mode.HardwarePages := 1; mode.MaxColor := 16; mode.PaletteSize := mode.MaxColor; mode.DirectColor := FALSE; mode.DirectPutPixel := @ptc_DirectPixelProc_8bpp; mode.PutPixel := @ptc_PutPixelProc_8bpp; mode.GetPixel := @ptc_GetPixelProc_8bpp; mode.PutImage := @ptc_PutImageProc_8bpp; mode.GetImage := @ptc_GetImageProc_8bpp; mode.GetScanLine := @ptc_GetScanLineProc_8bpp; mode.SetRGBPalette := @ptc_SetRGBPaletteProc; mode.GetRGBPalette := @ptc_GetRGBPaletteProc; mode.HLine := @ptc_HLineProc_8bpp; mode.VLine := @ptc_VLineProc_8bpp; mode.PatternLine := @ptc_PatternLineProc_8bpp; mode.SetVisualPage := @ptc_SetVisualPage; mode.SetActivePage := @ptc_SetActivePage; end; procedure FillCommonVESA256(var mode: TModeInfo); begin mode.HardwarePages := 1; mode.MaxColor := 256; mode.PaletteSize := mode.MaxColor; mode.DirectColor := FALSE; mode.DirectPutPixel := @ptc_DirectPixelProc_8bpp; mode.PutPixel := @ptc_PutPixelProc_8bpp; mode.GetPixel := @ptc_GetPixelProc_8bpp; mode.PutImage := @ptc_PutImageProc_8bpp; mode.GetImage := @ptc_GetImageProc_8bpp; mode.GetScanLine := @ptc_GetScanLineProc_8bpp; mode.SetRGBPalette := @ptc_SetRGBPaletteProc; mode.GetRGBPalette := @ptc_GetRGBPaletteProc; //mode.SetAllPalette := {$ifdef fpc}@{$endif}SetVGARGBAllPalette; mode.HLine := @ptc_HLineProc_8bpp; mode.VLine := @ptc_VLineProc_8bpp; mode.PatternLine := @ptc_PatternLineProc_8bpp; mode.SetVisualPage := @ptc_SetVisualPage; mode.SetActivePage := @ptc_SetActivePage; end; procedure FillCommonVESA32kOr64k(var mode: TModeInfo); begin mode.HardwarePages := 1; mode.DirectColor := TRUE; mode.DirectPutPixel := @ptc_DirectPixelProc_16bpp; mode.PutPixel := @ptc_PutPixelProc_16bpp; mode.GetPixel := @ptc_GetPixelProc_16bpp; mode.PutImage := @ptc_PutImageProc_16bpp; mode.GetImage := @ptc_GetImageProc_16bpp; mode.GetScanLine := @ptc_GetScanLineProc_16bpp; mode.SetRGBPalette := @ptc_SetRGBPaletteProc; mode.GetRGBPalette := @ptc_GetRGBPaletteProc; //mode.SetAllPalette := {$ifdef fpc}@{$endif}SetVGARGBAllPalette; mode.HLine := @ptc_HLineProc_16bpp; mode.VLine := @ptc_VLineProc_16bpp; mode.PatternLine := @ptc_PatternLineProc_16bpp; mode.SetVisualPage := @ptc_SetVisualPage; mode.SetActivePage := @ptc_SetActivePage; end; procedure FillCommonVESA32k(var mode: TModeInfo); begin FillCommonVESA32kOr64k(mode); mode.MaxColor := 32768; mode.PaletteSize := mode.MaxColor; end; procedure FillCommonVESA64k(var mode: TModeInfo); begin FillCommonVESA32kOr64k(mode); mode.MaxColor := 65536; mode.PaletteSize := mode.MaxColor; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} procedure FillCommonVESA32bpp(var mode: TModeInfo); begin mode.HardwarePages := 1; mode.MaxColor := 16777216; mode.PaletteSize := mode.MaxColor; mode.DirectColor := TRUE; mode.DirectPutPixel := @ptc_DirectPixelProc_32bpp; mode.PutPixel := @ptc_PutPixelProc_32bpp; mode.GetPixel := @ptc_GetPixelProc_32bpp; mode.PutImage := @ptc_PutImageProc_32bpp; mode.GetImage := @ptc_GetImageProc_32bpp; mode.GetScanLine := @ptc_GetScanLineProc_32bpp; mode.SetRGBPalette := @ptc_SetRGBPaletteProc; mode.GetRGBPalette := @ptc_GetRGBPaletteProc; //mode.SetAllPalette := {$ifdef fpc}@{$endif}SetVGARGBAllPalette; mode.HLine := @ptc_HLineProc_32bpp; mode.VLine := @ptc_VLineProc_32bpp; mode.PatternLine := @ptc_PatternLineProc_32bpp; mode.SetVisualPage := @ptc_SetVisualPage; mode.SetActivePage := @ptc_SetActivePage; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} function QueryAdapterInfo:PModeInfo; { This routine returns the head pointer to the list } { of supported graphics modes. } { Returns nil if no graphics mode supported. } { This list is READ ONLY! } var PTCModeList: TPTCModeList; function ModeListEmpty: Boolean; begin ModeListEmpty := Length(PTCModeList) = 0; end; function ContainsExactResolution(AWidth, AHeight: Integer): Boolean; var I: Integer; begin if ModeListEmpty then begin ContainsExactResolution := False; exit; end; for I := Low(PTCModeList) to High(PTCModeList) do with PTCModeList[I] do if (Width = AWidth) and (Height = AHeight) then begin ContainsExactResolution := True; exit; end; ContainsExactResolution := False; end; function ContainsAtLeast(AWidth, AHeight: Integer): Boolean; var I: Integer; begin if ModeListEmpty then begin ContainsAtLeast := False; exit; end; for I := Low(PTCModeList) to High(PTCModeList) do with PTCModeList[I] do if (Width >= AWidth) and (Height >= AHeight) then begin ContainsAtLeast := True; exit; end; ContainsAtLeast := False; end; function IsNonStandardResolution(AWidth, AHeight: Integer): Boolean; begin IsNonStandardResolution := not ((AWidth = 320) and (AHeight = 200)) and not ((AWidth = 640) and (AHeight = 200)) and not ((AWidth = 640) and (AHeight = 350)) and not ((AWidth = 640) and (AHeight = 400)) and not ((AWidth = 640) and (AHeight = 480)) and not ((AWidth = 720) and (AHeight = 348)) and not ((AWidth = 800) and (AHeight = 600)) and not ((AWidth = 1024) and (AHeight = 768)) and not ((AWidth = 1280) and (AHeight = 1024)); end; function CompareModes(AMode1, AMode2: IPTCMode): Boolean; begin if AMode1.Width <> AMode2.Width then CompareModes := AMode1.Width < AMode2.Width else if AMode1.Height <> AMode2.Height then CompareModes := AMode1.Height < AMode2.Height else if AMode1.Format.Bits <> AMode2.Format.Bits then CompareModes := AMode1.Format.Bits < AMode2.Format.Bits else CompareModes := PtrUInt(AMode1) < PtrUInt(AMode2); end; procedure SortModes(l,r: longint); var i,j: longint; x,y: IPTCMode; begin i:=l; j:=r; x:=PTCModeList[(l+r) div 2]; repeat while CompareModes(PTCModeList[i], x) do inc(i); while CompareModes(x, PTCModeList[j]) do dec(j); if not(i>j) then begin y:=PTCModeList[i]; PTCModeList[i]:=PTCModeList[j]; PTCModeList[j]:=y; inc(i); j:=j-1; end; until i>j; if l PTCModeList[I-1].Width) or (Height <> PTCModeList[I-1].Height))) then begin InitMode(graphmode); FillCommonVESA16(graphmode); with graphmode do begin ModeNumber := NextNonStandardModeNumber; DriverNumber := VESA; WriteStr(ModeName, Width, ' x ', Height, ' VESA'); MaxX := Width - 1; MaxY := Height - 1; InitMode := @ptc_InitNonStandard16; XAspect := 10000; YAspect := 10000; end; AddMode(graphmode); Inc(NextNonStandardModeNumber); if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then break; InitMode(graphmode); FillCommonVESA256(graphmode); with graphmode do begin ModeNumber := NextNonStandardModeNumber; DriverNumber := VESA; WriteStr(ModeName, Width, ' x ', Height, ' VESA'); MaxX := Width - 1; MaxY := Height - 1; InitMode := @ptc_InitNonStandard256; XAspect := 10000; YAspect := 10000; end; AddMode(graphmode); Inc(NextNonStandardModeNumber); if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then break; InitMode(graphmode); FillCommonVESA32k(graphmode); with graphmode do begin ModeNumber := NextNonStandardModeNumber; DriverNumber := VESA; WriteStr(ModeName, Width, ' x ', Height, ' VESA'); MaxX := Width - 1; MaxY := Height - 1; InitMode := @ptc_InitNonStandard32k; XAspect := 10000; YAspect := 10000; end; AddMode(graphmode); Inc(NextNonStandardModeNumber); if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then break; InitMode(graphmode); FillCommonVESA64k(graphmode); with graphmode do begin ModeNumber := NextNonStandardModeNumber; DriverNumber := VESA; WriteStr(ModeName, Width, ' x ', Height, ' VESA'); MaxX := Width - 1; MaxY := Height - 1; InitMode := @ptc_InitNonStandard64k; XAspect := 10000; YAspect := 10000; end; AddMode(graphmode); Inc(NextNonStandardModeNumber); if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then break; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} InitMode(graphmode); FillCommonVESA32bpp(graphmode); with graphmode do begin ModeNumber := NextNonStandardModeNumber; DriverNumber := VESA; WriteStr(ModeName, Width, ' x ', Height, ' VESA'); MaxX := Width - 1; MaxY := Height - 1; InitMode := @ptc_InitNonStandard32bpp; XAspect := 10000; YAspect := 10000; end; AddMode(graphmode); Inc(NextNonStandardModeNumber); if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then break; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} end; end; function InstallUserMode(Width, Height: SmallInt; Colors: LongInt; HardwarePages: SmallInt; XAspect, YAspect: Word): smallint; var graphmode: Tmodeinfo; begin if (NextNonStandardModeNumber > NonStandardModeNumberMaxLimit) or (HardwarePages < 1) or (Width <= 0) or (Height <= 0) or (XAspect <= 0) or (YAspect <= 0) then begin InstallUserMode := grError; exit; end; InitMode(graphmode); case Colors of { 2: begin end; 4: begin end;} 16: begin FillCommonVESA16(graphmode); graphmode.InitMode := @ptc_InitNonStandard16; end; 256: begin FillCommonVESA256(graphmode); graphmode.InitMode := @ptc_InitNonStandard256; end; 32768: begin FillCommonVESA32k(graphmode); graphmode.InitMode := @ptc_InitNonStandard32k; end; 65536: begin FillCommonVESA64k(graphmode); graphmode.InitMode := @ptc_InitNonStandard64k; end; {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} 16777216: begin FillCommonVESA32bpp(graphmode); graphmode.InitMode := @ptc_InitNonStandard32bpp; end; {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} else begin InstallUserMode := grError; exit; end; end; with graphmode do begin ModeNumber := NextNonStandardModeNumber; DriverNumber := VESA; WriteStr(ModeName, Width, ' x ', Height, ' VESA'); MaxX := Width - 1; MaxY := Height - 1; HardwarePages := 1; end; graphmode.XAspect := XAspect; graphmode.YAspect := YAspect; graphmode.HardwarePages := HardwarePages - 1; AddMode(graphmode); Inc(NextNonStandardModeNumber); InstallUserMode := graphmode.ModeNumber; end; initialization WindowTitle := ParamStr(0); PTCFormat8 := TPTCFormatFactory.CreateNew(8); PTCFormat15 := TPTCFormatFactory.CreateNew(16, $7C00, $03E0, $001F); PTCFormat16 := TPTCFormatFactory.CreateNew(16, $F800, $07E0, $001F); {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR} PTCFormat32 := TPTCFormatFactory.CreateNew(32, $00FF0000, $0000FF00, $000000FF); {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR} PTCWrapperObject := TPTCWrapperThread.Create; InitializeGraph; finalization PTCWrapperObject.Terminate; PTCWrapperObject.WaitFor; PTCWrapperObject.Free; end.