vesa.inc 37 KB

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