vesa.inc 92 KB

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