vesa.pp 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. {$MODE objfpc}
  2. {$ASMMODE intel}
  3. { $DEFINE DEBUGOUTPUT}
  4. Unit vesa;
  5. Interface
  6. Type
  7. TVesaModeInfoBlock = Packed Record
  8. {Mandatory information for all VBE revisions}
  9. ModeAttributes : Word; {mode attributes}
  10. WinAAttributes : Byte; {window A attributes}
  11. WinBAttributes : Byte; {window B attributes}
  12. WinGranularity : Word; {window granularity}
  13. WinSize : Word; {window size}
  14. WinASegment : Word; {window A start segment}
  15. WinBSegment : Word; {window B start segment}
  16. WinFuncPtr : DWord; {real mode pointer to window function}
  17. BytesPerScanLine : Word; {bytes per scan line}
  18. {Mandatory information for VBE 1.2 and above}
  19. XResolution : Word; {horizontal resolution in pixels or characters}
  20. YResolution : Word; {vertical resolution in pixels or characters}
  21. XCharSize : Byte; {character cell width in pixels}
  22. YCharSize : Byte; {character cell height in pixels}
  23. NumberOfPlanes : Byte; {number of memory planes}
  24. BitsPerPixel : Byte; {bits per pixel}
  25. NumberOfBanks : Byte; {number of banks}
  26. MemoryModel : Byte; {memory model type}
  27. BankSize : Byte; {bank size in KB}
  28. NumberOfImagePages : Byte; {number of images}
  29. Reserved : Byte;{=1} {reserved for page function}
  30. {Direct color fields (required for direct/6 and YUV/7 memory models)}
  31. RedMaskSize : Byte; {size of direct color red mask in bits}
  32. RedFieldPosition : Byte; {bit position of lsb of red mask}
  33. GreenMaskSize : Byte; {size of direct color green mask in bits}
  34. GreenFieldPosition : Byte; {bit position of lsb of green mask}
  35. BlueMaskSize : Byte; {size of direct color blue mask in bits}
  36. BlueFieldPosition : Byte; {bit position of lsb of blue mask}
  37. RsvdMaskSize : Byte; {size of direct color reserved mask in bits}
  38. RsvdFieldPosition : Byte; {bit position of lsb of reserved mask}
  39. DirectColorModeInfo : Byte; {direct color mode attributes}
  40. {Mandatory information for VBE 2.0 and above}
  41. PhysBasePtr : DWord; {physical address for flat memory frame buffer}
  42. Reserved2 : DWord;{=0} {Reserved - always set to 0}
  43. Reserved3 : Word;{=0} {Reserved - always set to 0}
  44. {Mandatory information for VBE 3.0 and above}
  45. LinBytesPerScanLine : Word; {bytes per scan line for linear modes}
  46. BnkNumberOfImagePages : Byte; {number of images for banked modes}
  47. LinNumberOfImagePages : Byte; {number of images for linear modes}
  48. LinRedMaskSize : Byte; {size of direct color red mask (linear modes)}
  49. LinRedFieldPosition : Byte; {bit position of lsb of red mask (linear modes)}
  50. LinGreenMaskSize : Byte; {size of direct color green mask (linear modes)}
  51. LinGreenFieldPosition : Byte; {bit position of lsb of green mask (linear modes)}
  52. LinBlueMaskSize : Byte; {size of direct color blue mask (linear modes)}
  53. LinBlueFieldPosition : Byte; {bit position of lsb of blue mask (linear modes)}
  54. LinRsvdMaskSize : Byte; {size of direct color reserved mask (linear modes)}
  55. LinRsvdFieldPosition : Byte; {bit position of lsb of reserved mask (linear modes)}
  56. MaxPixelClock : DWord; {maximum pixel clock (in Hz) for graphics mode}
  57. Reserved4 : Array[1..189] Of Byte; {remainder of ModeInfoBlock}
  58. End;
  59. PModeInfo = ^TModeInfo;
  60. TModeInfo = Record
  61. ModeNumber : DWord;
  62. VesaModeInfo : TVesaModeInfoBlock;
  63. End;
  64. Var
  65. ModeInfo : PModeInfo;
  66. NrOfModes : Integer;
  67. VBEPresent : Boolean;
  68. Procedure InitVESA;
  69. Function SetVESAMode(M : Integer) : Boolean;
  70. Procedure RestoreTextMode;
  71. Procedure WriteToVideoMemory(Src : Pointer; Dest : DWord; Size : DWord);
  72. Procedure SetPalette(Palette : Pointer; First, Num : Integer);
  73. Procedure GetPalette(Palette : Pointer; First, Num : Integer);
  74. Function MakeMask(MaskSize, FieldPosition : Integer) : DWord;
  75. Implementation
  76. Uses
  77. go32;
  78. Type
  79. TVBEInfoBlock = Packed Record
  80. {VBE 1.0+}
  81. VBESignature : DWord; {'VESA'}
  82. VBEVersion : Word;
  83. OemStringPtr : DWord; {VbeFarPtr to OEM String}
  84. Capabilities : DWord; {Capabilities of graphics controller}
  85. VideoModePtr : DWord; {VbeFarPtr to VideoModeList}
  86. {added for VBE 1.1+}
  87. TotalMemory : Word; {Number of 64kb memory blocks}
  88. {added for VBE 2.0+}
  89. OemSoftwareRev : Word; {VBE implementation Software revision}
  90. OemVendorNamePtr : DWord; {VbeFarPtr to Vendor Name String}
  91. OemProductNamePtr : DWord; {VbeFarPtr to Product Name String}
  92. OemProductRevPtr : DWord; {VbeFarPtr to Product Revision String}
  93. Reserved : Array[1..222] Of Byte; {Reserved for VBE implementation scratch area}
  94. OemData : Array[1..256] Of Char; {Data Area for OEM Strings}
  95. End;
  96. Var
  97. VBEInfoBlock : TVBEInfoBlock;
  98. VideoMemory : DWord;
  99. EightBitDACSupported : Boolean;
  100. nonVGA : Boolean;
  101. SnowyRAMDAC : Boolean;
  102. StereoSignalingSupport : Boolean;
  103. StereoSignalingVesaEVC : Boolean;
  104. OEMString : String;
  105. OEMVendorName : String;
  106. OEMProductName : String;
  107. OEMProductRev : String;
  108. OEMSoftwareRev : Integer;
  109. CurrentMode : Integer;
  110. LFBUsed : Boolean;
  111. UseLFB : Boolean;
  112. RealModePaletteSel : Word;
  113. RealModePaletteSeg : Word;
  114. SetPaletteHW : Boolean;
  115. PaletteDACbits : Integer;
  116. ReadWindow, WriteWindow : Integer;
  117. ReadWindowStart, WriteWindowStart : Integer;
  118. ReadWindowAddress, WriteWindowAddress : Integer;
  119. WindowGranularity : DWord;
  120. WindowSize, WindowSizeG : DWord;
  121. VESAInit : Boolean;
  122. RealRegs : TRealRegs;
  123. temp : Pointer;
  124. Procedure StandardMode(ModeNumber : DWord; Var ModeInfo : TVesaModeInfoBlock);
  125. Begin
  126. {
  127. 100 640x400x256
  128. 101 640x480x256
  129. 102 800x600x16
  130. 103 800x600x256
  131. 104 1024x768x16
  132. 105 1024x768x256
  133. 106 1280x1024x16
  134. 107 1280x1024x256
  135. 108 80x60t
  136. 109 132x25t
  137. 10A 132x43t
  138. 10B 132x50t
  139. 10C 132x60t
  140. 10D 320x200x32k
  141. 10E 320x200x64k
  142. 10F 320x200x16.8m
  143. 110 640x480x32k
  144. 111 640x480x64k
  145. 112 640x480x16.8m
  146. 113 800x600x32k
  147. 114 800x600x64k
  148. 115 800x600x16.8m
  149. 116 1024x768x32k
  150. 117 1024x768x64k
  151. 118 1024x768x16.8m
  152. 119 1280x1024x32k
  153. 11A 1280x1024x64k
  154. 11B 1280x1024x16.8m
  155. }
  156. With ModeInfo Do
  157. Begin
  158. ModeAttributes := ModeAttributes Or 2;
  159. Case ModeNumber Of
  160. $100 : Begin
  161. XResolution := 640;
  162. YResolution := 400;
  163. XCharSize := 8;
  164. YCharSize := 16;
  165. NumberOfPlanes := 1;
  166. BitsPerPixel := 8;
  167. MemoryModel := 4;
  168. End;
  169. $101 : Begin
  170. XResolution := 640;
  171. YResolution := 480;
  172. XCharSize := 8;
  173. YCharSize := 16;
  174. NumberOfPlanes := 1;
  175. BitsPerPixel := 8;
  176. MemoryModel := 4;
  177. End;
  178. $102 : Begin
  179. XResolution := 800;
  180. YResolution := 600;
  181. XCharSize := 8;
  182. YCharSize := 16;
  183. NumberOfPlanes := 4;
  184. BitsPerPixel := 4;
  185. MemoryModel := 3;
  186. End;
  187. $103 : Begin
  188. XResolution := 800;
  189. YResolution := 600;
  190. XCharSize := 8;
  191. YCharSize := 16;
  192. NumberOfPlanes := 1;
  193. BitsPerPixel := 8;
  194. MemoryModel := 4;
  195. End;
  196. $104 : Begin
  197. XResolution := 1024;
  198. YResolution := 768;
  199. XCharSize := 8;
  200. YCharSize := 16;
  201. NumberOfPlanes := 4;
  202. BitsPerPixel := 4;
  203. MemoryModel := 3;
  204. End;
  205. $105 : Begin
  206. XResolution := 1024;
  207. YResolution := 768;
  208. XCharSize := 8;
  209. YCharSize := 16;
  210. NumberOfPlanes := 1;
  211. BitsPerPixel := 8;
  212. MemoryModel := 4;
  213. End;
  214. $106 : Begin
  215. XResolution := 1280;
  216. YResolution := 1024;
  217. XCharSize := 8;
  218. YCharSize := 16;
  219. NumberOfPlanes := 4;
  220. BitsPerPixel := 4;
  221. MemoryModel := 3;
  222. End;
  223. $107 : Begin
  224. XResolution := 1280;
  225. YResolution := 1024;
  226. XCharSize := 8;
  227. YCharSize := 16;
  228. NumberOfPlanes := 1;
  229. BitsPerPixel := 8;
  230. MemoryModel := 4;
  231. End;
  232. $108 : Begin
  233. XResolution := 80;
  234. YResolution := 60;
  235. XCharSize := 8;
  236. YCharSize := 16;
  237. NumberOfPlanes := 4;
  238. BitsPerPixel := 4;
  239. MemoryModel := 0;
  240. End;
  241. $109 : Begin
  242. XResolution := 132;
  243. YResolution := 25;
  244. XCharSize := 8;
  245. YCharSize := 16;
  246. NumberOfPlanes := 4;
  247. BitsPerPixel := 4;
  248. MemoryModel := 0;
  249. End;
  250. $10A : Begin
  251. XResolution := 132;
  252. YResolution := 43;
  253. XCharSize := 8;
  254. YCharSize := 16;
  255. NumberOfPlanes := 4;
  256. BitsPerPixel := 4;
  257. MemoryModel := 0;
  258. End;
  259. $10B : Begin
  260. XResolution := 132;
  261. YResolution := 50;
  262. XCharSize := 8;
  263. YCharSize := 16;
  264. NumberOfPlanes := 4;
  265. BitsPerPixel := 4;
  266. MemoryModel := 0;
  267. End;
  268. $10C : Begin
  269. XResolution := 132;
  270. YResolution := 60;
  271. XCharSize := 8;
  272. YCharSize := 16;
  273. NumberOfPlanes := 4;
  274. BitsPerPixel := 4;
  275. MemoryModel := 0;
  276. End;
  277. {todo:10D..11B}
  278. Else
  279. ModeAttributes := ModeAttributes And $FFFD;
  280. End;
  281. // NumberOfImagePages := 0;{...}
  282. End;
  283. End;
  284. Function bcd(q : Integer) : Integer;
  285. Begin
  286. q := q And $FF;
  287. If ((q And $F) < 10) And ((q Shr 4) < 10) Then
  288. bcd := (q And $F) + (q Shr 4) * 10
  289. Else
  290. bcd := q;
  291. End;
  292. Procedure DisposeRealModePalette;
  293. Begin
  294. If RealModePaletteSel = 0 Then
  295. Exit;
  296. global_dos_free(RealModePaletteSel);
  297. RealModePaletteSel := 0;
  298. RealModePaletteSeg := 0;
  299. End;
  300. Procedure AllocateRealModePalette;
  301. Var
  302. Addr : DWord;
  303. Begin
  304. DisposeRealModePalette;
  305. Addr := global_dos_alloc(256*4);
  306. RealModePaletteSeg := Addr Shr 16;
  307. RealModePaletteSel := Addr And $FFFF;
  308. End;
  309. Procedure SetPalette2(Palette : Pointer; Num : Integer); Assembler;
  310. Asm
  311. push es
  312. cld
  313. mov ax, fs
  314. mov es, ax
  315. mov esi, [Palette]
  316. movzx edi, word [RealModePaletteSeg]
  317. shl edi, 4
  318. mov ecx, Num
  319. { mov edx, 03F3F3F3Fh}
  320. mov edx, 0003F3F3Fh
  321. @@1:
  322. lodsd
  323. shr eax, 2 {convert 8->6bit}
  324. and eax, edx
  325. stosd
  326. dec ecx
  327. jnz @@1
  328. pop es
  329. End;
  330. Procedure SetPalette3(Palette : Pointer; Num : Integer); Assembler;
  331. Asm
  332. push es
  333. cld
  334. mov ax, fs
  335. mov es, ax
  336. mov esi, [Palette]
  337. movzx edi, word [RealModePaletteSeg]
  338. shl edi, 4
  339. mov ecx, Num
  340. { mov edx, 07F7F7F7Fh}
  341. mov edx, 0007F7F7Fh
  342. @@1:
  343. lodsd
  344. shr eax, 1 {convert 8->7bit}
  345. and eax, edx
  346. stosd
  347. dec ecx
  348. jnz @@1
  349. pop es
  350. End;
  351. Procedure SetPaletteHW6(Palette : Pointer; First, Num : Integer);
  352. Var
  353. I : Integer;
  354. p : PDWord;
  355. c : DWord;
  356. Begin
  357. p := PDWord(Palette);
  358. outportb($3C8, First);
  359. While Num > 0 Do
  360. Begin
  361. c := (p^ Shr 2) And $3F3F3F;
  362. outportb($3C9, c Shr 16);
  363. outportb($3C9, c Shr 8);
  364. outportb($3C9, c);
  365. Inc(p);
  366. Dec(Num);
  367. End;
  368. End;
  369. Procedure SetPaletteHW7(Palette : Pointer; First, Num : Integer);
  370. Var
  371. I : Integer;
  372. p : PDWord;
  373. c : DWord;
  374. Begin
  375. p := PDWord(Palette);
  376. outportb($3C8, First);
  377. While Num > 0 Do
  378. Begin
  379. c := (p^ Shr 1) And $7F7F7F;
  380. outportb($3C9, c Shr 16);
  381. outportb($3C9, c Shr 8);
  382. outportb($3C9, c);
  383. Inc(p);
  384. Dec(Num);
  385. End;
  386. End;
  387. Procedure SetPaletteHW8(Palette : Pointer; First, Num : Integer);
  388. Var
  389. I : Integer;
  390. p : PDWord;
  391. Begin
  392. p := PDWord(Palette);
  393. outportb($3C8, First);
  394. While Num > 0 Do
  395. Begin
  396. outportb($3C9, p^ Shr 16);
  397. outportb($3C9, p^ Shr 8);
  398. outportb($3C9, p^);
  399. Inc(p);
  400. Dec(Num);
  401. End;
  402. End;
  403. Procedure SetPalette(Palette : Pointer; First, Num : Integer);
  404. Begin
  405. If SetPaletteHW Then
  406. Begin
  407. Case PaletteDACbits Of
  408. 8 : SetPaletteHW8(Palette, First, Num);
  409. 7 : SetPaletteHW7(Palette, First, Num);
  410. 6 : SetPaletteHW6(Palette, First, Num);
  411. End;
  412. End
  413. Else
  414. Begin
  415. If PaletteDACbits = 8 Then
  416. dosmemput(RealModePaletteSeg, 0, Palette^, Num * 4) {8bits}
  417. Else
  418. If PaletteDACbits = 7 Then
  419. SetPalette3(Palette, Num) {7bits}
  420. Else
  421. SetPalette2(Palette, Num); {6bits}
  422. RealRegs.ax := $4F09;
  423. RealRegs.bl := 0;
  424. RealRegs.cx := Num;
  425. RealRegs.dx := First;
  426. RealRegs.es := RealModePaletteSeg;
  427. RealRegs.di := 0;
  428. realintr($10, RealRegs);
  429. End;
  430. End;
  431. Procedure GetPalette(Palette : Pointer; First, Num : Integer);
  432. Begin
  433. RealRegs.ax := $4F09;
  434. RealRegs.bl := 1;
  435. RealRegs.cx := Num;
  436. RealRegs.dx := First;
  437. RealRegs.es := RealModePaletteSeg;
  438. RealRegs.di := 0;
  439. realintr($10, RealRegs);
  440. {...}
  441. End;
  442. Procedure SwitchTo8bitDAC;
  443. Begin
  444. RealRegs.ax := $4F08;
  445. RealRegs.bl := 0;
  446. RealRegs.bh := 8;
  447. realintr($10, RealRegs);
  448. PaletteDACbits := RealRegs.bh;
  449. If PaletteDACbits < 6 Then
  450. PaletteDACbits := 6;
  451. End;
  452. Function MakeMask(MaskSize, FieldPosition : Integer) : DWord;
  453. Var
  454. Mask : DWord;
  455. I : Integer;
  456. Begin
  457. Mask := 1 Shl FieldPosition;
  458. For I := 2 To MaskSize Do
  459. Mask := Mask Or (Mask Shl 1);
  460. MakeMask := Mask;
  461. End;
  462. Function GetRMString(SegOfs : DWord) : String;
  463. Var
  464. S : String;
  465. C : Char;
  466. Seg, Ofs : Word;
  467. Begin
  468. If SegOfs = 0 Then
  469. Begin
  470. GetRMString := '';
  471. Exit;
  472. End;
  473. S := '';
  474. Ofs := SegOfs And $FFFF;
  475. Seg := SegOfs Shr 16;
  476. Repeat
  477. dosmemget(Seg, Ofs, C, 1);
  478. If C <> #0 Then
  479. Begin
  480. S := S + C;
  481. If Ofs = $FFFF Then
  482. Begin
  483. Ofs := 0;
  484. Inc(Seg, $1000);
  485. End
  486. Else
  487. Inc(Ofs);
  488. End;
  489. Until C = #0;
  490. GetRMString := S;
  491. End;
  492. Procedure SetWriteWindowStart(WinPos : DWord);
  493. Begin
  494. RealRegs.ax := $4F05;
  495. RealRegs.bx := WriteWindow;
  496. RealRegs.dx := WinPos;
  497. realintr($10, RealRegs);
  498. End;
  499. Procedure WriteToVideoMemory(Src : Pointer; Dest : DWord; Size : DWord);
  500. Var
  501. WW : Integer;
  502. ToDo : Integer;
  503. Begin
  504. WW := Dest Div WindowGranularity;
  505. Dest := Dest Mod WindowGranularity;
  506. { Writeln(WindowSize);}
  507. While Size > 0 Do
  508. Begin
  509. { Write(WW, ' ');}
  510. SetWriteWindowStart(WW);
  511. ToDo := WindowSize - Dest;
  512. If Size < ToDo Then
  513. ToDo := Size;
  514. Asm
  515. push es
  516. mov esi, Src
  517. mov edi, Dest
  518. add edi, WriteWindowAddress
  519. mov ax, fs
  520. mov es, ax
  521. mov ecx, ToDo
  522. shr ecx, 2
  523. cld
  524. rep movsd
  525. mov ecx, ToDo
  526. and ecx, 3
  527. jz @@1
  528. rep movsb
  529. @@1:
  530. pop es
  531. End ['EAX', 'ECX', 'ESI', 'EDI'];
  532. Dest := 0;
  533. Inc(WW, WindowSizeG);
  534. { Inc(WW);}
  535. Inc(Src, ToDo);
  536. Dec(Size, ToDo);
  537. End;
  538. End;
  539. {$IFDEF DEBUGOUTPUT}
  540. Procedure WinAttrib(q : Integer);
  541. Begin
  542. If (q And 1) <> 0 Then
  543. Write(' supported')
  544. Else
  545. Write(' not_supported');
  546. If (q And 2) <> 0 Then
  547. Write(' readable');
  548. If (q And 4) <> 0 Then
  549. Write(' writeable');
  550. Writeln;
  551. End;
  552. {$ENDIF DEBUGOUTPUT}
  553. Procedure GetModes;
  554. Type
  555. PModesList = ^TModesList;
  556. TModesList = Record
  557. ModeInfo : TModeInfo;
  558. Next : PModesList;
  559. End;
  560. Var
  561. First, Last, Run, Tmp : PModesList;
  562. Procedure AddToList;
  563. Begin
  564. If Last = Nil Then
  565. Begin
  566. New(Last);
  567. First := Last;
  568. End
  569. Else
  570. Begin
  571. New(Last^.Next);
  572. Last := Last^.Next;
  573. Last^.Next := Nil;
  574. End;
  575. End;
  576. Var
  577. I : DWord;
  578. Addr : DWord;
  579. AddrSeg, AddrSel : Word;
  580. VesaModeInfo : TVesaModeInfoBlock;
  581. ScanStart, ScanEnd : Integer;
  582. ModeAttr : Integer;
  583. IsModeOk : Boolean;
  584. hasReadWindow, hasWriteWindow : Boolean;
  585. Begin
  586. NrOfModes := -1;
  587. First := Nil;
  588. Last := Nil;
  589. Addr := global_dos_alloc(512);
  590. AddrSeg := Addr Shr 16;
  591. AddrSel := Addr And $FFFF;
  592. ScanStart := 0;
  593. { ScanEnd := $7FFF;} {VBE 1.0+ ??}
  594. { ScanEnd := $3FFF;} {VBE 1.2+ ??}
  595. ScanEnd := $7FF; {VBE 3.0+}
  596. {$IFDEF DEBUGOUTPUT}
  597. Writeln('scanning modes $', HexStr(ScanStart, 4), '..$', HexStr(ScanEnd, 4));
  598. {$ENDIF DEBUGOUTPUT}
  599. For I := ScanStart To ScanEnd Do
  600. Begin
  601. FillChar(VesaModeInfo, SizeOf(VesaModeInfo), 0);
  602. dosmemput(AddrSeg, 0, VesaModeInfo, SizeOf(VesaModeInfo));
  603. RealRegs.ax := $4F01; {return VBE mode information}
  604. RealRegs.cx := I;
  605. RealRegs.es := AddrSeg;
  606. RealRegs.di := 0;
  607. realintr($10, RealRegs);
  608. dosmemget(AddrSeg, 0, VesaModeInfo, SizeOf(VesaModeInfo));
  609. {display mode info}
  610. {$IFDEF DEBUGOUTPUT}
  611. If ((VesaModeInfo.ModeAttributes And 1) <> 0) Or
  612. (VesaModeInfo.BytesPerScanLine <> 0) Then
  613. Begin
  614. Writeln('ModeNumber: $', HexStr(I, 4));
  615. Write('ModeAttributes:');
  616. If (VesaModeInfo.ModeAttributes And 1) <> 0 Then
  617. Write(' supported')
  618. Else
  619. Write(' not_supported');
  620. If (VesaModeInfo.ModeAttributes And 2) <> 0 Then
  621. Write('')
  622. Else
  623. Write(' reserved_is_zero(noresolutioninfo_for_vbe1.1-)');
  624. If (VesaModeInfo.ModeAttributes And 4) <> 0 Then
  625. Write(' TTY')
  626. Else
  627. Write(' noTTY');
  628. If (VesaModeInfo.ModeAttributes And 8) <> 0 Then
  629. Write(' color')
  630. Else
  631. Write(' monochrome');
  632. If (VesaModeInfo.ModeAttributes And 16) <> 0 Then
  633. Write(' graph')
  634. Else
  635. Write(' text');
  636. If (VesaModeInfo.ModeAttributes And 32) <> 0 Then
  637. Write(' nonVGA')
  638. Else
  639. Write(' VGA');
  640. If (VesaModeInfo.ModeAttributes And 64) <> 0 Then
  641. Write(' noWINDOWED')
  642. Else
  643. Write(' WINDOWED');
  644. If (VesaModeInfo.ModeAttributes And 128) <> 0 Then
  645. Write(' LFB')
  646. Else
  647. Write(' noLFB');
  648. If (VesaModeInfo.ModeAttributes And 256) <> 0 Then
  649. Write(' DoubleScanMode_is_available')
  650. Else
  651. Write('');
  652. If (VesaModeInfo.ModeAttributes And 512) <> 0 Then
  653. Write(' InterlacedMode_is_available')
  654. Else
  655. Write('');
  656. If (VesaModeInfo.ModeAttributes And 1024) <> 0 Then
  657. Write(' TripleBuffering')
  658. Else
  659. Write('');
  660. If (VesaModeInfo.ModeAttributes And 2048) <> 0 Then
  661. Write(' StereoscopicDisplaySupport')
  662. Else
  663. Write('');
  664. If (VesaModeInfo.ModeAttributes And 4096) <> 0 Then
  665. Write(' DualDisplayStartAddressSupport')
  666. Else
  667. Write('');
  668. Writeln;
  669. Write('WinAAtributes:');
  670. WinAttrib(VesaModeInfo.WinAAttributes);
  671. Write('WinBAttributes:');
  672. WinAttrib(VesaModeInfo.WinBAttributes);
  673. Writeln('WinGranularity: ', VesaModeInfo.WinGranularity, ' KB');
  674. Writeln('WinSize: ', VesaModeInfo.WinSize, ' KB');
  675. Writeln('WinASegment: $', HexStr(VesaModeInfo.WinASegment, 4));
  676. Writeln('WinBSegment: $', HexStr(VesaModeInfo.WinBSegment, 4));
  677. Writeln('WinFuncPtr: ', HexStr(VesaModeInfo.WinFuncPtr Shr 16, 4), ':', HexStr(VesaModeInfo.WinFuncPtr And $FFFF, 4));
  678. Writeln('BytesPerScanLine: ', VesaModeInfo.BytesPerScanLine);
  679. Writeln('vbe1.2+');
  680. Writeln('XResolution: ', VesaModeInfo.XResolution);
  681. Writeln('YResolution: ', VesaModeInfo.YResolution);
  682. Writeln('XCharSize: ', VesaModeInfo.XCharSize);
  683. Writeln('YCharSize: ', VesaModeInfo.YCharSize);
  684. Writeln('NumberOfPlanes: ', VesaModeInfo.NumberOfPlanes);
  685. Writeln('BitsPerPixel: ', VesaModeInfo.BitsPerPixel);
  686. Writeln('NumberOfBanks: ', VesaModeInfo.NumberOfBanks);
  687. Write('MemoryModel: ');
  688. Case VesaModeInfo.MemoryModel Of
  689. 0 : Write('Text mode');
  690. 1 : Write('CGA graphics');
  691. 2 : Write('Hercules graphics');
  692. 3 : Write('Planar');
  693. 4 : Write('Packed pixel');
  694. 5 : Write('Non-chain 4, 256 color');
  695. 6 : Write('Direct Color');
  696. 7 : Write('YUV');
  697. 8..15 : Write('Reserved, to be defined by VESA');
  698. Else
  699. Write('To be defined by OEM');
  700. End;
  701. Writeln('/', VesaModeInfo.MemoryModel);
  702. Writeln('BankSize: ', VesaModeInfo.BankSize, ' KB');
  703. Writeln('NumberOfImagePages: ', VesaModeInfo.NumberOfImagePages);
  704. Writeln('Reserved(=1): ', VesaModeInfo.Reserved);
  705. Writeln('RedMaskSize: ', VesaModeInfo.RedMaskSize);
  706. Writeln('RedFieldPosition: ', VesaModeInfo.RedFieldPosition);
  707. Writeln('GreenMaskSize: ', VesaModeInfo.GreenMaskSize);
  708. Writeln('GreenFieldPosition: ', VesaModeInfo.GreenFieldPosition);
  709. Writeln('BlueMaskSize: ', VesaModeInfo.BlueMaskSize);
  710. Writeln('BlueFieldPosition: ', VesaModeInfo.BlueFieldPosition);
  711. Writeln('RsvdMaskSize: ', VesaModeInfo.RsvdMaskSize);
  712. Writeln('RsvdFieldPosition: ', VesaModeInfo.RsvdFieldPosition);
  713. Write('DirectColorModeInfo:');
  714. If (VesaModeInfo.DirectColorModeInfo And 1) <> 0 Then
  715. Write(' Color_ramp_is_programmable')
  716. Else
  717. Write(' Color_ramp_is_fixed');
  718. If (VesaModeInfo.DirectColorModeInfo And 2) <> 0 Then
  719. Write(' Rsvd_bits_usable_by_app')
  720. Else
  721. Write(' Rsvd_bits_reserved');
  722. Writeln;
  723. Writeln('vbe2.0+');
  724. Writeln('PhysBasePtr: $', HexStr(VesaModeInfo.PhysBasePtr, 8));
  725. Writeln('Reserved2(=0): ', VesaModeInfo.Reserved2);
  726. Writeln('Reserved3(=0): ', VesaModeInfo.Reserved3);
  727. Writeln;
  728. { Write(VesaModeInfo.XResolution, 'x', VesaModeInfo.YResolution, 'x',
  729. VesaModeInfo.BitsPerPixel, '-', VesaModeInfo.MemoryModel,
  730. 'R', VesaModeInfo.RedMaskSize, ':', VesaModeInfo.RedFieldPosition,
  731. 'G', VesaModeInfo.GreenMaskSize, ':', VesaModeInfo.GreenFieldPosition,
  732. 'B', VesaModeInfo.BlueMaskSize, ':', VesaModeInfo.BlueFieldPosition,
  733. 'A', VesaModeInfo.RsvdMaskSize, ':', VesaModeInfo.RsvdFieldPosition, ' ');}
  734. End;
  735. {$ENDIF DEBUGOUTPUT}
  736. {/display mode info}
  737. If (VesaModeInfo.ModeAttributes And 1) <> 0 Then
  738. Begin
  739. If (VesaModeInfo.ModeAttributes And 2) = 0 Then
  740. Begin
  741. If VBEInfoBlock.VBEVersion >= $0102 Then
  742. IsModeOk := False
  743. Else
  744. StandardMode(I, VesaModeInfo);
  745. End;
  746. ModeAttr := (VesaModeInfo.ModeAttributes And $C0) Shr 6;
  747. IsModeOk := True;
  748. If ModeAttr = 1 Then
  749. IsModeOk := False;
  750. If IsModeOk And ((ModeAttr = 0) Or (ModeAttr = 2)) Then
  751. Begin {check windowed}
  752. hasReadWindow := False;
  753. hasWriteWindow := False;
  754. If (VesaModeInfo.WinAAttributes And $01) <> 0 Then
  755. Begin
  756. If (VesaModeInfo.WinAAttributes And $02) <> 0 Then
  757. hasReadWindow := True;
  758. If (VesaModeInfo.WinAAttributes And $04) <> 0 Then
  759. hasWriteWindow := True;
  760. End;
  761. If (VesaModeInfo.WinBAttributes And $01) <> 0 Then
  762. Begin
  763. If (VesaModeInfo.WinBAttributes And $02) <> 0 Then
  764. hasReadWindow := True;
  765. If (VesaModeInfo.WinBAttributes And $04) <> 0 Then
  766. hasWriteWindow := True;
  767. End;
  768. If (Not hasReadWindow) Or (Not hasWriteWindow) Then
  769. IsModeOk := False;
  770. End;
  771. If IsModeOk And ((ModeAttr = 2) Or (ModeAttr = 3)) Then
  772. Begin {check lfb...}
  773. {...}
  774. End;
  775. If IsModeOk Then
  776. Begin
  777. // Write(HexStr(I, 4), ' ');
  778. AddToList;
  779. Inc(NrOfModes);
  780. Last^.ModeInfo.ModeNumber := I;
  781. Last^.ModeInfo.VesaModeInfo := VesaModeInfo;
  782. End;
  783. End;
  784. End;
  785. global_dos_free(AddrSel);
  786. If ModeInfo <> Nil Then
  787. FreeMem(ModeInfo);
  788. If NrOfModes <> -1 Then
  789. ModeInfo := GetMem((NrOfModes + 1) * SizeOf(TModeInfo))
  790. Else
  791. ModeInfo := Nil;
  792. Run := First;
  793. For I := 0 To NrOfModes Do
  794. Begin
  795. ModeInfo[I] := Run^.ModeInfo;
  796. Tmp := Run;
  797. Run := Run^.Next;
  798. Dispose(Tmp);
  799. End;
  800. {$IFDEF DEBUGOUTPUT}
  801. Writeln;
  802. {$ENDIF DEBUGOUTPUT}
  803. End;
  804. Procedure GetVBEInfo;
  805. Var
  806. Addr : DWord;
  807. AddrSeg : Word;
  808. AddrSel : Word;
  809. tmp : DWord;
  810. Begin
  811. Addr := global_dos_alloc(512);
  812. AddrSeg := Addr Shr 16;
  813. AddrSel := Addr And $FFFF;
  814. VBEInfoBlock.VBESignature := $32454256; {'VBE2'}
  815. dosmemput(AddrSeg, 0, VBEInfoBlock, 4);
  816. RealRegs.ax := $4F00;
  817. RealRegs.es := AddrSeg;
  818. RealRegs.di := 0;
  819. realintr($10, RealRegs);
  820. VBEPresent := RealRegs.al = $4F;
  821. If VBEPresent Then
  822. Begin
  823. dosmemget(AddrSeg, 0, VBEInfoBlock, SizeOf(VBEInfoBlock));
  824. {todo: check for 'VESA' id string}
  825. VideoMemory := VBEInfoBlock.TotalMemory * 64;
  826. EightBitDACSupported := (VBEInfoBlock.Capabilities And 1) <> 0;
  827. nonVGA := (VBEInfoBlock.Capabilities And 2) <> 0;
  828. SnowyRAMDAC := (VBEInfoBlock.Capabilities And 4) <> 0;
  829. StereoSignalingSupport := (VBEInfoBlock.Capabilities And 8) <> 0;
  830. StereoSignalingVesaEVC := (VBEInfoBlock.Capabilities And 16) <> 0;
  831. OEMString := GetRMString(VBEInfoBlock.OemStringPtr);
  832. If VBEInfoBlock.VBEVersion >= $0200 Then
  833. Begin
  834. OEMVendorName := GetRMString(VBEInfoBlock.OemVendorNamePtr);
  835. OEMProductName := GetRMString(VBEInfoBlock.OemProductNamePtr);
  836. OEMProductRev := GetRMString(VBEInfoBlock.OemProductRevPtr);
  837. OEMSoftwareRev := VBEInfoBlock.OemSoftwareRev;
  838. End
  839. Else
  840. Begin
  841. OEMVendorName := '';
  842. OEMProductName := '';
  843. OEMProductRev := '';
  844. OEMSoftwareRev := -1;
  845. End;
  846. End;
  847. global_dos_free(AddrSel);
  848. {$IFDEF DEBUGOUTPUT}
  849. If VBEPresent Then
  850. Begin
  851. Writeln('VBEVersion: ', bcd(VBEInfoBlock.VBEVersion Shr 8), '.', bcd(VBEInfoBlock.VBEVersion And $FF));
  852. Writeln('VideoMemory: ', VideoMemory, ' KB');
  853. Writeln('EightBitDACSupported: ', EightBitDACSupported);
  854. Writeln('nonVGA: ', nonVGA);
  855. Writeln('SnowyRAMDAC: ', SnowyRAMDAC);
  856. Writeln('StereoSignalingSupport: ', StereoSignalingSupport);
  857. If StereoSignalingSupport Then
  858. If StereoSignalingVesaEVC Then
  859. Writeln('Stereo signaling supported via VESA EVC connector')
  860. Else
  861. Writeln('Stereo signaling supported via external VESA stereo connector');
  862. If OEMString <> '' Then
  863. Writeln('OEMString: ', OEMString);
  864. If OEMVendorName <> '' Then
  865. Writeln('OEMVendorName: ', OEMVendorName);
  866. If OEMProductName <> '' Then
  867. Writeln('OEMProductName: ', OEMProductName);
  868. If OEMProductRev <> '' Then
  869. Writeln('OEMProductRev: ', OEMProductRev);
  870. If OEMSoftwareRev <> -1 Then
  871. Writeln('OEMSoftwareRev: ', bcd(OEMSoftwareRev Shr 8), '.', bcd(OEMSoftwareRev And $FF));
  872. Write('VideoModeList:');
  873. tmp := (VBEInfoBlock.VideoModePtr Shr 16) * 16 + (VBEInfoBlock.VideoModePtr And $FFFF);
  874. While MemW[tmp] <> $FFFF Do
  875. Begin
  876. Write(' $', HexStr(MemW[tmp], 4));
  877. Inc(tmp, 2);
  878. End;
  879. Writeln;
  880. Writeln;
  881. End;
  882. {$ENDIF DEBUGOUTPUT}
  883. End;
  884. Function SetVESAMode(M : Integer) : Boolean;
  885. Var
  886. ModeAttr : DWord;
  887. lLFBUsed : Boolean;
  888. lReadWindow, lWriteWindow : Integer;
  889. lReadWindowStart, lWriteWindowStart : Integer;
  890. lReadWindowAddress, lWriteWindowAddress : Integer;
  891. lWindowGranularity : DWord;
  892. lWindowSize, lWindowSizeG : DWord;
  893. Begin
  894. SetVESAMode := False;
  895. DisposeRealModePalette;
  896. ModeAttr := (ModeInfo[M].VesaModeInfo.ModeAttributes And $C0) Shr 6;
  897. Case ModeAttr Of
  898. 0 : lLFBUsed := False; {windowed frame buffer only}
  899. 2 : lLFBUsed := UseLFB; {both windowed and linear}
  900. 3 : lLFBUsed := True; {linear frame buffer only}
  901. End;
  902. If Not lLFBUsed Then
  903. Begin
  904. With ModeInfo[M].VesaModeInfo Do
  905. Begin
  906. lReadWindow := -1;
  907. lWriteWindow := -1;
  908. If (WinAAttributes And $01) <> 0 Then
  909. Begin
  910. If (WinAAttributes And $02) <> 0 Then
  911. lReadWindow := 0;
  912. If (WinAAttributes And $04) <> 0 Then
  913. lWriteWindow := 0;
  914. End;
  915. If (lReadWindow = -1) Or (lWriteWindow = -1) Then
  916. If (WinBAttributes And $01) <> 0 Then
  917. Begin
  918. If (lReadWindow = -1) And ((WinBAttributes And $02) <> 0) Then
  919. lReadWindow := 1;
  920. If (lWriteWindow = -1) And ((WinBAttributes And $04) <> 0) Then
  921. lWriteWindow := 1;
  922. End;
  923. Case lReadWindow Of
  924. -1 : Exit{err};
  925. 0 : lReadWindowAddress := WinASegment Shl 4;
  926. 1 : lReadWindowAddress := WinBSegment Shl 4;
  927. End;
  928. Case lWriteWindow Of
  929. -1 : Exit{err};
  930. 0 : lWriteWindowAddress := WinASegment Shl 4;
  931. 1 : lWriteWindowAddress := WinBSegment Shl 4;
  932. End;
  933. lWindowGranularity := WinGranularity * 1024;
  934. lWindowSize := WinSize * 1024;
  935. lWindowSizeG := lWindowSize Div lWindowGranularity;
  936. lWindowSize := lWindowSizeG * lWindowGranularity;
  937. End;
  938. End
  939. Else
  940. Begin
  941. {TODO: lfb}
  942. End;
  943. RealRegs.ax := $4F02;
  944. If lLFBUsed Then
  945. RealRegs.bx := ModeInfo[M].ModeNumber Or $4000
  946. Else
  947. RealRegs.bx := ModeInfo[M].ModeNumber;
  948. realintr($10, RealRegs);
  949. PaletteDACbits := 6;
  950. With ModeInfo[M].VesaModeInfo Do
  951. Begin
  952. If (BitsPerPixel = 8) And (MemoryModel = 4{packed pixel}) Then
  953. Begin
  954. SetPaletteHW := True;
  955. If (VBEInfoBlock.VBEVersion >= $200) And
  956. ((ModeAttributes And 32) <> 0) Then {if nonVGA, use func9 to set palette}
  957. SetPaletteHW := False;
  958. If EightBitDACSupported Then
  959. SwitchTo8bitDAC;
  960. If Not SetPaletteHW Then
  961. AllocateRealModePalette;
  962. End;
  963. End;
  964. LFBUsed := lLFBUsed;
  965. ReadWindow := lReadWindow;
  966. WriteWindow := lWriteWindow;
  967. ReadWindowStart := lReadWindowStart;
  968. WriteWindowStart := lWriteWindowStart;
  969. ReadWindowAddress := lReadWindowAddress;
  970. WriteWindowAddress := lWriteWindowAddress;
  971. WindowGranularity := lWindowGranularity;
  972. WindowSize := lWindowSize;
  973. WindowSizeG := lWindowSizeG;
  974. SetVESAMode := True;
  975. End;
  976. Procedure RestoreTextMode;
  977. Begin
  978. DisposeRealModePalette;
  979. RealRegs.ax := $0003;
  980. realintr($10, RealRegs);
  981. End;
  982. Procedure InitVESA;
  983. Begin
  984. If Not VESAInit Then
  985. VESAInit := True
  986. Else
  987. Exit;
  988. GetVBEInfo;
  989. If VBEPresent Then
  990. GetModes;
  991. End;
  992. Initialization
  993. VESAInit := False;
  994. CurrentMode := -1;
  995. UseLFB := {True}False;
  996. ModeInfo := Nil;
  997. RealModePaletteSel := 0;
  998. RealModePaletteSeg := 0;
  999. Finalization
  1000. temp := ModeInfo;
  1001. ModeInfo := Nil;
  1002. If temp <> Nil Then
  1003. FreeMem(temp);
  1004. DisposeRealModePalette;
  1005. End.