vesa.inc 91 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Carl Eric Codere
  4. This include implements VESA basic access.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. type
  12. palrec = packed record { record used for set/get DAC palette }
  13. blue, green, red, align: byte;
  14. end;
  15. const
  16. { VESA attributes }
  17. attrSwitchDAC = $01; { DAC is switchable (1.2) }
  18. attrNotVGACompatible = $02; { Video is NOT VGA compatible (2.0) }
  19. attrSnowCheck = $04; { Video must use snow checking(2.0) }
  20. { mode attribute bits }
  21. modeAvail = $01; { Hardware supports this mode (1.0) }
  22. modeExtendInfo = $02; { Extended information (1.0) }
  23. modeBIOSSupport = $04; { TTY BIOS Support (1.0) }
  24. modeColor = $08; { This is a color mode (1.0) }
  25. modeGraphics = $10; { This is a graphics mode (1.0) }
  26. modeNotVGACompatible = $20; { this mode is NOT I/O VGA compatible (2.0)}
  27. modeNoWindowed = $40; { This mode does not support Windows (2.0) }
  28. modeLinearBuffer = $80; { This mode supports linear buffers (2.0) }
  29. { window attributes }
  30. winSupported = $01;
  31. winReadable = $02;
  32. winWritable = $04;
  33. { memory model }
  34. modelText = $00;
  35. modelCGA = $01;
  36. modelHerc = $02;
  37. model4plane = $03;
  38. modelPacked = $04;
  39. modelModeX = $05;
  40. modelRGB = $06;
  41. modelYUV = $07;
  42. {$ifndef dpmi}
  43. {$i vesah.inc}
  44. { otherwise it's already included in graph.pp }
  45. {$endif dpmi}
  46. var
  47. BytesPerLine: word; { Number of bytes per scanline }
  48. YOffset : word; { Pixel offset for VESA page flipping }
  49. { window management }
  50. ReadWindow : byte; { Window number for reading. }
  51. WriteWindow: byte; { Window number for writing. }
  52. winReadSeg : word; { Address of segment for read }
  53. winWriteSeg: word; { Address of segment for writes}
  54. CurrentReadBank : smallint; { active read bank }
  55. CurrentWriteBank: smallint; { active write bank }
  56. BankShift : word; { address to shift by when switching banks. }
  57. { linear mode specific stuff }
  58. InLinear : boolean; { true if in linear mode }
  59. LinearPageOfs : longint; { offset used to set active page }
  60. FrameBufferLinearAddress : longint;
  61. ScanLines: word; { maximum number of scan lines for mode }
  62. function hexstr(val : longint;cnt : byte) : string;
  63. const
  64. HexTbl : array[0..15] of char='0123456789ABCDEF';
  65. var
  66. i : longint;
  67. begin
  68. hexstr[0]:=char(cnt);
  69. for i:=cnt downto 1 do
  70. begin
  71. hexstr[i]:=hextbl[val and $f];
  72. val:=val shr 4;
  73. end;
  74. end;
  75. {$IFDEF DPMI}
  76. function getVESAInfo(var VESAInfo: TVESAInfo) : boolean;
  77. var
  78. ptrlong : longint;
  79. VESAPtr : ^TVESAInfo;
  80. st : string[4];
  81. regs : TDPMIRegisters;
  82. {$ifndef fpc}
  83. ModeSel: word;
  84. offs: longint;
  85. {$endif fpc}
  86. { added... }
  87. modelist: PmodeList;
  88. i: longint;
  89. RealSeg : word;
  90. begin
  91. { Allocate real mode buffer }
  92. {$ifndef fpc}
  93. Ptrlong:=GlobalDosAlloc(sizeof(TVESAInfo));
  94. { Get selector value }
  95. VESAPtr := pointer(Ptrlong shl 16);
  96. {$else fpc}
  97. Ptrlong:=Global_Dos_Alloc(sizeof(TVESAInfo));
  98. New(VESAPtr);
  99. {$endif fpc}
  100. { Get segment value }
  101. RealSeg := word(Ptrlong shr 16);
  102. if not assigned(VESAPtr) then
  103. RunError(203);
  104. FillChar(regs, sizeof(regs), #0);
  105. { Get VESA Mode information ... }
  106. regs.eax := $4f00;
  107. regs.es := RealSeg;
  108. regs.edi := $00;
  109. RealIntr($10, regs);
  110. {$ifdef fpc}
  111. { no far pointer support in FPC yet, so move the vesa info into a memory }
  112. { block in the DS slector space (JM) }
  113. dosmemget(RealSeg,0,VesaPtr^,SizeOf(TVESAInfo));
  114. {$endif fpc}
  115. St:=Vesaptr^.signature;
  116. if st<>'VESA' then
  117. begin
  118. {$ifdef logging}
  119. LogLn('No VESA detected.');
  120. {$endif logging}
  121. getVesaInfo := FALSE;
  122. {$ifndef fpc}
  123. GlobalDosFree(word(PtrLong and $ffff));
  124. {$else fpc}
  125. If not Global_Dos_Free(word(PtrLong and $ffff)) then
  126. RunError(216);
  127. { also free the extra allocated buffer }
  128. Dispose(VESAPtr);
  129. {$endif fpc}
  130. exit;
  131. end
  132. else
  133. getVesaInfo := TRUE;
  134. {$ifndef fpc}
  135. { The mode pointer buffer points to a real mode memory }
  136. { Therefore steps to get the modes: }
  137. { 1. Allocate Selector and SetLimit to max number of }
  138. { of possible modes. }
  139. ModeSel := AllocSelector(0);
  140. SetSelectorLimit(ModeSel, 256*sizeof(word));
  141. { 2. Set Selector linear address to the real mode pointer }
  142. { returned. }
  143. offs := longint(longint(VESAPtr^.ModeList) shr 16) shl 4;
  144. {shouldn't the OR in the next line be a + ?? (JM)}
  145. offs := offs OR (Longint(VESAPtr^.ModeList) and $ffff);
  146. SetSelectorBase(ModeSel, offs);
  147. { copy VESA mode information to a protected mode buffer and }
  148. { then free the real mode buffer... }
  149. Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
  150. GlobalDosFree(word(PtrLong and $ffff));
  151. { ModeList points to the mode list }
  152. { We must copy it somewhere... }
  153. ModeList := Ptr(ModeSel, 0);
  154. {$else fpc}
  155. { No far pointer support, so the Ptr(ModeSel, 0) doesn't work. }
  156. { Immediately copy everything to a buffer in the DS selector space }
  157. New(ModeList);
  158. { The following may copy data from outside the VESA buffer, but it }
  159. { shouldn't get past the 1MB limit, since that would mean the buffer }
  160. { has been allocated in the BIOS or high memory region, which seems }
  161. { impossible to me (JM)}
  162. DosMemGet(word(longint(VESAPtr^.ModeList) shr 16),
  163. word(longint(VESAPtr^.ModeList) and $ffff), ModeList^,256*sizeof(word));
  164. { copy VESA mode information to a protected mode buffer and }
  165. { then free the real mode buffer... }
  166. Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
  167. If not Global_Dos_Free(word(PtrLong and $ffff)) then
  168. RunError(216);
  169. Dispose(VESAPtr);
  170. {$endif fpc}
  171. i:=0;
  172. new(VESAInfo.ModeList);
  173. while ModeList^[i]<> $ffff do
  174. begin
  175. {$ifdef logging}
  176. LogLn('Found mode $'+hexstr(ModeList^[i],4));
  177. {$endif loggin}
  178. VESAInfo.ModeList^[i] := ModeList^[i];
  179. Inc(i);
  180. end;
  181. VESAInfo.ModeList^[i]:=$ffff;
  182. { Free the temporary selector used to get mode information }
  183. {$ifdef logging}
  184. LogLn(strf(i) + ' modes found.');
  185. {$endif logging}
  186. {$ifndef fpc}
  187. FreeSelector(ModeSel);
  188. {$else fpc}
  189. Dispose(ModeList);
  190. {$endif fpc}
  191. end;
  192. function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;
  193. var
  194. Ptr: longint;
  195. {$ifndef fpc}
  196. VESAPtr : ^TVESAModeInfo;
  197. {$endif fpc}
  198. regs : TDPMIRegisters;
  199. RealSeg: word;
  200. begin
  201. { Alllocate real mode buffer }
  202. {$ifndef fpc}
  203. Ptr:=GlobalDosAlloc(sizeof(TVESAModeInfo));
  204. { get the selector value }
  205. VESAPtr := pointer(longint(Ptr shl 16));
  206. if not assigned(VESAPtr) then
  207. RunError(203);
  208. {$else fpc}
  209. Ptr:=Global_Dos_Alloc(sizeof(TVESAModeInfo));
  210. {$endif fpc}
  211. { get the segment value }
  212. RealSeg := word(Ptr shr 16);
  213. { setup interrupt registers }
  214. FillChar(regs, sizeof(regs), #0);
  215. { call VESA mode information...}
  216. regs.eax := $4f01;
  217. regs.es := RealSeg;
  218. regs.edi := $00;
  219. regs.ecx := mode;
  220. RealIntr($10, regs);
  221. if word(regs.eax) <> $4f then
  222. getVESAModeInfo := FALSE
  223. else
  224. getVESAModeInfo := TRUE;
  225. { copy to protected mode buffer ... }
  226. {$ifndef fpc}
  227. Move(VESAPtr^, ModeInfo, sizeof(ModeInfo));
  228. {$else fpc}
  229. DosMemGet(RealSeg,0,ModeInfo,sizeof(ModeInfo));
  230. {$endif fpc}
  231. { free real mode memory }
  232. {$ifndef fpc}
  233. GlobalDosFree(Word(Ptr and $ffff));
  234. {$else fpc}
  235. If not Global_Dos_Free(Word(Ptr and $ffff)) then
  236. RunError(216);
  237. {$endif fpc}
  238. end;
  239. {$ELSE}
  240. function getVESAInfo(var VESAInfo: TVESAInfo) : boolean; assembler;
  241. asm
  242. mov ax,4F00h
  243. les di,VESAInfo
  244. int 10h
  245. sub ax,004Fh {make sure we got 004Fh back}
  246. cmp ax,1
  247. sbb al,al
  248. cmp word ptr es:[di],'V'or('E'shl 8) {signature should be 'VESA'}
  249. jne @@ERR
  250. cmp word ptr es:[di+2],'S'or('A'shl 8)
  251. je @@X
  252. @@ERR:
  253. mov al,0
  254. @@X:
  255. end;
  256. function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;assembler;
  257. asm
  258. mov ax,4F01h
  259. mov cx,mode
  260. les di,ModeInfo
  261. int 10h
  262. sub ax,004Fh {make sure it's 004Fh}
  263. cmp ax,1
  264. sbb al,al
  265. end;
  266. {$ENDIF}
  267. function SearchVESAModes(mode: Word): boolean;
  268. {********************************************************}
  269. { Searches for a specific DEFINED vesa mode. If the mode }
  270. { is not available for some reason, then returns FALSE }
  271. { otherwise returns TRUE. }
  272. {********************************************************}
  273. var
  274. i: word;
  275. ModeSupported : Boolean;
  276. begin
  277. i:=0;
  278. { let's assume it's not available ... }
  279. ModeSupported := FALSE;
  280. { This is a STUB VESA implementation }
  281. if VESAInfo.ModeList^[0] = $FFFF then exit;
  282. repeat
  283. if VESAInfo.ModeList^[i] = mode then
  284. begin
  285. { we found it, the card supports this mode... }
  286. ModeSupported := TRUE;
  287. break;
  288. end;
  289. Inc(i);
  290. until VESAInfo.ModeList^[i] = $ffff;
  291. { now check if the hardware supports it... }
  292. If ModeSupported then
  293. begin
  294. { we have to init everything to zero, since VBE < 1.1 }
  295. { may not setup fields correctly. }
  296. FillChar(VESAModeInfo, sizeof(VESAModeInfo), #0);
  297. If GetVESAModeInfo(VESAModeInfo, Mode) And
  298. ((VESAModeInfo.attr and modeAvail) <> 0) then
  299. ModeSupported := TRUE
  300. else
  301. ModeSupported := FALSE;
  302. end;
  303. SearchVESAModes := ModeSupported;
  304. end;
  305. procedure SetBankIndex(win: byte; BankNr: smallint); assembler;
  306. asm
  307. {$IFDEF REGCALL}
  308. mov bl, al
  309. {$ELSE REGCALL}
  310. mov bl,[Win]
  311. {$ENDIF REGCALL}
  312. mov ax,4f05h
  313. mov bh,00h
  314. {$IFNDEF REGCALL}
  315. mov dx,[BankNr]
  316. {$ENDIF REGCALL}
  317. {$ifdef fpc}
  318. push ebp
  319. {$endif fpc}
  320. int 10h
  321. {$ifdef fpc}
  322. pop ebp
  323. {$endif fpc}
  324. end;
  325. {********************************************************}
  326. { There are two routines for setting banks. This may in }
  327. { in some cases optimize a bit some operations, if the }
  328. { hardware supports it, because one window is used for }
  329. { reading and one window is used for writing. }
  330. {********************************************************}
  331. procedure SetReadBank(BankNr: smallint);
  332. begin
  333. { check if this is the current bank... if so do nothing. }
  334. if BankNr = CurrentReadBank then exit;
  335. {$ifdef logging}
  336. { LogLn('Setting read bank to '+strf(BankNr));}
  337. {$endif logging}
  338. CurrentReadBank := BankNr; { save current bank number }
  339. BankNr := BankNr shl BankShift; { adjust to window granularity }
  340. { we set both banks, since one may read only }
  341. SetBankIndex(ReadWindow, BankNr);
  342. { if the hardware supports only one window }
  343. { then there is only one single bank, so }
  344. { update both bank numbers. }
  345. if ReadWindow = WriteWindow then
  346. CurrentWriteBank := CurrentReadBank;
  347. end;
  348. procedure SetWriteBank(BankNr: smallint);
  349. begin
  350. { check if this is the current bank... if so do nothing. }
  351. if BankNr = CurrentWriteBank then exit;
  352. {$ifdef logging}
  353. { LogLn('Setting write bank to '+strf(BankNr));}
  354. {$endif logging}
  355. CurrentWriteBank := BankNr; { save current bank number }
  356. BankNr := BankNr shl BankShift; { adjust to window granularity }
  357. { we set both banks, since one may read only }
  358. SetBankIndex(WriteWindow, BankNr);
  359. { if the hardware supports only one window }
  360. { then there is only one single bank, so }
  361. { update both bank numbers. }
  362. if ReadWindow = WriteWindow then
  363. CurrentReadBank := CurrentWriteBank;
  364. end;
  365. {************************************************************************}
  366. {* 8-bit pixels VESA mode routines *}
  367. {************************************************************************}
  368. procedure PutPixVESA256(x, y : smallint; color : word); {$ifndef fpc}far;{$endif fpc}
  369. var
  370. offs : longint;
  371. begin
  372. X:= X + StartXViewPort;
  373. Y:= Y + StartYViewPort;
  374. { convert to absolute coordinates and then verify clipping...}
  375. if ClipPixels then
  376. Begin
  377. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  378. exit;
  379. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  380. exit;
  381. end;
  382. Y := Y + YOffset; { adjust pixel for correct virtual page }
  383. offs := longint(y) * BytesPerLine + x;
  384. begin
  385. SetWriteBank(smallint(offs shr 16));
  386. mem[WinWriteSeg : word(offs)] := byte(color);
  387. end;
  388. end;
  389. procedure DirectPutPixVESA256(x, y : smallint); {$ifndef fpc}far;{$endif fpc}
  390. var
  391. offs : longint;
  392. col : byte;
  393. begin
  394. offs := (longint(y) + YOffset) * BytesPerLine + x;
  395. Case CurrentWriteMode of
  396. XorPut:
  397. Begin
  398. SetReadBank(smallint(offs shr 16));
  399. col := mem[WinReadSeg : word(offs)] xor byte(CurrentColor);
  400. End;
  401. AndPut:
  402. Begin
  403. SetReadBank(smallint(offs shr 16));
  404. col := mem[WinReadSeg : word(offs)] And byte(CurrentColor);
  405. End;
  406. OrPut:
  407. Begin
  408. SetReadBank(smallint(offs shr 16));
  409. col := mem[WinReadSeg : word(offs)] or byte(currentcolor);
  410. End
  411. else
  412. Begin
  413. If CurrentWriteMode <> NotPut then
  414. col := Byte(CurrentColor)
  415. else col := Not(Byte(CurrentColor));
  416. End
  417. End;
  418. SetWriteBank(smallint(offs shr 16));
  419. mem[WinWriteSeg : word(offs)] := Col;
  420. end;
  421. function GetPixVESA256(x, y : smallint): word; {$ifndef fpc}far;{$endif fpc}
  422. var
  423. offs : longint;
  424. begin
  425. X:= X + StartXViewPort;
  426. Y:= Y + StartYViewPort + YOffset;
  427. offs := longint(y) * BytesPerLine + x;
  428. SetReadBank(smallint(offs shr 16));
  429. GetPixVESA256:=mem[WinReadSeg : word(offs)];
  430. end;
  431. Procedure GetScanLineVESA256(x1, x2, y: smallint; var data); {$ifndef fpc}far;{$endif}
  432. var offs: Longint;
  433. l, amount, bankrest, index, pixels: longint;
  434. curbank: smallint;
  435. begin
  436. inc(x1,StartXViewPort);
  437. inc(x2,StartXViewPort);
  438. {$ifdef logging}
  439. LogLn('getscanline256 '+strf(x1)+' - '+strf(x2)+' at '+strf(y+StartYViewPort));
  440. {$endif logging}
  441. index := 0;
  442. amount := x2-x1+1;
  443. Offs:=(Longint(y)+StartYViewPort+YOffset)*bytesperline+x1;
  444. Repeat
  445. curbank := smallint(offs shr 16);
  446. SetReadBank(curbank);
  447. {$ifdef logging}
  448. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  449. {$endif logging}
  450. If ((amount >= 4) and
  451. ((offs and 3) = 0)) or
  452. (amount >= 4+4-(offs and 3)) Then
  453. { allign target }
  454. Begin
  455. If (offs and 3) <> 0 then
  456. { this cannot go past a window boundary bacause the }
  457. { size of a window is always a multiple of 4 }
  458. Begin
  459. {$ifdef logging}
  460. LogLn('Alligning by reading '+strf(4-(offs and 3))+' pixels');
  461. {$endif logging}
  462. for l := 1 to 4-(offs and 3) do
  463. WordArray(Data)[index+l-1] :=
  464. Mem[WinReadSeg:word(offs)+l-1];
  465. inc(index, l);
  466. inc(offs, l);
  467. dec(amount, l);
  468. End;
  469. {$ifdef logging}
  470. LogLn('Offset is now '+hexstr(offs,8)+', amount left: '+strf(amount));
  471. {$endif logging}
  472. { offs is now 4-bytes alligned }
  473. If amount <= ($10000-(Offs and $ffff)) Then
  474. bankrest := amount
  475. else {the rest won't fit anymore in the current window }
  476. bankrest := $10000 - (Offs and $ffff);
  477. { it is possible that by aligning, we ended up in a new }
  478. { bank, so set the correct bank again to make sure }
  479. setreadbank(offs shr 16);
  480. {$ifdef logging}
  481. LogLn('Rest to be read from this window: '+strf(bankrest));
  482. {$endif logging}
  483. For l := 0 to (Bankrest div 4)-1 Do
  484. begin
  485. pixels := MemL[WinWriteSeg:word(offs)+l*4];
  486. WordArray(Data)[index+l*4] := pixels and $ff;
  487. pixels := pixels shr 8;
  488. WordArray(Data)[index+l*4+1] := pixels and $ff;
  489. pixels := pixels shr 8;
  490. WordArray(Data)[index+l*4+2] := pixels and $ff;
  491. pixels := pixels shr 8;
  492. WordArray(Data)[index+l*4+3] := pixels{ and $ff};
  493. end;
  494. inc(index,l*4+4);
  495. inc(offs,l*4+4);
  496. dec(amount,l*4+4);
  497. {$ifdef logging}
  498. LogLn('Offset is now '+hexstr(offs,8)+', amount left: '+strf(amount));
  499. {$endif logging}
  500. End
  501. Else
  502. Begin
  503. {$ifdef logging}
  504. LogLn('Leftover: '+strf(amount)+' at offset '+hexstr(offs,8));
  505. {$endif logging}
  506. For l := 0 to amount - 1 do
  507. begin
  508. { this may cross a bank at any time, so adjust }
  509. { because this loop alwys runs for very little pixels, }
  510. { there's little gained by splitting it up }
  511. setreadbank(offs shr 16);
  512. WordArray(Data)[index+l] := mem[WinReadSeg:word(offs)];
  513. inc(offs);
  514. end;
  515. amount := 0
  516. End
  517. Until amount = 0;
  518. end;
  519. procedure HLineVESA256(x,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
  520. var Offs: Longint;
  521. mask, l, bankrest: longint;
  522. curbank, hlength: smallint;
  523. Begin
  524. { must we swap the values? }
  525. if x > x2 then
  526. Begin
  527. x := x xor x2;
  528. x2 := x xor x2;
  529. x:= x xor x2;
  530. end;
  531. { First convert to global coordinates }
  532. X := X + StartXViewPort;
  533. X2 := X2 + StartXViewPort;
  534. Y := Y + StartYViewPort;
  535. if ClipPixels then
  536. Begin
  537. if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  538. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  539. exit;
  540. end;
  541. {$ifdef logging2}
  542. LogLn('hline '+strf(x)+' - '+strf(x2)+' on '+strf(y)+' in mode '+strf(currentwritemode));
  543. {$endif logging2}
  544. HLength := x2 - x + 1;
  545. {$ifdef logging2}
  546. LogLn('length: '+strf(hlength));
  547. {$endif logging2}
  548. if HLength>0 then
  549. begin
  550. Offs:=(Longint(y)+YOffset)*bytesperline+x;
  551. {$ifdef logging2}
  552. LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
  553. {$endif logging2}
  554. Mask := byte(CurrentColor)+byte(CurrentColor) shl 8;
  555. Mask := Mask + Mask shl 16;
  556. Case CurrentWriteMode of
  557. AndPut:
  558. Begin
  559. Repeat
  560. curbank := smallint(offs shr 16);
  561. SetWriteBank(curbank);
  562. SetReadBank(curbank);
  563. {$ifdef logging2}
  564. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  565. {$endif logging2}
  566. If ((HLength >= 4) and
  567. ((offs and 3) = 0)) or
  568. (HLength >= 4+4-(offs and 3)) Then
  569. { align target }
  570. Begin
  571. l := 0;
  572. If (offs and 3) <> 0 then
  573. { this cannot go past a window boundary bacause the }
  574. { size of a window is always a multiple of 4 }
  575. Begin
  576. {$ifdef logging2}
  577. LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
  578. {$endif logging2}
  579. for l := 1 to 4-(offs and 3) do
  580. Mem[WinWriteSeg:word(offs)+l-1] :=
  581. Mem[WinReadSeg:word(offs)+l-1] And Byte(CurrentColor);
  582. End;
  583. Dec(HLength, l);
  584. inc(offs, l);
  585. {$ifdef logging2}
  586. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  587. {$endif logging}
  588. { offs is now 4-bytes alligned }
  589. If HLength <= ($10000-(Offs and $ffff)) Then
  590. bankrest := HLength
  591. else {the rest won't fit anymore in the current window }
  592. bankrest := $10000 - (Offs and $ffff);
  593. { it is possible that by aligningm we ended up in a new }
  594. { bank, so set the correct bank again to make sure }
  595. setwritebank(offs shr 16);
  596. setreadbank(offs shr 16);
  597. {$ifdef logging2}
  598. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  599. {$endif logging}
  600. For l := 0 to (Bankrest div 4)-1 Do
  601. MemL[WinWriteSeg:word(offs)+l*4] :=
  602. MemL[WinReadSeg:word(offs)+l*4] And Mask;
  603. inc(offs,l*4+4);
  604. dec(hlength,l*4+4);
  605. {$ifdef logging2}
  606. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  607. {$endif logging}
  608. End
  609. Else
  610. Begin
  611. {$ifdef logging2}
  612. LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
  613. {$endif logging}
  614. For l := 0 to HLength - 1 do
  615. begin
  616. { this may cross a bank at any time, so adjust }
  617. { becauese this loop alwys runs for very little pixels, }
  618. { there's little gained by splitting it up }
  619. setreadbank(offs shr 16);
  620. setwritebank(offs shr 16);
  621. Mem[WinWriteSeg:word(offs)] :=
  622. Mem[WinReadSeg:word(offs)] And byte(currentColor);
  623. inc(offs);
  624. end;
  625. HLength := 0
  626. End
  627. Until HLength = 0;
  628. End;
  629. XorPut:
  630. Begin
  631. Repeat
  632. curbank := smallint(offs shr 16);
  633. SetWriteBank(curbank);
  634. SetReadBank(curbank);
  635. {$ifdef logging2}
  636. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  637. {$endif logging}
  638. If ((HLength >= 4) and
  639. ((offs and 3) = 0)) or
  640. (HLength >= 4+4-(offs and 3)) Then
  641. { allign target }
  642. Begin
  643. l := 0;
  644. If (offs and 3) <> 0 then
  645. { this cannot go past a window boundary bacause the }
  646. { size of a window is always a multiple of 4 }
  647. Begin
  648. {$ifdef logging2}
  649. LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
  650. {$endif logging}
  651. for l := 1 to 4-(offs and 3) do
  652. Mem[WinWriteSeg:word(offs)+l-1] :=
  653. Mem[WinReadSeg:word(offs)+l-1] Xor Byte(CurrentColor);
  654. End;
  655. Dec(HLength, l);
  656. inc(offs, l);
  657. {$ifdef logging2}
  658. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  659. {$endif logging}
  660. { offs is now 4-bytes alligned }
  661. If HLength <= ($10000-(Offs and $ffff)) Then
  662. bankrest := HLength
  663. else {the rest won't fit anymore in the current window }
  664. bankrest := $10000 - (Offs and $ffff);
  665. { it is possible that by aligningm we ended up in a new }
  666. { bank, so set the correct bank again to make sure }
  667. setwritebank(offs shr 16);
  668. setreadbank(offs shr 16);
  669. {$ifdef logging2}
  670. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  671. {$endif logging}
  672. For l := 0 to (Bankrest div 4)-1 Do
  673. MemL[WinWriteSeg:word(offs)+l*4] :=
  674. MemL[WinReadSeg:word(offs)+l*4] Xor Mask;
  675. inc(offs,l*4+4);
  676. dec(hlength,l*4+4);
  677. {$ifdef logging2}
  678. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  679. {$endif logging}
  680. End
  681. Else
  682. Begin
  683. {$ifdef logging2}
  684. LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
  685. {$endif logging}
  686. For l := 0 to HLength - 1 do
  687. begin
  688. { this may cross a bank at any time, so adjust }
  689. { because this loop alwys runs for very little pixels, }
  690. { there's little gained by splitting it up }
  691. setreadbank(offs shr 16);
  692. setwritebank(offs shr 16);
  693. Mem[WinWriteSeg:word(offs)] :=
  694. Mem[WinReadSeg:word(offs)] xor byte(currentColor);
  695. inc(offs);
  696. end;
  697. HLength := 0
  698. End
  699. Until HLength = 0;
  700. End;
  701. OrPut:
  702. Begin
  703. Repeat
  704. curbank := smallint(offs shr 16);
  705. SetWriteBank(curbank);
  706. SetReadBank(curbank);
  707. {$ifdef logging2}
  708. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  709. {$endif logging}
  710. If ((HLength >= 4) and
  711. ((offs and 3) = 0)) or
  712. (HLength >= 4+4-(offs and 3)) Then
  713. { allign target }
  714. Begin
  715. l := 0;
  716. If (offs and 3) <> 0 then
  717. { this cannot go past a window boundary bacause the }
  718. { size of a window is always a multiple of 4 }
  719. Begin
  720. {$ifdef logging2}
  721. LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
  722. {$endif logging}
  723. for l := 1 to 4-(offs and 3) do
  724. Mem[WinWriteSeg:word(offs)+l-1] :=
  725. Mem[WinReadSeg:word(offs)+l-1] Or Byte(CurrentColor);
  726. End;
  727. Dec(HLength, l);
  728. inc(offs, l);
  729. { it is possible that by aligningm we ended up in a new }
  730. { bank, so set the correct bank again to make sure }
  731. setwritebank(offs shr 16);
  732. setreadbank(offs shr 16);
  733. {$ifdef logging2}
  734. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  735. {$endif logging}
  736. { offs is now 4-bytes alligned }
  737. If HLength <= ($10000-(Offs and $ffff)) Then
  738. bankrest := HLength
  739. else {the rest won't fit anymore in the current window }
  740. bankrest := $10000 - (Offs and $ffff);
  741. {$ifdef logging2}
  742. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  743. {$endif logging}
  744. For l := 0 to (Bankrest div 4)-1 Do
  745. MemL[WinWriteSeg:offs+l*4] :=
  746. MemL[WinReadSeg:word(offs)+l*4] Or Mask;
  747. inc(offs,l*4+4);
  748. dec(hlength,l*4+4);
  749. {$ifdef logging2}
  750. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  751. {$endif logging}
  752. End
  753. Else
  754. Begin
  755. {$ifdef logging2}
  756. LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
  757. {$endif logging}
  758. For l := 0 to HLength - 1 do
  759. begin
  760. { this may cross a bank at any time, so adjust }
  761. { because this loop alwys runs for very little pixels, }
  762. { there's little gained by splitting it up }
  763. setreadbank(offs shr 16);
  764. setwritebank(offs shr 16);
  765. Mem[WinWriteSeg:word(offs)] :=
  766. Mem[WinReadSeg:word(offs)] And byte(currentColor);
  767. inc(offs);
  768. end;
  769. HLength := 0
  770. End
  771. Until HLength = 0;
  772. End
  773. Else
  774. Begin
  775. If CurrentWriteMode = NotPut Then
  776. Mask := Not(Mask);
  777. Repeat
  778. curbank := smallint(offs shr 16);
  779. SetWriteBank(curbank);
  780. {$ifdef logging2}
  781. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)+' -- '+strf(offs));
  782. {$endif logging}
  783. If ((HLength >= 4) and
  784. ((offs and 3) = 0)) or
  785. (HLength >= 4+4-(offs and 3)) Then
  786. { allign target }
  787. Begin
  788. l := 0;
  789. If (offs and 3) <> 0 then
  790. { this cannot go past a window boundary bacause the }
  791. { size of a window is always a multiple of 4 }
  792. Begin
  793. {$ifdef logging2}
  794. LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
  795. {$endif logging}
  796. for l := 1 to 4-(offs and 3) do
  797. Mem[WinWriteSeg:word(offs)+l-1] := Byte(Mask);
  798. End;
  799. Dec(HLength, l);
  800. inc(offs, l);
  801. {$ifdef logging2}
  802. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  803. {$endif logging}
  804. { offs is now 4-bytes alligned }
  805. If HLength <= ($10000-(Offs and $ffff)) Then
  806. bankrest := HLength
  807. else {the rest won't fit anymore in the current window }
  808. bankrest := $10000 - (Offs and $ffff);
  809. { it is possible that by aligningm we ended up in a new }
  810. { bank, so set the correct bank again to make sure }
  811. setwritebank(offs shr 16);
  812. {$ifdef logging2}
  813. LogLn('Rest to be drawn in this window: '+strf(bankrest)+' -- '+hexstr(bankrest,8));
  814. {$endif logging}
  815. For l := 0 to (Bankrest div 4)-1 Do
  816. MemL[WinWriteSeg:word(offs)+l*4] := Mask;
  817. inc(offs,l*4+4);
  818. dec(hlength,l*4+4);
  819. {$ifdef logging2}
  820. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
  821. {$endif logging}
  822. End
  823. Else
  824. Begin
  825. {$ifdef logging2}
  826. LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
  827. {$endif logging}
  828. For l := 0 to HLength - 1 do
  829. begin
  830. { this may cross a bank at any time, so adjust }
  831. { because this loop alwys runs for very little pixels, }
  832. { there's little gained by splitting it up }
  833. setwritebank(offs shr 16);
  834. Mem[WinWriteSeg:word(offs)] := byte(mask);
  835. inc(offs);
  836. end;
  837. HLength := 0
  838. End
  839. Until HLength = 0;
  840. End;
  841. End;
  842. end;
  843. end;
  844. procedure VLineVESA256(x,y,y2: smallint); {$ifndef fpc}far;{$endif fpc}
  845. var Offs: Longint;
  846. l, bankrest: longint;
  847. curbank, vlength: smallint;
  848. col: byte;
  849. Begin
  850. { must we swap the values? }
  851. if y > y2 then
  852. Begin
  853. y := y xor y2;
  854. y2 := y xor y2;
  855. y:= y xor y2;
  856. end;
  857. { First convert to global coordinates }
  858. X := X + StartXViewPort;
  859. Y := Y + StartYViewPort;
  860. Y2 := Y2 + StartYViewPort;
  861. if ClipPixels then
  862. Begin
  863. if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
  864. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  865. exit;
  866. end;
  867. Col := Byte(CurrentColor);
  868. {$ifdef logging2}
  869. LogLn('vline '+strf(y)+' - '+strf(y2)+' on '+strf(x)+' in mode '+strf(currentwritemode));
  870. {$endif logging}
  871. VLength := y2 - y + 1;
  872. {$ifdef logging2}
  873. LogLn('length: '+strf(vlength));
  874. {$endif logging}
  875. if VLength>0 then
  876. begin
  877. Offs:=(Longint(y)+YOffset)*bytesperline+x;
  878. {$ifdef logging2}
  879. LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
  880. {$endif logging}
  881. Case CurrentWriteMode of
  882. AndPut:
  883. Begin
  884. Repeat
  885. curbank := smallint(offs shr 16);
  886. SetWriteBank(curbank);
  887. SetReadBank(curbank);
  888. {$ifdef logging2}
  889. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  890. {$endif logging}
  891. If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
  892. bankrest := VLength
  893. else {the rest won't fit anymore in the current window }
  894. bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
  895. {$ifdef logging2}
  896. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  897. {$endif logging}
  898. For l := 0 to Bankrest-1 Do
  899. begin
  900. Mem[WinWriteSeg:word(offs)] :=
  901. Mem[WinReadSeg:word(offs)] And Col;
  902. inc(offs,bytesperline);
  903. end;
  904. dec(VLength,l+1);
  905. {$ifdef logging2}
  906. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
  907. {$endif logging}
  908. Until VLength = 0;
  909. End;
  910. XorPut:
  911. Begin
  912. Repeat
  913. curbank := smallint(offs shr 16);
  914. SetWriteBank(curbank);
  915. SetReadBank(curbank);
  916. {$ifdef logging2}
  917. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  918. {$endif logging}
  919. If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
  920. bankrest := VLength
  921. else {the rest won't fit anymore in the current window }
  922. bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
  923. {$ifdef logging2}
  924. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  925. {$endif logging}
  926. For l := 0 to Bankrest-1 Do
  927. begin
  928. Mem[WinWriteSeg:word(offs)] :=
  929. Mem[WinReadSeg:word(offs)] Xor Col;
  930. inc(offs,bytesperline);
  931. end;
  932. dec(VLength,l+1);
  933. {$ifdef logging2}
  934. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
  935. {$endif logging}
  936. Until VLength = 0;
  937. End;
  938. OrPut:
  939. Begin
  940. Repeat
  941. curbank := smallint(offs shr 16);
  942. SetWriteBank(curbank);
  943. SetReadBank(curbank);
  944. {$ifdef logging2}
  945. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  946. {$endif logging}
  947. If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
  948. bankrest := VLength
  949. else {the rest won't fit anymore in the current window }
  950. bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
  951. {$ifdef logging2}
  952. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  953. {$endif logging}
  954. For l := 0 to Bankrest-1 Do
  955. begin
  956. Mem[WinWriteSeg:word(offs)] :=
  957. Mem[WinReadSeg:word(offs)] Or Col;
  958. inc(offs,bytesperline);
  959. end;
  960. dec(VLength,l+1);
  961. {$ifdef logging2}
  962. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
  963. {$endif logging}
  964. Until VLength = 0;
  965. End;
  966. Else
  967. Begin
  968. If CurrentWriteMode = NotPut Then
  969. Col := Not(Col);
  970. Repeat
  971. curbank := smallint(offs shr 16);
  972. SetWriteBank(curbank);
  973. {$ifdef logging2}
  974. LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
  975. {$endif logging}
  976. If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
  977. bankrest := VLength
  978. else {the rest won't fit anymore in the current window }
  979. bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
  980. {$ifdef logging2}
  981. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  982. {$endif logging}
  983. For l := 0 to Bankrest-1 Do
  984. begin
  985. Mem[WinWriteSeg:word(offs)] := Col;
  986. inc(offs,bytesperline);
  987. end;
  988. dec(VLength,l+1);
  989. {$ifdef logging2}
  990. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
  991. {$endif logging}
  992. Until VLength = 0;
  993. End;
  994. End;
  995. end;
  996. end;
  997. procedure PatternLineVESA256(x1,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
  998. {********************************************************}
  999. { Draws a horizontal patterned line according to the }
  1000. { current Fill Settings. }
  1001. {********************************************************}
  1002. { Important notes: }
  1003. { - CurrentColor must be set correctly before entering }
  1004. { this routine. }
  1005. {********************************************************}
  1006. type
  1007. TVESA256Fill = Record
  1008. case byte of
  1009. 0: (data1, data2: longint);
  1010. 1: (pat: array[0..7] of byte);
  1011. end;
  1012. var
  1013. fill: TVESA256Fill;
  1014. bankrest, l : longint;
  1015. offs, amount: longint;
  1016. i : smallint;
  1017. j : smallint;
  1018. OldWriteMode : word;
  1019. TmpFillPattern, patternPos : byte;
  1020. begin
  1021. { convert to global coordinates ... }
  1022. x1 := x1 + StartXViewPort;
  1023. x2 := x2 + StartXViewPort;
  1024. y := y + StartYViewPort;
  1025. { if line was fully clipped then exit...}
  1026. if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort,
  1027. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  1028. exit;
  1029. OldWriteMode := CurrentWriteMode;
  1030. CurrentWriteMode := NormalPut;
  1031. { Get the current pattern }
  1032. TmpFillPattern := FillPatternTable
  1033. [FillSettings.Pattern][((y + startYViewPort) and $7)+1];
  1034. {$ifdef logging2}
  1035. LogLn('patternline '+strf(x1)+' - '+strf(x2)+' on '+strf(y));
  1036. {$endif logging2}
  1037. { how long is the line }
  1038. amount := x2 - x1 + 1;
  1039. { offset to start at }
  1040. offs := (longint(y)+yoffset)*bytesperline+x1;
  1041. { convert the pattern data into the actual color sequence }
  1042. j := 1;
  1043. FillChar(fill,sizeOf(fill),byte(currentBkColor));
  1044. for i := 0 to 7 do
  1045. begin
  1046. if TmpFillPattern and j <> 0 then
  1047. fill.pat[7-i] := currentColor;
  1048. {$ifopt q+}
  1049. {$q-}
  1050. {$define overflowOn}
  1051. {$endif}
  1052. j := j shl 1;
  1053. {$ifdef overflowOn}
  1054. {$q+}
  1055. {$undef overflowOn}
  1056. {$endif}
  1057. end;
  1058. Repeat
  1059. SetWriteBank(smallint(offs shr 16));
  1060. If (amount > 7) and
  1061. (((offs and 7) = 0) or
  1062. (amount > 7+8-(offs and 7))) Then
  1063. Begin
  1064. { align target }
  1065. l := 0;
  1066. If (offs and 7) <> 0 then
  1067. { this cannot go past a window boundary bacause the }
  1068. { size of a window is always a multiple of 8 }
  1069. Begin
  1070. { position in the pattern where to start }
  1071. patternPos := offs and 7;
  1072. {$ifdef logging2}
  1073. LogLn('Aligning by drawing '+strf(8-(offs and 7))+' pixels');
  1074. {$endif logging2}
  1075. for l := 1 to 8-(offs and 7) do
  1076. begin
  1077. Mem[WinWriteSeg:word(offs)+l-1] := fill.pat[patternPos and 7];
  1078. inc(patternPos)
  1079. end;
  1080. End;
  1081. Dec(amount, l);
  1082. inc(offs, l);
  1083. {$ifdef logging2}
  1084. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(amount));
  1085. {$endif logging2}
  1086. { offs is now 8-bytes alligned }
  1087. If amount <= ($10000-(Offs and $ffff)) Then
  1088. bankrest := amount
  1089. else {the rest won't fit anymore in the current window }
  1090. bankrest := $10000 - (Offs and $ffff);
  1091. { it is possible that by aligningm we ended up in a new }
  1092. { bank, so set the correct bank again to make sure }
  1093. setwritebank(offs shr 16);
  1094. {$ifdef logging2}
  1095. LogLn('Rest to be drawn in this window: '+strf(bankrest));
  1096. {$endif logging2}
  1097. for l := 0 to (bankrest div 8)-1 Do
  1098. begin
  1099. MemL[WinWriteSeg:word(offs)+l*8] := fill.data1;
  1100. MemL[WinWriteSeg:word(offs)+l*8+4] := fill.data2;
  1101. end;
  1102. inc(offs,l*8+8);
  1103. dec(amount,l*8+8);
  1104. {$ifdef logging2}
  1105. LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(amount));
  1106. {$endif logging2}
  1107. End
  1108. Else
  1109. Begin
  1110. {$ifdef logging2}
  1111. LogLn('Drawing leftover: '+strf(amount)+' at offset '+hexstr(offs,8));
  1112. {$endif logging2}
  1113. patternPos := offs and 7;
  1114. For l := 0 to amount - 1 do
  1115. begin
  1116. { this may cross a bank at any time, so adjust }
  1117. { because this loop alwys runs for very little pixels, }
  1118. { there's little gained by splitting it up }
  1119. setwritebank(offs shr 16);
  1120. Mem[WinWriteSeg:word(offs)] := fill.pat[patternPos and 7];
  1121. inc(offs);
  1122. inc(patternPos);
  1123. end;
  1124. amount := 0;
  1125. End
  1126. Until amount = 0;
  1127. currentWriteMode := oldWriteMode;
  1128. end;
  1129. {************************************************************************}
  1130. {* 256 colors VESA mode routines Linear mode *}
  1131. {************************************************************************}
  1132. {$ifdef FPC}
  1133. type
  1134. pbyte = ^byte;
  1135. pword = ^word;
  1136. procedure DirectPutPixVESA256Linear(x, y : smallint); {$ifndef fpc}far;{$endif fpc}
  1137. var
  1138. offs : longint;
  1139. col : byte;
  1140. begin
  1141. offs := longint(y) * BytesPerLine + x;
  1142. Case CurrentWriteMode of
  1143. XorPut:
  1144. Begin
  1145. if UseNoSelector then
  1146. col:=pbyte(LFBPointer+offs+LinearPageOfs)^
  1147. else
  1148. seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
  1149. col := col xor byte(CurrentColor);
  1150. End;
  1151. AndPut:
  1152. Begin
  1153. if UseNoSelector then
  1154. col:=pbyte(LFBPointer+offs+LinearPageOfs)^
  1155. else
  1156. seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
  1157. col := col and byte(CurrentColor);
  1158. End;
  1159. OrPut:
  1160. Begin
  1161. if UseNoSelector then
  1162. col:=pbyte(LFBPointer+offs+LinearPageOfs)^
  1163. else
  1164. seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
  1165. col := col or byte(CurrentColor);
  1166. End
  1167. else
  1168. Begin
  1169. If CurrentWriteMode <> NotPut then
  1170. col := Byte(CurrentColor)
  1171. else col := Not(Byte(CurrentColor));
  1172. End
  1173. End;
  1174. if UseNoSelector then
  1175. pbyte(LFBPointer+offs+LinearPageOfs)^:=col
  1176. else
  1177. seg_move(get_ds,longint(@col),WinWriteSeg,offs+LinearPageOfs,1);
  1178. end;
  1179. procedure PutPixVESA256Linear(x, y : smallint; color : word); {$ifndef fpc}far;{$endif fpc}
  1180. var
  1181. offs : longint;
  1182. begin
  1183. X:= X + StartXViewPort;
  1184. Y:= Y + StartYViewPort;
  1185. { convert to absolute coordinates and then verify clipping...}
  1186. if ClipPixels then
  1187. Begin
  1188. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  1189. exit;
  1190. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  1191. exit;
  1192. end;
  1193. offs := longint(y) * BytesPerLine + x;
  1194. {$ifdef logging}
  1195. logln('putpix offset: '+hexstr(offs,8)+', color: '+strf(color)+', lpo: $'+
  1196. hexstr(LinearPageOfs,8));
  1197. {$endif logging}
  1198. if UseNoSelector then
  1199. pbyte(LFBPointer+offs+LinearPageOfs)^:=byte(color)
  1200. else
  1201. seg_move(get_ds,longint(@color),WinWriteSeg,offs+LinearPageOfs,1);
  1202. end;
  1203. function GetPixVESA256Linear(x, y : smallint): word; {$ifndef fpc}far;{$endif fpc}
  1204. var
  1205. offs : longint;
  1206. col : byte;
  1207. begin
  1208. X:= X + StartXViewPort;
  1209. Y:= Y + StartYViewPort;
  1210. offs := longint(y) * BytesPerLine + x;
  1211. {$ifdef logging}
  1212. logln('getpix offset: '+hexstr(offs,8)+', lpo: $'+
  1213. hexstr(LinearPageOfs,8));
  1214. {$endif logging}
  1215. if UseNoSelector then
  1216. col:=pbyte(LFBPointer+offs+LinearPageOfs)^
  1217. else
  1218. seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
  1219. GetPixVESA256Linear:=col;
  1220. end;
  1221. (*
  1222. function SetVESADisplayStart(PageNum : word;x,y : smallint):Boolean;
  1223. var
  1224. dregs : registers;
  1225. begin
  1226. if PageNum>VesaModeInfo.NumberOfPages then
  1227. PageNum:=0;
  1228. {$ifdef DEBUG}
  1229. if PageNum>0 then
  1230. writeln(stderr,'Setting Display Page ',PageNum);
  1231. {$endif DEBUG}
  1232. dregs.RealEBX:=0{ $80 for Wait for retrace };
  1233. dregs.RealECX:=x;
  1234. dregs.RealEDX:=y+PageNum*maxy;
  1235. dregs.RealSP:=0;
  1236. dregs.RealSS:=0;
  1237. dregs.RealEAX:=$4F07; RealIntr($10,dregs);
  1238. { idem as above !!! }
  1239. if (dregs.RealEAX and $1FF) <> $4F then
  1240. begin
  1241. {$ifdef DEBUG}
  1242. writeln(stderr,'Set Display start error');
  1243. {$endif DEBUG}
  1244. SetVESADisplayStart:=false;
  1245. end
  1246. else
  1247. SetVESADisplayStart:=true;
  1248. end;
  1249. *)
  1250. {$endif FPC}
  1251. {************************************************************************}
  1252. {* 15/16bit pixels VESA mode routines *}
  1253. {************************************************************************}
  1254. procedure PutPixVESA32kOr64k(x, y : smallint; color : word); {$ifndef fpc}far;{$endif fpc}
  1255. var
  1256. offs : longint;
  1257. begin
  1258. {$ifdef logging}
  1259. logln('putpixvesa32kor64k('+strf(x)+','+strf(y)+')');
  1260. {$endif logging}
  1261. X:= X + StartXViewPort;
  1262. Y:= Y + StartYViewPort;
  1263. { convert to absolute coordinates and then verify clipping...}
  1264. if ClipPixels then
  1265. Begin
  1266. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  1267. exit;
  1268. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  1269. exit;
  1270. end;
  1271. Y := Y + YOffset; { adjust pixel for correct virtual page }
  1272. offs := longint(y) * BytesPerLine + 2*x;
  1273. SetWriteBank(smallint(offs shr 16));
  1274. {$ifdef logging}
  1275. logln('putpixvesa32kor64k offset: '+strf(word(offs)));
  1276. {$endif logging}
  1277. memW[WinWriteSeg : word(offs)] := color;
  1278. end;
  1279. function GetPixVESA32kOr64k(x, y : smallint): word; {$ifndef fpc}far;{$endif fpc}
  1280. var
  1281. offs : longint;
  1282. begin
  1283. X:= X + StartXViewPort;
  1284. Y:= Y + StartYViewPort + YOffset;
  1285. offs := longint(y) * BytesPerLine + 2*x;
  1286. SetReadBank(smallint(offs shr 16));
  1287. GetPixVESA32kOr64k:=memW[WinReadSeg : word(offs)];
  1288. end;
  1289. procedure DirectPutPixVESA32kOr64k(x, y : smallint); {$ifndef fpc}far;{$endif fpc}
  1290. var
  1291. offs : longint;
  1292. col : word;
  1293. begin
  1294. {$ifdef logging}
  1295. logln('directputpixvesa32kor64k('+strf(x)+','+strf(y)+')');
  1296. {$endif logging}
  1297. y:= Y + YOffset;
  1298. offs := longint(y) * BytesPerLine + 2*x;
  1299. SetWriteBank(smallint((offs shr 16) and $ff));
  1300. Case CurrentWriteMode of
  1301. XorPut:
  1302. Begin
  1303. SetReadBank(smallint(offs shr 16));
  1304. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] xor currentcolor;
  1305. End;
  1306. AndPut:
  1307. Begin
  1308. SetReadBank(smallint(offs shr 16));
  1309. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] And currentcolor;
  1310. End;
  1311. OrPut:
  1312. Begin
  1313. SetReadBank(smallint(offs shr 16));
  1314. memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] or currentcolor;
  1315. End
  1316. else
  1317. Begin
  1318. If CurrentWriteMode <> NotPut Then
  1319. col := CurrentColor
  1320. Else col := Not(CurrentColor);
  1321. {$ifdef logging}
  1322. logln('directputpixvesa32kor64k offset: '+strf(word(offs)));
  1323. {$endif logging}
  1324. memW[WinWriteSeg : word(offs)] := Col;
  1325. End
  1326. End;
  1327. end;
  1328. {$ifdef FPC}
  1329. {************************************************************************}
  1330. {* 15/16bit pixels VESA mode routines Linear mode *}
  1331. {************************************************************************}
  1332. procedure PutPixVESA32kor64kLinear(x, y : smallint; color : word); {$ifndef fpc}far;{$endif fpc}
  1333. var
  1334. offs : longint;
  1335. begin
  1336. X:= X + StartXViewPort;
  1337. Y:= Y + StartYViewPort;
  1338. { convert to absolute coordinates and then verify clipping...}
  1339. if ClipPixels then
  1340. Begin
  1341. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  1342. exit;
  1343. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  1344. exit;
  1345. end;
  1346. offs := longint(y) * BytesPerLine + 2*x;
  1347. if UseNoSelector then
  1348. pword(LFBPointer+offs+LinearPageOfs)^:=color
  1349. else
  1350. seg_move(get_ds,longint(@color),WinWriteSeg,offs+LinearPageOfs,2);
  1351. end;
  1352. function GetPixVESA32kor64kLinear(x, y : smallint): word; {$ifndef fpc}far;{$endif fpc}
  1353. var
  1354. offs : longint;
  1355. color : word;
  1356. begin
  1357. X:= X + StartXViewPort;
  1358. Y:= Y + StartYViewPort;
  1359. offs := longint(y) * BytesPerLine + 2*x;
  1360. if UseNoSelector then
  1361. color:=pword(LFBPointer+offs+LinearPageOfs)^
  1362. else
  1363. seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@color),2);
  1364. GetPixVESA32kor64kLinear:=color;
  1365. end;
  1366. procedure DirectPutPixVESA32kor64kLinear(x, y : smallint); {$ifndef fpc}far;{$endif fpc}
  1367. var
  1368. offs : longint;
  1369. col : word;
  1370. begin
  1371. offs := longint(y) * BytesPerLine + 2*x;
  1372. Case CurrentWriteMode of
  1373. XorPut:
  1374. Begin
  1375. if UseNoSelector then
  1376. col:=pword(LFBPointer+offs+LinearPageOfs)^
  1377. else
  1378. seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
  1379. col := col xor currentcolor;
  1380. End;
  1381. AndPut:
  1382. Begin
  1383. if UseNoSelector then
  1384. col:=pword(LFBPointer+offs+LinearPageOfs)^
  1385. else
  1386. seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
  1387. col := col and currentcolor;
  1388. End;
  1389. OrPut:
  1390. Begin
  1391. if UseNoSelector then
  1392. col:=pword(LFBPointer+offs+LinearPageOfs)^
  1393. else
  1394. seg_move(WinWriteSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
  1395. col := col or currentcolor;
  1396. End
  1397. else
  1398. Begin
  1399. If CurrentWriteMode <> NotPut Then
  1400. col := CurrentColor
  1401. Else col := Not(CurrentColor);
  1402. End
  1403. End;
  1404. if UseNoSelector then
  1405. pword(LFBPointer+offs+LinearPageOfs)^:=col
  1406. else
  1407. seg_move(get_ds,longint(@col),WinWriteSeg,offs+LinearPageOfs,2);
  1408. end;
  1409. {$endif FPC}
  1410. {************************************************************************}
  1411. {* 4-bit pixels VESA mode routines *}
  1412. {************************************************************************}
  1413. procedure PutPixVESA16(x, y : smallint; color : word); {$ifndef fpc}far;{$endif fpc}
  1414. var
  1415. offs : longint;
  1416. dummy : byte;
  1417. begin
  1418. X:= X + StartXViewPort;
  1419. Y:= Y + StartYViewPort;
  1420. { convert to absolute coordinates and then verify clipping...}
  1421. if ClipPixels then
  1422. Begin
  1423. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  1424. exit;
  1425. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  1426. exit;
  1427. end;
  1428. Y := Y + YOffset; { adjust pixel for correct virtual page }
  1429. { }
  1430. offs := longint(y) * BytesPerLine + (x div 8);
  1431. SetWriteBank(smallint(offs shr 16));
  1432. PortW[$3ce] := $0f01; { Index 01 : Enable ops on all 4 planes }
  1433. PortW[$3ce] := color shl 8; { Index 00 : Enable correct plane and write color }
  1434. Port[$3ce] := 8; { Index 08 : Bitmask register. }
  1435. Port[$3cf] := $80 shr (x and $7); { Select correct bits to modify }
  1436. dummy := Mem[WinWriteSeg: offs]; { Latch the data into host space. }
  1437. Mem[WinWriteSeg: offs] := dummy; { Write the data into video memory }
  1438. PortW[$3ce] := $ff08; { Enable all bit planes. }
  1439. PortW[$3ce] := $0001; { Index 01 : Disable ops on all four planes. }
  1440. { }
  1441. end;
  1442. Function GetPixVESA16(X,Y: smallint):word; {$ifndef fpc}far;{$endif fpc}
  1443. Var dummy, offset: Word;
  1444. shift: byte;
  1445. Begin
  1446. X:= X + StartXViewPort;
  1447. Y:= Y + StartYViewPort + YOffset;
  1448. offset := longint(Y) * BytesPerLine + (x div 8);
  1449. SetReadBank(smallint(offset shr 16));
  1450. Port[$3ce] := 4;
  1451. shift := 7 - (X and 7);
  1452. Port[$3cf] := 0;
  1453. dummy := (Mem[WinReadSeg:offset] shr shift) and 1;
  1454. Port[$3cf] := 1;
  1455. dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 1);
  1456. Port[$3cf] := 2;
  1457. dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 2);
  1458. Port[$3cf] := 3;
  1459. dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 3);
  1460. GetPixVESA16 := dummy;
  1461. end;
  1462. procedure DirectPutPixVESA16(x, y : smallint); {$ifndef fpc}far;{$endif fpc}
  1463. var
  1464. offs : longint;
  1465. dummy : byte;
  1466. Color : word;
  1467. begin
  1468. y:= Y + YOffset;
  1469. case CurrentWriteMode of
  1470. XORPut:
  1471. begin
  1472. { getpixel wants local/relative coordinates }
  1473. Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
  1474. Color := CurrentColor Xor Color;
  1475. end;
  1476. OrPut:
  1477. begin
  1478. { getpixel wants local/relative coordinates }
  1479. Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
  1480. Color := CurrentColor Or Color;
  1481. end;
  1482. AndPut:
  1483. begin
  1484. { getpixel wants local/relative coordinates }
  1485. Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
  1486. Color := CurrentColor And Color;
  1487. end;
  1488. NotPut:
  1489. begin
  1490. Color := Not Color;
  1491. end
  1492. else
  1493. Color := CurrentColor;
  1494. end;
  1495. offs := longint(y) * BytesPerLine + (x div 8);
  1496. SetWriteBank(smallint(offs shr 16));
  1497. PortW[$3ce] := $0f01; { Index 01 : Enable ops on all 4 planes }
  1498. PortW[$3ce] := color shl 8; { Index 00 : Enable correct plane and write color }
  1499. Port[$3ce] := 8; { Index 08 : Bitmask register. }
  1500. Port[$3cf] := $80 shr (x and $7); { Select correct bits to modify }
  1501. dummy := Mem[WinWriteSeg: offs]; { Latch the data into host space. }
  1502. Mem[WinWriteSeg: offs] := dummy; { Write the data into video memory }
  1503. PortW[$3ce] := $ff08; { Enable all bit planes. }
  1504. PortW[$3ce] := $0001; { Index 01 : Disable ops on all four planes. }
  1505. end;
  1506. {************************************************************************}
  1507. {* VESA Palette entries *}
  1508. {************************************************************************}
  1509. {$IFDEF DPMI}
  1510. {$ifdef fpc}
  1511. Procedure SetVESARGBAllPalette(const Palette:PaletteType);
  1512. var
  1513. pal: array[0..255] of palrec;
  1514. regs: TDPMIRegisters;
  1515. c, Ptr: longint;
  1516. RealSeg: word;
  1517. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  1518. begin
  1519. if DirectColor then
  1520. Begin
  1521. _GraphResult := grError;
  1522. exit;
  1523. end;
  1524. { use the set/get palette function }
  1525. if VESAInfo.Version >= $0200 then
  1526. Begin
  1527. { check if blanking bit must be set when programming }
  1528. { the RAMDAC. }
  1529. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  1530. FunctionNr := $80
  1531. else
  1532. FunctionNr := $00;
  1533. fillChar(pal,sizeof(pal),0);
  1534. { Convert to vesa format }
  1535. for c := 0 to 255 do
  1536. begin
  1537. pal[c].red := byte(palette.colors[c].red);
  1538. pal[c].green := byte(palette.colors[c].green);
  1539. pal[c].blue := byte(palette.colors[c].blue);
  1540. end;
  1541. { Alllocate real mode buffer }
  1542. Ptr:=Global_Dos_Alloc(sizeof(pal));
  1543. {get the segment value}
  1544. RealSeg := word(Ptr shr 16);
  1545. { setup interrupt registers }
  1546. FillChar(regs, sizeof(regs), #0);
  1547. { copy palette values to real mode buffer }
  1548. DosMemPut(RealSeg,0,pal,sizeof(pal));
  1549. regs.eax := $4F09;
  1550. regs.ebx := FunctionNr;
  1551. regs.ecx := 256;
  1552. regs.edx := 0;
  1553. regs.es := RealSeg;
  1554. regs.edi := 0; { offset is always zero }
  1555. RealIntr($10, regs);
  1556. { free real mode memory }
  1557. If not Global_Dos_Free(word(Ptr and $ffff)) then
  1558. RunError(216);
  1559. if word(regs.eax) <> $004F then
  1560. begin
  1561. _GraphResult := grError;
  1562. exit;
  1563. end;
  1564. end
  1565. else
  1566. { assume it's fully VGA compatible palette-wise. }
  1567. Begin
  1568. SetVGARGBAllPalette(palette);
  1569. end;
  1570. setallpalettedefault(palette);
  1571. end;
  1572. {$endif fpc}
  1573. Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
  1574. BlueValue : smallint);
  1575. var
  1576. pal: palrec;
  1577. regs: TDPMIRegisters;
  1578. Ptr: longint;
  1579. {$ifndef fpc}
  1580. PalPtr : ^PalRec;
  1581. {$endif fpc}
  1582. RealSeg: word;
  1583. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  1584. begin
  1585. if DirectColor then
  1586. Begin
  1587. {$ifdef logging}
  1588. logln('setvesargbpalette called with directcolor = true');
  1589. {$endif logging}
  1590. _GraphResult := grError;
  1591. exit;
  1592. end;
  1593. pal.align := 0;
  1594. pal.red := byte(RedValue) shr 2;
  1595. pal.green := byte(GreenValue) shr 2;
  1596. pal.blue := byte(BlueValue) shr 2;
  1597. { use the set/get palette function }
  1598. if VESAInfo.Version >= $0200 then
  1599. Begin
  1600. { check if blanking bit must be set when programming }
  1601. { the RAMDAC. }
  1602. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  1603. FunctionNr := $80
  1604. else
  1605. FunctionNr := $00;
  1606. { Alllocate real mode buffer }
  1607. {$ifndef fpc}
  1608. Ptr:=GlobalDosAlloc(sizeof(palrec));
  1609. { get the selector values }
  1610. PalPtr := pointer(Ptr shl 16);
  1611. if not assigned(PalPtr) then
  1612. RunError(203);
  1613. {$else fpc}
  1614. Ptr:=Global_Dos_Alloc(sizeof(palrec));
  1615. {$endif fpc}
  1616. {get the segment value}
  1617. RealSeg := word(Ptr shr 16);
  1618. { setup interrupt registers }
  1619. FillChar(regs, sizeof(regs), #0);
  1620. { copy palette values to real mode buffer }
  1621. {$ifndef fpc}
  1622. move(pal, palptr^, sizeof(pal));
  1623. {$else fpc}
  1624. DosMemPut(RealSeg,0,pal,sizeof(pal));
  1625. {$endif fpc}
  1626. regs.eax := $4F09;
  1627. regs.ebx := FunctionNr;
  1628. regs.ecx := $01;
  1629. regs.edx := ColorNum;
  1630. regs.es := RealSeg;
  1631. regs.edi := 0; { offset is always zero }
  1632. RealIntr($10, regs);
  1633. { free real mode memory }
  1634. {$ifndef fpc}
  1635. GlobalDosFree(word(Ptr and $ffff));
  1636. {$else fpc}
  1637. If not Global_Dos_Free(word(Ptr and $ffff)) then
  1638. RunError(216);
  1639. {$endif fpc}
  1640. if word(regs.eax) <> $004F then
  1641. begin
  1642. {$ifdef logging}
  1643. logln('setvesargbpalette failed while directcolor = false!');
  1644. {$endif logging}
  1645. _GraphResult := grError;
  1646. exit;
  1647. end;
  1648. end
  1649. else
  1650. { assume it's fully VGA compatible palette-wise. }
  1651. Begin
  1652. SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  1653. end;
  1654. end;
  1655. Procedure GetVESARGBPalette(ColorNum: smallint; Var
  1656. RedValue, GreenValue, BlueValue : smallint);
  1657. var
  1658. pal: PalRec;
  1659. {$ifndef fpc}
  1660. palptr : ^PalRec;
  1661. {$endif fpc}
  1662. regs : TDPMIRegisters;
  1663. RealSeg: word;
  1664. ptr: longint;
  1665. begin
  1666. if DirectColor then
  1667. Begin
  1668. {$ifdef logging}
  1669. logln('getvesargbpalette called with directcolor = true');
  1670. {$endif logging}
  1671. _GraphResult := grError;
  1672. exit;
  1673. end;
  1674. { use the set/get palette function }
  1675. if VESAInfo.Version >= $0200 then
  1676. Begin
  1677. { Alllocate real mode buffer }
  1678. {$ifndef fpc}
  1679. Ptr:=GlobalDosAlloc(sizeof(palrec));
  1680. { get the selector value }
  1681. PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
  1682. if not assigned(PalPtr) then
  1683. RunError(203);
  1684. {$else fpc}
  1685. Ptr:=Global_Dos_Alloc(sizeof(palrec));
  1686. {$endif fpc}
  1687. { get the segment value }
  1688. RealSeg := word(Ptr shr 16);
  1689. { setup interrupt registers }
  1690. FillChar(regs, sizeof(regs), #0);
  1691. regs.eax := $4F09;
  1692. regs.ebx := $01; { get palette data }
  1693. regs.ecx := $01;
  1694. regs.edx := ColorNum;
  1695. regs.es := RealSeg;
  1696. regs.edi := 0; { offset is always zero }
  1697. RealIntr($10, regs);
  1698. { copy to protected mode buffer ... }
  1699. {$ifndef fpc}
  1700. Move(PalPtr^, Pal, sizeof(pal));
  1701. {$else fpc}
  1702. DosMemGet(RealSeg,0,Pal,sizeof(pal));
  1703. {$endif fpc}
  1704. { free real mode memory }
  1705. {$ifndef fpc}
  1706. GlobalDosFree(word(Ptr and $ffff));
  1707. {$else fpc}
  1708. If not Global_Dos_Free(word(Ptr and $ffff)) then
  1709. RunError(216);
  1710. {$endif fpc}
  1711. if word(regs.eax) <> $004F then
  1712. begin
  1713. {$ifdef logging}
  1714. logln('getvesargbpalette failed while directcolor = false!');
  1715. {$endif logging}
  1716. _GraphResult := grError;
  1717. exit;
  1718. end
  1719. else
  1720. begin
  1721. RedValue := smallint(pal.Red);
  1722. GreenValue := smallint(pal.Green);
  1723. BlueValue := smallint(pal.Blue);
  1724. end;
  1725. end
  1726. else
  1727. GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  1728. end;
  1729. {$ELSE}
  1730. Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
  1731. BlueValue : smallint); far;
  1732. var
  1733. FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
  1734. pal: ^palrec;
  1735. Error : boolean; { VBE call error }
  1736. begin
  1737. if DirectColor then
  1738. Begin
  1739. _GraphResult := grError;
  1740. exit;
  1741. end;
  1742. Error := FALSE;
  1743. new(pal);
  1744. if not assigned(pal) then RunError(203);
  1745. pal^.align := 0;
  1746. pal^.red := byte(RedValue);
  1747. pal^.green := byte(GreenValue);
  1748. pal^.blue := byte(BlueValue);
  1749. { use the set/get palette function }
  1750. if VESAInfo.Version >= $0200 then
  1751. Begin
  1752. { check if blanking bit must be set when programming }
  1753. { the RAMDAC. }
  1754. if (VESAInfo.caps and attrSnowCheck) <> 0 then
  1755. FunctionNr := $80
  1756. else
  1757. FunctionNr := $00;
  1758. asm
  1759. mov ax, 4F09h { Set/Get Palette data }
  1760. mov bl, [FunctionNr] { Set palette data }
  1761. mov cx, 01h { update one palette reg. }
  1762. mov dx, [ColorNum] { register number to update }
  1763. les di, [pal] { get palette address }
  1764. int 10h
  1765. cmp ax, 004Fh { check if success }
  1766. jz @noerror
  1767. mov [Error], TRUE
  1768. @noerror:
  1769. end;
  1770. if not Error then
  1771. Dispose(pal)
  1772. else
  1773. begin
  1774. _GraphResult := grError;
  1775. exit;
  1776. end;
  1777. end
  1778. else
  1779. { assume it's fully VGA compatible palette-wise. }
  1780. Begin
  1781. SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  1782. end;
  1783. end;
  1784. Procedure GetVESARGBPalette(ColorNum: smallint; Var RedValue, GreenValue,
  1785. BlueValue : smallint); far;
  1786. var
  1787. Error: boolean;
  1788. pal: ^palrec;
  1789. begin
  1790. if DirectColor then
  1791. Begin
  1792. _GraphResult := grError;
  1793. exit;
  1794. end;
  1795. Error := FALSE;
  1796. new(pal);
  1797. if not assigned(pal) then RunError(203);
  1798. FillChar(pal^, sizeof(palrec), #0);
  1799. { use the set/get palette function }
  1800. if VESAInfo.Version >= $0200 then
  1801. Begin
  1802. asm
  1803. mov ax, 4F09h { Set/Get Palette data }
  1804. mov bl, 01h { Set palette data }
  1805. mov cx, 01h { update one palette reg. }
  1806. mov dx, [ColorNum] { register number to update }
  1807. les di, [pal] { get palette address }
  1808. int 10h
  1809. cmp ax, 004Fh { check if success }
  1810. jz @noerror
  1811. mov [Error], TRUE
  1812. @noerror:
  1813. end;
  1814. if not Error then
  1815. begin
  1816. RedValue := smallint(pal^.Red);
  1817. GreenValue := smallint(pal^.Green);
  1818. BlueValue := smallint(pal^.Blue);
  1819. Dispose(pal);
  1820. end
  1821. else
  1822. begin
  1823. _GraphResult := grError;
  1824. exit;
  1825. end;
  1826. end
  1827. else
  1828. GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
  1829. end;
  1830. {$ENDIF}
  1831. (*
  1832. type
  1833. heaperrorproc=function(size:longint):smallint;
  1834. Const
  1835. HeapErrorIsHooked : boolean = false;
  1836. OldHeapError : HeapErrorProc = nil;
  1837. DsLimit : dword = 0;
  1838. function NewHeapError(size : longint) : smallint;
  1839. begin
  1840. set_segment_limit(get_ds,DsLimit);
  1841. NewHeapError:=OldHeapError(size);
  1842. DsLimit:=get_segment_limit(get_ds);
  1843. { The base of ds can be changed
  1844. we need to compute the address again PM }
  1845. LFBPointer:=pointer(FrameBufferLinearAddress-get_segment_base_address(get_ds));
  1846. if dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1 > DsLimit then
  1847. set_segment_limit(get_ds,dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1);
  1848. end;
  1849. procedure HookHeapError;
  1850. begin
  1851. if HeapErrorIsHooked then
  1852. exit;
  1853. DsLimit:=get_segment_limit(get_ds);
  1854. OldHeapError:=HeapErrorProc(HeapError);
  1855. HeapError:=@NewHeapError;
  1856. HeapErrorIsHooked:=true;
  1857. end;
  1858. procedure UnHookHeapError;
  1859. begin
  1860. if not HeapErrorIsHooked then
  1861. exit;
  1862. LFBPointer:=nil;
  1863. set_segment_limit(get_ds,DsLimit);
  1864. HeapError:=OldHeapError;
  1865. HeapErrorIsHooked:=false;
  1866. end;
  1867. *)
  1868. function SetupLinear(var ModeInfo: TVESAModeInfo;mode : word) : boolean;
  1869. begin
  1870. SetUpLinear:=false;
  1871. {$ifdef FPC}
  1872. case mode of
  1873. m320x200x32k,
  1874. m320x200x64k,
  1875. m640x480x32k,
  1876. m640x480x64k,
  1877. m800x600x32k,
  1878. m800x600x64k,
  1879. m1024x768x32k,
  1880. m1024x768x64k,
  1881. m1280x1024x32k,
  1882. m1280x1024x64k :
  1883. begin
  1884. DirectPutPixel:=@DirectPutPixVESA32kor64kLinear;
  1885. PutPixel:=@PutPixVESA32kor64kLinear;
  1886. GetPixel:=@GetPixVESA32kor64kLinear;
  1887. { linear mode for lines not yet implemented PM }
  1888. HLine:=@HLineDefault;
  1889. VLine:=@VLineDefault;
  1890. GetScanLine := @GetScanLineDefault;
  1891. PatternLine := @PatternLineDefault;
  1892. end;
  1893. m640x400x256,
  1894. m640x480x256,
  1895. m800x600x256,
  1896. m1024x768x256,
  1897. m1280x1024x256:
  1898. begin
  1899. DirectPutPixel:=@DirectPutPixVESA256Linear;
  1900. PutPixel:=@PutPixVESA256Linear;
  1901. GetPixel:=@GetPixVESA256Linear;
  1902. { linear mode for lines not yet implemented PM }
  1903. HLine:=@HLineDefault;
  1904. VLine:=@VLineDefault;
  1905. GetScanLine := @GetScanLineDefault;
  1906. PatternLine := @PatternLineDefault;
  1907. end;
  1908. else
  1909. exit;
  1910. end;
  1911. FrameBufferLinearAddress:=Get_linear_addr(VESAModeInfo.PhysAddress and $FFFF0000,
  1912. VESAInfo.TotalMem shl 16);
  1913. {$ifdef logging}
  1914. logln('framebuffer linear address: '+hexstr(FrameBufferLinearAddress div (1024*1024),8));
  1915. logln('total mem shl 16: '+strf(vesainfo.totalmem shl 16));
  1916. {$endif logging}
  1917. if int31error<>0 then
  1918. begin
  1919. {$ifdef logging}
  1920. logln('Unable to get linear address for '+hexstr(VESAModeInfo.PhysAddress,8));
  1921. {$endif logging}
  1922. writeln(stderr,'Unable to get linear address for ',hexstr(VESAModeInfo.PhysAddress,8));
  1923. exit;
  1924. end;
  1925. if UseNoSelector then
  1926. begin
  1927. { HookHeapError; }
  1928. LFBPointer:=pointer(FrameBufferLinearAddress-get_segment_base_address(get_ds));
  1929. if dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1 > dword(get_segment_limit(get_ds)) then
  1930. set_segment_limit(get_ds,dword(LFBPointer)+dword(VESAInfo.TotalMem shl 16)-1);
  1931. end
  1932. else
  1933. begin
  1934. WinWriteSeg:=allocate_ldt_descriptors(1);
  1935. {$ifdef logging}
  1936. logln('writeseg1: '+hexstr(winwriteseg,8));
  1937. {$endif logging}
  1938. set_segment_base_address(WinWriteSeg,FrameBufferLinearAddress);
  1939. set_segment_limit(WinWriteSeg,(VESAInfo.TotalMem shl 16)-1);
  1940. lock_linear_region(FrameBufferLinearAddress,(VESAInfo.TotalMem shl 16));
  1941. if int31error<>0 then
  1942. begin
  1943. {$ifdef logging}
  1944. logln('Error in linear memory selectors creation');
  1945. {$endif logging}
  1946. writeln(stderr,'Error in linear memory selectors creation');
  1947. exit;
  1948. end;
  1949. end;
  1950. LinearPageOfs := 0;
  1951. InLinear:=true;
  1952. SetUpLinear:=true;
  1953. { WinSize:=(VGAInfo.TotalMem shl 16);
  1954. WinLoMask:=(VGAInfo.TotalMem shl 16)-1;
  1955. WinShift:=15;
  1956. Temp:=VGAInfo.TotalMem;
  1957. while Temp>0 do
  1958. begin
  1959. inc(WinShift);
  1960. Temp:=Temp shr 1;
  1961. end; }
  1962. {$endif FPC}
  1963. end;
  1964. procedure SetupWindows(var ModeInfo: TVESAModeInfo);
  1965. begin
  1966. InLinear:=false;
  1967. { now we check the windowing scheme ...}
  1968. if (ModeInfo.WinAAttr and WinSupported) <> 0 then
  1969. { is this window supported ... }
  1970. begin
  1971. { now check if the window is R/W }
  1972. if (ModeInfo.WinAAttr and WinReadable) <> 0 then
  1973. begin
  1974. ReadWindow := 0;
  1975. WinReadSeg := ModeInfo.WinASeg;
  1976. end;
  1977. if (ModeInfo.WinAAttr and WinWritable) <> 0 then
  1978. begin
  1979. WriteWindow := 0;
  1980. WinWriteSeg := ModeInfo.WinASeg;
  1981. end;
  1982. end;
  1983. if (ModeInfo.WinBAttr and WinSupported) <> 0 then
  1984. { is this window supported ... }
  1985. begin
  1986. { OPTIMIZATION ... }
  1987. { if window A supports both read/write, then we try to optimize }
  1988. { everything, by using a different window for Read and/or write.}
  1989. if (WinReadSeg <> 0) and (WinWriteSeg <> 0) then
  1990. begin
  1991. { check if winB supports read }
  1992. if (ModeInfo.WinBAttr and winReadable) <> 0 then
  1993. begin
  1994. WinReadSeg := ModeInfo.WinBSeg;
  1995. ReadWindow := 1;
  1996. end
  1997. else
  1998. { check if WinB supports write }
  1999. if (ModeInfo.WinBAttr and WinWritable) <> 0 then
  2000. begin
  2001. WinWriteSeg := ModeInfo.WinBSeg;
  2002. WriteWindow := 1;
  2003. end;
  2004. end
  2005. else
  2006. { Window A only supported Read OR Write, no we have to make }
  2007. { sure that window B supports the other mode. }
  2008. if (WinReadSeg = 0) and (WinWriteSeg<>0) then
  2009. begin
  2010. if (ModeInfo.WinBAttr and WinReadable <> 0) then
  2011. begin
  2012. ReadWindow := 1;
  2013. WinReadSeg := ModeInfo.WinBSeg;
  2014. end
  2015. else
  2016. { impossible, this VESA mode is WRITE only! }
  2017. begin
  2018. WriteLn('Invalid VESA Window attribute.');
  2019. Halt(255);
  2020. end;
  2021. end
  2022. else
  2023. if (winWriteSeg = 0) and (WinReadSeg<>0) then
  2024. begin
  2025. if (ModeInfo.WinBAttr and WinWritable) <> 0 then
  2026. begin
  2027. WriteWindow := 1;
  2028. WinWriteSeg := ModeInfo.WinBSeg;
  2029. end
  2030. else
  2031. { impossible, this VESA mode is READ only! }
  2032. begin
  2033. WriteLn('Invalid VESA Window attribute.');
  2034. Halt(255);
  2035. end;
  2036. end
  2037. else
  2038. if (winReadSeg = 0) and (winWriteSeg = 0) then
  2039. { no read/write in this mode! }
  2040. begin
  2041. WriteLn('Invalid VESA Window attribute.');
  2042. Halt(255);
  2043. end;
  2044. YOffset := 0;
  2045. end;
  2046. { if both windows are not supported, then we can assume }
  2047. { that there is ONE single NON relocatable window. }
  2048. if (WinWriteSeg = 0) and (WinReadSeg = 0) then
  2049. begin
  2050. WinWriteSeg := ModeInfo.WinASeg;
  2051. WinReadSeg := ModeInfo.WinASeg;
  2052. end;
  2053. { 16-bit Protected mode checking code... }
  2054. { change segment values to protected mode }
  2055. { selectors. }
  2056. if WinReadSeg = $A000 then
  2057. WinReadSeg := SegA000
  2058. else
  2059. if WinReadSeg = $B000 then
  2060. WinReadSeg := SegB000
  2061. else
  2062. if WinReadSeg = $B800 then
  2063. WinReadSeg := SegB800
  2064. else
  2065. begin
  2066. WriteLn('Invalid segment address.');
  2067. Halt(255);
  2068. end;
  2069. if WinWriteSeg = $A000 then
  2070. WinWriteSeg := SegA000
  2071. else
  2072. if WinWriteSeg = $B000 then
  2073. WinWriteSeg := SegB000
  2074. else
  2075. if WinWriteSeg = $B800 then
  2076. WinWriteSeg := SegB800
  2077. else
  2078. begin
  2079. WriteLn('Invalid segment address.');
  2080. Halt(255);
  2081. end;
  2082. end;
  2083. function setVESAMode(mode:word):boolean;
  2084. var i:word;
  2085. res: boolean;
  2086. begin
  2087. { Init mode information, for compatibility with VBE < 1.1 }
  2088. FillChar(VESAModeInfo, sizeof(TVESAModeInfo), #0);
  2089. { get the video mode information }
  2090. if getVESAModeInfo(VESAmodeinfo, mode) then
  2091. begin
  2092. { checks if the hardware supports the video mode. }
  2093. if (VESAModeInfo.attr and modeAvail) = 0 then
  2094. begin
  2095. SetVESAmode := FALSE;
  2096. {$ifdef logging}
  2097. logln(' vesa mode '+strf(mode)+' not supported!!!');
  2098. {$endif logging}
  2099. _GraphResult := grError;
  2100. exit;
  2101. end;
  2102. SetVESAMode := TRUE;
  2103. BankShift := 0;
  2104. while (64 shr BankShift) <> VESAModeInfo.WinGranularity do
  2105. Inc(BankShift);
  2106. CurrentWriteBank := -1;
  2107. CurrentReadBank := -1;
  2108. BytesPerLine := VESAModeInfo.BytesPerScanLine;
  2109. { These are the window adresses ... }
  2110. WinWriteSeg := 0; { This is the segment to use for writes }
  2111. WinReadSeg := 0; { This is the segment to use for reads }
  2112. ReadWindow := 0;
  2113. WriteWindow := 0;
  2114. { VBE 2.0 and higher supports >= non VGA linear buffer types...}
  2115. { this is backward compatible. }
  2116. if (((VESAModeInfo.Attr and ModeNoWindowed) <> 0) or UseLFB) and
  2117. ((VESAModeInfo.Attr and ModeLinearBuffer) <> 0) then
  2118. begin
  2119. if not SetupLinear(VESAModeInfo,mode) then
  2120. SetUpWindows(VESAModeInfo);
  2121. end
  2122. else
  2123. { if linear and windowed is supported, then use windowed }
  2124. { method. }
  2125. SetUpWindows(VESAModeInfo);
  2126. {$ifdef logging}
  2127. LogLn('Entering vesa mode '+strf(mode));
  2128. LogLn('Read segment: $'+hexstr(winreadseg,4));
  2129. LogLn('Write segment: $'+hexstr(winwriteseg,4));
  2130. LogLn('Window granularity: '+strf(VESAModeInfo.WinGranularity)+'kb');
  2131. LogLn('Window size: '+strf(VESAModeInfo.winSize)+'kb');
  2132. LogLn('Bytes per line: '+strf(bytesperline));
  2133. {$endif logging}
  2134. { Select the correct mode number if we're going to use linear access! }
  2135. if InLinear then
  2136. inc(mode,$4000);
  2137. asm
  2138. mov ax,4F02h
  2139. mov bx,mode
  2140. {$ifdef fpc}
  2141. push ebp
  2142. {$endif fpc}
  2143. int 10h
  2144. {$ifdef fpc}
  2145. pop ebp
  2146. {$endif fpc}
  2147. sub ax,004Fh
  2148. cmp ax,1
  2149. sbb al,al
  2150. mov res,al
  2151. end;
  2152. if not res then
  2153. _GraphResult := GrNotDetected
  2154. else _GraphResult := grOk;
  2155. end;
  2156. end;
  2157. (*
  2158. function getVESAMode:word;assembler;
  2159. asm {return -1 if error}
  2160. mov ax,4F03h
  2161. {$ifdef fpc}
  2162. push ebp
  2163. {$endif fpc}
  2164. int 10h
  2165. {$ifdef fpc}
  2166. pop ebp
  2167. {$endif fpc}
  2168. cmp ax,004Fh
  2169. je @@OK
  2170. mov ax,-1
  2171. jmp @@X
  2172. @@OK:
  2173. mov ax,bx
  2174. @@X:
  2175. end;
  2176. *)
  2177. {************************************************************************}
  2178. {* VESA Modes inits *}
  2179. {************************************************************************}
  2180. {$IFDEF DPMI}
  2181. {******************************************************** }
  2182. { Function GetMaxScanLines() }
  2183. {-------------------------------------------------------- }
  2184. { This routine returns the maximum number of scan lines }
  2185. { possible for this mode. This is done using the Get }
  2186. { Scan Line length VBE function. }
  2187. {******************************************************** }
  2188. function GetMaxScanLines: word;
  2189. var
  2190. regs : TDPMIRegisters;
  2191. begin
  2192. FillChar(regs, sizeof(regs), #0);
  2193. { play it safe, call the real mode int, the 32-bit entry point }
  2194. { may not be defined as stated in VBE v3.0 }
  2195. regs.eax := $4f06; {_ setup function }
  2196. regs.ebx := $0001; { get scan line length }
  2197. RealIntr($10, regs);
  2198. GetMaxScanLines := (regs.edx and $0000ffff);
  2199. end;
  2200. {$ELSE}
  2201. function GetMaxScanLines: word; assembler;
  2202. asm
  2203. mov ax, 4f06h
  2204. mov bx, 0001h
  2205. int 10h
  2206. mov ax, dx
  2207. end;
  2208. {$ENDIF}
  2209. procedure Init1280x1024x64k; {$ifndef fpc}far;{$endif fpc}
  2210. begin
  2211. SetVesaMode(m1280x1024x64k);
  2212. { Get maximum number of scanlines for page flipping }
  2213. ScanLines := GetMaxScanLines;
  2214. end;
  2215. procedure Init1280x1024x32k; {$ifndef fpc}far;{$endif fpc}
  2216. begin
  2217. SetVESAMode(m1280x1024x32k);
  2218. { Get maximum number of scanlines for page flipping }
  2219. ScanLines := GetMaxScanLines;
  2220. end;
  2221. procedure Init1280x1024x256; {$ifndef fpc}far;{$endif fpc}
  2222. begin
  2223. SetVESAMode(m1280x1024x256);
  2224. { Get maximum number of scanlines for page flipping }
  2225. ScanLines := GetMaxScanLines;
  2226. end;
  2227. procedure Init1280x1024x16; {$ifndef fpc}far;{$endif fpc}
  2228. begin
  2229. SetVESAMode(m1280x1024x16);
  2230. { Get maximum number of scanlines for page flipping }
  2231. ScanLines := GetMaxScanLines;
  2232. end;
  2233. procedure Init1024x768x64k; {$ifndef fpc}far;{$endif fpc}
  2234. begin
  2235. SetVESAMode(m1024x768x64k);
  2236. { Get maximum number of scanlines for page flipping }
  2237. ScanLines := GetMaxScanLines;
  2238. end;
  2239. procedure Init640x480x32k; {$ifndef fpc}far;{$endif fpc}
  2240. begin
  2241. SetVESAMode(m640x480x32k);
  2242. { Get maximum number of scanlines for page flipping }
  2243. ScanLines := GetMaxScanLines;
  2244. end;
  2245. procedure Init1024x768x256; {$ifndef fpc}far;{$endif fpc}
  2246. begin
  2247. SetVESAMode(m1024x768x256);
  2248. { Get maximum number of scanlines for page flipping }
  2249. ScanLines := GetMaxScanLines;
  2250. end;
  2251. procedure Init1024x768x16; {$ifndef fpc}far;{$endif fpc}
  2252. begin
  2253. SetVESAMode(m1024x768x16);
  2254. { Get maximum number of scanlines for page flipping }
  2255. ScanLines := GetMaxScanLines;
  2256. end;
  2257. procedure Init800x600x64k; {$ifndef fpc}far;{$endif fpc}
  2258. begin
  2259. SetVESAMode(m800x600x64k);
  2260. { Get maximum number of scanlines for page flipping }
  2261. ScanLines := GetMaxScanLines;
  2262. end;
  2263. procedure Init800x600x32k; {$ifndef fpc}far;{$endif fpc}
  2264. begin
  2265. SetVESAMode(m800x600x32k);
  2266. { Get maximum number of scanlines for page flipping }
  2267. ScanLines := GetMaxScanLines;
  2268. end;
  2269. procedure Init800x600x256; {$ifndef fpc}far;{$endif fpc}
  2270. begin
  2271. SetVESAMode(m800x600x256);
  2272. { Get maximum number of scanlines for page flipping }
  2273. ScanLines := GetMaxScanLines;
  2274. end;
  2275. procedure Init800x600x16; {$ifndef fpc}far;{$endif fpc}
  2276. begin
  2277. SetVesaMode(m800x600x16);
  2278. { Get maximum number of scanlines for page flipping }
  2279. ScanLines := GetMaxScanLines;
  2280. end;
  2281. procedure Init640x480x64k; {$ifndef fpc}far;{$endif fpc}
  2282. begin
  2283. SetVESAMode(m640x480x64k);
  2284. { Get maximum number of scanlines for page flipping }
  2285. ScanLines := GetMaxScanLines;
  2286. end;
  2287. procedure Init640x480x256; {$ifndef fpc}far;{$endif fpc}
  2288. begin
  2289. SetVESAMode(m640x480x256);
  2290. { Get maximum number of scanlines for page flipping }
  2291. ScanLines := GetMaxScanLines;
  2292. end;
  2293. procedure Init640x400x256; {$ifndef fpc}far;{$endif fpc}
  2294. begin
  2295. SetVESAMode(m640x400x256);
  2296. { Get maximum number of scanlines for page flipping }
  2297. ScanLines := GetMaxScanLines;
  2298. end;
  2299. procedure Init320x200x64k; {$ifndef fpc}far;{$endif fpc}
  2300. begin
  2301. SetVESAMode(m320x200x64k);
  2302. { Get maximum number of scanlines for page flipping }
  2303. ScanLines := GetMaxScanLines;
  2304. end;
  2305. procedure Init320x200x32k; {$ifndef fpc}far;{$endif fpc}
  2306. begin
  2307. SetVESAMode(m320x200x32k);
  2308. { Get maximum number of scanlines for page flipping }
  2309. ScanLines := GetMaxScanLines;
  2310. end;
  2311. {$IFDEF DPMI}
  2312. Procedure SaveStateVESA; {$ifndef fpc}far;{$endif fpc}
  2313. var
  2314. PtrLong: longint;
  2315. regs: TDPMIRegisters;
  2316. begin
  2317. SaveSupported := FALSE;
  2318. SavePtr := nil;
  2319. {$ifdef logging}
  2320. LogLn('Get the video mode...');
  2321. {$endif logging}
  2322. { Get the video mode }
  2323. asm
  2324. mov ah,0fh
  2325. {$ifdef fpc}
  2326. push ebp
  2327. {$endif fpc}
  2328. int 10h
  2329. {$ifdef fpc}
  2330. pop ebp
  2331. {$endif fpc}
  2332. mov [VideoMode], al
  2333. end;
  2334. { saving/restoring video state screws up Windows (JM) }
  2335. if inWindows then
  2336. exit;
  2337. {$ifdef logging}
  2338. LogLn('Prepare to save VESA video state');
  2339. {$endif logging}
  2340. { Prepare to save video state...}
  2341. asm
  2342. mov ax, 4F04h { get buffer size to save state }
  2343. mov dx, 00h
  2344. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  2345. {$ifdef fpc}
  2346. push ebp
  2347. {$endif fpc}
  2348. int 10h
  2349. {$ifdef fpc}
  2350. pop ebp
  2351. {$endif fpc}
  2352. mov [StateSize], bx
  2353. cmp al,04fh
  2354. jnz @notok
  2355. mov [SaveSupported],TRUE
  2356. @notok:
  2357. end;
  2358. regs.eax := $4f04;
  2359. regs.edx := $0000;
  2360. regs.ecx := $000F;
  2361. RealIntr($10, regs);
  2362. StateSize := word(regs.ebx);
  2363. if byte(regs.eax) = $4f then
  2364. SaveSupported := TRUE;
  2365. if SaveSupported then
  2366. begin
  2367. {$ifdef logging}
  2368. LogLn('allocating VESA save buffer of '+strf(64*StateSize));
  2369. {$endif logging}
  2370. {$ifndef fpc}
  2371. PtrLong:=GlobalDosAlloc(64*StateSize); { values returned in 64-byte blocks }
  2372. {$else fpc}
  2373. PtrLong:=Global_Dos_Alloc(64*StateSize); { values returned in 64-byte blocks }
  2374. {$endif fpc}
  2375. if PtrLong = 0 then
  2376. RunError(203);
  2377. SavePtr := pointer(longint(PtrLong and $0000ffff) shl 16);
  2378. {$ifndef fpc}
  2379. { In FPC mode, we can't do anything with this (no far pointers) }
  2380. { However, we still need to keep it to be able to free the }
  2381. { memory afterwards. Since this data is not accessed in PM code, }
  2382. { there's no need to save it in a seperate buffer (JM) }
  2383. if not assigned(SavePtr) then
  2384. RunError(203);
  2385. {$endif fpc}
  2386. RealStateSeg := word(PtrLong shr 16);
  2387. FillChar(regs, sizeof(regs), #0);
  2388. { call the real mode interrupt ... }
  2389. regs.eax := $4F04; { save the state buffer }
  2390. regs.ecx := $0F; { Save DAC / Data areas / Hardware states }
  2391. regs.edx := $01; { save state }
  2392. regs.es := RealStateSeg;
  2393. regs.ebx := 0;
  2394. RealIntr($10,regs);
  2395. FillChar(regs, sizeof(regs), #0);
  2396. { restore state, according to Ralph Brown Interrupt list }
  2397. { some BIOS corrupt the hardware after a save... }
  2398. regs.eax := $4F04; { restore the state buffer }
  2399. regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
  2400. regs.edx := $02;
  2401. regs.es := RealStateSeg;
  2402. regs.ebx := 0;
  2403. RealIntr($10,regs);
  2404. end;
  2405. end;
  2406. procedure RestoreStateVESA; {$ifndef fpc}far;{$endif fpc}
  2407. var
  2408. regs:TDPMIRegisters;
  2409. begin
  2410. { go back to the old video mode...}
  2411. asm
  2412. mov ah,00
  2413. mov al,[VideoMode]
  2414. {$ifdef fpc}
  2415. push ebp
  2416. {$endif fpc}
  2417. int 10h
  2418. {$ifdef fpc}
  2419. pop ebp
  2420. {$endif fpc}
  2421. end;
  2422. { then restore all state information }
  2423. {$ifndef fpc}
  2424. if assigned(SavePtr) and (SaveSupported=TRUE) then
  2425. {$else fpc}
  2426. { No far pointer support, so it's possible that that assigned(SavePtr) }
  2427. { would return false under FPC. Just check if it's different from nil. }
  2428. if (SavePtr <> nil) and (SaveSupported=TRUE) then
  2429. {$endif fpc}
  2430. begin
  2431. FillChar(regs, sizeof(regs), #0);
  2432. { restore state, according to Ralph Brown Interrupt list }
  2433. { some BIOS corrupt the hardware after a save... }
  2434. regs.eax := $4F04; { restore the state buffer }
  2435. regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
  2436. regs.edx := $02; { restore state }
  2437. regs.es := RealStateSeg;
  2438. regs.ebx := 0;
  2439. RealIntr($10,regs);
  2440. {$ifndef fpc}
  2441. if GlobalDosFree(longint(SavePtr) shr 16)<>0 then
  2442. {$else fpc}
  2443. if Not(Global_Dos_Free(longint(SavePtr) shr 16)) then
  2444. {$endif fpc}
  2445. RunError(216);
  2446. SavePtr := nil;
  2447. end;
  2448. end;
  2449. {$ELSE}
  2450. {**************************************************************}
  2451. {* Real mode routines *}
  2452. {**************************************************************}
  2453. Procedure SaveStateVESA; far;
  2454. begin
  2455. SavePtr := nil;
  2456. SaveSupported := FALSE;
  2457. { Get the video mode }
  2458. asm
  2459. mov ah,0fh
  2460. int 10h
  2461. mov [VideoMode], al
  2462. end;
  2463. { Prepare to save video state...}
  2464. asm
  2465. mov ax, 4f04h { get buffer size to save state }
  2466. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  2467. mov dx, 00h
  2468. int 10h
  2469. mov [StateSize], bx
  2470. cmp al,04fh
  2471. jnz @notok
  2472. mov [SaveSupported],TRUE
  2473. @notok:
  2474. end;
  2475. if SaveSupported then
  2476. Begin
  2477. GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
  2478. if not assigned(SavePtr) then
  2479. RunError(203);
  2480. asm
  2481. mov ax, 4F04h { save the state buffer }
  2482. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  2483. mov dx, 01h
  2484. mov es, WORD PTR [SavePtr+2]
  2485. mov bx, WORD PTR [SavePtr]
  2486. int 10h
  2487. end;
  2488. { restore state, according to Ralph Brown Interrupt list }
  2489. { some BIOS corrupt the hardware after a save... }
  2490. asm
  2491. mov ax, 4F04h { save the state buffer }
  2492. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  2493. mov dx, 02h
  2494. mov es, WORD PTR [SavePtr+2]
  2495. mov bx, WORD PTR [SavePtr]
  2496. int 10h
  2497. end;
  2498. end;
  2499. end;
  2500. procedure RestoreStateVESA; far;
  2501. begin
  2502. { go back to the old video mode...}
  2503. asm
  2504. mov ah,00
  2505. mov al,[VideoMode]
  2506. int 10h
  2507. end;
  2508. { then restore all state information }
  2509. if assigned(SavePtr) and (SaveSupported=TRUE) then
  2510. begin
  2511. { restore state, according to Ralph Brown Interrupt list }
  2512. asm
  2513. mov ax, 4F04h { save the state buffer }
  2514. mov cx, 00001111b { Save DAC / Data areas / Hardware states }
  2515. mov dx, 02h { restore state }
  2516. mov es, WORD PTR [SavePtr+2]
  2517. mov bx, WORD PTR [SavePtr]
  2518. int 10h
  2519. end;
  2520. FreeMem(SavePtr, 64*StateSize);
  2521. SavePtr := nil;
  2522. end;
  2523. end;
  2524. {$ENDIF DPMI}
  2525. {************************************************************************}
  2526. {* VESA Page flipping routines *}
  2527. {************************************************************************}
  2528. { Note: These routines, according to the VBE3 specification, will NOT }
  2529. { work with the 24 bpp modes, because of the alignment. }
  2530. {************************************************************************}
  2531. {******************************************************** }
  2532. { Procedure SetVisualVESA() }
  2533. {-------------------------------------------------------- }
  2534. { This routine changes the page which will be displayed }
  2535. { on the screen, since the method has changed somewhat }
  2536. { between VBE versions , we will use the old method where }
  2537. { the new pixel offset is used to display different pages }
  2538. {******************************************************** }
  2539. procedure SetVisualVESA(page: word); {$ifndef fpc}far;{$endif fpc}
  2540. var
  2541. newStartVisible : word;
  2542. begin
  2543. if page > HardwarePages then
  2544. begin
  2545. _graphresult := grError;
  2546. exit;
  2547. end;
  2548. newStartVisible := (MaxY+1)*page;
  2549. if newStartVisible > ScanLines then
  2550. begin
  2551. _graphresult := grError;
  2552. exit;
  2553. end;
  2554. asm
  2555. mov ax, 4f07h
  2556. mov bx, 0000h { set display start }
  2557. mov cx, 0000h { pixel zero ! }
  2558. mov dx, [NewStartVisible] { new scanline }
  2559. {$ifdef fpc}
  2560. push ebp
  2561. {$endif}
  2562. int 10h
  2563. {$ifdef fpc}
  2564. pop ebp
  2565. {$endif}
  2566. end;
  2567. end;
  2568. procedure SetActiveVESA(page: word); {$ifndef fpc}far;{$endif fpc}
  2569. begin
  2570. { video offset is in pixels under VESA VBE! }
  2571. { This value is reset after a mode set to page ZERO = YOffset = 0 ) }
  2572. if page > HardwarePages then
  2573. begin
  2574. _graphresult := grError;
  2575. exit;
  2576. end;
  2577. YOffset := (MaxY+1)*page;
  2578. LinearPageOfs := YOffset*(MaxX+1);
  2579. end;