vesa.inc 91 KB

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