vesa.inc 44 KB

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