vesa.inc 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950
  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. palrec = packed record { record used for set/get DAC palette }
  14. align: byte;
  15. blue : byte;
  16. green: byte;
  17. red: byte;
  18. end;
  19. const
  20. { VESA attributes }
  21. attrSwitchDAC = $01; { DAC is switchable (1.2) }
  22. attrNotVGACompatible = $02; { Video is NOT VGA compatible (2.0) }
  23. attrSnowCheck = $04; { Video must use snow checking(2.0) }
  24. { mode attribute bits }
  25. modeAvail = $01; { Hardware supports this mode (1.0) }
  26. modeExtendInfo = $02; { Extended information (1.0) }
  27. modeBIOSSupport = $04; { TTY BIOS Support (1.0) }
  28. modeColor = $08; { This is a color mode (1.0) }
  29. modeGraphics = $10; { This is a graphics mode (1.0) }
  30. modeNotVGACompatible = $20; { this mode is NOT I/O VGA compatible (2.0)}
  31. modeNoWindowed = $40; { This mode does not support Windows (2.0) }
  32. modeLinearBuffer = $80; { This mode supports linear buffers (2.0) }
  33. { window attributes }
  34. winSupported = $01;
  35. winReadable = $02;
  36. winWritable = $04;
  37. { memory model }
  38. modelText = $00;
  39. modelCGA = $01;
  40. modelHerc = $02;
  41. model4plane = $03;
  42. modelPacked = $04;
  43. modelModeX = $05;
  44. modelRGB = $06;
  45. modelYUV = $07;
  46. {$ifndef dpmi}
  47. {$i vesah.inc}
  48. { otherwise it's already included in graph.pp }
  49. {$endif dpmi}
  50. var
  51. BytesPerLine: word; { Number of bytes per scanline }
  52. { window management }
  53. ReadWindow : byte; { Window number for reading. }
  54. WriteWindow: byte; { Window number for writing. }
  55. winReadSeg : word; { Address of segment for read }
  56. winWriteSeg: word; { Address of segment for writes}
  57. CurrentReadBank : integer; { active read bank }
  58. CurrentWriteBank: integer; { active write bank }
  59. BankShift : word; { address to shift by when switching banks. }
  60. function hexstr(val : longint;cnt : byte) : string;
  61. const
  62. HexTbl : array[0..15] of char='0123456789ABCDEF';
  63. var
  64. i : longint;
  65. begin
  66. hexstr[0]:=char(cnt);
  67. for i:=cnt downto 1 do
  68. begin
  69. hexstr[i]:=hextbl[val and $f];
  70. val:=val shr 4;
  71. end;
  72. end;
  73. {$IFDEF DPMI}
  74. function getVESAInfo(var VESAInfo: TVESAInfo) : boolean;
  75. var
  76. ptrlong : longint;
  77. VESAPtr : ^TVESAInfo;
  78. regs : TDPMIRegisters;
  79. {$ifndef fpc}
  80. ModeSel: word;
  81. offs: longint;
  82. {$endif fpc}
  83. { added... }
  84. modelist: PmodeList;
  85. i: longint;
  86. RealSeg : word;
  87. begin
  88. { Allocate real mode buffer }
  89. {$ifndef fpc}
  90. Ptrlong:=GlobalDosAlloc(sizeof(TVESAInfo));
  91. { Get selector value }
  92. VESAPtr := pointer(Ptrlong shl 16);
  93. {$else fpc}
  94. Ptrlong:=Global_Dos_Alloc(sizeof(TVESAInfo));
  95. New(VESAPtr);
  96. {$endif fpc}
  97. { Get segment value }
  98. RealSeg := word(Ptrlong shr 16);
  99. if not assigned(VESAPtr) then
  100. RunError(203);
  101. FillChar(regs, sizeof(regs), #0);
  102. { Get VESA Mode information ... }
  103. regs.eax := $4f00;
  104. regs.es := RealSeg;
  105. regs.edi := $00;
  106. RealIntr($10, regs);
  107. {$ifdef fpc}
  108. { no far pointer support in FPC yet, so move the vesa info into a memory }
  109. { block in the DS slector space (JM) }
  110. dosmemget(RealSeg,0,VesaPtr^,SizeOf(TVESAInfo));
  111. {$endif fpc}
  112. if VESAPtr^.Signature <> 'VESA' then
  113. begin
  114. {$ifdef logging}
  115. LogLn('No VESA detected.');
  116. {$endif logging}
  117. getVesaInfo := FALSE;
  118. {$ifndef fpc}
  119. GlobalDosFree(word(PtrLong and $ffff));
  120. {$else fpc}
  121. If not Global_Dos_Free(word(PtrLong and $ffff)) then
  122. RunError(216);
  123. { also free the extra allocated buffer }
  124. Dispose(VESAPtr);
  125. {$endif fpc}
  126. exit;
  127. end
  128. else
  129. getVesaInfo := TRUE;
  130. {$ifndef fpc}
  131. { The mode pointer buffer points to a real mode memory }
  132. { Therefore steps to get the modes: }
  133. { 1. Allocate Selector and SetLimit to max number of }
  134. { of possible modes. }
  135. ModeSel := AllocSelector(0);
  136. SetSelectorLimit(ModeSel, 256*sizeof(word));
  137. { 2. Set Selector linear address to the real mode pointer }
  138. { returned. }
  139. offs := longint(longint(VESAPtr^.ModeList) shr 16) shl 4;
  140. {shouldn't the OR in the next line be a + ?? (JM)}
  141. offs := offs OR (Longint(VESAPtr^.ModeList) and $ffff);
  142. SetSelectorBase(ModeSel, offs);
  143. { copy VESA mode information to a protected mode buffer and }
  144. { then free the real mode buffer... }
  145. Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
  146. GlobalDosFree(word(PtrLong and $ffff));
  147. { ModeList points to the mode list }
  148. { We must copy it somewhere... }
  149. ModeList := Ptr(ModeSel, 0);
  150. {$else fpc}
  151. { No far pointer support, so the Ptr(ModeSel, 0) doesn't work. }
  152. { Immediately copy everything to a buffer in the DS selector space }
  153. New(ModeList);
  154. { The following may copy data from outside the VESA buffer, but it }
  155. { shouldn't get past the 1MB limit, since that would mean the buffer }
  156. { has been allocated in the BIOS or high memory region, which seems }
  157. { impossible to me (JM)}
  158. DosMemGet(word(longint(VESAPtr^.ModeList) shr 16),
  159. word(longint(VESAPtr^.ModeList) and $ffff), ModeList^,256*sizeof(word));
  160. { copy VESA mode information to a protected mode buffer and }
  161. { then free the real mode buffer... }
  162. Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
  163. If not Global_Dos_Free(word(PtrLong and $ffff)) then
  164. RunError(216);
  165. Dispose(VESAPtr);
  166. {$endif fpc}
  167. i:=0;
  168. new(VESAInfo.ModeList);
  169. while ModeList^[i]<> $ffff do
  170. begin
  171. VESAInfo.ModeList^[i] := ModeList^[i];
  172. Inc(i);
  173. end;
  174. VESAInfo.ModeList^[i]:=$ffff;
  175. { Free the temporary selector used to get mode information }
  176. {$ifdef logging}
  177. LogLn(strf(i) + ' modes found.');
  178. {$endif logging}
  179. {$ifndef fpc}
  180. FreeSelector(ModeSel);
  181. {$else fpc}
  182. Dispose(ModeList);
  183. {$endif fpc}
  184. end;
  185. function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;
  186. var
  187. Ptr: longint;
  188. {$ifndef fpc}
  189. VESAPtr : ^TVESAModeInfo;
  190. {$endif fpc}
  191. regs : TDPMIRegisters;
  192. RealSeg: word;
  193. begin
  194. { Alllocate real mode buffer }
  195. {$ifndef fpc}
  196. Ptr:=GlobalDosAlloc(sizeof(TVESAModeInfo));
  197. { get the selector value }
  198. VESAPtr := pointer(longint(Ptr shl 16));
  199. if not assigned(VESAPtr) then
  200. RunError(203);
  201. {$else fpc}
  202. Ptr:=Global_Dos_Alloc(sizeof(TVESAModeInfo));
  203. {$endif fpc}
  204. { get the segment value }
  205. RealSeg := word(Ptr shr 16);
  206. { setup interrupt registers }
  207. FillChar(regs, sizeof(regs), #0);
  208. { call VESA mode information...}
  209. regs.eax := $4f01;
  210. regs.es := RealSeg;
  211. regs.edi := $00;
  212. regs.ecx := mode;
  213. RealIntr($10, regs);
  214. if word(regs.eax) <> $4f then
  215. getVESAModeInfo := FALSE
  216. else
  217. getVESAModeInfo := TRUE;
  218. { copy to protected mode buffer ... }
  219. {$ifndef fpc}
  220. Move(VESAPtr^, ModeInfo, sizeof(ModeInfo));
  221. {$else fpc}
  222. DosMemGet(RealSeg,0,ModeInfo,sizeof(ModeInfo));
  223. {$endif fpc}
  224. { free real mode memory }
  225. {$ifndef fpc}
  226. GlobalDosFree(Word(Ptr and $ffff));
  227. {$else fpc}
  228. If not Global_Dos_Free(Word(Ptr and $ffff)) then
  229. RunError(216);
  230. {$endif fpc}
  231. end;
  232. {$ELSE}
  233. function getVESAInfo(var VESAInfo: TVESAInfo) : boolean; assembler;
  234. asm
  235. mov ax,4F00h
  236. les di,VESAInfo
  237. int 10h
  238. sub ax,004Fh {make sure we got 004Fh back}
  239. cmp ax,1
  240. sbb al,al
  241. cmp word ptr es:[di],'V'or('E'shl 8) {signature should be 'VESA'}
  242. jne @@ERR
  243. cmp word ptr es:[di+2],'S'or('A'shl 8)
  244. je @@X
  245. @@ERR:
  246. mov al,0
  247. @@X:
  248. end;
  249. function getModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;assembler;
  250. asm
  251. mov ax,4F01h
  252. mov cx,mode
  253. les di,ModeInfo
  254. int 10h
  255. sub ax,004Fh {make sure it's 004Fh}
  256. cmp ax,1
  257. sbb al,al
  258. end;
  259. {$ENDIF}
  260. function SearchVESAModes(mode: Word): boolean;
  261. {********************************************************}
  262. { Searches for a specific DEFINED vesa mode. If the mode }
  263. { is not available for some reason, then returns FALSE }
  264. { otherwise returns TRUE. }
  265. {********************************************************}
  266. var
  267. i: word;
  268. ModeSupported : Boolean;
  269. begin
  270. i:=0;
  271. { let's assume it's not available ... }
  272. ModeSupported := FALSE;
  273. { This is a STUB VESA implementation }
  274. if VESAInfo.ModeList^[0] = $FFFF then exit;
  275. repeat
  276. if VESAInfo.ModeList^[i] = mode then
  277. begin
  278. { we found it, the card supports this mode... }
  279. ModeSupported := TRUE;
  280. break;
  281. end;
  282. Inc(i);
  283. until VESAInfo.ModeList^[i] = $ffff;
  284. { now check if the hardware supports it... }
  285. If ModeSupported then
  286. begin
  287. { we have to init everything to zero, since VBE < 1.1 }
  288. { may not setup fields correctly. }
  289. FillChar(VESAModeInfo, sizeof(VESAModeInfo), #0);
  290. If GetVESAModeInfo(VESAModeInfo, Mode) And
  291. ((VESAModeInfo.attr and modeAvail) <> 0) then
  292. ModeSupported := TRUE
  293. else
  294. ModeSupported := FALSE;
  295. end;
  296. SearchVESAModes := ModeSupported;
  297. end;
  298. procedure SetBankIndex(win: byte; BankNr: Integer); assembler;
  299. asm
  300. mov ax,4f05h
  301. mov bh,00h
  302. mov bl,[Win]
  303. mov dx,[BankNr]
  304. {$ifdef fpc}
  305. push ebp
  306. {$endif fpc}
  307. int 10h
  308. {$ifdef fpc}
  309. pop ebp
  310. {$endif fpc}
  311. end;
  312. {********************************************************}
  313. { There are two routines for setting banks. This may in }
  314. { in some cases optimize a bit some operations, if the }
  315. { hardware supports it, because one window is used for }
  316. { reading and one window is used for writing. }
  317. {********************************************************}
  318. procedure SetReadBank(BankNr: Integer);
  319. begin
  320. { check if this is the current bank... if so do nothing. }
  321. if BankNr = CurrentReadBank then exit;
  322. {$ifdef logging}
  323. { LogLn('Setting read bank to '+strf(BankNr));}
  324. {$endif logging}
  325. CurrentReadBank := BankNr; { save current bank number }
  326. BankNr := BankNr shl BankShift; { adjust to window granularity }
  327. { we set both banks, since one may read only }
  328. SetBankIndex(ReadWindow, BankNr);
  329. { if the hardware supports only one window }
  330. { then there is only one single bank, so }
  331. { update both bank numbers. }
  332. if ReadWindow = WriteWindow then
  333. CurrentWriteBank := CurrentReadBank;
  334. end;
  335. procedure SetWriteBank(BankNr: Integer);
  336. begin
  337. { check if this is the current bank... if so do nothing. }
  338. if BankNr = CurrentWriteBank then exit;
  339. {$ifdef logging}
  340. { LogLn('Setting write bank to '+strf(BankNr));}
  341. {$endif logging}
  342. CurrentWriteBank := BankNr; { save current bank number }
  343. BankNr := BankNr shl BankShift; { adjust to window granularity }
  344. { we set both banks, since one may read only }
  345. SetBankIndex(WriteWindow, BankNr);
  346. { if the hardware supports only one window }
  347. { then there is only one single bank, so }
  348. { update both bank numbers. }
  349. if ReadWindow = WriteWindow then
  350. CurrentReadBank := CurrentWriteBank;
  351. end;
  352. {************************************************************************}
  353. {* 8-bit pixels VESA mode routines *}
  354. {************************************************************************}
  355. procedure PutPixVESA256(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
  356. var
  357. offs : longint;
  358. begin
  359. X:= X + StartXViewPort;
  360. Y:= Y + StartYViewPort;
  361. { convert to absolute coordinates and then verify clipping...}
  362. if ClipPixels then
  363. Begin
  364. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  365. exit;
  366. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  367. exit;
  368. end;
  369. offs := longint(y) * BytesPerLine + x;
  370. SetWriteBank(integer(offs shr 16));
  371. mem[WinWriteSeg : word(offs)] := byte(color);
  372. end;
  373. procedure DirectPutPixVESA256(x, y : integer); {$ifndef fpc}far;{$endif fpc}
  374. var
  375. offs : longint;
  376. col : byte;
  377. begin
  378. offs := longint(y) * BytesPerLine + x;
  379. SetWriteBank(integer(offs shr 16));
  380. Case CurrentWriteMode of
  381. XorPut:
  382. Begin
  383. SetReadBank(integer(offs shr 16));
  384. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] xor byte(CurrentColor);
  385. End;
  386. AndPut:
  387. Begin
  388. SetReadBank(integer(offs shr 16));
  389. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] And byte(CurrentColor);
  390. End;
  391. OrPut:
  392. Begin
  393. SetReadBank(integer(offs shr 16));
  394. mem[WinWriteSeg : word(offs)] := mem[WinReadSeg : word(offs)] or byte(currentcolor);
  395. End
  396. else
  397. Begin
  398. If CurrentWriteMode <> NotPut then
  399. col := Byte(CurrentColor)
  400. else col := Not(Byte(CurrentColor));
  401. mem[WinWriteSeg : word(offs)] := Col;
  402. End
  403. End;
  404. end;
  405. function GetPixVESA256(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
  406. var
  407. offs : longint;
  408. begin
  409. X:= X + StartXViewPort;
  410. Y:= Y + StartYViewPort;
  411. offs := longint(y) * BytesPerLine + x;
  412. SetReadBank(integer(offs shr 16));
  413. GetPixVESA256:=mem[WinReadSeg : word(offs)];
  414. end;
  415. procedure HLineVESA256(x,x2,y: integer); {$ifndef fpc}far;{$endif fpc}
  416. var Offs: Longint;
  417. mask, l, bankrest: longint;
  418. curbank, hlength: integer;
  419. Begin
  420. { must we swap the values? }
  421. if x > x2 then
  422. Begin
  423. x := x xor x2;
  424. x2 := x xor x2;
  425. x:= x xor x2;
  426. end;
  427. { First convert to global coordinates }
  428. X := X + StartXViewPort;
  429. X2 := X2 + StartXViewPort;
  430. Y := Y + StartYViewPort;
  431. if ClipPixels then
  432. Begin
  433. if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  434. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  435. exit;
  436. end;
  437. {$ifdef logging}
  438. LogLn('hline '+strf(x)+' - '+strf(x2)+' on '+strf(y)+' in mode '+strf(currentwritemode));
  439. {$endif logging}
  440. HLength := x2 - x + 1;
  441. {$ifdef logging}
  442. LogLn('length: '+strf(hlength));
  443. {$endif logging}
  444. if HLength>0 then
  445. begin
  446. Offs:=Longint(y)*bytesperline+x;
  447. {$ifdef logging}
  448. LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
  449. {$endif logging}
  450. Mask := byte(CurrentColor)+byte(CurrentColor) shl 8;
  451. Mask := Mask + Mask shl 16;
  452. Case CurrentWriteMode of
  453. AndPut:
  454. Begin
  455. Repeat
  456. curbank := integer(offs shr 16);
  457. SetWriteBank(curbank);
  458. SetReadBank(curbank);
  459. {$ifdef logging}
  460. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  461. {$endif logging}
  462. If HLength > 3 Then
  463. { allign target }
  464. Begin
  465. l := 0;
  466. If (offs and 3) <> 0 then
  467. { this cannot go past a window boundary bacause the }
  468. { size of a window is always a multiple of 4 }
  469. Begin
  470. {$ifdef logging}
  471. LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
  472. {$endif logging}
  473. for l := 1 to 4-(offs and 3) do
  474. Mem[WinWriteSeg:word(offs)+l-1] :=
  475. Mem[WinReadSeg:word(offs)+l-1] And Byte(CurrentColor);
  476. End;
  477. Dec(HLength, l);
  478. inc(offs, l);
  479. {$ifdef logging}
  480. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  481. {$endif logging}
  482. { offs is now 4-bytes alligned }
  483. If HLength <= ($10000-(Offs and $ffff)) Then
  484. bankrest := HLength
  485. else {the rest won't fit anymore in the current window }
  486. bankrest := $10000 - (Offs and $ffff);
  487. {$ifdef logging}
  488. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  489. {$endif logging}
  490. For l := 0 to (Bankrest div 4)-1 Do
  491. MemL[WinWriteSeg:word(offs)+l*4] :=
  492. MemL[WinReadSeg:word(offs)+l*4] And Mask;
  493. inc(offs,l*4+4);
  494. dec(hlength,l*4+4);
  495. {$ifdef logging}
  496. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  497. {$endif logging}
  498. End
  499. Else
  500. Begin
  501. {$ifdef logging}
  502. LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
  503. {$endif logging}
  504. x := offs mod bytesperline;
  505. For l := 0 to HLength - 1 do
  506. DirectPutPixVESA256(x+l,y);
  507. HLength := 0
  508. End
  509. Until HLength = 0;
  510. End;
  511. XorPut:
  512. Begin
  513. Repeat
  514. curbank := integer(offs shr 16);
  515. SetWriteBank(curbank);
  516. SetReadBank(curbank);
  517. {$ifdef logging}
  518. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  519. {$endif logging}
  520. If HLength > 3 Then
  521. { allign target }
  522. Begin
  523. l := 0;
  524. If (offs and 3) <> 0 then
  525. { this cannot go past a window boundary bacause the }
  526. { size of a window is always a multiple of 4 }
  527. Begin
  528. {$ifdef logging}
  529. LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
  530. {$endif logging}
  531. for l := 1 to 4-(offs and 3) do
  532. Mem[WinWriteSeg:word(offs)+l-1] :=
  533. Mem[WinReadSeg:word(offs)+l-1] Xor Byte(CurrentColor);
  534. End;
  535. Dec(HLength, l);
  536. inc(offs, l);
  537. {$ifdef logging}
  538. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  539. {$endif logging}
  540. { offs is now 4-bytes alligned }
  541. If HLength <= ($10000-(Offs and $ffff)) Then
  542. bankrest := HLength
  543. else {the rest won't fit anymore in the current window }
  544. bankrest := $10000 - (Offs and $ffff);
  545. {$ifdef logging}
  546. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  547. {$endif logging}
  548. For l := 0 to (Bankrest div 4)-1 Do
  549. MemL[WinWriteSeg:word(offs)+l*4] :=
  550. MemL[WinReadSeg:word(offs)+l*4] Xor Mask;
  551. inc(offs,l*4+4);
  552. dec(hlength,l*4+4);
  553. {$ifdef logging}
  554. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  555. {$endif logging}
  556. End
  557. Else
  558. Begin
  559. {$ifdef logging}
  560. LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
  561. {$endif logging}
  562. x := offs mod bytesperline;
  563. For l := 0 to HLength - 1 do
  564. DirectPutPixVESA256(x+l,y);
  565. HLength := 0
  566. End
  567. Until HLength = 0;
  568. End;
  569. OrPut:
  570. Begin
  571. Repeat
  572. curbank := integer(offs shr 16);
  573. SetWriteBank(curbank);
  574. SetReadBank(curbank);
  575. {$ifdef logging}
  576. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  577. {$endif logging}
  578. If HLength > 3 Then
  579. { allign target }
  580. Begin
  581. l := 0;
  582. If (offs and 3) <> 0 then
  583. { this cannot go past a window boundary bacause the }
  584. { size of a window is always a multiple of 4 }
  585. Begin
  586. {$ifdef logging}
  587. LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
  588. {$endif logging}
  589. for l := 1 to 4-(offs and 3) do
  590. Mem[WinWriteSeg:word(offs)+l-1] :=
  591. Mem[WinReadSeg:word(offs)+l-1] Or Byte(CurrentColor);
  592. End;
  593. Dec(HLength, l);
  594. inc(offs, l);
  595. {$ifdef logging}
  596. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  597. {$endif logging}
  598. { offs is now 4-bytes alligned }
  599. If HLength <= ($10000-(Offs and $ffff)) Then
  600. bankrest := HLength
  601. else {the rest won't fit anymore in the current window }
  602. bankrest := $10000 - (Offs and $ffff);
  603. {$ifdef logging}
  604. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  605. {$endif logging}
  606. For l := 0 to (Bankrest div 4)-1 Do
  607. MemL[WinWriteSeg:offs+l*4] :=
  608. MemL[WinReadSeg:word(offs)+l*4] Or Mask;
  609. inc(offs,l*4+4);
  610. dec(hlength,l*4+4);
  611. {$ifdef logging}
  612. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  613. {$endif logging}
  614. End
  615. Else
  616. Begin
  617. {$ifdef logging}
  618. LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
  619. {$endif logging}
  620. x := offs mod bytesperline;
  621. For l := 0 to HLength - 1 do
  622. DirectPutPixVESA256(x+l,y);
  623. HLength := 0
  624. End
  625. Until HLength = 0;
  626. End
  627. Else
  628. Begin
  629. If CurrentWriteMode = NotPut Then
  630. Mask := Not(Mask);
  631. Repeat
  632. curbank := integer(offs shr 16);
  633. SetWriteBank(curbank);
  634. {$ifdef logging}
  635. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)+' -- '+strf(offs));
  636. {$endif logging}
  637. If HLength > 3 Then
  638. { allign target }
  639. Begin
  640. l := 0;
  641. If (offs and 3) <> 0 then
  642. { this cannot go past a window boundary bacause the }
  643. { size of a window is always a multiple of 4 }
  644. Begin
  645. {$ifdef logging}
  646. LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
  647. {$endif logging}
  648. for l := 1 to 4-(offs and 3) do
  649. Mem[WinWriteSeg:word(offs)+l-1] := Byte(Mask);
  650. End;
  651. Dec(HLength, l);
  652. inc(offs, l);
  653. {$ifdef logging}
  654. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  655. {$endif logging}
  656. { offs is now 4-bytes alligned }
  657. If HLength <= ($10000-(Offs and $ffff)) Then
  658. bankrest := HLength
  659. else {the rest won't fit anymore in the current window }
  660. bankrest := $10000 - (Offs and $ffff);
  661. {$ifdef logging}
  662. LogLn('Rest to be drawn in this window: '+strf(bankrest)+' -- '+hexstr(bankrest,8));
  663. {$endif logging}
  664. For l := 0 to (Bankrest div 4)-1 Do
  665. MemL[WinWriteSeg:word(offs)+l*4] := Mask;
  666. inc(offs,l*4+4);
  667. dec(hlength,l*4+4);
  668. {$ifdef logging}
  669. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  670. {$endif logging}
  671. End
  672. Else
  673. Begin
  674. {$ifdef logging}
  675. LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
  676. {$endif logging}
  677. x := offs mod bytesperline;
  678. For l := 0 to HLength - 1 do
  679. DirectPutPixVESA256(x+l,y);
  680. HLength := 0
  681. End
  682. Until HLength = 0;
  683. End;
  684. End;
  685. end;
  686. end;
  687. procedure VLineVESA256(x,y,y2: integer); {$ifndef fpc}far;{$endif fpc}
  688. var Offs: Longint;
  689. l, bankrest: longint;
  690. curbank, vlength: integer;
  691. col: byte;
  692. Begin
  693. { must we swap the values? }
  694. if y > y2 then
  695. Begin
  696. y := y xor y2;
  697. y2 := y xor y2;
  698. y:= y xor y2;
  699. end;
  700. { First convert to global coordinates }
  701. X := X + StartXViewPort;
  702. Y := Y + StartYViewPort;
  703. Y2 := Y2 + StartYViewPort;
  704. if ClipPixels then
  705. Begin
  706. if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
  707. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  708. exit;
  709. end;
  710. {$ifdef logging}
  711. LogLn('vline '+strf(y)+' - '+strf(y2)+' on '+strf(x)+' in mode '+strf(currentwritemode));
  712. {$endif logging}
  713. VLength := y2 - y + 1;
  714. {$ifdef logging}
  715. LogLn('length: '+strf(vlength));
  716. {$endif logging}
  717. if VLength>0 then
  718. begin
  719. Offs:=Longint(y)*bytesperline+x;
  720. {$ifdef logging}
  721. LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
  722. {$endif logging}
  723. Case CurrentWriteMode of
  724. AndPut:
  725. Begin
  726. Repeat
  727. curbank := integer(offs shr 16);
  728. SetWriteBank(curbank);
  729. SetReadBank(curbank);
  730. {$ifdef logging}
  731. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  732. {$endif logging}
  733. If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
  734. bankrest := VLength
  735. else {the rest won't fit anymore in the current window }
  736. bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
  737. {$ifdef logging}
  738. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  739. {$endif logging}
  740. For l := 0 to Bankrest-1 Do
  741. begin
  742. Mem[WinWriteSeg:word(offs)] :=
  743. Mem[WinReadSeg:word(offs)] And Byte(CurrentColor);
  744. inc(offs,bytesperline);
  745. end;
  746. dec(VLength,l+1);
  747. {$ifdef logging}
  748. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
  749. {$endif logging}
  750. Until VLength = 0;
  751. End;
  752. XorPut:
  753. Begin
  754. Repeat
  755. curbank := integer(offs shr 16);
  756. SetWriteBank(curbank);
  757. SetReadBank(curbank);
  758. {$ifdef logging}
  759. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  760. {$endif logging}
  761. If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
  762. bankrest := VLength
  763. else {the rest won't fit anymore in the current window }
  764. bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
  765. {$ifdef logging}
  766. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  767. {$endif logging}
  768. For l := 0 to Bankrest-1 Do
  769. begin
  770. Mem[WinWriteSeg:word(offs)] :=
  771. Mem[WinReadSeg:word(offs)] Xor Byte(CurrentColor);
  772. inc(offs,bytesperline);
  773. end;
  774. dec(VLength,l+1);
  775. {$ifdef logging}
  776. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
  777. {$endif logging}
  778. Until VLength = 0;
  779. End;
  780. OrPut:
  781. Begin
  782. Repeat
  783. curbank := integer(offs shr 16);
  784. SetWriteBank(curbank);
  785. SetReadBank(curbank);
  786. {$ifdef logging}
  787. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  788. {$endif logging}
  789. If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
  790. bankrest := VLength
  791. else {the rest won't fit anymore in the current window }
  792. bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
  793. {$ifdef logging}
  794. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  795. {$endif logging}
  796. For l := 0 to Bankrest-1 Do
  797. begin
  798. Mem[WinWriteSeg:word(offs)] :=
  799. Mem[WinReadSeg:word(offs)] Or Byte(CurrentColor);
  800. inc(offs,bytesperline);
  801. end;
  802. dec(VLength,l+1);
  803. {$ifdef logging}
  804. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
  805. {$endif logging}
  806. Until VLength = 0;
  807. End;
  808. Else
  809. Begin
  810. If CurrentWriteMode = NotPut Then
  811. Col := Not(CurrentColor);
  812. Repeat
  813. curbank := integer(offs shr 16);
  814. SetWriteBank(curbank);
  815. {$ifdef logging}
  816. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  817. {$endif logging}
  818. If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
  819. bankrest := VLength
  820. else {the rest won't fit anymore in the current window }
  821. bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
  822. {$ifdef logging}
  823. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  824. {$endif logging}
  825. For l := 0 to Bankrest-1 Do
  826. begin
  827. Mem[WinWriteSeg:word(offs)] := Col;
  828. inc(offs,bytesperline);
  829. end;
  830. dec(VLength,l+1);
  831. {$ifdef logging}
  832. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
  833. {$endif logging}
  834. Until VLength = 0;
  835. End;
  836. End;
  837. end;
  838. end;
  839. {************************************************************************}
  840. {* 15/16bit pixels VESA mode routines *}
  841. {************************************************************************}
  842. procedure PutPixVESA32k(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
  843. var
  844. offs : longint;
  845. begin
  846. X:= X + StartXViewPort;
  847. Y:= Y + StartYViewPort;
  848. { convert to absolute coordinates and then verify clipping...}
  849. if ClipPixels then
  850. Begin
  851. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  852. exit;
  853. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  854. exit;
  855. end;
  856. offs := longint(y) * BytesPerLine + 2*x;
  857. SetWriteBank(integer(offs shr 16));
  858. memW[WinWriteSeg : word(offs)] := color;
  859. end;
  860. procedure PutPixVESA64k(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
  861. var
  862. offs : longint;
  863. begin
  864. X:= X + StartXViewPort;
  865. Y:= Y + StartYViewPort;
  866. { convert to absolute coordinates and then verify clipping...}
  867. if ClipPixels then
  868. Begin
  869. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  870. exit;
  871. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  872. exit;
  873. end;
  874. offs := longint(y) * BytesPerLine + 2*x;
  875. SetWriteBank(integer(offs shr 16));
  876. memW[WinWriteSeg : word(offs)] := color;
  877. end;
  878. function GetPixVESA32k(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
  879. var
  880. offs : longint;
  881. begin
  882. X:= X + StartXViewPort;
  883. Y:= Y + StartYViewPort;
  884. offs := longint(y) * BytesPerLine + 2*x;
  885. SetReadBank(integer(offs shr 16));
  886. GetPixVESA32k:=memW[WinReadSeg : word(offs)];
  887. end;
  888. function GetPixVESA64k(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
  889. var
  890. offs : longint;
  891. begin
  892. X:= X + StartXViewPort;
  893. Y:= Y + StartYViewPort;
  894. offs := longint(y) * BytesPerLine + 2*x;
  895. SetReadBank(integer(offs shr 16));
  896. GetPixVESA64k:=memW[WinReadSeg : word(offs)];
  897. end;
  898. procedure DirectPutPixVESA32k(x, y : integer); {$ifndef fpc}far;{$endif fpc}
  899. var
  900. offs : longint;
  901. col : word;
  902. begin
  903. offs := longint(y) * BytesPerLine + 2*x;
  904. SetWriteBank(integer((offs shr 16) and $ff));
  905. Case CurrentWriteMode of
  906. XorPut:
  907. Begin
  908. SetReadBank(integer(offs shr 16));
  909. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] xor currentcolor;
  910. End;
  911. AndPut:
  912. Begin
  913. SetReadBank(integer(offs shr 16));
  914. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] And currentcolor;
  915. End;
  916. OrPut:
  917. Begin
  918. SetReadBank(integer(offs shr 16));
  919. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] or currentcolor;
  920. End
  921. else
  922. Begin
  923. If CurrentWriteMode <> NotPut Then
  924. col := CurrentColor
  925. Else col := Not(CurrentColor);
  926. memW[WinWriteSeg : word(offs)] := Col;
  927. End
  928. End;
  929. end;
  930. procedure DirectPutPixVESA64k(x, y : integer); {$ifndef fpc}far;{$endif fpc}
  931. var
  932. offs : longint;
  933. Col : word;
  934. begin
  935. offs := longint(y) * BytesPerLine + 2*x;
  936. SetWriteBank(integer(offs shr 16));
  937. Case CurrentWriteMode of
  938. XorPut:
  939. Begin
  940. SetReadBank(integer(offs shr 16));
  941. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] xor currentcolor;
  942. End;
  943. AndPut:
  944. Begin
  945. SetReadBank(integer(offs shr 16));
  946. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] And currentcolor;
  947. End;
  948. OrPut:
  949. Begin
  950. SetReadBank(integer(offs shr 16));
  951. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] or currentcolor;
  952. End
  953. Else
  954. Begin
  955. If CurrentWriteMode <> NotPut Then
  956. col := CurrentColor
  957. Else col := Not(CurrentColor);
  958. memW[WinWriteSeg : word(offs)] := Col;
  959. End
  960. End;
  961. end;
  962. {************************************************************************}
  963. {* 4-bit pixels VESA mode routines *}
  964. {************************************************************************}
  965. procedure PutPixVESA16(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
  966. var
  967. offs : longint;
  968. dummy_read : byte;
  969. begin
  970. X:= X + StartXViewPort;
  971. Y:= Y + StartYViewPort;
  972. { convert to absolute coordinates and then verify clipping...}
  973. if ClipPixels then
  974. Begin
  975. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  976. exit;
  977. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  978. exit;
  979. end;
  980. { this can be done only once at InitGraph }
  981. PortW[$3C4] := $0f02;
  982. PortW[$3CE] := $0003;
  983. PortW[$3CE] := $0205;
  984. { }
  985. offs := longint(y) * BytesPerLine + (x div 8);
  986. SetWriteBank(integer(offs shr 16));
  987. port[$3CE] := $08;
  988. port[$3CF] := ($80 shr (x and 7));
  989. dummy_read := mem[WinWriteSeg : word(offs)];
  990. mem[winWriteSeg : offs] := byte(color);
  991. { this can be done only once at DoneGraph..}
  992. PortW[$3CE] := $FF08;
  993. PortW[$3CE] := $0005;
  994. { }
  995. end;
  996. procedure DirectPutPixVESA16(x, y : integer); {$ifndef fpc}far;{$endif fpc}
  997. var
  998. offs : longint;
  999. dummy_read : byte;
  1000. begin
  1001. { this can be done only once at InitGraph }
  1002. PortW[$3C4] := $0f02;
  1003. PortW[$3CE] := $0003;
  1004. PortW[$3CE] := $0205;
  1005. { }
  1006. offs := longint(y) * BytesPerLine + (x div 8);
  1007. SetWriteBank(integer(offs shr 16));
  1008. port[$3CE] := $08;
  1009. port[$3CF] := ($80 shr (x and 7));
  1010. dummy_read := mem[WinWriteSeg : word(offs)];
  1011. mem[winWriteSeg : offs] := byte(CurrentColor);
  1012. { this can be done only once at DoneGraph..}
  1013. PortW[$3CE] := $FF08;
  1014. PortW[$3CE] := $0005;
  1015. { }
  1016. end;
  1017. {************************************************************************}
  1018. {* VESA Palette entries *}
  1019. {************************************************************************}
  1020. {$IFDEF DPMI}
  1021. Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
  1022. BlueValue : Integer);
  1023. var
  1024. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  1025. pal: palrec;
  1026. Error : boolean; { VBE call error }
  1027. regs: TDPMIRegisters;
  1028. Ptr: longint;
  1029. {$ifndef fpc}
  1030. PalPtr : ^PalRec;
  1031. {$endif fpc}
  1032. RealSeg: word;
  1033. begin
  1034. if DirectColor then
  1035. Begin
  1036. _GraphResult := grError;
  1037. exit;
  1038. end;
  1039. Error := TRUE;
  1040. pal.align := 0;
  1041. pal.red := byte(RedValue);
  1042. pal.green := byte(GreenValue);
  1043. pal.blue := byte(BlueValue);
  1044. { use the set/get palette function }
  1045. if VESAInfo.Version >= $0200 then
  1046. Begin
  1047. { check if blanking bit must be set when programming }
  1048. { the RAMDAC. }
  1049. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  1050. FunctionNr := $80
  1051. else
  1052. FunctionNr := $00;
  1053. { Alllocate real mode buffer }
  1054. {$ifndef fpc}
  1055. Ptr:=GlobalDosAlloc(sizeof(palrec));
  1056. { get the selector values }
  1057. PalPtr := pointer(Ptr shl 16);
  1058. if not assigned(PalPtr) then
  1059. RunError(203);
  1060. {$else fpc}
  1061. Ptr:=Global_Dos_Alloc(sizeof(palrec));
  1062. {$endif fpc}
  1063. {get the segment value}
  1064. RealSeg := word(Ptr shr 16);
  1065. { setup interrupt registers }
  1066. FillChar(regs, sizeof(regs), #0);
  1067. { copy palette values to real mode buffer }
  1068. {$ifndef fpc}
  1069. move(pal, palptr^, sizeof(pal));
  1070. {$else fpc}
  1071. DosMemPut(RealSeg,0,pal,sizeof(pal));
  1072. {$endif fpc}
  1073. regs.eax := $4F09;
  1074. regs.ebx := FunctionNr;
  1075. regs.ecx := $01;
  1076. regs.edx := ColorNum;
  1077. regs.es := RealSeg;
  1078. regs.edi := 0; { offset is always zero }
  1079. RealIntr($10, regs);
  1080. { free real mode memory }
  1081. {$ifndef fpc}
  1082. GlobalDosFree(word(Ptr and $ffff));
  1083. {$else fpc}
  1084. If not Global_Dos_Free(word(Ptr and $ffff)) then
  1085. RunError(216);
  1086. {$endif fpc}
  1087. if word(regs.eax) <> $004F then
  1088. begin
  1089. _GraphResult := grError;
  1090. exit;
  1091. end;
  1092. end
  1093. else
  1094. { assume it's fully VGA compatible palette-wise. }
  1095. Begin
  1096. SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  1097. end;
  1098. end;
  1099. Procedure GetVESARGBPalette(ColorNum: integer; Var
  1100. RedValue, GreenValue, BlueValue : integer);
  1101. var
  1102. pal: PalRec;
  1103. {$ifndef fpc}
  1104. palptr : ^PalRec;
  1105. {$endif fpc}
  1106. regs : TDPMIRegisters;
  1107. RealSeg: word;
  1108. ptr: longint;
  1109. begin
  1110. if DirectColor then
  1111. Begin
  1112. _GraphResult := grError;
  1113. exit;
  1114. end;
  1115. { use the set/get palette function }
  1116. if VESAInfo.Version >= $0200 then
  1117. Begin
  1118. { Alllocate real mode buffer }
  1119. {$ifndef fpc}
  1120. Ptr:=GlobalDosAlloc(sizeof(palrec));
  1121. { get the selector value }
  1122. PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
  1123. if not assigned(PalPtr) then
  1124. RunError(203);
  1125. {$else fpc}
  1126. Ptr:=Global_Dos_Alloc(sizeof(palrec));
  1127. {$endif fpc}
  1128. { get the segment value }
  1129. RealSeg := word(Ptr shr 16);
  1130. { setup interrupt registers }
  1131. FillChar(regs, sizeof(regs), #0);
  1132. regs.eax := $4F09;
  1133. regs.ebx := $01; { get palette data }
  1134. regs.ecx := $01;
  1135. regs.edx := ColorNum;
  1136. regs.es := RealSeg;
  1137. regs.edi := 0; { offset is always zero }
  1138. RealIntr($10, regs);
  1139. { copy to protected mode buffer ... }
  1140. {$ifndef fpc}
  1141. Move(PalPtr^, Pal, sizeof(pal));
  1142. {$else fpc}
  1143. DosMemGet(RealSeg,0,Pal,sizeof(pal));
  1144. {$endif fpc}
  1145. { free real mode memory }
  1146. {$ifndef fpc}
  1147. GlobalDosFree(word(Ptr and $ffff));
  1148. {$else fpc}
  1149. If not Global_Dos_Free(word(Ptr and $ffff)) then
  1150. RunError(216);
  1151. {$endif fpc}
  1152. if word(regs.eax) <> $004F then
  1153. begin
  1154. _GraphResult := grError;
  1155. exit;
  1156. end
  1157. else
  1158. begin
  1159. RedValue := Integer(pal.Red);
  1160. GreenValue := Integer(pal.Green);
  1161. BlueValue := Integer(pal.Blue);
  1162. end;
  1163. end
  1164. else
  1165. GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  1166. end;
  1167. {$ELSE}
  1168. Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
  1169. BlueValue : Integer); far;
  1170. var
  1171. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  1172. pal: ^palrec;
  1173. Error : boolean; { VBE call error }
  1174. begin
  1175. if DirectColor then
  1176. Begin
  1177. _GraphResult := grError;
  1178. exit;
  1179. end;
  1180. Error := FALSE;
  1181. new(pal);
  1182. if not assigned(pal) then RunError(203);
  1183. pal^.align := 0;
  1184. pal^.red := byte(RedValue);
  1185. pal^.green := byte(GreenValue);
  1186. pal^.blue := byte(BlueValue);
  1187. { use the set/get palette function }
  1188. if VESAInfo.Version >= $0200 then
  1189. Begin
  1190. { check if blanking bit must be set when programming }
  1191. { the RAMDAC. }
  1192. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  1193. FunctionNr := $80
  1194. else
  1195. FunctionNr := $00;
  1196. asm
  1197. mov ax, 4F09h { Set/Get Palette data }
  1198. mov bl, [FunctionNr] { Set palette data }
  1199. mov cx, 01h { update one palette reg. }
  1200. mov dx, [ColorNum] { register number to update }
  1201. les di, [pal] { get palette address }
  1202. int 10h
  1203. cmp ax, 004Fh { check if success }
  1204. jz @noerror
  1205. mov [Error], TRUE
  1206. @noerror:
  1207. end;
  1208. if not Error then
  1209. Dispose(pal)
  1210. else
  1211. begin
  1212. _GraphResult := grError;
  1213. exit;
  1214. end;
  1215. end
  1216. else
  1217. { assume it's fully VGA compatible palette-wise. }
  1218. Begin
  1219. SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  1220. end;
  1221. end;
  1222. Procedure GetVESARGBPalette(ColorNum: integer; Var RedValue, GreenValue,
  1223. BlueValue : integer); far;
  1224. var
  1225. Error: boolean;
  1226. pal: ^palrec;
  1227. begin
  1228. if DirectColor then
  1229. Begin
  1230. _GraphResult := grError;
  1231. exit;
  1232. end;
  1233. Error := FALSE;
  1234. new(pal);
  1235. if not assigned(pal) then RunError(203);
  1236. FillChar(pal^, sizeof(palrec), #0);
  1237. { use the set/get palette function }
  1238. if VESAInfo.Version >= $0200 then
  1239. Begin
  1240. asm
  1241. mov ax, 4F09h { Set/Get Palette data }
  1242. mov bl, 01h { Set palette data }
  1243. mov cx, 01h { update one palette reg. }
  1244. mov dx, [ColorNum] { register number to update }
  1245. les di, [pal] { get palette address }
  1246. int 10h
  1247. cmp ax, 004Fh { check if success }
  1248. jz @noerror
  1249. mov [Error], TRUE
  1250. @noerror:
  1251. end;
  1252. if not Error then
  1253. begin
  1254. RedValue := Integer(pal^.Red);
  1255. GreenValue := Integer(pal^.Green);
  1256. BlueValue := Integer(pal^.Blue);
  1257. Dispose(pal);
  1258. end
  1259. else
  1260. begin
  1261. _GraphResult := grError;
  1262. exit;
  1263. end;
  1264. end
  1265. else
  1266. GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  1267. end;
  1268. {$ENDIF}
  1269. procedure SetupLinear(var ModeInfo: TVESAModeInfo);
  1270. begin
  1271. { !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! }
  1272. end;
  1273. procedure SetupWindows(var ModeInfo: TVESAModeInfo);
  1274. begin
  1275. { now we check the windowing scheme ...}
  1276. if (ModeInfo.WinAAttr and WinSupported) <> 0 then
  1277. { is this window supported ... }
  1278. begin
  1279. { now check if the window is R/W }
  1280. if (ModeInfo.WinAAttr and WinReadable) <> 0 then
  1281. begin
  1282. ReadWindow := 0;
  1283. WinReadSeg := ModeInfo.WinASeg;
  1284. end;
  1285. if (ModeInfo.WinAAttr and WinWritable) <> 0 then
  1286. begin
  1287. WriteWindow := 0;
  1288. WinWriteSeg := ModeInfo.WinASeg;
  1289. end;
  1290. end;
  1291. if (ModeInfo.WinBAttr and WinSupported) <> 0 then
  1292. { is this window supported ... }
  1293. begin
  1294. { OPTIMIZATION ... }
  1295. { if window A supports both read/write, then we try to optimize }
  1296. { everything, by using a different window for Read and/or write.}
  1297. if (WinReadSeg <> 0) and (WinWriteSeg <> 0) then
  1298. begin
  1299. { check if winB supports read }
  1300. if (ModeInfo.WinBAttr and winReadable) <> 0 then
  1301. begin
  1302. WinReadSeg := ModeInfo.WinBSeg;
  1303. ReadWindow := 1;
  1304. end
  1305. else
  1306. { check if WinB supports write }
  1307. if (ModeInfo.WinBAttr and WinWritable) <> 0 then
  1308. begin
  1309. WinWriteSeg := ModeInfo.WinBSeg;
  1310. WriteWindow := 1;
  1311. end;
  1312. end
  1313. else
  1314. { Window A only supported Read OR Write, no we have to make }
  1315. { sure that window B supports the other mode. }
  1316. if (WinReadSeg = 0) and (WinWriteSeg<>0) then
  1317. begin
  1318. if (ModeInfo.WinBAttr and WinReadable <> 0) then
  1319. begin
  1320. ReadWindow := 1;
  1321. WinReadSeg := ModeInfo.WinBSeg;
  1322. end
  1323. else
  1324. { impossible, this VESA mode is WRITE only! }
  1325. begin
  1326. WriteLn('Invalid VESA Window attribute.');
  1327. Halt(255);
  1328. end;
  1329. end
  1330. else
  1331. if (winWriteSeg = 0) and (WinReadSeg<>0) then
  1332. begin
  1333. if (ModeInfo.WinBAttr and WinWritable) <> 0 then
  1334. begin
  1335. WriteWindow := 1;
  1336. WinWriteSeg := ModeInfo.WinBSeg;
  1337. end
  1338. else
  1339. { impossible, this VESA mode is READ only! }
  1340. begin
  1341. WriteLn('Invalid VESA Window attribute.');
  1342. Halt(255);
  1343. end;
  1344. end
  1345. else
  1346. if (winReadSeg = 0) and (winWriteSeg = 0) then
  1347. { no read/write in this mode! }
  1348. begin
  1349. WriteLn('Invalid VESA Window attribute.');
  1350. Halt(255);
  1351. end;
  1352. end;
  1353. { if both windows are not supported, then we can assume }
  1354. { that there is ONE single NON relocatable window. }
  1355. if (WinWriteSeg = 0) and (WinReadSeg = 0) then
  1356. begin
  1357. WinWriteSeg := ModeInfo.WinASeg;
  1358. WinReadSeg := ModeInfo.WinASeg;
  1359. end;
  1360. { 16-bit Protected mode checking code... }
  1361. { change segment values to protected mode }
  1362. { selectors. }
  1363. if WinReadSeg = $A000 then
  1364. WinReadSeg := SegA000
  1365. else
  1366. if WinReadSeg = $B000 then
  1367. WinReadSeg := SegB000
  1368. else
  1369. if WinReadSeg = $B800 then
  1370. WinReadSeg := SegB800
  1371. else
  1372. begin
  1373. WriteLn('Invalid segment address.');
  1374. Halt(255);
  1375. end;
  1376. if WinWriteSeg = $A000 then
  1377. WinWriteSeg := SegA000
  1378. else
  1379. if WinWriteSeg = $B000 then
  1380. WinWriteSeg := SegB000
  1381. else
  1382. if WinWriteSeg = $B800 then
  1383. WinWriteSeg := SegB800
  1384. else
  1385. begin
  1386. WriteLn('Invalid segment address.');
  1387. Halt(255);
  1388. end;
  1389. end;
  1390. function setVESAMode(mode:word):boolean;
  1391. var i:word;
  1392. begin
  1393. { Init mode information, for compatibility with VBE < 1.1 }
  1394. FillChar(VESAModeInfo, sizeof(TVESAModeInfo), #0);
  1395. { get the video mode information }
  1396. if getVESAModeInfo(VESAmodeinfo, mode) then
  1397. begin
  1398. { checks if the hardware supports the video mode. }
  1399. if (VESAModeInfo.attr and modeAvail) <> 0 then
  1400. begin
  1401. SetVESAMode := TRUE;
  1402. end
  1403. else
  1404. begin
  1405. SetVESAmode := FALSE;
  1406. _GraphResult := grError;
  1407. exit;
  1408. end;
  1409. BankShift := 0;
  1410. while (64 shr BankShift) <> VESAModeInfo.WinGranularity do
  1411. Inc(BankShift);
  1412. CurrentWriteBank := -1;
  1413. CurrentReadBank := -1;
  1414. BytesPerLine := VESAModeInfo.BytesPerScanLine;
  1415. { These are the window adresses ... }
  1416. WinWriteSeg := 0; { This is the segment to use for writes }
  1417. WinReadSeg := 0; { This is the segment to use for reads }
  1418. ReadWindow := 0;
  1419. WriteWindow := 0;
  1420. { VBE 2.0 and higher supports >= non VGA linear buffer types...}
  1421. { this is backward compatible. }
  1422. if ((VESAModeInfo.Attr and ModeNoWindowed) <> 0) and
  1423. ((VESAModeInfo.Attr and ModeLinearBuffer) <> 0) then
  1424. SetupLinear(VESAModeInfo)
  1425. else
  1426. { if linear and windowed is supported, then use windowed }
  1427. { method. }
  1428. SetUpWindows(VESAModeInfo);
  1429. asm
  1430. mov ax,4F02h
  1431. mov bx,mode
  1432. {$ifdef fpc}
  1433. push ebp
  1434. {$endif fpc}
  1435. int 10h
  1436. {$ifdef fpc}
  1437. pop ebp
  1438. {$endif fpc}
  1439. sub ax,004Fh
  1440. cmp ax,1
  1441. sbb al,al
  1442. mov @RESULT,al
  1443. end;
  1444. end;
  1445. end;
  1446. function getVESAMode:word;assembler;
  1447. asm {return -1 if error}
  1448. mov ax,4F03h
  1449. {$ifdef fpc}
  1450. push ebp
  1451. {$endif fpc}
  1452. int 10h
  1453. {$ifdef fpc}
  1454. pop ebp
  1455. {$endif fpc}
  1456. cmp ax,004Fh
  1457. je @@OK
  1458. mov ax,-1
  1459. jmp @@X
  1460. @@OK:
  1461. mov ax,bx
  1462. @@X:
  1463. end;
  1464. {************************************************************************}
  1465. {* VESA Modes inits *}
  1466. {************************************************************************}
  1467. procedure Init1280x1024x64k; {$ifndef fpc}far;{$endif fpc}
  1468. begin
  1469. SetVesaMode(m1280x1024x64k);
  1470. end;
  1471. procedure Init1280x1024x32k; {$ifndef fpc}far;{$endif fpc}
  1472. begin
  1473. SetVESAMode(m1280x1024x32k);
  1474. end;
  1475. procedure Init1280x1024x256; {$ifndef fpc}far;{$endif fpc}
  1476. begin
  1477. SetVESAMode(m1280x1024x256);
  1478. end;
  1479. procedure Init1280x1024x16; {$ifndef fpc}far;{$endif fpc}
  1480. begin
  1481. SetVESAMode(m1280x1024x16);
  1482. end;
  1483. procedure Init1024x768x64k; {$ifndef fpc}far;{$endif fpc}
  1484. begin
  1485. SetVESAMode(m1024x768x64k);
  1486. end;
  1487. procedure Init640x480x32k; {$ifndef fpc}far;{$endif fpc}
  1488. begin
  1489. SetVESAMode(m640x480x32k);
  1490. end;
  1491. procedure Init1024x768x256; {$ifndef fpc}far;{$endif fpc}
  1492. begin
  1493. SetVESAMode(m1024x768x256);
  1494. end;
  1495. procedure Init1024x768x16; {$ifndef fpc}far;{$endif fpc}
  1496. begin
  1497. SetVESAMode(m1024x768x16);
  1498. end;
  1499. procedure Init800x600x64k; {$ifndef fpc}far;{$endif fpc}
  1500. begin
  1501. SetVESAMode(m800x600x64k);
  1502. end;
  1503. procedure Init800x600x32k; {$ifndef fpc}far;{$endif fpc}
  1504. begin
  1505. SetVESAMode(m800x600x32k);
  1506. end;
  1507. procedure Init800x600x256; {$ifndef fpc}far;{$endif fpc}
  1508. begin
  1509. SetVESAMode(m800x600x256);
  1510. end;
  1511. procedure Init800x600x16; {$ifndef fpc}far;{$endif fpc}
  1512. begin
  1513. SetVesaMode(m800x600x16);
  1514. end;
  1515. procedure Init640x480x64k; {$ifndef fpc}far;{$endif fpc}
  1516. begin
  1517. SetVESAMode(m640x480x64k);
  1518. end;
  1519. procedure Init640x480x256; {$ifndef fpc}far;{$endif fpc}
  1520. begin
  1521. SetVESAMode(m640x480x256);
  1522. end;
  1523. procedure Init640x400x256; {$ifndef fpc}far;{$endif fpc}
  1524. begin
  1525. SetVESAMode(m640x400x256);
  1526. end;
  1527. procedure Init320x200x64k; {$ifndef fpc}far;{$endif fpc}
  1528. begin
  1529. SetVESAMode(m320x200x64k);
  1530. end;
  1531. procedure Init320x200x32k; {$ifndef fpc}far;{$endif fpc}
  1532. begin
  1533. SetVESAMode(m320x200x32k);
  1534. end;
  1535. {$IFDEF DPMI}
  1536. Procedure SaveStateVESA; {$ifndef fpc}far;{$endif fpc}
  1537. var
  1538. PtrLong: longint;
  1539. regs: TDPMIRegisters;
  1540. begin
  1541. SaveSupported := FALSE;
  1542. SavePtr := nil;
  1543. { Get the video mode }
  1544. asm
  1545. mov ah,0fh
  1546. {$ifdef fpc}
  1547. push ebp
  1548. {$endif fpc}
  1549. int 10h
  1550. {$ifdef fpc}
  1551. pop ebp
  1552. {$endif fpc}
  1553. mov [VideoMode], al
  1554. end;
  1555. { Prepare to save video state...}
  1556. asm
  1557. mov ax, 4F04h { get buffer size to save state }
  1558. mov dx, 00h
  1559. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1560. {$ifdef fpc}
  1561. push ebp
  1562. {$endif fpc}
  1563. int 10h
  1564. {$ifdef fpc}
  1565. pop ebp
  1566. {$endif fpc}
  1567. mov [StateSize], bx
  1568. cmp al,04fh
  1569. jnz @notok
  1570. mov [SaveSupported],TRUE
  1571. @notok:
  1572. end;
  1573. if SaveSupported then
  1574. begin
  1575. {$ifdef logging}
  1576. LogLn('allocating VESA save buffer of '+strf(64*StateSize));
  1577. {$endif logging}
  1578. {$ifndef fpc}
  1579. PtrLong:=GlobalDosAlloc(64*StateSize); { values returned in 64-byte blocks }
  1580. {$else fpc}
  1581. PtrLong:=Global_Dos_Alloc(64*StateSize); { values returned in 64-byte blocks }
  1582. {$endif fpc}
  1583. if PtrLong = 0 then
  1584. RunError(203);
  1585. SavePtr := pointer(longint(PtrLong and $0000ffff) shl 16);
  1586. {$ifndef fpc}
  1587. { In FPC mode, we can't do anything with this (no far pointers) }
  1588. { However, we still need to keep it to be able to free the }
  1589. { memory afterwards. Since this data is not accessed in PM code, }
  1590. { there's no need to save it in a seperate buffer (JM) }
  1591. if not assigned(SavePtr) then
  1592. RunError(203);
  1593. {$endif fpc}
  1594. RealStateSeg := word(PtrLong shr 16);
  1595. FillChar(regs, sizeof(regs), #0);
  1596. { call the real mode interrupt ... }
  1597. regs.eax := $4F04; { save the state buffer }
  1598. regs.ecx := $0F; { Save DAC / Data areas / Hardware states }
  1599. regs.edx := $01; { save state }
  1600. regs.es := RealStateSeg;
  1601. regs.ebx := 0;
  1602. RealIntr($10,regs);
  1603. FillChar(regs, sizeof(regs), #0);
  1604. { restore state, according to Ralph Brown Interrupt list }
  1605. { some BIOS corrupt the hardware after a save... }
  1606. regs.eax := $4F04; { restore the state buffer }
  1607. regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
  1608. regs.edx := $02;
  1609. regs.es := RealStateSeg;
  1610. regs.ebx := 0;
  1611. RealIntr($10,regs);
  1612. end;
  1613. end;
  1614. procedure RestoreStateVESA; {$ifndef fpc}far;{$endif fpc}
  1615. var
  1616. regs:TDPMIRegisters;
  1617. begin
  1618. { go back to the old video mode...}
  1619. asm
  1620. mov ah,00
  1621. mov al,[VideoMode]
  1622. {$ifdef fpc}
  1623. push ebp
  1624. {$endif fpc}
  1625. int 10h
  1626. {$ifdef fpc}
  1627. pop ebp
  1628. {$endif fpc}
  1629. end;
  1630. { then restore all state information }
  1631. {$ifndef fpc}
  1632. if assigned(SavePtr) and (SaveSupported=TRUE) then
  1633. {$else fpc}
  1634. { No far pointer support, so it's possible that that assigned(SavePtr) }
  1635. { would return false under FPC. Just check if it's different from nil. }
  1636. if (SavePtr <> nil) and (SaveSupported=TRUE) then
  1637. {$endif fpc}
  1638. begin
  1639. FillChar(regs, sizeof(regs), #0);
  1640. { restore state, according to Ralph Brown Interrupt list }
  1641. { some BIOS corrupt the hardware after a save... }
  1642. regs.eax := $4F04; { restore the state buffer }
  1643. regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
  1644. regs.edx := $02; { restore state }
  1645. regs.es := RealStateSeg;
  1646. regs.ebx := 0;
  1647. RealIntr($10,regs);
  1648. {$ifndef fpc}
  1649. if GlobalDosFree(longint(SavePtr) shr 16)<>0 then
  1650. {$else fpc}
  1651. if Not(Global_Dos_Free(longint(SavePtr) shr 16)) then
  1652. {$endif fpc}
  1653. RunError(216);
  1654. SavePtr := nil;
  1655. end;
  1656. end;
  1657. {$ELSE}
  1658. {**************************************************************}
  1659. {* Real mode routines *}
  1660. {**************************************************************}
  1661. Procedure SaveStateVESA; far;
  1662. begin
  1663. SavePtr := nil;
  1664. SaveSupported := FALSE;
  1665. { Get the video mode }
  1666. asm
  1667. mov ah,0fh
  1668. int 10h
  1669. mov [VideoMode], al
  1670. end;
  1671. { Prepare to save video state...}
  1672. asm
  1673. mov ax, 1C00h { get buffer size to save state }
  1674. mov cx, 00000111b { Save DAC / Data areas / Hardware states }
  1675. int 10h
  1676. mov [StateSize], bx
  1677. cmp al,01ch
  1678. jnz @notok
  1679. mov [SaveSupported],TRUE
  1680. @notok:
  1681. end;
  1682. if SaveSupported then
  1683. Begin
  1684. GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
  1685. if not assigned(SavePtr) then
  1686. RunError(203);
  1687. asm
  1688. mov ax, 4F04h { save the state buffer }
  1689. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1690. mov dx, 01h
  1691. mov es, WORD PTR [SavePtr+2]
  1692. mov bx, WORD PTR [SavePtr]
  1693. int 10h
  1694. end;
  1695. { restore state, according to Ralph Brown Interrupt list }
  1696. { some BIOS corrupt the hardware after a save... }
  1697. asm
  1698. mov ax, 4F04h { save the state buffer }
  1699. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1700. mov dx, 02h
  1701. mov es, WORD PTR [SavePtr+2]
  1702. mov bx, WORD PTR [SavePtr]
  1703. int 10h
  1704. end;
  1705. end;
  1706. end;
  1707. procedure RestoreStateVESA; far;
  1708. begin
  1709. { go back to the old video mode...}
  1710. asm
  1711. mov ah,00
  1712. mov al,[VideoMode]
  1713. int 10h
  1714. end;
  1715. { then restore all state information }
  1716. if assigned(SavePtr) and (SaveSupported=TRUE) then
  1717. begin
  1718. { restore state, according to Ralph Brown Interrupt list }
  1719. asm
  1720. mov ax, 4F04h { save the state buffer }
  1721. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  1722. mov dx, 02h { restore state }
  1723. mov es, WORD PTR [SavePtr+2]
  1724. mov bx, WORD PTR [SavePtr]
  1725. int 10h
  1726. end;
  1727. FreeMem(SavePtr, 64*StateSize);
  1728. SavePtr := nil;
  1729. end;
  1730. end;
  1731. {$ENDIF DPMI}
  1732. {************************************************************************}
  1733. {* VESA Page flipping routines *}
  1734. {************************************************************************}
  1735. { Note: These routines, according to the VBE3 specification, will NOT }
  1736. { work with the 24 bpp modes, because of the alignment. }
  1737. {************************************************************************}
  1738. procedure SetVisualVESA(page: word); {$ifndef fpc}far;{$endif fpc}
  1739. { two page support... }
  1740. begin
  1741. if page > HardwarePages then exit;
  1742. end;
  1743. procedure SetActiveVESA(page: word); {$ifndef fpc}far;{$endif fpc}
  1744. { two page support... }
  1745. begin
  1746. end;
  1747. {
  1748. $Log$
  1749. Revision 1.18 1999-09-28 13:56:31 jonas
  1750. * reordered some local variables (first 4 byte vars, then 2 byte vars
  1751. etc)
  1752. * font data is now disposed in exitproc, exitproc is now called
  1753. GraphExitProc (was CleanModes) and resides in graph.pp instead of in
  1754. modes.inc
  1755. Revision 1.17 1999/09/27 23:34:42 peter
  1756. * new graph unit is default for go32v2
  1757. * removed warnings/notes
  1758. Revision 1.16 1999/09/26 13:31:07 jonas
  1759. * changed name of modeinfo variable to vesamodeinfo and fixed
  1760. associated errors (fillchar(modeinfo,sizeof(tmodeinfo),#0) instead
  1761. of sizeof(TVesamodeinfo) etc)
  1762. * changed several sizeof(type) to sizeof(varname) to avoid similar
  1763. errors in the future
  1764. Revision 1.15 1999/09/24 22:52:39 jonas
  1765. * optimized patternline a bit (always use hline when possible)
  1766. * isgraphmode stuff cleanup
  1767. * vesainfo.modelist now gets disposed in cleanmode instead of in
  1768. closegraph (required moving of some declarations from vesa.inc to
  1769. new vesah.inc)
  1770. * queryadapter gets no longer called from initgraph (is called from
  1771. initialization of graph unit)
  1772. * bugfix for notput in 32k and 64k vesa modes
  1773. * a div replaced by / in fillpoly
  1774. Revision 1.14 1999/09/23 14:00:42 jonas
  1775. * -dlogging no longer required to fuction correctly
  1776. * some typo's fixed
  1777. Revision 1.13 1999/09/20 09:34:30 florian
  1778. * conflicts solved
  1779. Revision 1.12 1999/09/18 22:21:11 jonas
  1780. + hlinevesa256 and vlinevesa256
  1781. + support for not/xor/or/andput in vesamodes with 32k/64k colors
  1782. * lots of changes to avoid warnings under FPC
  1783. Revision 1.11 1999/09/15 11:40:30 jonas
  1784. * fixed PutPixVESA256
  1785. Revision 1.10 1999/09/11 19:43:02 jonas
  1786. * FloodFill: did not take into account current viewport settings
  1787. * GetScanLine: only get line inside viewport, data outside of it
  1788. is not used anyway
  1789. * InternalEllipseDefault: fix for when xradius or yradius = 0 and
  1790. increase xradius and yradius always by one (TP does this too)
  1791. * fixed conlict in vesa.inc from last update
  1792. * some conditionals to avoid range check and overflow errors in
  1793. places where it doesn't matter
  1794. Revision 1.9 1999/08/01 14:51:07 jonas
  1795. * removed and/or/xorput support from vesaputpix256 (not in TP either)
  1796. * added notput support to directputpix256
  1797. Revision 1.8 1999/07/18 15:07:21 jonas
  1798. + xor-, and and- orput support for VESA256 modes
  1799. * compile with -dlogging if you wnt some info to be logged to grlog.txt
  1800. Revision 1.7 1999/07/14 15:21:49 jonas
  1801. * fixed initialization of bankshift var ('64 shr banshift' instead of shl)
  1802. Revision 1.6 1999/07/14 13:17:29 jonas
  1803. * bugfix in getmodeinfo (SizeOf(TModeInfo) -> SizeOf(TVESAModeInfo))
  1804. * as the result of the above bugfix, the graph unit doesn't crash
  1805. anymore under FPC if compiler with -dsupportVESA, but it doesn't
  1806. work yet either...
  1807. Revision 1.5 1999/07/12 13:28:33 jonas
  1808. * forgot log tag in previous commit
  1809. }