vesa.inc 95 KB

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