vesa.inc 41 KB

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