vesa.inc 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,99 by Carl Eric Codere
  5. This include implements VESA basic access.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. type
  13. pModeList = ^tModeList;
  14. tModeList = Array [0..255] of word; {list of modes terminated by -1}
  15. {VESA modes are >=100h}
  16. palrec = packed record { record used for set/get DAC palette }
  17. align: byte;
  18. blue : byte;
  19. green: byte;
  20. red: byte;
  21. end;
  22. const
  23. { VESA attributes }
  24. attrSwitchDAC = $01; { DAC is switchable (1.2) }
  25. attrNotVGACompatible = $02; { Video is NOT VGA compatible (2.0) }
  26. attrSnowCheck = $04; { Video must use snow checking(2.0) }
  27. { mode attribute bits }
  28. modeAvail = $01; { Hardware supports this mode (1.0) }
  29. modeExtendInfo = $02; { Extended information (1.0) }
  30. modeBIOSSupport = $04; { TTY BIOS Support (1.0) }
  31. modeColor = $08; { This is a color mode (1.0) }
  32. modeGraphics = $10; { This is a graphics mode (1.0) }
  33. modeNotVGACompatible = $20; { this mode is NOT I/O VGA compatible (2.0)}
  34. modeNoWindowed = $40; { This mode does not support Windows (2.0) }
  35. modeLinearBuffer = $80; { This mode supports linear buffers (2.0) }
  36. { window attributes }
  37. winSupported = $01;
  38. winReadable = $02;
  39. winWritable = $04;
  40. { memory model }
  41. modelText = $00;
  42. modelCGA = $01;
  43. modelHerc = $02;
  44. model4plane = $03;
  45. modelPacked = $04;
  46. modelModeX = $05;
  47. modelRGB = $06;
  48. modelYUV = $07;
  49. TYPE
  50. TVESAinfo = packed record { VESA Information request }
  51. signature : array [1..4] of char; { This should be VESA }
  52. version : word; { VESA revision }
  53. str : pChar; { pointer to OEM string }
  54. caps : longint; { video capabilities }
  55. modeList : pModeList; { pointer to SVGA modes }
  56. pad : array [18..260] of byte; { extra padding more then }
  57. end; { VESA standard because of bugs on }
  58. { some video cards. }
  59. TVESAModeInfo = packed record
  60. attr : word; { mode attributes (1.0) }
  61. winAAttr,
  62. winBAttr : byte; { window attributes (1.0) }
  63. winGranularity : word; {in K} { Window granularity (1.0) }
  64. winSize : word; {in K} { window size (1.0) }
  65. winASeg, { Window A Segment address (1.0) }
  66. winBSeg : word; { Window B Segment address (1.0) }
  67. winFunct : procedure; { Function to swtich bank }
  68. BytesPerScanLine: word; {bytes per scan line (1.0) }
  69. { extended information }
  70. xRes, yRes : word; {pixels}
  71. xCharSize,
  72. yCharSize : byte;
  73. planes : byte;
  74. bitsPixel : byte;
  75. banks : byte;
  76. memModel : byte;
  77. bankSize : byte; {in K}
  78. NumberOfPages: byte;
  79. pad : array [29..260] of byte; { always put some more space then required}
  80. end;
  81. var
  82. VESAInfo : TVESAInfo; { VESA Driver information }
  83. ModeInfo : TVESAModeInfo; { Current Mode information }
  84. BytesPerLine: word; { Number of bytes per scanline }
  85. { window management }
  86. ReadWindow : byte; { Window number for reading. }
  87. WriteWindow: byte; { Window number for writing. }
  88. winReadSeg : word; { Address of segment for read }
  89. winWriteSeg: word; { Address of segment for writes}
  90. CurrentReadBank : integer; { active read bank }
  91. CurrentWriteBank: integer; { active write bank }
  92. BankShift : word; { address to shift by when switching banks. }
  93. hasVesa: Boolean; { true if we have a VESA compatible graphics card}
  94. { initialized in QueryAdapterInfo in graph.inc }
  95. function hexstr(val : longint;cnt : byte) : string;
  96. const
  97. HexTbl : array[0..15] of char='0123456789ABCDEF';
  98. var
  99. i : longint;
  100. begin
  101. hexstr[0]:=char(cnt);
  102. for i:=cnt downto 1 do
  103. begin
  104. hexstr[i]:=hextbl[val and $f];
  105. val:=val shr 4;
  106. end;
  107. end;
  108. {$IFDEF DPMI}
  109. function getVESAInfo(var VESAInfo: TVESAInfo) : boolean;
  110. var
  111. ptrlong : longint;
  112. VESAPtr : ^TVESAInfo;
  113. regs : TDPMIRegisters;
  114. ModeSel: word;
  115. offs: longint;
  116. { added... }
  117. modelist: PmodeList;
  118. modeptr : pointer;
  119. i: longint;
  120. RealSeg : word;
  121. begin
  122. { Allocate real mode buffer }
  123. {$ifndef fpc}
  124. Ptrlong:=GlobalDosAlloc(sizeof(TVESAInfo));
  125. { Get selector value }
  126. VESAPtr := pointer(Ptrlong shl 16);
  127. {$else fpc}
  128. Ptrlong:=Global_Dos_Alloc(sizeof(TVESAInfo));
  129. New(VESAPtr);
  130. {$endif fpc}
  131. { Get segment value }
  132. RealSeg := word(Ptrlong shr 16);
  133. if not assigned(VESAPtr) then
  134. RunError(203);
  135. FillChar(regs, sizeof(TDPMIRegisters), #0);
  136. { Get VESA Mode information ... }
  137. regs.eax := $4f00;
  138. regs.es := RealSeg;
  139. regs.edi := $00;
  140. RealIntr($10, regs);
  141. {$ifdef fpc}
  142. { no far pointer support in FPC yet, so move the vesa info into a memory }
  143. { block in the DS slector space (JM) }
  144. dosmemget(RealSeg,0,VesaPtr^,SizeOf(TVESAInfo));
  145. {$endif fpc}
  146. if VESAPtr^.Signature <> 'VESA' then
  147. begin
  148. getVesaInfo := FALSE;
  149. {$ifndef fpc}
  150. GlobalDosFree(word(PtrLong and $ffff));
  151. {$else fpc}
  152. If not Global_Dos_Free(word(PtrLong and $ffff)) then
  153. RunError(216);
  154. { also free the extra allocated buffer }
  155. Dispose(VESAPtr);
  156. {$endif fpc}
  157. exit;
  158. end
  159. else
  160. getVesaInfo := TRUE;
  161. {$ifndef fpc}
  162. { The mode pointer buffer points to a real mode memory }
  163. { Therefore steps to get the modes: }
  164. { 1. Allocate Selector and SetLimit to max number of }
  165. { of possible modes. }
  166. ModeSel := AllocSelector(0);
  167. SetSelectorLimit(ModeSel, 256*sizeof(word));
  168. { 2. Set Selector linear address to the real mode pointer }
  169. { returned. }
  170. offs := longint(longint(VESAPtr^.ModeList) shr 16) shl 4;
  171. {shouldn't the OR in the next line be a + ?? (JM)}
  172. offs := offs OR (Longint(VESAPtr^.ModeList) and $ffff);
  173. SetSelectorBase(ModeSel, offs);
  174. { copy VESA mode information to a protected mode buffer and }
  175. { then free the real mode buffer... }
  176. Move(VESAPtr^, VESAInfo, sizeof(TVESAInfo));
  177. GlobalDosFree(word(PtrLong and $ffff));
  178. { ModeList points to the mode list }
  179. { We must copy it somewhere... }
  180. ModeList := Ptr(ModeSel, 0);
  181. {$else fpc}
  182. { No far pointer support, so the Ptr(ModeSel, 0) doesn't work. }
  183. { Immediately copy everything to a buffer in the DS selector space }
  184. New(ModeList);
  185. { The following may copy data from outside the VESA buffer, but it }
  186. { shouldn't get past the 1MB limit, since that would mean the buffer }
  187. { has been allocated in the BIOS or high memory region, which seems }
  188. { impossible to me (JM)}
  189. DosMemGet(word(longint(VESAPtr^.ModeList) shr 16),
  190. word(longint(VESAPtr^.ModeList) and $ffff), ModeList^,256*sizeof(word));
  191. { copy VESA mode information to a protected mode buffer and }
  192. { then free the real mode buffer... }
  193. Move(VESAPtr^, VESAInfo, sizeof(TVESAInfo));
  194. If not Global_Dos_Free(word(PtrLong and $ffff)) then
  195. RunError(216);
  196. Dispose(VESAPtr);
  197. {$endif fpc}
  198. i:=0;
  199. new(VESAInfo.ModeList);
  200. while ModeList^[i]<> $ffff do
  201. begin
  202. VESAInfo.ModeList^[i] := ModeList^[i];
  203. Inc(i);
  204. end;
  205. VESAInfo.ModeList^[i]:=$ffff;
  206. { Free the temporary selector used to get mode information }
  207. {$ifndef fpc}
  208. FreeSelector(ModeSel);
  209. {$else fpc}
  210. Dispose(ModeList);
  211. {$endif fpc}
  212. end;
  213. function getModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;
  214. var
  215. Ptr: longint;
  216. {$ifndef fpc}
  217. VESAPtr : ^TVESAModeInfo;
  218. {$endif fpc}
  219. regs : TDPMIRegisters;
  220. RealSeg: word;
  221. begin
  222. { Alllocate real mode buffer }
  223. {$ifndef fpc}
  224. Ptr:=GlobalDosAlloc(sizeof(TVESAModeInfo));
  225. { get the selector value }
  226. VESAPtr := pointer(longint(Ptr shl 16));
  227. if not assigned(VESAPtr) then
  228. RunError(203);
  229. {$else fpc}
  230. Ptr:=Global_Dos_Alloc(sizeof(TVESAModeInfo));
  231. {$endif fpc}
  232. { get the segment value }
  233. RealSeg := word(Ptr shr 16);
  234. { setup interrupt registers }
  235. FillChar(regs, sizeof(TDPMIRegisters), #0);
  236. { call VESA mode information...}
  237. regs.eax := $4f01;
  238. regs.es := RealSeg;
  239. regs.edi := $00;
  240. regs.ecx := mode;
  241. RealIntr($10, regs);
  242. if word(regs.eax) <> $4f then
  243. getModeInfo := FALSE
  244. else
  245. getModeInfo := TRUE;
  246. { copy to protected mode buffer ... }
  247. {$ifndef fpc}
  248. Move(VESAPtr^, ModeInfo, sizeof(TVESAModeInfo));
  249. {$else fpc}
  250. DosMemGet(RealSeg,0,ModeInfo,sizeof(TVESAModeInfo));
  251. {$endif fpc}
  252. { free real mode memory }
  253. {$ifndef fpc}
  254. GlobalDosFree(Word(Ptr and $ffff));
  255. {$else fpc}
  256. If not Global_Dos_Free(Word(Ptr and $ffff)) then
  257. RunError(216);
  258. {$endif fpc}
  259. end;
  260. {$ELSE}
  261. function getVESAInfo(var VESAInfo: TVESAInfo) : boolean; assembler;
  262. asm
  263. mov ax,4F00h
  264. les di,VESAInfo
  265. int 10h
  266. sub ax,004Fh {make sure we got 004Fh back}
  267. cmp ax,1
  268. sbb al,al
  269. cmp word ptr es:[di],'V'or('E'shl 8) {signature should be 'VESA'}
  270. jne @@ERR
  271. cmp word ptr es:[di+2],'S'or('A'shl 8)
  272. je @@X
  273. @@ERR:
  274. mov al,0
  275. @@X:
  276. end;
  277. function getModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;assembler;
  278. asm
  279. mov ax,4F01h
  280. mov cx,mode
  281. les di,ModeInfo
  282. int 10h
  283. sub ax,004Fh {make sure it's 004Fh}
  284. cmp ax,1
  285. sbb al,al
  286. end;
  287. {$ENDIF}
  288. function SearchVESAModes(mode: Word): boolean;
  289. {********************************************************}
  290. { Searches for a specific DEFINED vesa mode. If the mode }
  291. { is not available for some reason, then returns FALSE }
  292. { otherwise returns TRUE. }
  293. {********************************************************}
  294. var
  295. i: word;
  296. ModeSupported : Boolean;
  297. begin
  298. i:=0;
  299. { let's assume it's not available ... }
  300. ModeSupported := FALSE;
  301. { This is a STUB VESA implementation }
  302. if VESAInfo.ModeList^[0] = $FFFF then exit;
  303. repeat
  304. if VESAInfo.ModeList^[i] = mode then
  305. begin
  306. { we found it, the card supports this mode... }
  307. ModeSupported := TRUE;
  308. break;
  309. end;
  310. Inc(i);
  311. until VESAInfo.ModeList^[i] = $ffff;
  312. { now check if the hardware supports it... }
  313. If ModeSupported then
  314. begin
  315. { we have to init everything to zero, since VBE < 1.1 }
  316. { may not setup fields correctly. }
  317. FillChar(ModeInfo, sizeof(ModeInfo), #0);
  318. If GetModeInfo(ModeInfo, Mode) And
  319. ((ModeInfo.attr and modeAvail) <> 0) then
  320. ModeSupported := TRUE
  321. else
  322. ModeSupported := FALSE;
  323. end;
  324. SearchVESAModes := ModeSupported;
  325. end;
  326. procedure SetBankIndex(win: byte; BankNr: Integer); assembler;
  327. asm
  328. mov ax,4f05h
  329. mov bh,00h
  330. mov bl,[Win]
  331. mov dx,[BankNr]
  332. {$ifdef fpc}
  333. push ebp
  334. {$endif fpc}
  335. int 10h
  336. {$ifdef fpc}
  337. pop ebp
  338. {$endif fpc}
  339. end;
  340. {********************************************************}
  341. { There are two routines for setting banks. This may in }
  342. { in some cases optimize a bit some operations, if the }
  343. { hardware supports it, because one window is used for }
  344. { reading and one window is used for writing. }
  345. {********************************************************}
  346. procedure SetReadBank(BankNr: Integer);
  347. begin
  348. { check if this is the current bank... if so do nothing. }
  349. if BankNr = CurrentReadBank then exit;
  350. CurrentReadBank := BankNr; { save current bank number }
  351. BankNr := BankNr shl BankShift; { adjust to window granularity }
  352. { we set both banks, since one may read only }
  353. SetBankIndex(ReadWindow, BankNr);
  354. { if the hardware supports only one window }
  355. { then there is only one single bank, so }
  356. { update both bank numbers. }
  357. if ReadWindow = WriteWindow then
  358. CurrentWriteBank := CurrentReadBank;
  359. end;
  360. procedure SetWriteBank(BankNr: Integer);
  361. begin
  362. { check if this is the current bank... if so do nothing. }
  363. if BankNr = CurrentWriteBank then exit;
  364. CurrentWriteBank := BankNr; { save current bank number }
  365. BankNr := BankNr shl BankShift; { adjust to window granularity }
  366. { we set both banks, since one may read only }
  367. SetBankIndex(WriteWindow, BankNr);
  368. { if the hardware supports only one window }
  369. { then there is only one single bank, so }
  370. { update both bank numbers. }
  371. if ReadWindow = WriteWindow then
  372. CurrentReadBank := CurrentWriteBank;
  373. end;
  374. {************************************************************************}
  375. {* 8-bit pixels VESA mode routines *}
  376. {************************************************************************}
  377. procedure PutPixVESA256(x, y : integer; color : word); far;
  378. var
  379. bank : word;
  380. offs : longint;
  381. begin
  382. X:= X + StartXViewPort;
  383. Y:= Y + StartYViewPort;
  384. { convert to absolute coordinates and then verify clipping...}
  385. if ClipPixels then
  386. Begin
  387. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  388. exit;
  389. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  390. exit;
  391. end;
  392. offs := longint(y) * BytesPerLine + x;
  393. SetWriteBank(integer(offs shr 16));
  394. mem[WinWriteSeg : word(offs)] := byte(color);
  395. end;
  396. procedure DirectPutPixVESA256(x, y : integer); far;
  397. var
  398. bank : word;
  399. offs : longint;
  400. begin
  401. offs := longint(y) * BytesPerLine + x;
  402. SetWriteBank(integer(offs shr 16));
  403. mem[WinWriteSeg : word(offs)] := byte(CurrentColor);
  404. end;
  405. function GetPixVESA256(x, y : integer): word; far;
  406. var
  407. bank : word;
  408. offs : longint;
  409. begin
  410. X:= X + StartXViewPort;
  411. Y:= Y + StartYViewPort;
  412. offs := longint(y) * BytesPerLine + x;
  413. SetReadBank(integer(offs shr 16));
  414. GetPixVESA256:=mem[WinReadSeg : word(offs)];
  415. end;
  416. {************************************************************************}
  417. {* 15/16bit pixels VESA mode routines *}
  418. {************************************************************************}
  419. procedure PutPixVESA32k(x, y : integer; color : word); far;
  420. var
  421. bank : word;
  422. offs : longint;
  423. begin
  424. X:= X + StartXViewPort;
  425. Y:= Y + StartYViewPort;
  426. { convert to absolute coordinates and then verify clipping...}
  427. if ClipPixels then
  428. Begin
  429. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  430. exit;
  431. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  432. exit;
  433. end;
  434. offs := longint(y) * BytesPerLine + 2*x;
  435. SetWriteBank(integer(offs shr 16));
  436. memW[WinWriteSeg : word(offs)] := color;
  437. end;
  438. procedure PutPixVESA64k(x, y : integer; color : word); far;
  439. var
  440. bank : word;
  441. offs : longint;
  442. begin
  443. X:= X + StartXViewPort;
  444. Y:= Y + StartYViewPort;
  445. { convert to absolute coordinates and then verify clipping...}
  446. if ClipPixels then
  447. Begin
  448. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  449. exit;
  450. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  451. exit;
  452. end;
  453. offs := longint(y) * BytesPerLine + 2*x;
  454. SetWriteBank(integer(offs shr 16));
  455. memW[WinWriteSeg : word(offs)] := color;
  456. end;
  457. function GetPixVESA32k(x, y : integer): word; far;
  458. var
  459. bank : word;
  460. offs : longint;
  461. begin
  462. X:= X + StartXViewPort;
  463. Y:= Y + StartYViewPort;
  464. offs := longint(y) * BytesPerLine + 2*x;
  465. SetReadBank(integer(offs shr 16));
  466. GetPixVESA32k:=memW[WinReadSeg : word(offs)];
  467. end;
  468. function GetPixVESA64k(x, y : integer): word; far;
  469. var
  470. bank : word;
  471. offs : longint;
  472. begin
  473. X:= X + StartXViewPort;
  474. Y:= Y + StartYViewPort;
  475. offs := longint(y) * BytesPerLine + 2*x;
  476. SetReadBank(integer(offs shr 16));
  477. GetPixVESA64k:=memW[WinReadSeg : word(offs)];
  478. end;
  479. procedure DirectPutPixVESA32k(x, y : integer); far;
  480. var
  481. bank : word;
  482. offs : longint;
  483. begin
  484. offs := longint(y) * BytesPerLine + 2*x;
  485. SetWriteBank(integer((offs shr 16) and $ff));
  486. memW[WinWriteSeg : word(offs)] := CurrentColor;
  487. end;
  488. procedure DirectPutPixVESA64k(x, y : integer); far;
  489. var
  490. bank : word;
  491. offs : longint;
  492. begin
  493. offs := longint(y) * BytesPerLine + 2*x;
  494. SetWriteBank(integer(offs shr 16));
  495. memW[WinWriteSeg : word(offs)] := CurrentColor;
  496. end;
  497. {************************************************************************}
  498. {* 4-bit pixels VESA mode routines *}
  499. {************************************************************************}
  500. procedure PutPixVESA16(x, y : integer; color : word); far;
  501. var
  502. bank : word;
  503. offs : longint;
  504. dummy_read : byte;
  505. begin
  506. X:= X + StartXViewPort;
  507. Y:= Y + StartYViewPort;
  508. { convert to absolute coordinates and then verify clipping...}
  509. if ClipPixels then
  510. Begin
  511. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  512. exit;
  513. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  514. exit;
  515. end;
  516. { this can be done only once at InitGraph }
  517. PortW[$3C4] := $0f02;
  518. PortW[$3CE] := $0003;
  519. PortW[$3CE] := $0205;
  520. { }
  521. offs := longint(y) * BytesPerLine + (x div 8);
  522. SetWriteBank(integer(offs shr 16));
  523. port[$3CE] := $08;
  524. port[$3CF] := ($80 shr (x and 7));
  525. dummy_read := mem[WinWriteSeg : word(offs)];
  526. mem[winWriteSeg : offs] := byte(color);
  527. { this can be done only once at DoneGraph..}
  528. PortW[$3CE] := $FF08;
  529. PortW[$3CE] := $0005;
  530. { }
  531. end;
  532. procedure DirectPutPixVESA16(x, y : integer); far;
  533. var
  534. bank : word;
  535. offs : longint;
  536. dummy_read : byte;
  537. begin
  538. { this can be done only once at InitGraph }
  539. PortW[$3C4] := $0f02;
  540. PortW[$3CE] := $0003;
  541. PortW[$3CE] := $0205;
  542. { }
  543. offs := longint(y) * BytesPerLine + (x div 8);
  544. SetWriteBank(integer(offs shr 16));
  545. port[$3CE] := $08;
  546. port[$3CF] := ($80 shr (x and 7));
  547. dummy_read := mem[WinWriteSeg : word(offs)];
  548. mem[winWriteSeg : offs] := byte(CurrentColor);
  549. { this can be done only once at DoneGraph..}
  550. PortW[$3CE] := $FF08;
  551. PortW[$3CE] := $0005;
  552. { }
  553. end;
  554. {************************************************************************}
  555. {* VESA Palette entries *}
  556. {************************************************************************}
  557. {$IFDEF DPMI}
  558. Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
  559. BlueValue : Integer);
  560. var
  561. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  562. pal: palrec;
  563. Error : boolean; { VBE call error }
  564. regs: TDPMIRegisters;
  565. Ptr: longint;
  566. {$ifndef fpc}
  567. PalPtr : ^PalRec;
  568. {$endif fpc}
  569. RealSeg: word;
  570. begin
  571. if DirectColor then
  572. Begin
  573. _GraphResult := grError;
  574. exit;
  575. end;
  576. Error := TRUE;
  577. pal.align := 0;
  578. pal.red := byte(RedValue);
  579. pal.green := byte(GreenValue);
  580. pal.blue := byte(BlueValue);
  581. { use the set/get palette function }
  582. if VESAInfo.Version >= $0200 then
  583. Begin
  584. { check if blanking bit must be set when programming }
  585. { the RAMDAC. }
  586. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  587. FunctionNr := $80
  588. else
  589. FunctionNr := $00;
  590. { Alllocate real mode buffer }
  591. {$ifndef fpc}
  592. Ptr:=GlobalDosAlloc(sizeof(palrec));
  593. { get the selector values }
  594. PalPtr := pointer(Ptr shl 16);
  595. if not assigned(PalPtr) then
  596. RunError(203);
  597. {$else fpc}
  598. Ptr:=Global_Dos_Alloc(sizeof(palrec));
  599. {$endif fpc}
  600. {get the segment value}
  601. RealSeg := word(Ptr shr 16);
  602. { setup interrupt registers }
  603. FillChar(regs, sizeof(TDPMIRegisters), #0);
  604. { copy palette values to real mode buffer }
  605. {$ifndef fpc}
  606. move(pal, palptr^, sizeof(palrec));
  607. {$else fpc}
  608. DosMemPut(RealSeg,0,pal,sizeof(palrec));
  609. {$endif fpc}
  610. regs.eax := $4F09;
  611. regs.ebx := FunctionNr;
  612. regs.ecx := $01;
  613. regs.edx := ColorNum;
  614. regs.es := RealSeg;
  615. regs.edi := 0; { offset is always zero }
  616. RealIntr($10, regs);
  617. { free real mode memory }
  618. {$ifndef fpc}
  619. GlobalDosFree(word(Ptr and $ffff));
  620. {$else fpc}
  621. If not Global_Dos_Free(word(Ptr and $ffff)) then
  622. RunError(216);
  623. {$endif fpc}
  624. if word(regs.eax) <> $004F then
  625. begin
  626. _GraphResult := grError;
  627. exit;
  628. end;
  629. end
  630. else
  631. { assume it's fully VGA compatible palette-wise. }
  632. Begin
  633. SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  634. end;
  635. end;
  636. Procedure GetVESARGBPalette(ColorNum: integer; Var
  637. RedValue, GreenValue, BlueValue : integer);
  638. var
  639. pal: PalRec;
  640. Error: boolean;
  641. palptr : ^PalRec;
  642. regs : TDPMIRegisters;
  643. RealSeg: word;
  644. ptr: longint;
  645. begin
  646. if DirectColor then
  647. Begin
  648. _GraphResult := grError;
  649. exit;
  650. end;
  651. { use the set/get palette function }
  652. if VESAInfo.Version >= $0200 then
  653. Begin
  654. { Alllocate real mode buffer }
  655. {$ifndef fpc}
  656. Ptr:=GlobalDosAlloc(sizeof(palrec));
  657. { get the selector value }
  658. PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
  659. if not assigned(PalPtr) then
  660. RunError(203);
  661. {$else fpc}
  662. Ptr:=Global_Dos_Alloc(sizeof(palrec));
  663. {$endif fpc}
  664. { get the segment value }
  665. RealSeg := word(Ptr shr 16);
  666. { setup interrupt registers }
  667. FillChar(regs, sizeof(TDPMIRegisters), #0);
  668. regs.eax := $4F09;
  669. regs.ebx := $01; { get palette data }
  670. regs.ecx := $01;
  671. regs.edx := ColorNum;
  672. regs.es := RealSeg;
  673. regs.edi := 0; { offset is always zero }
  674. RealIntr($10, regs);
  675. { copy to protected mode buffer ... }
  676. {$ifndef fpc}
  677. Move(PalPtr^, Pal, sizeof(palrec));
  678. {$else fpc}
  679. DosMemGet(RealSeg,0,Pal,sizeof(palrec));
  680. {$endif fpc}
  681. { free real mode memory }
  682. {$ifndef fpc}
  683. GlobalDosFree(word(Ptr and $ffff));
  684. {$else fpc}
  685. If not Global_Dos_Free(word(Ptr and $ffff)) then
  686. RunError(216);
  687. {$endif fpc}
  688. if word(regs.eax) <> $004F then
  689. begin
  690. _GraphResult := grError;
  691. exit;
  692. end
  693. else
  694. begin
  695. RedValue := Integer(pal.Red);
  696. GreenValue := Integer(pal.Green);
  697. BlueValue := Integer(pal.Blue);
  698. end;
  699. end
  700. else
  701. GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  702. end;
  703. {$ELSE}
  704. Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
  705. BlueValue : Integer); far;
  706. var
  707. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  708. pal: ^palrec;
  709. Error : boolean; { VBE call error }
  710. begin
  711. if DirectColor then
  712. Begin
  713. _GraphResult := grError;
  714. exit;
  715. end;
  716. Error := FALSE;
  717. new(pal);
  718. if not assigned(pal) then RunError(203);
  719. pal^.align := 0;
  720. pal^.red := byte(RedValue);
  721. pal^.green := byte(GreenValue);
  722. pal^.blue := byte(BlueValue);
  723. { use the set/get palette function }
  724. if VESAInfo.Version >= $0200 then
  725. Begin
  726. { check if blanking bit must be set when programming }
  727. { the RAMDAC. }
  728. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  729. FunctionNr := $80
  730. else
  731. FunctionNr := $00;
  732. asm
  733. mov ax, 4F09h { Set/Get Palette data }
  734. mov bl, [FunctionNr] { Set palette data }
  735. mov cx, 01h { update one palette reg. }
  736. mov dx, [ColorNum] { register number to update }
  737. les di, [pal] { get palette address }
  738. int 10h
  739. cmp ax, 004Fh { check if success }
  740. jz @noerror
  741. mov [Error], TRUE
  742. @noerror:
  743. end;
  744. if not Error then
  745. Dispose(pal)
  746. else
  747. begin
  748. _GraphResult := grError;
  749. exit;
  750. end;
  751. end
  752. else
  753. { assume it's fully VGA compatible palette-wise. }
  754. Begin
  755. SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  756. end;
  757. end;
  758. Procedure GetVESARGBPalette(ColorNum: integer; Var
  759. RedValue, GreenValue, BlueValue : integer); far;
  760. var
  761. Error: boolean;
  762. pal: ^palrec;
  763. begin
  764. if DirectColor then
  765. Begin
  766. _GraphResult := grError;
  767. exit;
  768. end;
  769. Error := FALSE;
  770. new(pal);
  771. if not assigned(pal) then RunError(203);
  772. FillChar(pal^, sizeof(palrec), #0);
  773. { use the set/get palette function }
  774. if VESAInfo.Version >= $0200 then
  775. Begin
  776. asm
  777. mov ax, 4F09h { Set/Get Palette data }
  778. mov bl, 01h { Set palette data }
  779. mov cx, 01h { update one palette reg. }
  780. mov dx, [ColorNum] { register number to update }
  781. les di, [pal] { get palette address }
  782. int 10h
  783. cmp ax, 004Fh { check if success }
  784. jz @noerror
  785. mov [Error], TRUE
  786. @noerror:
  787. end;
  788. if not Error then
  789. begin
  790. RedValue := Integer(pal^.Red);
  791. GreenValue := Integer(pal^.Green);
  792. BlueValue := Integer(pal^.Blue);
  793. Dispose(pal);
  794. end
  795. else
  796. begin
  797. _GraphResult := grError;
  798. exit;
  799. end;
  800. end
  801. else
  802. GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  803. end;
  804. {$ENDIF}
  805. procedure SetupLinear(var ModeInfo: TVESAModeInfo);
  806. begin
  807. { !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! }
  808. end;
  809. procedure SetupWindows(var ModeInfo: TVESAModeInfo);
  810. begin
  811. { now we check the windowing scheme ...}
  812. if (ModeInfo.WinAAttr and WinSupported) <> 0 then
  813. { is this window supported ... }
  814. begin
  815. { now check if the window is R/W }
  816. if (ModeInfo.WinAAttr and WinReadable) <> 0 then
  817. begin
  818. ReadWindow := 0;
  819. WinReadSeg := ModeInfo.WinASeg;
  820. end;
  821. if (ModeInfo.WinAAttr and WinWritable) <> 0 then
  822. begin
  823. WriteWindow := 0;
  824. WinWriteSeg := ModeInfo.WinASeg;
  825. end;
  826. end;
  827. if (ModeInfo.WinBAttr and WinSupported) <> 0 then
  828. { is this window supported ... }
  829. begin
  830. { OPTIMIZATION ... }
  831. { if window A supports both read/write, then we try to optimize }
  832. { everything, by using a different window for Read and/or write.}
  833. if (WinReadSeg <> 0) and (WinWriteSeg <> 0) then
  834. begin
  835. { check if winB supports read }
  836. if (ModeInfo.WinBAttr and winReadable) <> 0 then
  837. begin
  838. WinReadSeg := ModeInfo.WinBSeg;
  839. ReadWindow := 1;
  840. end
  841. else
  842. { check if WinB supports write }
  843. if (ModeInfo.WinBAttr and WinWritable) <> 0 then
  844. begin
  845. WinWriteSeg := ModeInfo.WinBSeg;
  846. WriteWindow := 1;
  847. end;
  848. end
  849. else
  850. { Window A only supported Read OR Write, no we have to make }
  851. { sure that window B supports the other mode. }
  852. if (WinReadSeg = 0) and (WinWriteSeg<>0) then
  853. begin
  854. if (ModeInfo.WinBAttr and WinReadable <> 0) then
  855. begin
  856. ReadWindow := 1;
  857. WinReadSeg := ModeInfo.WinBSeg;
  858. end
  859. else
  860. { impossible, this VESA mode is WRITE only! }
  861. begin
  862. WriteLn('Invalid VESA Window attribute.');
  863. Halt(255);
  864. end;
  865. end
  866. else
  867. if (winWriteSeg = 0) and (WinReadSeg<>0) then
  868. begin
  869. if (ModeInfo.WinBAttr and WinWritable) <> 0 then
  870. begin
  871. WriteWindow := 1;
  872. WinWriteSeg := ModeInfo.WinBSeg;
  873. end
  874. else
  875. { impossible, this VESA mode is READ only! }
  876. begin
  877. WriteLn('Invalid VESA Window attribute.');
  878. Halt(255);
  879. end;
  880. end
  881. else
  882. if (winReadSeg = 0) and (winWriteSeg = 0) then
  883. { no read/write in this mode! }
  884. begin
  885. WriteLn('Invalid VESA Window attribute.');
  886. Halt(255);
  887. end;
  888. end;
  889. { if both windows are not supported, then we can assume }
  890. { that there is ONE single NON relocatable window. }
  891. if (WinWriteSeg = 0) and (WinReadSeg = 0) then
  892. begin
  893. WinWriteSeg := ModeInfo.WinASeg;
  894. WinReadSeg := ModeInfo.WinASeg;
  895. end;
  896. { 16-bit Protected mode checking code... }
  897. { change segment values to protected mode }
  898. { selectors. }
  899. if WinReadSeg = $A000 then
  900. WinReadSeg := SegA000
  901. else
  902. if WinReadSeg = $B000 then
  903. WinReadSeg := SegB000
  904. else
  905. if WinReadSeg = $B800 then
  906. WinReadSeg := SegB800
  907. else
  908. begin
  909. WriteLn('Invalid segment address.');
  910. Halt(255);
  911. end;
  912. if WinWriteSeg = $A000 then
  913. WinWriteSeg := SegA000
  914. else
  915. if WinWriteSeg = $B000 then
  916. WinWriteSeg := SegB000
  917. else
  918. if WinWriteSeg = $B800 then
  919. WinWriteSeg := SegB800
  920. else
  921. begin
  922. WriteLn('Invalid segment address.');
  923. Halt(255);
  924. end;
  925. end;
  926. function setVESAMode(mode:word):boolean;
  927. var i:word;
  928. begin
  929. { Init mode information, for compatibility with VBE < 1.1 }
  930. FillChar(ModeInfo, sizeof(ModeInfo), #0);
  931. { get the video mode information }
  932. if getModeInfo(modeinfo, mode) then
  933. begin
  934. { checks if the hardware supports the video mode. }
  935. if (ModeInfo.attr and modeAvail) <> 0 then
  936. begin
  937. SetVESAMode := TRUE;
  938. end
  939. else
  940. begin
  941. SetVESAmode := FALSE;
  942. _GraphResult := grError;
  943. exit;
  944. end;
  945. BankShift := 0;
  946. while (64 shr BankShift) <> ModeInfo.WinGranularity do
  947. Inc(BankShift);
  948. CurrentWriteBank := -1;
  949. CurrentReadBank := -1;
  950. BytesPerLine := ModeInfo.BytesPerScanLine;
  951. { These are the window adresses ... }
  952. WinWriteSeg := 0; { This is the segment to use for writes }
  953. WinReadSeg := 0; { This is the segment to use for reads }
  954. ReadWindow := 0;
  955. WriteWindow := 0;
  956. { VBE 2.0 and higher supports >= non VGA linear buffer types...}
  957. { this is backward compatible. }
  958. if ((ModeInfo.Attr and ModeNoWindowed) <> 0) and
  959. ((ModeInfo.Attr and ModeLinearBuffer) <> 0) then
  960. SetupLinear(ModeInfo)
  961. else
  962. { if linear and windowed is supported, then use windowed }
  963. { method. }
  964. SetUpWindows(ModeInfo);
  965. asm
  966. mov ax,4F02h
  967. mov bx,mode
  968. {$ifdef fpc}
  969. push ebp
  970. {$endif fpc}
  971. int 10h
  972. {$ifdef fpc}
  973. pop ebp
  974. {$endif fpc}
  975. sub ax,004Fh
  976. cmp ax,1
  977. sbb al,al
  978. mov @RESULT,al
  979. end;
  980. end;
  981. end;
  982. function getVESAMode:word;assembler;
  983. asm {return -1 if error}
  984. mov ax,4F03h
  985. {$ifdef fpc}
  986. push ebp
  987. {$endif fpc}
  988. int 10h
  989. {$ifdef fpc}
  990. pop ebp
  991. {$endif fpc}
  992. cmp ax,004Fh
  993. je @@OK
  994. mov ax,-1
  995. jmp @@X
  996. @@OK:
  997. mov ax,bx
  998. @@X:
  999. end;
  1000. {************************************************************************}
  1001. {* VESA Modes inits *}
  1002. {************************************************************************}
  1003. procedure Init1280x1024x64k; far;
  1004. begin
  1005. SetVesaMode(m1280x1024x64k);
  1006. end;
  1007. procedure Init1280x1024x32k; far;
  1008. begin
  1009. SetVESAMode(m1280x1024x32k);
  1010. end;
  1011. procedure Init1280x1024x256; far;
  1012. begin
  1013. SetVESAMode(m1280x1024x256);
  1014. end;
  1015. procedure Init1280x1024x16; far;
  1016. begin
  1017. SetVESAMode(m1280x1024x16);
  1018. end;
  1019. procedure Init1024x768x64k; far;
  1020. begin
  1021. SetVESAMode(m1024x768x64k);
  1022. end;
  1023. procedure Init640x480x32k; far;
  1024. begin
  1025. SetVESAMode(m640x480x32k);
  1026. end;
  1027. procedure Init1024x768x256; far;
  1028. begin
  1029. SetVESAMode(m1024x768x256);
  1030. end;
  1031. procedure Init1024x768x16; far;
  1032. begin
  1033. SetVESAMode(m1024x768x16);
  1034. end;
  1035. procedure Init800x600x64k; far;
  1036. begin
  1037. SetVESAMode(m800x600x64k);
  1038. end;
  1039. procedure Init800x600x32k; far;
  1040. begin
  1041. SetVESAMode(m800x600x32k);
  1042. end;
  1043. procedure Init800x600x256; far;
  1044. begin
  1045. SetVESAMode(m800x600x256);
  1046. end;
  1047. procedure Init800x600x16; far;
  1048. begin
  1049. SetVesaMode(m800x600x16);
  1050. end;
  1051. procedure Init640x480x64k; far;
  1052. begin
  1053. SetVESAMode(m640x480x64k);
  1054. end;
  1055. procedure Init640x480x256; far;
  1056. begin
  1057. SetVESAMode(m640x480x256);
  1058. end;
  1059. procedure Init640x400x256; far;
  1060. begin
  1061. SetVESAMode(m640x400x256);
  1062. end;
  1063. procedure Init320x200x64k; far;
  1064. begin
  1065. SetVESAMode(m320x200x64k);
  1066. end;
  1067. procedure Init320x200x32k; far;
  1068. begin
  1069. SetVESAMode(m320x200x32k);
  1070. end;
  1071. {$IFDEF DPMI}
  1072. Procedure SaveStateVESA;
  1073. var
  1074. PtrLong: longint;
  1075. regs: TDPMIRegisters;
  1076. begin
  1077. SaveSupported := FALSE;
  1078. SavePtr := nil;
  1079. { Get the video mode }
  1080. asm
  1081. mov ah,0fh
  1082. {$ifdef fpc}
  1083. push ebp
  1084. {$endif fpc}
  1085. int 10h
  1086. {$ifdef fpc}
  1087. pop ebp
  1088. {$endif fpc}
  1089. mov [VideoMode], al
  1090. end;
  1091. { Prepare to save video state...}
  1092. asm
  1093. mov ax, 4F04h { get buffer size to save state }
  1094. mov dx, 00h
  1095. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1096. {$ifdef fpc}
  1097. push ebp
  1098. {$endif fpc}
  1099. int 10h
  1100. {$ifdef fpc}
  1101. pop ebp
  1102. {$endif fpc}
  1103. mov [StateSize], bx
  1104. cmp al,04fh
  1105. jnz @notok
  1106. mov [SaveSupported],TRUE
  1107. @notok:
  1108. end;
  1109. if SaveSupported then
  1110. begin
  1111. {$ifndef fpc}
  1112. PtrLong:=GlobalDosAlloc(64*StateSize); { values returned in 64-byte blocks }
  1113. {$else fpc}
  1114. PtrLong:=Global_Dos_Alloc(64*StateSize); { values returned in 64-byte blocks }
  1115. {$endif fpc}
  1116. if PtrLong = 0 then
  1117. RunError(203);
  1118. SavePtr := pointer(longint(PtrLong and $0000ffff) shl 16);
  1119. {$ifndef fpc}
  1120. { In FPC mode, we can't do anything with this (no far pointers) }
  1121. { However, we still need to keep it to be able to free the }
  1122. { memory afterwards. Since this data is not accessed in PM code, }
  1123. { there's no need to save it in a seperate buffer (JM) }
  1124. if not assigned(SavePtr) then
  1125. RunError(203);
  1126. {$endif fpc}
  1127. RealStateSeg := word(PtrLong shr 16);
  1128. FillChar(regs, sizeof(regs), #0);
  1129. { call the real mode interrupt ... }
  1130. regs.eax := $4F04; { save the state buffer }
  1131. regs.ecx := $0F; { Save DAC / Data areas / Hardware states }
  1132. regs.edx := $01; { save state }
  1133. regs.es := RealStateSeg;
  1134. regs.ebx := 0;
  1135. RealIntr($10,regs);
  1136. FillChar(regs, sizeof(regs), #0);
  1137. { restore state, according to Ralph Brown Interrupt list }
  1138. { some BIOS corrupt the hardware after a save... }
  1139. regs.eax := $4F04; { restore the state buffer }
  1140. regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
  1141. regs.edx := $02;
  1142. regs.es := RealStateSeg;
  1143. regs.ebx := 0;
  1144. RealIntr($10,regs);
  1145. end;
  1146. end;
  1147. procedure RestoreStateVESA;
  1148. var
  1149. regs:TDPMIRegisters;
  1150. begin
  1151. { go back to the old video mode...}
  1152. asm
  1153. mov ah,00
  1154. mov al,[VideoMode]
  1155. {$ifdef fpc}
  1156. push ebp
  1157. {$endif fpc}
  1158. int 10h
  1159. {$ifdef fpc}
  1160. pop ebp
  1161. {$endif fpc}
  1162. end;
  1163. { then restore all state information }
  1164. {$ifndef fpc}
  1165. if assigned(SavePtr) and (SaveSupported=TRUE) then
  1166. {$else fpc}
  1167. { No far pointer support, so it's possible that that assigned(SavePtr) }
  1168. { would return false under FPC. Just check if it's different from nil. }
  1169. if (SavePtr <> nil) and (SaveSupported=TRUE) then
  1170. {$endif fpc}
  1171. begin
  1172. FillChar(regs, sizeof(regs), #0);
  1173. { restore state, according to Ralph Brown Interrupt list }
  1174. { some BIOS corrupt the hardware after a save... }
  1175. regs.eax := $4F04; { restore the state buffer }
  1176. regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
  1177. regs.edx := $02; { restore state }
  1178. regs.es := RealStateSeg;
  1179. regs.ebx := 0;
  1180. RealIntr($10,regs);
  1181. {$ifndef fpc}
  1182. if GlobalDosFree(longint(SavePtr) shr 16)<>0 then
  1183. {$else fpc}
  1184. if Not(Global_Dos_Free(longint(SavePtr) shr 16)) then
  1185. {$endif fpc}
  1186. RunError(216);
  1187. SavePtr := nil;
  1188. end;
  1189. end;
  1190. {$ELSE}
  1191. {**************************************************************}
  1192. {* Real mode routines *}
  1193. {**************************************************************}
  1194. Procedure SaveStateVESA; far;
  1195. begin
  1196. SavePtr := nil;
  1197. SaveSupported := FALSE;
  1198. { Get the video mode }
  1199. asm
  1200. mov ah,0fh
  1201. int 10h
  1202. mov [VideoMode], al
  1203. end;
  1204. { Prepare to save video state...}
  1205. asm
  1206. mov ax, 1C00h { get buffer size to save state }
  1207. mov cx, 00000111b { Save DAC / Data areas / Hardware states }
  1208. int 10h
  1209. mov [StateSize], bx
  1210. cmp al,01ch
  1211. jnz @notok
  1212. mov [SaveSupported],TRUE
  1213. @notok:
  1214. end;
  1215. if SaveSupported then
  1216. Begin
  1217. GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
  1218. if not assigned(SavePtr) then
  1219. RunError(203);
  1220. asm
  1221. mov ax, 4F04h { save the state buffer }
  1222. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1223. mov dx, 01h
  1224. mov es, WORD PTR [SavePtr+2]
  1225. mov bx, WORD PTR [SavePtr]
  1226. int 10h
  1227. end;
  1228. { restore state, according to Ralph Brown Interrupt list }
  1229. { some BIOS corrupt the hardware after a save... }
  1230. asm
  1231. mov ax, 4F04h { save the state buffer }
  1232. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1233. mov dx, 02h
  1234. mov es, WORD PTR [SavePtr+2]
  1235. mov bx, WORD PTR [SavePtr]
  1236. int 10h
  1237. end;
  1238. end;
  1239. end;
  1240. procedure RestoreStateVESA; far;
  1241. begin
  1242. { go back to the old video mode...}
  1243. asm
  1244. mov ah,00
  1245. mov al,[VideoMode]
  1246. int 10h
  1247. end;
  1248. { then restore all state information }
  1249. if assigned(SavePtr) and (SaveSupported=TRUE) then
  1250. begin
  1251. { restore state, according to Ralph Brown Interrupt list }
  1252. asm
  1253. mov ax, 4F04h { save the state buffer }
  1254. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1255. mov dx, 02h { restore state }
  1256. mov es, WORD PTR [SavePtr+2]
  1257. mov bx, WORD PTR [SavePtr]
  1258. int 10h
  1259. end;
  1260. FreeMem(SavePtr, 64*StateSize);
  1261. SavePtr := nil;
  1262. end;
  1263. end;
  1264. {$ENDIF DPMI}
  1265. {************************************************************************}
  1266. {* VESA Page flipping routines *}
  1267. {************************************************************************}
  1268. { Note: These routines, according to the VBE3 specification, will NOT }
  1269. { work with the 24 bpp modes, because of the alignment. }
  1270. {************************************************************************}
  1271. procedure SetVisualVESA(page: word); far;
  1272. { two page support... }
  1273. begin
  1274. if page > HardwarePages then exit;
  1275. end;
  1276. procedure SetActiveVESA(page: word); far;
  1277. { two page support... }
  1278. begin
  1279. end;
  1280. {
  1281. $Log$
  1282. Revision 1.7 1999-07-14 15:21:49 jonas
  1283. * fixed initialization of bankshift var ('64 shr banshift' instead of shl)
  1284. Revision 1.6 1999/07/14 13:17:29 jonas
  1285. * bugfix in getmodeinfo (SizeOf(TModeInfo) -> SizeOf(TVESAModeInfo))
  1286. * as the result of the above bugfix, the graph unit doesn't crash
  1287. anymore under FPC if compiler with -dsupportVESA, but it doesn't
  1288. work yet either...
  1289. Revision 1.5 1999/07/12 13:28:33 jonas
  1290. * forgot log tag in previous commit
  1291. }