vesa.inc 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494
  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. Case CurrentWriteMode of
  407. XorPut:
  408. Begin
  409. SetReadBank(integer(offs shr 16));
  410. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] xor byte(color);
  411. End;
  412. AndPut:
  413. Begin
  414. SetReadBank(integer(offs shr 16));
  415. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] And byte(color);
  416. End;
  417. OrPut:
  418. Begin
  419. SetReadBank(integer(offs shr 16));
  420. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] or byte(color);
  421. End;
  422. NormalPut:
  423. mem[WinWriteSeg : word(offs)] := byte(color)
  424. Else mem[WinWriteSeg : word(offs)] := byte(color);
  425. End;
  426. end;
  427. procedure DirectPutPixVESA256(x, y : integer); far;
  428. var
  429. bank : word;
  430. offs : longint;
  431. begin
  432. offs := longint(y) * BytesPerLine + x;
  433. SetWriteBank(integer(offs shr 16));
  434. Case CurrentWriteMode of
  435. XorPut:
  436. Begin
  437. SetReadBank(integer(offs shr 16));
  438. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] xor byte(currentcolor);
  439. End;
  440. AndPut:
  441. Begin
  442. SetReadBank(integer(offs shr 16));
  443. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] And byte(currentcolor);
  444. End;
  445. OrPut:
  446. Begin
  447. SetReadBank(integer(offs shr 16));
  448. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] or byte(currentcolor);
  449. End;
  450. NormalPut:
  451. mem[WinWriteSeg : word(offs)] := byte(currentcolor)
  452. else mem[WinWriteSeg : word(offs)] := byte(CurrentColor);
  453. End;
  454. end;
  455. function GetPixVESA256(x, y : integer): word; far;
  456. var
  457. bank : word;
  458. offs : longint;
  459. begin
  460. X:= X + StartXViewPort;
  461. Y:= Y + StartYViewPort;
  462. offs := longint(y) * BytesPerLine + x;
  463. SetReadBank(integer(offs shr 16));
  464. GetPixVESA256:=mem[WinReadSeg : word(offs)];
  465. end;
  466. {************************************************************************}
  467. {* 15/16bit pixels VESA mode routines *}
  468. {************************************************************************}
  469. procedure PutPixVESA32k(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. procedure PutPixVESA64k(x, y : integer; color : word); far;
  489. var
  490. bank : word;
  491. offs : longint;
  492. begin
  493. X:= X + StartXViewPort;
  494. Y:= Y + StartYViewPort;
  495. { convert to absolute coordinates and then verify clipping...}
  496. if ClipPixels then
  497. Begin
  498. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  499. exit;
  500. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  501. exit;
  502. end;
  503. offs := longint(y) * BytesPerLine + 2*x;
  504. SetWriteBank(integer(offs shr 16));
  505. memW[WinWriteSeg : word(offs)] := color;
  506. end;
  507. function GetPixVESA32k(x, y : integer): word; far;
  508. var
  509. bank : word;
  510. offs : longint;
  511. begin
  512. X:= X + StartXViewPort;
  513. Y:= Y + StartYViewPort;
  514. offs := longint(y) * BytesPerLine + 2*x;
  515. SetReadBank(integer(offs shr 16));
  516. GetPixVESA32k:=memW[WinReadSeg : word(offs)];
  517. end;
  518. function GetPixVESA64k(x, y : integer): word; far;
  519. var
  520. bank : word;
  521. offs : longint;
  522. begin
  523. X:= X + StartXViewPort;
  524. Y:= Y + StartYViewPort;
  525. offs := longint(y) * BytesPerLine + 2*x;
  526. SetReadBank(integer(offs shr 16));
  527. GetPixVESA64k:=memW[WinReadSeg : word(offs)];
  528. end;
  529. procedure DirectPutPixVESA32k(x, y : integer); far;
  530. var
  531. bank : word;
  532. offs : longint;
  533. begin
  534. offs := longint(y) * BytesPerLine + 2*x;
  535. SetWriteBank(integer((offs shr 16) and $ff));
  536. memW[WinWriteSeg : word(offs)] := CurrentColor;
  537. end;
  538. procedure DirectPutPixVESA64k(x, y : integer); far;
  539. var
  540. bank : word;
  541. offs : longint;
  542. begin
  543. offs := longint(y) * BytesPerLine + 2*x;
  544. SetWriteBank(integer(offs shr 16));
  545. memW[WinWriteSeg : word(offs)] := CurrentColor;
  546. end;
  547. {************************************************************************}
  548. {* 4-bit pixels VESA mode routines *}
  549. {************************************************************************}
  550. procedure PutPixVESA16(x, y : integer; color : word); far;
  551. var
  552. bank : word;
  553. offs : longint;
  554. dummy_read : byte;
  555. begin
  556. X:= X + StartXViewPort;
  557. Y:= Y + StartYViewPort;
  558. { convert to absolute coordinates and then verify clipping...}
  559. if ClipPixels then
  560. Begin
  561. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  562. exit;
  563. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  564. exit;
  565. end;
  566. { this can be done only once at InitGraph }
  567. PortW[$3C4] := $0f02;
  568. PortW[$3CE] := $0003;
  569. PortW[$3CE] := $0205;
  570. { }
  571. offs := longint(y) * BytesPerLine + (x div 8);
  572. SetWriteBank(integer(offs shr 16));
  573. port[$3CE] := $08;
  574. port[$3CF] := ($80 shr (x and 7));
  575. dummy_read := mem[WinWriteSeg : word(offs)];
  576. mem[winWriteSeg : offs] := byte(color);
  577. { this can be done only once at DoneGraph..}
  578. PortW[$3CE] := $FF08;
  579. PortW[$3CE] := $0005;
  580. { }
  581. end;
  582. procedure DirectPutPixVESA16(x, y : integer); far;
  583. var
  584. bank : word;
  585. offs : longint;
  586. dummy_read : byte;
  587. begin
  588. { this can be done only once at InitGraph }
  589. PortW[$3C4] := $0f02;
  590. PortW[$3CE] := $0003;
  591. PortW[$3CE] := $0205;
  592. { }
  593. offs := longint(y) * BytesPerLine + (x div 8);
  594. SetWriteBank(integer(offs shr 16));
  595. port[$3CE] := $08;
  596. port[$3CF] := ($80 shr (x and 7));
  597. dummy_read := mem[WinWriteSeg : word(offs)];
  598. mem[winWriteSeg : offs] := byte(CurrentColor);
  599. { this can be done only once at DoneGraph..}
  600. PortW[$3CE] := $FF08;
  601. PortW[$3CE] := $0005;
  602. { }
  603. end;
  604. {************************************************************************}
  605. {* VESA Palette entries *}
  606. {************************************************************************}
  607. {$IFDEF DPMI}
  608. Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
  609. BlueValue : Integer);
  610. var
  611. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  612. pal: palrec;
  613. Error : boolean; { VBE call error }
  614. regs: TDPMIRegisters;
  615. Ptr: longint;
  616. {$ifndef fpc}
  617. PalPtr : ^PalRec;
  618. {$endif fpc}
  619. RealSeg: word;
  620. begin
  621. if DirectColor then
  622. Begin
  623. _GraphResult := grError;
  624. exit;
  625. end;
  626. Error := TRUE;
  627. pal.align := 0;
  628. pal.red := byte(RedValue);
  629. pal.green := byte(GreenValue);
  630. pal.blue := byte(BlueValue);
  631. { use the set/get palette function }
  632. if VESAInfo.Version >= $0200 then
  633. Begin
  634. { check if blanking bit must be set when programming }
  635. { the RAMDAC. }
  636. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  637. FunctionNr := $80
  638. else
  639. FunctionNr := $00;
  640. { Alllocate real mode buffer }
  641. {$ifndef fpc}
  642. Ptr:=GlobalDosAlloc(sizeof(palrec));
  643. { get the selector values }
  644. PalPtr := pointer(Ptr shl 16);
  645. if not assigned(PalPtr) then
  646. RunError(203);
  647. {$else fpc}
  648. Ptr:=Global_Dos_Alloc(sizeof(palrec));
  649. {$endif fpc}
  650. {get the segment value}
  651. RealSeg := word(Ptr shr 16);
  652. { setup interrupt registers }
  653. FillChar(regs, sizeof(TDPMIRegisters), #0);
  654. { copy palette values to real mode buffer }
  655. {$ifndef fpc}
  656. move(pal, palptr^, sizeof(palrec));
  657. {$else fpc}
  658. DosMemPut(RealSeg,0,pal,sizeof(palrec));
  659. {$endif fpc}
  660. regs.eax := $4F09;
  661. regs.ebx := FunctionNr;
  662. regs.ecx := $01;
  663. regs.edx := ColorNum;
  664. regs.es := RealSeg;
  665. regs.edi := 0; { offset is always zero }
  666. RealIntr($10, regs);
  667. { free real mode memory }
  668. {$ifndef fpc}
  669. GlobalDosFree(word(Ptr and $ffff));
  670. {$else fpc}
  671. If not Global_Dos_Free(word(Ptr and $ffff)) then
  672. RunError(216);
  673. {$endif fpc}
  674. if word(regs.eax) <> $004F then
  675. begin
  676. _GraphResult := grError;
  677. exit;
  678. end;
  679. end
  680. else
  681. { assume it's fully VGA compatible palette-wise. }
  682. Begin
  683. SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  684. end;
  685. end;
  686. Procedure GetVESARGBPalette(ColorNum: integer; Var
  687. RedValue, GreenValue, BlueValue : integer);
  688. var
  689. pal: PalRec;
  690. Error: boolean;
  691. palptr : ^PalRec;
  692. regs : TDPMIRegisters;
  693. RealSeg: word;
  694. ptr: longint;
  695. begin
  696. if DirectColor then
  697. Begin
  698. _GraphResult := grError;
  699. exit;
  700. end;
  701. { use the set/get palette function }
  702. if VESAInfo.Version >= $0200 then
  703. Begin
  704. { Alllocate real mode buffer }
  705. {$ifndef fpc}
  706. Ptr:=GlobalDosAlloc(sizeof(palrec));
  707. { get the selector value }
  708. PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
  709. if not assigned(PalPtr) then
  710. RunError(203);
  711. {$else fpc}
  712. Ptr:=Global_Dos_Alloc(sizeof(palrec));
  713. {$endif fpc}
  714. { get the segment value }
  715. RealSeg := word(Ptr shr 16);
  716. { setup interrupt registers }
  717. FillChar(regs, sizeof(TDPMIRegisters), #0);
  718. regs.eax := $4F09;
  719. regs.ebx := $01; { get palette data }
  720. regs.ecx := $01;
  721. regs.edx := ColorNum;
  722. regs.es := RealSeg;
  723. regs.edi := 0; { offset is always zero }
  724. RealIntr($10, regs);
  725. { copy to protected mode buffer ... }
  726. {$ifndef fpc}
  727. Move(PalPtr^, Pal, sizeof(palrec));
  728. {$else fpc}
  729. DosMemGet(RealSeg,0,Pal,sizeof(palrec));
  730. {$endif fpc}
  731. { free real mode memory }
  732. {$ifndef fpc}
  733. GlobalDosFree(word(Ptr and $ffff));
  734. {$else fpc}
  735. If not Global_Dos_Free(word(Ptr and $ffff)) then
  736. RunError(216);
  737. {$endif fpc}
  738. if word(regs.eax) <> $004F then
  739. begin
  740. _GraphResult := grError;
  741. exit;
  742. end
  743. else
  744. begin
  745. RedValue := Integer(pal.Red);
  746. GreenValue := Integer(pal.Green);
  747. BlueValue := Integer(pal.Blue);
  748. end;
  749. end
  750. else
  751. GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  752. end;
  753. {$ELSE}
  754. Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
  755. BlueValue : Integer); far;
  756. var
  757. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  758. pal: ^palrec;
  759. Error : boolean; { VBE call error }
  760. begin
  761. if DirectColor then
  762. Begin
  763. _GraphResult := grError;
  764. exit;
  765. end;
  766. Error := FALSE;
  767. new(pal);
  768. if not assigned(pal) then RunError(203);
  769. pal^.align := 0;
  770. pal^.red := byte(RedValue);
  771. pal^.green := byte(GreenValue);
  772. pal^.blue := byte(BlueValue);
  773. { use the set/get palette function }
  774. if VESAInfo.Version >= $0200 then
  775. Begin
  776. { check if blanking bit must be set when programming }
  777. { the RAMDAC. }
  778. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  779. FunctionNr := $80
  780. else
  781. FunctionNr := $00;
  782. asm
  783. mov ax, 4F09h { Set/Get Palette data }
  784. mov bl, [FunctionNr] { Set palette data }
  785. mov cx, 01h { update one palette reg. }
  786. mov dx, [ColorNum] { register number to update }
  787. les di, [pal] { get palette address }
  788. int 10h
  789. cmp ax, 004Fh { check if success }
  790. jz @noerror
  791. mov [Error], TRUE
  792. @noerror:
  793. end;
  794. if not Error then
  795. Dispose(pal)
  796. else
  797. begin
  798. _GraphResult := grError;
  799. exit;
  800. end;
  801. end
  802. else
  803. { assume it's fully VGA compatible palette-wise. }
  804. Begin
  805. SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  806. end;
  807. end;
  808. Procedure GetVESARGBPalette(ColorNum: integer; Var
  809. RedValue, GreenValue, BlueValue : integer); far;
  810. var
  811. Error: boolean;
  812. pal: ^palrec;
  813. begin
  814. if DirectColor then
  815. Begin
  816. _GraphResult := grError;
  817. exit;
  818. end;
  819. Error := FALSE;
  820. new(pal);
  821. if not assigned(pal) then RunError(203);
  822. FillChar(pal^, sizeof(palrec), #0);
  823. { use the set/get palette function }
  824. if VESAInfo.Version >= $0200 then
  825. Begin
  826. asm
  827. mov ax, 4F09h { Set/Get Palette data }
  828. mov bl, 01h { Set palette data }
  829. mov cx, 01h { update one palette reg. }
  830. mov dx, [ColorNum] { register number to update }
  831. les di, [pal] { get palette address }
  832. int 10h
  833. cmp ax, 004Fh { check if success }
  834. jz @noerror
  835. mov [Error], TRUE
  836. @noerror:
  837. end;
  838. if not Error then
  839. begin
  840. RedValue := Integer(pal^.Red);
  841. GreenValue := Integer(pal^.Green);
  842. BlueValue := Integer(pal^.Blue);
  843. Dispose(pal);
  844. end
  845. else
  846. begin
  847. _GraphResult := grError;
  848. exit;
  849. end;
  850. end
  851. else
  852. GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  853. end;
  854. {$ENDIF}
  855. procedure SetupLinear(var ModeInfo: TVESAModeInfo);
  856. begin
  857. { !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! }
  858. end;
  859. procedure SetupWindows(var ModeInfo: TVESAModeInfo);
  860. begin
  861. { now we check the windowing scheme ...}
  862. if (ModeInfo.WinAAttr and WinSupported) <> 0 then
  863. { is this window supported ... }
  864. begin
  865. { now check if the window is R/W }
  866. if (ModeInfo.WinAAttr and WinReadable) <> 0 then
  867. begin
  868. ReadWindow := 0;
  869. WinReadSeg := ModeInfo.WinASeg;
  870. end;
  871. if (ModeInfo.WinAAttr and WinWritable) <> 0 then
  872. begin
  873. WriteWindow := 0;
  874. WinWriteSeg := ModeInfo.WinASeg;
  875. end;
  876. end;
  877. if (ModeInfo.WinBAttr and WinSupported) <> 0 then
  878. { is this window supported ... }
  879. begin
  880. { OPTIMIZATION ... }
  881. { if window A supports both read/write, then we try to optimize }
  882. { everything, by using a different window for Read and/or write.}
  883. if (WinReadSeg <> 0) and (WinWriteSeg <> 0) then
  884. begin
  885. { check if winB supports read }
  886. if (ModeInfo.WinBAttr and winReadable) <> 0 then
  887. begin
  888. WinReadSeg := ModeInfo.WinBSeg;
  889. ReadWindow := 1;
  890. end
  891. else
  892. { check if WinB supports write }
  893. if (ModeInfo.WinBAttr and WinWritable) <> 0 then
  894. begin
  895. WinWriteSeg := ModeInfo.WinBSeg;
  896. WriteWindow := 1;
  897. end;
  898. end
  899. else
  900. { Window A only supported Read OR Write, no we have to make }
  901. { sure that window B supports the other mode. }
  902. if (WinReadSeg = 0) and (WinWriteSeg<>0) then
  903. begin
  904. if (ModeInfo.WinBAttr and WinReadable <> 0) then
  905. begin
  906. ReadWindow := 1;
  907. WinReadSeg := ModeInfo.WinBSeg;
  908. end
  909. else
  910. { impossible, this VESA mode is WRITE only! }
  911. begin
  912. WriteLn('Invalid VESA Window attribute.');
  913. Halt(255);
  914. end;
  915. end
  916. else
  917. if (winWriteSeg = 0) and (WinReadSeg<>0) then
  918. begin
  919. if (ModeInfo.WinBAttr and WinWritable) <> 0 then
  920. begin
  921. WriteWindow := 1;
  922. WinWriteSeg := ModeInfo.WinBSeg;
  923. end
  924. else
  925. { impossible, this VESA mode is READ only! }
  926. begin
  927. WriteLn('Invalid VESA Window attribute.');
  928. Halt(255);
  929. end;
  930. end
  931. else
  932. if (winReadSeg = 0) and (winWriteSeg = 0) then
  933. { no read/write in this mode! }
  934. begin
  935. WriteLn('Invalid VESA Window attribute.');
  936. Halt(255);
  937. end;
  938. end;
  939. { if both windows are not supported, then we can assume }
  940. { that there is ONE single NON relocatable window. }
  941. if (WinWriteSeg = 0) and (WinReadSeg = 0) then
  942. begin
  943. WinWriteSeg := ModeInfo.WinASeg;
  944. WinReadSeg := ModeInfo.WinASeg;
  945. end;
  946. { 16-bit Protected mode checking code... }
  947. { change segment values to protected mode }
  948. { selectors. }
  949. if WinReadSeg = $A000 then
  950. WinReadSeg := SegA000
  951. else
  952. if WinReadSeg = $B000 then
  953. WinReadSeg := SegB000
  954. else
  955. if WinReadSeg = $B800 then
  956. WinReadSeg := SegB800
  957. else
  958. begin
  959. WriteLn('Invalid segment address.');
  960. Halt(255);
  961. end;
  962. if WinWriteSeg = $A000 then
  963. WinWriteSeg := SegA000
  964. else
  965. if WinWriteSeg = $B000 then
  966. WinWriteSeg := SegB000
  967. else
  968. if WinWriteSeg = $B800 then
  969. WinWriteSeg := SegB800
  970. else
  971. begin
  972. WriteLn('Invalid segment address.');
  973. Halt(255);
  974. end;
  975. end;
  976. function setVESAMode(mode:word):boolean;
  977. var i:word;
  978. begin
  979. { Init mode information, for compatibility with VBE < 1.1 }
  980. FillChar(ModeInfo, sizeof(ModeInfo), #0);
  981. { get the video mode information }
  982. if getModeInfo(modeinfo, mode) then
  983. begin
  984. { checks if the hardware supports the video mode. }
  985. if (ModeInfo.attr and modeAvail) <> 0 then
  986. begin
  987. SetVESAMode := TRUE;
  988. end
  989. else
  990. begin
  991. SetVESAmode := FALSE;
  992. _GraphResult := grError;
  993. exit;
  994. end;
  995. BankShift := 0;
  996. while (64 shr BankShift) <> ModeInfo.WinGranularity do
  997. Inc(BankShift);
  998. CurrentWriteBank := -1;
  999. CurrentReadBank := -1;
  1000. BytesPerLine := ModeInfo.BytesPerScanLine;
  1001. { These are the window adresses ... }
  1002. WinWriteSeg := 0; { This is the segment to use for writes }
  1003. WinReadSeg := 0; { This is the segment to use for reads }
  1004. ReadWindow := 0;
  1005. WriteWindow := 0;
  1006. { VBE 2.0 and higher supports >= non VGA linear buffer types...}
  1007. { this is backward compatible. }
  1008. if ((ModeInfo.Attr and ModeNoWindowed) <> 0) and
  1009. ((ModeInfo.Attr and ModeLinearBuffer) <> 0) then
  1010. SetupLinear(ModeInfo)
  1011. else
  1012. { if linear and windowed is supported, then use windowed }
  1013. { method. }
  1014. SetUpWindows(ModeInfo);
  1015. asm
  1016. mov ax,4F02h
  1017. mov bx,mode
  1018. {$ifdef fpc}
  1019. push ebp
  1020. {$endif fpc}
  1021. int 10h
  1022. {$ifdef fpc}
  1023. pop ebp
  1024. {$endif fpc}
  1025. sub ax,004Fh
  1026. cmp ax,1
  1027. sbb al,al
  1028. mov @RESULT,al
  1029. end;
  1030. end;
  1031. end;
  1032. function getVESAMode:word;assembler;
  1033. asm {return -1 if error}
  1034. mov ax,4F03h
  1035. {$ifdef fpc}
  1036. push ebp
  1037. {$endif fpc}
  1038. int 10h
  1039. {$ifdef fpc}
  1040. pop ebp
  1041. {$endif fpc}
  1042. cmp ax,004Fh
  1043. je @@OK
  1044. mov ax,-1
  1045. jmp @@X
  1046. @@OK:
  1047. mov ax,bx
  1048. @@X:
  1049. end;
  1050. {************************************************************************}
  1051. {* VESA Modes inits *}
  1052. {************************************************************************}
  1053. procedure Init1280x1024x64k; far;
  1054. begin
  1055. SetVesaMode(m1280x1024x64k);
  1056. end;
  1057. procedure Init1280x1024x32k; far;
  1058. begin
  1059. SetVESAMode(m1280x1024x32k);
  1060. end;
  1061. procedure Init1280x1024x256; far;
  1062. begin
  1063. SetVESAMode(m1280x1024x256);
  1064. end;
  1065. procedure Init1280x1024x16; far;
  1066. begin
  1067. SetVESAMode(m1280x1024x16);
  1068. end;
  1069. procedure Init1024x768x64k; far;
  1070. begin
  1071. SetVESAMode(m1024x768x64k);
  1072. end;
  1073. procedure Init640x480x32k; far;
  1074. begin
  1075. SetVESAMode(m640x480x32k);
  1076. end;
  1077. procedure Init1024x768x256; far;
  1078. begin
  1079. SetVESAMode(m1024x768x256);
  1080. end;
  1081. procedure Init1024x768x16; far;
  1082. begin
  1083. SetVESAMode(m1024x768x16);
  1084. end;
  1085. procedure Init800x600x64k; far;
  1086. begin
  1087. SetVESAMode(m800x600x64k);
  1088. end;
  1089. procedure Init800x600x32k; far;
  1090. begin
  1091. SetVESAMode(m800x600x32k);
  1092. end;
  1093. procedure Init800x600x256; far;
  1094. begin
  1095. SetVESAMode(m800x600x256);
  1096. end;
  1097. procedure Init800x600x16; far;
  1098. begin
  1099. SetVesaMode(m800x600x16);
  1100. end;
  1101. procedure Init640x480x64k; far;
  1102. begin
  1103. SetVESAMode(m640x480x64k);
  1104. end;
  1105. procedure Init640x480x256; far;
  1106. begin
  1107. SetVESAMode(m640x480x256);
  1108. end;
  1109. procedure Init640x400x256; far;
  1110. begin
  1111. SetVESAMode(m640x400x256);
  1112. end;
  1113. procedure Init320x200x64k; far;
  1114. begin
  1115. SetVESAMode(m320x200x64k);
  1116. end;
  1117. procedure Init320x200x32k; far;
  1118. begin
  1119. SetVESAMode(m320x200x32k);
  1120. end;
  1121. {$IFDEF DPMI}
  1122. Procedure SaveStateVESA;
  1123. var
  1124. PtrLong: longint;
  1125. regs: TDPMIRegisters;
  1126. begin
  1127. SaveSupported := FALSE;
  1128. SavePtr := nil;
  1129. { Get the video mode }
  1130. asm
  1131. mov ah,0fh
  1132. {$ifdef fpc}
  1133. push ebp
  1134. {$endif fpc}
  1135. int 10h
  1136. {$ifdef fpc}
  1137. pop ebp
  1138. {$endif fpc}
  1139. mov [VideoMode], al
  1140. end;
  1141. { Prepare to save video state...}
  1142. asm
  1143. mov ax, 4F04h { get buffer size to save state }
  1144. mov dx, 00h
  1145. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1146. {$ifdef fpc}
  1147. push ebp
  1148. {$endif fpc}
  1149. int 10h
  1150. {$ifdef fpc}
  1151. pop ebp
  1152. {$endif fpc}
  1153. mov [StateSize], bx
  1154. cmp al,04fh
  1155. jnz @notok
  1156. mov [SaveSupported],TRUE
  1157. @notok:
  1158. end;
  1159. if SaveSupported then
  1160. begin
  1161. {$ifndef fpc}
  1162. PtrLong:=GlobalDosAlloc(64*StateSize); { values returned in 64-byte blocks }
  1163. {$else fpc}
  1164. PtrLong:=Global_Dos_Alloc(64*StateSize); { values returned in 64-byte blocks }
  1165. {$endif fpc}
  1166. if PtrLong = 0 then
  1167. RunError(203);
  1168. SavePtr := pointer(longint(PtrLong and $0000ffff) shl 16);
  1169. {$ifndef fpc}
  1170. { In FPC mode, we can't do anything with this (no far pointers) }
  1171. { However, we still need to keep it to be able to free the }
  1172. { memory afterwards. Since this data is not accessed in PM code, }
  1173. { there's no need to save it in a seperate buffer (JM) }
  1174. if not assigned(SavePtr) then
  1175. RunError(203);
  1176. {$endif fpc}
  1177. RealStateSeg := word(PtrLong shr 16);
  1178. FillChar(regs, sizeof(regs), #0);
  1179. { call the real mode interrupt ... }
  1180. regs.eax := $4F04; { save the state buffer }
  1181. regs.ecx := $0F; { Save DAC / Data areas / Hardware states }
  1182. regs.edx := $01; { save state }
  1183. regs.es := RealStateSeg;
  1184. regs.ebx := 0;
  1185. RealIntr($10,regs);
  1186. FillChar(regs, sizeof(regs), #0);
  1187. { restore state, according to Ralph Brown Interrupt list }
  1188. { some BIOS corrupt the hardware after a save... }
  1189. regs.eax := $4F04; { restore the state buffer }
  1190. regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
  1191. regs.edx := $02;
  1192. regs.es := RealStateSeg;
  1193. regs.ebx := 0;
  1194. RealIntr($10,regs);
  1195. end;
  1196. end;
  1197. procedure RestoreStateVESA;
  1198. var
  1199. regs:TDPMIRegisters;
  1200. begin
  1201. { go back to the old video mode...}
  1202. asm
  1203. mov ah,00
  1204. mov al,[VideoMode]
  1205. {$ifdef fpc}
  1206. push ebp
  1207. {$endif fpc}
  1208. int 10h
  1209. {$ifdef fpc}
  1210. pop ebp
  1211. {$endif fpc}
  1212. end;
  1213. { then restore all state information }
  1214. {$ifndef fpc}
  1215. if assigned(SavePtr) and (SaveSupported=TRUE) then
  1216. {$else fpc}
  1217. { No far pointer support, so it's possible that that assigned(SavePtr) }
  1218. { would return false under FPC. Just check if it's different from nil. }
  1219. if (SavePtr <> nil) and (SaveSupported=TRUE) then
  1220. {$endif fpc}
  1221. begin
  1222. FillChar(regs, sizeof(regs), #0);
  1223. { restore state, according to Ralph Brown Interrupt list }
  1224. { some BIOS corrupt the hardware after a save... }
  1225. regs.eax := $4F04; { restore the state buffer }
  1226. regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
  1227. regs.edx := $02; { restore state }
  1228. regs.es := RealStateSeg;
  1229. regs.ebx := 0;
  1230. RealIntr($10,regs);
  1231. {$ifndef fpc}
  1232. if GlobalDosFree(longint(SavePtr) shr 16)<>0 then
  1233. {$else fpc}
  1234. if Not(Global_Dos_Free(longint(SavePtr) shr 16)) then
  1235. {$endif fpc}
  1236. RunError(216);
  1237. SavePtr := nil;
  1238. end;
  1239. end;
  1240. {$ELSE}
  1241. {**************************************************************}
  1242. {* Real mode routines *}
  1243. {**************************************************************}
  1244. Procedure SaveStateVESA; far;
  1245. begin
  1246. SavePtr := nil;
  1247. SaveSupported := FALSE;
  1248. { Get the video mode }
  1249. asm
  1250. mov ah,0fh
  1251. int 10h
  1252. mov [VideoMode], al
  1253. end;
  1254. { Prepare to save video state...}
  1255. asm
  1256. mov ax, 1C00h { get buffer size to save state }
  1257. mov cx, 00000111b { Save DAC / Data areas / Hardware states }
  1258. int 10h
  1259. mov [StateSize], bx
  1260. cmp al,01ch
  1261. jnz @notok
  1262. mov [SaveSupported],TRUE
  1263. @notok:
  1264. end;
  1265. if SaveSupported then
  1266. Begin
  1267. GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
  1268. if not assigned(SavePtr) then
  1269. RunError(203);
  1270. asm
  1271. mov ax, 4F04h { save the state buffer }
  1272. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1273. mov dx, 01h
  1274. mov es, WORD PTR [SavePtr+2]
  1275. mov bx, WORD PTR [SavePtr]
  1276. int 10h
  1277. end;
  1278. { restore state, according to Ralph Brown Interrupt list }
  1279. { some BIOS corrupt the hardware after a save... }
  1280. asm
  1281. mov ax, 4F04h { save the state buffer }
  1282. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1283. mov dx, 02h
  1284. mov es, WORD PTR [SavePtr+2]
  1285. mov bx, WORD PTR [SavePtr]
  1286. int 10h
  1287. end;
  1288. end;
  1289. end;
  1290. procedure RestoreStateVESA; far;
  1291. begin
  1292. { go back to the old video mode...}
  1293. asm
  1294. mov ah,00
  1295. mov al,[VideoMode]
  1296. int 10h
  1297. end;
  1298. { then restore all state information }
  1299. if assigned(SavePtr) and (SaveSupported=TRUE) then
  1300. begin
  1301. { restore state, according to Ralph Brown Interrupt list }
  1302. asm
  1303. mov ax, 4F04h { save the state buffer }
  1304. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1305. mov dx, 02h { restore state }
  1306. mov es, WORD PTR [SavePtr+2]
  1307. mov bx, WORD PTR [SavePtr]
  1308. int 10h
  1309. end;
  1310. FreeMem(SavePtr, 64*StateSize);
  1311. SavePtr := nil;
  1312. end;
  1313. end;
  1314. {$ENDIF DPMI}
  1315. {************************************************************************}
  1316. {* VESA Page flipping routines *}
  1317. {************************************************************************}
  1318. { Note: These routines, according to the VBE3 specification, will NOT }
  1319. { work with the 24 bpp modes, because of the alignment. }
  1320. {************************************************************************}
  1321. procedure SetVisualVESA(page: word); far;
  1322. { two page support... }
  1323. begin
  1324. if page > HardwarePages then exit;
  1325. end;
  1326. procedure SetActiveVESA(page: word); far;
  1327. { two page support... }
  1328. begin
  1329. end;
  1330. {
  1331. $Log$
  1332. Revision 1.10 1999-09-11 19:43:02 jonas
  1333. * FloodFill: did not take into account current viewport settings
  1334. * GetScanLine: only get line inside viewport, data outside of it
  1335. is not used anyway
  1336. * InternalEllipseDefault: fix for when xradius or yradius = 0 and
  1337. increase xradius and yradius always by one (TP does this too)
  1338. * fixed conlict in vesa.inc from last update
  1339. * some conditionals to avoid range check and overflow errors in
  1340. places where it doesn't matter
  1341. Revision 1.9 1999/08/01 14:51:07 jonas
  1342. * removed and/or/xorput support from vesaputpix256 (not in TP either)
  1343. * added notput support to directputpix256
  1344. Revision 1.8 1999/07/18 15:07:21 jonas
  1345. + xor-, and and- orput support for VESA256 modes
  1346. * compile with -dlogging if you wnt some info to be logged to grlog.txt
  1347. Revision 1.7 1999/07/14 15:21:49 jonas
  1348. * fixed initialization of bankshift var ('64 shr banshift' instead of shl)
  1349. Revision 1.6 1999/07/14 13:17:29 jonas
  1350. * bugfix in getmodeinfo (SizeOf(TModeInfo) -> SizeOf(TVESAModeInfo))
  1351. * as the result of the above bugfix, the graph unit doesn't crash
  1352. anymore under FPC if compiler with -dsupportVESA, but it doesn't
  1353. work yet either...
  1354. Revision 1.5 1999/07/12 13:28:33 jonas
  1355. * forgot log tag in previous commit
  1356. }