12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by Carl Eric Codere
- This include implements VESA basic access.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- type
- palrec = packed record { record used for set/get DAC palette }
- blue, green, red, align: byte;
- end;
- const
- { VESA attributes }
- attrSwitchDAC = $01; { DAC is switchable (1.2) }
- attrNotVGACompatible = $02; { Video is NOT VGA compatible (2.0) }
- attrSnowCheck = $04; { Video must use snow checking(2.0) }
- { mode attribute bits }
- modeAvail = $01; { Hardware supports this mode (1.0) }
- modeExtendInfo = $02; { Extended information (1.0) }
- modeBIOSSupport = $04; { TTY BIOS Support (1.0) }
- modeColor = $08; { This is a color mode (1.0) }
- modeGraphics = $10; { This is a graphics mode (1.0) }
- modeNotVGACompatible = $20; { this mode is NOT I/O VGA compatible (2.0)}
- modeNoWindowed = $40; { This mode does not support Windows (2.0) }
- modeLinearBuffer = $80; { This mode supports linear buffers (2.0) }
- { window attributes }
- winSupported = $01;
- winReadable = $02;
- winWritable = $04;
- { memory model }
- modelText = $00;
- modelCGA = $01;
- modelHerc = $02;
- model4plane = $03;
- modelPacked = $04;
- modelModeX = $05;
- modelRGB = $06;
- modelYUV = $07;
- {$ifndef dpmi}
- {$i vesah.inc}
- { otherwise it's already included in graph.pp }
- {$endif dpmi}
- var
- BytesPerLine: word; { Number of bytes per scanline }
- YOffset : word; { Pixel offset for VESA page flipping }
- { window management }
- ReadWindow : byte; { Window number for reading. }
- WriteWindow: byte; { Window number for writing. }
- winReadSeg : word; { Address of segment for read }
- winWriteSeg: word; { Address of segment for writes}
- CurrentReadBank : integer; { active read bank }
- CurrentWriteBank: integer; { active write bank }
- BankShift : word; { address to shift by when switching banks. }
- { linear mode specific stuff }
- InLinear : boolean; { true if in linear mode }
- LinearPageOfs : longint; { offset used to set active page }
- FrameBufferLinearAddress : longint;
- ScanLines: word; { maximum number of scan lines for mode }
- function hexstr(val : longint;cnt : byte) : string;
- const
- HexTbl : array[0..15] of char='0123456789ABCDEF';
- var
- i : longint;
- begin
- hexstr[0]:=char(cnt);
- for i:=cnt downto 1 do
- begin
- hexstr[i]:=hextbl[val and $f];
- val:=val shr 4;
- end;
- end;
- {$IFDEF DPMI}
- function getVESAInfo(var VESAInfo: TVESAInfo) : boolean;
- var
- ptrlong : longint;
- VESAPtr : ^TVESAInfo;
- st : string[4];
- regs : TDPMIRegisters;
- {$ifndef fpc}
- ModeSel: word;
- offs: longint;
- {$endif fpc}
- { added... }
- modelist: PmodeList;
- i: longint;
- RealSeg : word;
- begin
- { Allocate real mode buffer }
- {$ifndef fpc}
- Ptrlong:=GlobalDosAlloc(sizeof(TVESAInfo));
- { Get selector value }
- VESAPtr := pointer(Ptrlong shl 16);
- {$else fpc}
- Ptrlong:=Global_Dos_Alloc(sizeof(TVESAInfo));
- New(VESAPtr);
- {$endif fpc}
- { Get segment value }
- RealSeg := word(Ptrlong shr 16);
- if not assigned(VESAPtr) then
- RunError(203);
- FillChar(regs, sizeof(regs), #0);
- { Get VESA Mode information ... }
- regs.eax := $4f00;
- regs.es := RealSeg;
- regs.edi := $00;
- RealIntr($10, regs);
- {$ifdef fpc}
- { no far pointer support in FPC yet, so move the vesa info into a memory }
- { block in the DS slector space (JM) }
- dosmemget(RealSeg,0,VesaPtr^,SizeOf(TVESAInfo));
- {$endif fpc}
- St:=Vesaptr^.signature;
- if st<>'VESA' then
- begin
- {$ifdef logging}
- LogLn('No VESA detected.');
- {$endif logging}
- getVesaInfo := FALSE;
- {$ifndef fpc}
- GlobalDosFree(word(PtrLong and $ffff));
- {$else fpc}
- If not Global_Dos_Free(word(PtrLong and $ffff)) then
- RunError(216);
- { also free the extra allocated buffer }
- Dispose(VESAPtr);
- {$endif fpc}
- exit;
- end
- else
- getVesaInfo := TRUE;
- {$ifndef fpc}
- { The mode pointer buffer points to a real mode memory }
- { Therefore steps to get the modes: }
- { 1. Allocate Selector and SetLimit to max number of }
- { of possible modes. }
- ModeSel := AllocSelector(0);
- SetSelectorLimit(ModeSel, 256*sizeof(word));
- { 2. Set Selector linear address to the real mode pointer }
- { returned. }
- offs := longint(longint(VESAPtr^.ModeList) shr 16) shl 4;
- {shouldn't the OR in the next line be a + ?? (JM)}
- offs := offs OR (Longint(VESAPtr^.ModeList) and $ffff);
- SetSelectorBase(ModeSel, offs);
- { copy VESA mode information to a protected mode buffer and }
- { then free the real mode buffer... }
- Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
- GlobalDosFree(word(PtrLong and $ffff));
- { ModeList points to the mode list }
- { We must copy it somewhere... }
- ModeList := Ptr(ModeSel, 0);
- {$else fpc}
- { No far pointer support, so the Ptr(ModeSel, 0) doesn't work. }
- { Immediately copy everything to a buffer in the DS selector space }
- New(ModeList);
- { The following may copy data from outside the VESA buffer, but it }
- { shouldn't get past the 1MB limit, since that would mean the buffer }
- { has been allocated in the BIOS or high memory region, which seems }
- { impossible to me (JM)}
- DosMemGet(word(longint(VESAPtr^.ModeList) shr 16),
- word(longint(VESAPtr^.ModeList) and $ffff), ModeList^,256*sizeof(word));
- { copy VESA mode information to a protected mode buffer and }
- { then free the real mode buffer... }
- Move(VESAPtr^, VESAInfo, sizeof(VESAInfo));
- If not Global_Dos_Free(word(PtrLong and $ffff)) then
- RunError(216);
- Dispose(VESAPtr);
- {$endif fpc}
- i:=0;
- new(VESAInfo.ModeList);
- while ModeList^[i]<> $ffff do
- begin
- {$ifdef logging}
- LogLn('Found mode $'+hexstr(ModeList^[i],4));
- {$endif loggin}
- VESAInfo.ModeList^[i] := ModeList^[i];
- Inc(i);
- end;
- VESAInfo.ModeList^[i]:=$ffff;
- { Free the temporary selector used to get mode information }
- {$ifdef logging}
- LogLn(strf(i) + ' modes found.');
- {$endif logging}
- {$ifndef fpc}
- FreeSelector(ModeSel);
- {$else fpc}
- Dispose(ModeList);
- {$endif fpc}
- end;
- function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;
- var
- Ptr: longint;
- {$ifndef fpc}
- VESAPtr : ^TVESAModeInfo;
- {$endif fpc}
- regs : TDPMIRegisters;
- RealSeg: word;
- begin
- { Alllocate real mode buffer }
- {$ifndef fpc}
- Ptr:=GlobalDosAlloc(sizeof(TVESAModeInfo));
- { get the selector value }
- VESAPtr := pointer(longint(Ptr shl 16));
- if not assigned(VESAPtr) then
- RunError(203);
- {$else fpc}
- Ptr:=Global_Dos_Alloc(sizeof(TVESAModeInfo));
- {$endif fpc}
- { get the segment value }
- RealSeg := word(Ptr shr 16);
- { setup interrupt registers }
- FillChar(regs, sizeof(regs), #0);
- { call VESA mode information...}
- regs.eax := $4f01;
- regs.es := RealSeg;
- regs.edi := $00;
- regs.ecx := mode;
- RealIntr($10, regs);
- if word(regs.eax) <> $4f then
- getVESAModeInfo := FALSE
- else
- getVESAModeInfo := TRUE;
- { copy to protected mode buffer ... }
- {$ifndef fpc}
- Move(VESAPtr^, ModeInfo, sizeof(ModeInfo));
- {$else fpc}
- DosMemGet(RealSeg,0,ModeInfo,sizeof(ModeInfo));
- {$endif fpc}
- { free real mode memory }
- {$ifndef fpc}
- GlobalDosFree(Word(Ptr and $ffff));
- {$else fpc}
- If not Global_Dos_Free(Word(Ptr and $ffff)) then
- RunError(216);
- {$endif fpc}
- end;
- {$ELSE}
- function getVESAInfo(var VESAInfo: TVESAInfo) : boolean; assembler;
- asm
- mov ax,4F00h
- les di,VESAInfo
- int 10h
- sub ax,004Fh {make sure we got 004Fh back}
- cmp ax,1
- sbb al,al
- cmp word ptr es:[di],'V'or('E'shl 8) {signature should be 'VESA'}
- jne @@ERR
- cmp word ptr es:[di+2],'S'or('A'shl 8)
- je @@X
- @@ERR:
- mov al,0
- @@X:
- end;
- function getVESAModeInfo(var ModeInfo: TVESAModeInfo;mode:word):boolean;assembler;
- asm
- mov ax,4F01h
- mov cx,mode
- les di,ModeInfo
- int 10h
- sub ax,004Fh {make sure it's 004Fh}
- cmp ax,1
- sbb al,al
- end;
- {$ENDIF}
- function SearchVESAModes(mode: Word): boolean;
- {********************************************************}
- { Searches for a specific DEFINED vesa mode. If the mode }
- { is not available for some reason, then returns FALSE }
- { otherwise returns TRUE. }
- {********************************************************}
- var
- i: word;
- ModeSupported : Boolean;
- begin
- i:=0;
- { let's assume it's not available ... }
- ModeSupported := FALSE;
- { This is a STUB VESA implementation }
- if VESAInfo.ModeList^[0] = $FFFF then exit;
- repeat
- if VESAInfo.ModeList^[i] = mode then
- begin
- { we found it, the card supports this mode... }
- ModeSupported := TRUE;
- break;
- end;
- Inc(i);
- until VESAInfo.ModeList^[i] = $ffff;
- { now check if the hardware supports it... }
- If ModeSupported then
- begin
- { we have to init everything to zero, since VBE < 1.1 }
- { may not setup fields correctly. }
- FillChar(VESAModeInfo, sizeof(VESAModeInfo), #0);
- If GetVESAModeInfo(VESAModeInfo, Mode) And
- ((VESAModeInfo.attr and modeAvail) <> 0) then
- ModeSupported := TRUE
- else
- ModeSupported := FALSE;
- end;
- SearchVESAModes := ModeSupported;
- end;
- procedure SetBankIndex(win: byte; BankNr: Integer); assembler;
- asm
- mov ax,4f05h
- mov bh,00h
- mov bl,[Win]
- mov dx,[BankNr]
- {$ifdef fpc}
- push ebp
- {$endif fpc}
- int 10h
- {$ifdef fpc}
- pop ebp
- {$endif fpc}
- end;
- {********************************************************}
- { There are two routines for setting banks. This may in }
- { in some cases optimize a bit some operations, if the }
- { hardware supports it, because one window is used for }
- { reading and one window is used for writing. }
- {********************************************************}
- procedure SetReadBank(BankNr: Integer);
- begin
- { check if this is the current bank... if so do nothing. }
- if BankNr = CurrentReadBank then exit;
- {$ifdef logging}
- { LogLn('Setting read bank to '+strf(BankNr));}
- {$endif logging}
- CurrentReadBank := BankNr; { save current bank number }
- BankNr := BankNr shl BankShift; { adjust to window granularity }
- { we set both banks, since one may read only }
- SetBankIndex(ReadWindow, BankNr);
- { if the hardware supports only one window }
- { then there is only one single bank, so }
- { update both bank numbers. }
- if ReadWindow = WriteWindow then
- CurrentWriteBank := CurrentReadBank;
- end;
- procedure SetWriteBank(BankNr: Integer);
- begin
- { check if this is the current bank... if so do nothing. }
- if BankNr = CurrentWriteBank then exit;
- {$ifdef logging}
- { LogLn('Setting write bank to '+strf(BankNr));}
- {$endif logging}
- CurrentWriteBank := BankNr; { save current bank number }
- BankNr := BankNr shl BankShift; { adjust to window granularity }
- { we set both banks, since one may read only }
- SetBankIndex(WriteWindow, BankNr);
- { if the hardware supports only one window }
- { then there is only one single bank, so }
- { update both bank numbers. }
- if ReadWindow = WriteWindow then
- CurrentReadBank := CurrentWriteBank;
- end;
- {************************************************************************}
- {* 8-bit pixels VESA mode routines *}
- {************************************************************************}
- procedure PutPixVESA256(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- Y := Y + YOffset; { adjust pixel for correct virtual page }
- offs := longint(y) * BytesPerLine + x;
- begin
- SetWriteBank(integer(offs shr 16));
- mem[WinWriteSeg : word(offs)] := byte(color);
- end;
- end;
- procedure DirectPutPixVESA256(x, y : integer); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- col : byte;
- begin
- offs := (longint(y) + YOffset) * BytesPerLine + x;
- Case CurrentWriteMode of
- XorPut:
- Begin
- SetReadBank(integer(offs shr 16));
- col := mem[WinReadSeg : word(offs)] xor byte(CurrentColor);
- End;
- AndPut:
- Begin
- SetReadBank(integer(offs shr 16));
- col := mem[WinReadSeg : word(offs)] And byte(CurrentColor);
- End;
- OrPut:
- Begin
- SetReadBank(integer(offs shr 16));
- col := mem[WinReadSeg : word(offs)] or byte(currentcolor);
- End
- else
- Begin
- If CurrentWriteMode <> NotPut then
- col := Byte(CurrentColor)
- else col := Not(Byte(CurrentColor));
- End
- End;
- SetWriteBank(integer(offs shr 16));
- mem[WinWriteSeg : word(offs)] := Col;
- end;
- function GetPixVESA256(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort + YOffset;
- offs := longint(y) * BytesPerLine + x;
- SetReadBank(integer(offs shr 16));
- GetPixVESA256:=mem[WinReadSeg : word(offs)];
- end;
- Procedure GetScanLineVESA256(x1, x2, y: integer; var data); {$ifndef fpc}far;{$endif}
- var offs: Longint;
- l, amount, bankrest, index, pixels: longint;
- curbank: integer;
- begin
- inc(x1,StartXViewPort);
- inc(x2,StartXViewPort);
- {$ifdef logging}
- LogLn('getscanline256 '+strf(x1)+' - '+strf(x2)+' at '+strf(y+StartYViewPort));
- {$endif logging}
- index := 0;
- amount := x2-x1+1;
- Offs:=(Longint(y)+StartYViewPort+YOffset)*bytesperline+x1;
- Repeat
- curbank := integer(offs shr 16);
- SetReadBank(curbank);
- {$ifdef logging}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
- {$endif logging}
- If ((amount >= 4) and
- ((offs and 3) = 0)) or
- (amount >= 4+4-(offs and 3)) Then
- { allign target }
- Begin
- If (offs and 3) <> 0 then
- { this cannot go past a window boundary bacause the }
- { size of a window is always a multiple of 4 }
- Begin
- {$ifdef logging}
- LogLn('Alligning by reading '+strf(4-(offs and 3))+' pixels');
- {$endif logging}
- for l := 1 to 4-(offs and 3) do
- WordArray(Data)[index+l-1] :=
- Mem[WinReadSeg:word(offs)+l-1];
- inc(index, l);
- inc(offs, l);
- dec(amount, l);
- End;
- {$ifdef logging}
- LogLn('Offset is now '+hexstr(offs,8)+', amount left: '+strf(amount));
- {$endif logging}
- { offs is now 4-bytes alligned }
- If amount <= ($10000-(Offs and $ffff)) Then
- bankrest := amount
- else {the rest won't fit anymore in the current window }
- bankrest := $10000 - (Offs and $ffff);
- { it is possible that by aligning, we ended up in a new }
- { bank, so set the correct bank again to make sure }
- setreadbank(offs shr 16);
- {$ifdef logging}
- LogLn('Rest to be read from this window: '+strf(bankrest));
- {$endif logging}
- For l := 0 to (Bankrest div 4)-1 Do
- begin
- pixels := MemL[WinWriteSeg:word(offs)+l*4];
- WordArray(Data)[index+l*4] := pixels and $ff;
- pixels := pixels shr 8;
- WordArray(Data)[index+l*4+1] := pixels and $ff;
- pixels := pixels shr 8;
- WordArray(Data)[index+l*4+2] := pixels and $ff;
- pixels := pixels shr 8;
- WordArray(Data)[index+l*4+3] := pixels{ and $ff};
- end;
- inc(index,l*4+4);
- inc(offs,l*4+4);
- dec(amount,l*4+4);
- {$ifdef logging}
- LogLn('Offset is now '+hexstr(offs,8)+', amount left: '+strf(amount));
- {$endif logging}
- End
- Else
- Begin
- {$ifdef logging}
- LogLn('Leftover: '+strf(amount)+' at offset '+hexstr(offs,8));
- {$endif logging}
- For l := 0 to amount - 1 do
- begin
- { this may cross a bank at any time, so adjust }
- { because this loop alwys runs for very little pixels, }
- { there's little gained by splitting it up }
- setreadbank(offs shr 16);
- WordArray(Data)[index+l] := mem[WinReadSeg:word(offs)];
- inc(offs);
- end;
- amount := 0
- End
- Until amount = 0;
- end;
- procedure HLineVESA256(x,x2,y: integer); {$ifndef fpc}far;{$endif fpc}
- var Offs: Longint;
- mask, l, bankrest: longint;
- curbank, hlength: integer;
- Begin
- { must we swap the values? }
- if x > x2 then
- Begin
- x := x xor x2;
- x2 := x xor x2;
- x:= x xor x2;
- end;
- { First convert to global coordinates }
- X := X + StartXViewPort;
- X2 := X2 + StartXViewPort;
- Y := Y + StartYViewPort;
- if ClipPixels then
- Begin
- if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
- StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
- exit;
- end;
- {$ifdef logging2}
- LogLn('hline '+strf(x)+' - '+strf(x2)+' on '+strf(y)+' in mode '+strf(currentwritemode));
- {$endif logging2}
- HLength := x2 - x + 1;
- {$ifdef logging2}
- LogLn('length: '+strf(hlength));
- {$endif logging2}
- if HLength>0 then
- begin
- Offs:=(Longint(y)+YOffset)*bytesperline+x;
- {$ifdef logging2}
- LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
- {$endif logging2}
- Mask := byte(CurrentColor)+byte(CurrentColor) shl 8;
- Mask := Mask + Mask shl 16;
- Case CurrentWriteMode of
- AndPut:
- Begin
- Repeat
- curbank := integer(offs shr 16);
- SetWriteBank(curbank);
- SetReadBank(curbank);
- {$ifdef logging2}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
- {$endif logging2}
- If ((HLength >= 4) and
- ((offs and 3) = 0)) or
- (HLength >= 4+4-(offs and 3)) Then
- { align target }
- Begin
- l := 0;
- If (offs and 3) <> 0 then
- { this cannot go past a window boundary bacause the }
- { size of a window is always a multiple of 4 }
- Begin
- {$ifdef logging2}
- LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
- {$endif logging2}
- for l := 1 to 4-(offs and 3) do
- Mem[WinWriteSeg:word(offs)+l-1] :=
- Mem[WinReadSeg:word(offs)+l-1] And Byte(CurrentColor);
- End;
- Dec(HLength, l);
- inc(offs, l);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
- {$endif logging}
- { offs is now 4-bytes alligned }
- If HLength <= ($10000-(Offs and $ffff)) Then
- bankrest := HLength
- else {the rest won't fit anymore in the current window }
- bankrest := $10000 - (Offs and $ffff);
- { it is possible that by aligningm we ended up in a new }
- { bank, so set the correct bank again to make sure }
- setwritebank(offs shr 16);
- setreadbank(offs shr 16);
- {$ifdef logging2}
- LogLn('Rest to be drawn in this window: '+strf(bankrest));
- {$endif logging}
- For l := 0 to (Bankrest div 4)-1 Do
- MemL[WinWriteSeg:word(offs)+l*4] :=
- MemL[WinReadSeg:word(offs)+l*4] And Mask;
- inc(offs,l*4+4);
- dec(hlength,l*4+4);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
- {$endif logging}
- End
- Else
- Begin
- {$ifdef logging2}
- LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
- {$endif logging}
- For l := 0 to HLength - 1 do
- begin
- { this may cross a bank at any time, so adjust }
- { becauese this loop alwys runs for very little pixels, }
- { there's little gained by splitting it up }
- setreadbank(offs shr 16);
- setwritebank(offs shr 16);
- Mem[WinWriteSeg:word(offs)] :=
- Mem[WinReadSeg:word(offs)] And byte(currentColor);
- inc(offs);
- end;
- HLength := 0
- End
- Until HLength = 0;
- End;
- XorPut:
- Begin
- Repeat
- curbank := integer(offs shr 16);
- SetWriteBank(curbank);
- SetReadBank(curbank);
- {$ifdef logging2}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
- {$endif logging}
- If ((HLength >= 4) and
- ((offs and 3) = 0)) or
- (HLength >= 4+4-(offs and 3)) Then
- { allign target }
- Begin
- l := 0;
- If (offs and 3) <> 0 then
- { this cannot go past a window boundary bacause the }
- { size of a window is always a multiple of 4 }
- Begin
- {$ifdef logging2}
- LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
- {$endif logging}
- for l := 1 to 4-(offs and 3) do
- Mem[WinWriteSeg:word(offs)+l-1] :=
- Mem[WinReadSeg:word(offs)+l-1] Xor Byte(CurrentColor);
- End;
- Dec(HLength, l);
- inc(offs, l);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
- {$endif logging}
- { offs is now 4-bytes alligned }
- If HLength <= ($10000-(Offs and $ffff)) Then
- bankrest := HLength
- else {the rest won't fit anymore in the current window }
- bankrest := $10000 - (Offs and $ffff);
- { it is possible that by aligningm we ended up in a new }
- { bank, so set the correct bank again to make sure }
- setwritebank(offs shr 16);
- setreadbank(offs shr 16);
- {$ifdef logging2}
- LogLn('Rest to be drawn in this window: '+strf(bankrest));
- {$endif logging}
- For l := 0 to (Bankrest div 4)-1 Do
- MemL[WinWriteSeg:word(offs)+l*4] :=
- MemL[WinReadSeg:word(offs)+l*4] Xor Mask;
- inc(offs,l*4+4);
- dec(hlength,l*4+4);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
- {$endif logging}
- End
- Else
- Begin
- {$ifdef logging2}
- LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
- {$endif logging}
- For l := 0 to HLength - 1 do
- begin
- { this may cross a bank at any time, so adjust }
- { because this loop alwys runs for very little pixels, }
- { there's little gained by splitting it up }
- setreadbank(offs shr 16);
- setwritebank(offs shr 16);
- Mem[WinWriteSeg:word(offs)] :=
- Mem[WinReadSeg:word(offs)] xor byte(currentColor);
- inc(offs);
- end;
- HLength := 0
- End
- Until HLength = 0;
- End;
- OrPut:
- Begin
- Repeat
- curbank := integer(offs shr 16);
- SetWriteBank(curbank);
- SetReadBank(curbank);
- {$ifdef logging2}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
- {$endif logging}
- If ((HLength >= 4) and
- ((offs and 3) = 0)) or
- (HLength >= 4+4-(offs and 3)) Then
- { allign target }
- Begin
- l := 0;
- If (offs and 3) <> 0 then
- { this cannot go past a window boundary bacause the }
- { size of a window is always a multiple of 4 }
- Begin
- {$ifdef logging2}
- LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
- {$endif logging}
- for l := 1 to 4-(offs and 3) do
- Mem[WinWriteSeg:word(offs)+l-1] :=
- Mem[WinReadSeg:word(offs)+l-1] Or Byte(CurrentColor);
- End;
- Dec(HLength, l);
- inc(offs, l);
- { it is possible that by aligningm we ended up in a new }
- { bank, so set the correct bank again to make sure }
- setwritebank(offs shr 16);
- setreadbank(offs shr 16);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
- {$endif logging}
- { offs is now 4-bytes alligned }
- If HLength <= ($10000-(Offs and $ffff)) Then
- bankrest := HLength
- else {the rest won't fit anymore in the current window }
- bankrest := $10000 - (Offs and $ffff);
- {$ifdef logging2}
- LogLn('Rest to be drawn in this window: '+strf(bankrest));
- {$endif logging}
- For l := 0 to (Bankrest div 4)-1 Do
- MemL[WinWriteSeg:offs+l*4] :=
- MemL[WinReadSeg:word(offs)+l*4] Or Mask;
- inc(offs,l*4+4);
- dec(hlength,l*4+4);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
- {$endif logging}
- End
- Else
- Begin
- {$ifdef logging2}
- LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
- {$endif logging}
- For l := 0 to HLength - 1 do
- begin
- { this may cross a bank at any time, so adjust }
- { because this loop alwys runs for very little pixels, }
- { there's little gained by splitting it up }
- setreadbank(offs shr 16);
- setwritebank(offs shr 16);
- Mem[WinWriteSeg:word(offs)] :=
- Mem[WinReadSeg:word(offs)] And byte(currentColor);
- inc(offs);
- end;
- HLength := 0
- End
- Until HLength = 0;
- End
- Else
- Begin
- If CurrentWriteMode = NotPut Then
- Mask := Not(Mask);
- Repeat
- curbank := integer(offs shr 16);
- SetWriteBank(curbank);
- {$ifdef logging2}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)+' -- '+strf(offs));
- {$endif logging}
- If ((HLength >= 4) and
- ((offs and 3) = 0)) or
- (HLength >= 4+4-(offs and 3)) Then
- { allign target }
- Begin
- l := 0;
- If (offs and 3) <> 0 then
- { this cannot go past a window boundary bacause the }
- { size of a window is always a multiple of 4 }
- Begin
- {$ifdef logging2}
- LogLn('Alligning by drawing '+strf(4-(offs and 3))+' pixels');
- {$endif logging}
- for l := 1 to 4-(offs and 3) do
- Mem[WinWriteSeg:word(offs)+l-1] := Byte(Mask);
- End;
- Dec(HLength, l);
- inc(offs, l);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
- {$endif logging}
- { offs is now 4-bytes alligned }
- If HLength <= ($10000-(Offs and $ffff)) Then
- bankrest := HLength
- else {the rest won't fit anymore in the current window }
- bankrest := $10000 - (Offs and $ffff);
- { it is possible that by aligningm we ended up in a new }
- { bank, so set the correct bank again to make sure }
- setwritebank(offs shr 16);
- {$ifdef logging2}
- LogLn('Rest to be drawn in this window: '+strf(bankrest)+' -- '+hexstr(bankrest,8));
- {$endif logging}
- For l := 0 to (Bankrest div 4)-1 Do
- MemL[WinWriteSeg:word(offs)+l*4] := Mask;
- inc(offs,l*4+4);
- dec(hlength,l*4+4);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength));
- {$endif logging}
- End
- Else
- Begin
- {$ifdef logging2}
- LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8));
- {$endif logging}
- For l := 0 to HLength - 1 do
- begin
- { this may cross a bank at any time, so adjust }
- { because this loop alwys runs for very little pixels, }
- { there's little gained by splitting it up }
- setwritebank(offs shr 16);
- Mem[WinWriteSeg:word(offs)] := byte(mask);
- inc(offs);
- end;
- HLength := 0
- End
- Until HLength = 0;
- End;
- End;
- end;
- end;
- procedure VLineVESA256(x,y,y2: integer); {$ifndef fpc}far;{$endif fpc}
- var Offs: Longint;
- l, bankrest: longint;
- curbank, vlength: integer;
- col: byte;
- Begin
- { must we swap the values? }
- if y > y2 then
- Begin
- y := y xor y2;
- y2 := y xor y2;
- y:= y xor y2;
- end;
- { First convert to global coordinates }
- X := X + StartXViewPort;
- Y := Y + StartYViewPort;
- Y2 := Y2 + StartYViewPort;
- if ClipPixels then
- Begin
- if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
- StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
- exit;
- end;
- Col := Byte(CurrentColor);
- {$ifdef logging2}
- LogLn('vline '+strf(y)+' - '+strf(y2)+' on '+strf(x)+' in mode '+strf(currentwritemode));
- {$endif logging}
- VLength := y2 - y + 1;
- {$ifdef logging2}
- LogLn('length: '+strf(vlength));
- {$endif logging}
- if VLength>0 then
- begin
- Offs:=(Longint(y)+YOffset)*bytesperline+x;
- {$ifdef logging2}
- LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8));
- {$endif logging}
- Case CurrentWriteMode of
- AndPut:
- Begin
- Repeat
- curbank := integer(offs shr 16);
- SetWriteBank(curbank);
- SetReadBank(curbank);
- {$ifdef logging2}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
- {$endif logging}
- If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
- bankrest := VLength
- else {the rest won't fit anymore in the current window }
- bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
- {$ifdef logging2}
- LogLn('Rest to be drawn in this window: '+strf(bankrest));
- {$endif logging}
- For l := 0 to Bankrest-1 Do
- begin
- Mem[WinWriteSeg:word(offs)] :=
- Mem[WinReadSeg:word(offs)] And Col;
- inc(offs,bytesperline);
- end;
- dec(VLength,l+1);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
- {$endif logging}
- Until VLength = 0;
- End;
- XorPut:
- Begin
- Repeat
- curbank := integer(offs shr 16);
- SetWriteBank(curbank);
- SetReadBank(curbank);
- {$ifdef logging2}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
- {$endif logging}
- If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
- bankrest := VLength
- else {the rest won't fit anymore in the current window }
- bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
- {$ifdef logging2}
- LogLn('Rest to be drawn in this window: '+strf(bankrest));
- {$endif logging}
- For l := 0 to Bankrest-1 Do
- begin
- Mem[WinWriteSeg:word(offs)] :=
- Mem[WinReadSeg:word(offs)] Xor Col;
- inc(offs,bytesperline);
- end;
- dec(VLength,l+1);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
- {$endif logging}
- Until VLength = 0;
- End;
- OrPut:
- Begin
- Repeat
- curbank := integer(offs shr 16);
- SetWriteBank(curbank);
- SetReadBank(curbank);
- {$ifdef logging2}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
- {$endif logging}
- If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
- bankrest := VLength
- else {the rest won't fit anymore in the current window }
- bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
- {$ifdef logging2}
- LogLn('Rest to be drawn in this window: '+strf(bankrest));
- {$endif logging}
- For l := 0 to Bankrest-1 Do
- begin
- Mem[WinWriteSeg:word(offs)] :=
- Mem[WinReadSeg:word(offs)] Or Col;
- inc(offs,bytesperline);
- end;
- dec(VLength,l+1);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
- {$endif logging}
- Until VLength = 0;
- End;
- Else
- Begin
- If CurrentWriteMode = NotPut Then
- Col := Not(Col);
- Repeat
- curbank := integer(offs shr 16);
- SetWriteBank(curbank);
- {$ifdef logging2}
- LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
- {$endif logging}
- If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
- bankrest := VLength
- else {the rest won't fit anymore in the current window }
- bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
- {$ifdef logging2}
- LogLn('Rest to be drawn in this window: '+strf(bankrest));
- {$endif logging}
- For l := 0 to Bankrest-1 Do
- begin
- Mem[WinWriteSeg:word(offs)] := Col;
- inc(offs,bytesperline);
- end;
- dec(VLength,l+1);
- {$ifdef logging2}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(vlength));
- {$endif logging}
- Until VLength = 0;
- End;
- End;
- end;
- end;
- procedure PatternLineVESA256(x1,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
- {********************************************************}
- { Draws a horizontal patterned line according to the }
- { current Fill Settings. }
- {********************************************************}
- { Important notes: }
- { - CurrentColor must be set correctly before entering }
- { this routine. }
- {********************************************************}
- type
- TVESA256Fill = Record
- case byte of
- 0: (data1, data2: longint);
- 1: (pat: array[0..7] of byte);
- end;
- var
- fill: TVESA256Fill;
- bankrest, l : longint;
- offs, amount: longint;
- i : smallint;
- j : smallint;
- OldWriteMode : word;
- TmpFillPattern, patternPos : byte;
- begin
- { convert to global coordinates ... }
- x1 := x1 + StartXViewPort;
- x2 := x2 + StartXViewPort;
- y := y + StartYViewPort;
- { if line was fully clipped then exit...}
- if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort,
- StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
- exit;
- OldWriteMode := CurrentWriteMode;
- CurrentWriteMode := NormalPut;
- { Get the current pattern }
- TmpFillPattern := FillPatternTable
- [FillSettings.Pattern][((y + startYViewPort) and $7)+1];
- {$ifdef logging}
- LogLn('patternline '+strf(x1)+' - '+strf(x2)+' on '+strf(y));
- {$endif logging}
- { how long is the line }
- amount := x2 - x1 + 1;
- { offset to start at }
- offs := (longint(y)+yoffset)*bytesperline+x1;
- { convert the pattern data into the actual color sequence }
- j := 1;
- FillChar(fill,sizeOf(fill),byte(currentBkColor));
- for i := 0 to 7 do
- begin
- if TmpFillPattern and j <> 0 then
- fill.pat[7-i] := currentColor;
- {$ifopt q+}
- {$q-}
- {$define overflowOn}
- {$endif}
- j := j shl 1;
- {$ifdef overflowOn}
- {$q+}
- {$undef overflowOn}
- {$endif}
- end;
- Repeat
- SetWriteBank(integer(offs shr 16));
- If (amount > 7) and
- (((offs and 7) = 0) or
- (amount > 7+8-(offs and 7))) Then
- Begin
- { align target }
- l := 0;
- If (offs and 7) <> 0 then
- { this cannot go past a window boundary bacause the }
- { size of a window is always a multiple of 8 }
- Begin
- { position in the pattern where to start }
- patternPos := offs and 7;
- {$ifdef logging}
- LogLn('Aligning by drawing '+strf(8-(offs and 7))+' pixels');
- {$endif logging}
- for l := 1 to 8-(offs and 7) do
- begin
- Mem[WinWriteSeg:word(offs)+l-1] := fill.pat[patternPos and 7];
- inc(patternPos)
- end;
- End;
- Dec(amount, l);
- inc(offs, l);
- {$ifdef logging}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(amount));
- {$endif logging}
- { offs is now 8-bytes alligned }
- If amount <= ($10000-(Offs and $ffff)) Then
- bankrest := amount
- else {the rest won't fit anymore in the current window }
- bankrest := $10000 - (Offs and $ffff);
- { it is possible that by aligningm we ended up in a new }
- { bank, so set the correct bank again to make sure }
- setwritebank(offs shr 16);
- {$ifdef logging}
- LogLn('Rest to be drawn in this window: '+strf(bankrest));
- {$endif logging}
- for l := 0 to (bankrest div 8)-1 Do
- begin
- MemL[WinWriteSeg:word(offs)+l*8] := fill.data1;
- MemL[WinWriteSeg:word(offs)+l*8+4] := fill.data2;
- end;
- inc(offs,l*8+8);
- dec(amount,l*8+8);
- {$ifdef logging}
- LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(amount));
- {$endif logging}
- End
- Else
- Begin
- {$ifdef logging}
- LogLn('Drawing leftover: '+strf(amount)+' at offset '+hexstr(offs,8));
- {$endif logging}
- patternPos := offs and 7;
- For l := 0 to amount - 1 do
- begin
- { this may cross a bank at any time, so adjust }
- { because this loop alwys runs for very little pixels, }
- { there's little gained by splitting it up }
- setwritebank(offs shr 16);
- Mem[WinWriteSeg:word(offs)] := fill.pat[patternPos and 7];
- inc(offs);
- inc(patternPos);
- end;
- amount := 0;
- End
- Until amount = 0;
- currentWriteMode := oldWriteMode;
- end;
- {************************************************************************}
- {* 256 colors VESA mode routines Linear mode *}
- {************************************************************************}
- {$ifdef FPC}
- procedure DirectPutPixVESA256Linear(x, y : integer); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- col : byte;
- begin
- offs := longint(y) * BytesPerLine + x;
- Case CurrentWriteMode of
- XorPut:
- Begin
- seg_move(WinReadSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
- col := col xor byte(CurrentColor);
- End;
- AndPut:
- Begin
- seg_move(WinReadSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
- col := col and byte(CurrentColor);
- End;
- OrPut:
- Begin
- seg_move(WinReadSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
- col := col or byte(CurrentColor);
- End
- else
- Begin
- If CurrentWriteMode <> NotPut then
- col := Byte(CurrentColor)
- else col := Not(Byte(CurrentColor));
- End
- End;
- seg_move(get_ds,longint(@col),WinWriteSeg,offs+LinearPageOfs,1);
- end;
- procedure PutPixVESA256Linear(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- offs := longint(y) * BytesPerLine + x;
- seg_move(get_ds,longint(@color),WinWriteSeg,offs+LinearPageOfs,1);
- end;
- function GetPixVESA256Linear(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- col : byte;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- offs := longint(y) * BytesPerLine + x;
- seg_move(WinReadSeg,offs+LinearPageOfs,get_ds,longint(@col),1);
- GetPixVESA256Linear:=col;
- end;
- (*
- function SetVESADisplayStart(PageNum : word;x,y : integer):Boolean;
- var
- dregs : registers;
- begin
- if PageNum>VesaModeInfo.NumberOfPages then
- PageNum:=0;
- {$ifdef DEBUG}
- if PageNum>0 then
- writeln(stderr,'Setting Display Page ',PageNum);
- {$endif DEBUG}
- dregs.RealEBX:=0{ $80 for Wait for retrace };
- dregs.RealECX:=x;
- dregs.RealEDX:=y+PageNum*maxy;
- dregs.RealSP:=0;
- dregs.RealSS:=0;
- dregs.RealEAX:=$4F07; RealIntr($10,dregs);
- { idem as above !!! }
- if (dregs.RealEAX and $1FF) <> $4F then
- begin
- {$ifdef DEBUG}
- writeln(stderr,'Set Display start error');
- {$endif DEBUG}
- SetVESADisplayStart:=false;
- end
- else
- SetVESADisplayStart:=true;
- end;
- *)
- {$endif FPC}
- {************************************************************************}
- {* 15/16bit pixels VESA mode routines *}
- {************************************************************************}
- procedure PutPixVESA32kOr64k(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- Y := Y + YOffset; { adjust pixel for correct virtual page }
- offs := longint(y) * BytesPerLine + 2*x;
- SetWriteBank(integer(offs shr 16));
- memW[WinWriteSeg : word(offs)] := color;
- end;
- function GetPixVESA32kOr64k(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort + YOffset;
- offs := longint(y) * BytesPerLine + 2*x;
- SetReadBank(integer(offs shr 16));
- GetPixVESA32kOr64k:=memW[WinReadSeg : word(offs)];
- end;
- procedure DirectPutPixVESA32kOr64k(x, y : integer); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- col : word;
- begin
- y:= Y + YOffset;
- offs := longint(y) * BytesPerLine + 2*x;
- SetWriteBank(integer((offs shr 16) and $ff));
- Case CurrentWriteMode of
- XorPut:
- Begin
- SetReadBank(integer(offs shr 16));
- memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] xor currentcolor;
- End;
- AndPut:
- Begin
- SetReadBank(integer(offs shr 16));
- memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] And currentcolor;
- End;
- OrPut:
- Begin
- SetReadBank(integer(offs shr 16));
- memW[WinWriteSeg : word(offs)] := memW[WinReadSeg : word(offs)] or currentcolor;
- End
- else
- Begin
- If CurrentWriteMode <> NotPut Then
- col := CurrentColor
- Else col := Not(CurrentColor);
- memW[WinWriteSeg : word(offs)] := Col;
- End
- End;
- end;
- {$ifdef FPC}
- {************************************************************************}
- {* 15/16bit pixels VESA mode routines Linear mode *}
- {************************************************************************}
- procedure PutPixVESA32kor64kLinear(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- offs := longint(y) * BytesPerLine + 2*x;
- seg_move(get_ds,longint(@color),WinWriteSeg,offs+LinearPageOfs,2);
- end;
- function GetPixVESA32kor64kLinear(x, y : integer): word; {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- color : word;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- offs := longint(y) * BytesPerLine + 2*x;
- seg_move(WinReadSeg,offs+LinearPageOfs,get_ds,longint(@color),2);
- GetPixVESA32kor64kLinear:=color;
- end;
- procedure DirectPutPixVESA32kor64kLinear(x, y : integer); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- col : word;
- begin
- offs := longint(y) * BytesPerLine + 2*x;
- Case CurrentWriteMode of
- XorPut:
- Begin
- seg_move(WinReadSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
- col := col xor currentcolor;
- End;
- AndPut:
- Begin
- seg_move(WinReadSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
- col := col and currentcolor;
- End;
- OrPut:
- Begin
- seg_move(WinReadSeg,offs+LinearPageOfs,get_ds,longint(@col),2);
- col := col or currentcolor;
- End
- else
- Begin
- If CurrentWriteMode <> NotPut Then
- col := CurrentColor
- Else col := Not(CurrentColor);
- End
- End;
- seg_move(get_ds,longint(@col),WinWriteSeg,offs+LinearPageOfs,2);
- end;
- {$endif FPC}
- {************************************************************************}
- {* 4-bit pixels VESA mode routines *}
- {************************************************************************}
- procedure PutPixVESA16(x, y : integer; color : word); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- dummy : byte;
- begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort;
- { convert to absolute coordinates and then verify clipping...}
- if ClipPixels then
- Begin
- if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
- exit;
- if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
- exit;
- end;
- Y := Y + YOffset; { adjust pixel for correct virtual page }
- { }
- offs := longint(y) * BytesPerLine + (x div 8);
- SetWriteBank(integer(offs shr 16));
- PortW[$3ce] := $0f01; { Index 01 : Enable ops on all 4 planes }
- PortW[$3ce] := color shl 8; { Index 00 : Enable correct plane and write color }
- Port[$3ce] := 8; { Index 08 : Bitmask register. }
- Port[$3cf] := $80 shr (x and $7); { Select correct bits to modify }
- dummy := Mem[WinWriteSeg: offs]; { Latch the data into host space. }
- Mem[WinWriteSeg: offs] := dummy; { Write the data into video memory }
- PortW[$3ce] := $ff08; { Enable all bit planes. }
- PortW[$3ce] := $0001; { Index 01 : Disable ops on all four planes. }
- { }
- end;
- Function GetPixVESA16(X,Y: Integer):word; {$ifndef fpc}far;{$endif fpc}
- Var dummy, offset: Word;
- shift: byte;
- Begin
- X:= X + StartXViewPort;
- Y:= Y + StartYViewPort + YOffset;
- offset := longint(Y) * BytesPerLine + (x div 8);
- SetReadBank(integer(offset shr 16));
- Port[$3ce] := 4;
- shift := 7 - (X and 7);
- Port[$3cf] := 0;
- dummy := (Mem[WinReadSeg:offset] shr shift) and 1;
- Port[$3cf] := 1;
- dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 1);
- Port[$3cf] := 2;
- dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 2);
- Port[$3cf] := 3;
- dummy := dummy or (((Mem[WinReadSeg:offset] shr shift) and 1) shl 3);
- GetPixVESA16 := dummy;
- end;
- procedure DirectPutPixVESA16(x, y : integer); {$ifndef fpc}far;{$endif fpc}
- var
- offs : longint;
- dummy : byte;
- Color : word;
- begin
- y:= Y + YOffset;
- case CurrentWriteMode of
- XORPut:
- begin
- { getpixel wants local/relative coordinates }
- Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
- Color := CurrentColor Xor Color;
- end;
- OrPut:
- begin
- { getpixel wants local/relative coordinates }
- Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
- Color := CurrentColor Or Color;
- end;
- AndPut:
- begin
- { getpixel wants local/relative coordinates }
- Color := GetPixVESA16(x-StartXViewPort,y-StartYViewPort);
- Color := CurrentColor And Color;
- end;
- NotPut:
- begin
- Color := Not Color;
- end
- else
- Color := CurrentColor;
- end;
- offs := longint(y) * BytesPerLine + (x div 8);
- SetWriteBank(integer(offs shr 16));
- PortW[$3ce] := $0f01; { Index 01 : Enable ops on all 4 planes }
- PortW[$3ce] := color shl 8; { Index 00 : Enable correct plane and write color }
- Port[$3ce] := 8; { Index 08 : Bitmask register. }
- Port[$3cf] := $80 shr (x and $7); { Select correct bits to modify }
- dummy := Mem[WinWriteSeg: offs]; { Latch the data into host space. }
- Mem[WinWriteSeg: offs] := dummy; { Write the data into video memory }
- PortW[$3ce] := $ff08; { Enable all bit planes. }
- PortW[$3ce] := $0001; { Index 01 : Disable ops on all four planes. }
- end;
- {************************************************************************}
- {* VESA Palette entries *}
- {************************************************************************}
- {$IFDEF DPMI}
- Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
- BlueValue : Integer);
- var
- pal: palrec;
- regs: TDPMIRegisters;
- Ptr: longint;
- {$ifndef fpc}
- PalPtr : ^PalRec;
- {$endif fpc}
- RealSeg: word;
- FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
- begin
- if DirectColor then
- Begin
- _GraphResult := grError;
- exit;
- end;
- pal.align := 0;
- pal.red := byte(RedValue);
- pal.green := byte(GreenValue);
- pal.blue := byte(BlueValue);
- { use the set/get palette function }
- if VESAInfo.Version >= $0200 then
- Begin
- { check if blanking bit must be set when programming }
- { the RAMDAC. }
- if (VESAInfo.caps and attrSnowCheck) <> 0 then
- FunctionNr := $80
- else
- FunctionNr := $00;
- { Alllocate real mode buffer }
- {$ifndef fpc}
- Ptr:=GlobalDosAlloc(sizeof(palrec));
- { get the selector values }
- PalPtr := pointer(Ptr shl 16);
- if not assigned(PalPtr) then
- RunError(203);
- {$else fpc}
- Ptr:=Global_Dos_Alloc(sizeof(palrec));
- {$endif fpc}
- {get the segment value}
- RealSeg := word(Ptr shr 16);
- { setup interrupt registers }
- FillChar(regs, sizeof(regs), #0);
- { copy palette values to real mode buffer }
- {$ifndef fpc}
- move(pal, palptr^, sizeof(pal));
- {$else fpc}
- DosMemPut(RealSeg,0,pal,sizeof(pal));
- {$endif fpc}
- regs.eax := $4F09;
- regs.ebx := FunctionNr;
- regs.ecx := $01;
- regs.edx := ColorNum;
- regs.es := RealSeg;
- regs.edi := 0; { offset is always zero }
- RealIntr($10, regs);
- { free real mode memory }
- {$ifndef fpc}
- GlobalDosFree(word(Ptr and $ffff));
- {$else fpc}
- If not Global_Dos_Free(word(Ptr and $ffff)) then
- RunError(216);
- {$endif fpc}
- if word(regs.eax) <> $004F then
- begin
- _GraphResult := grError;
- exit;
- end;
- end
- else
- { assume it's fully VGA compatible palette-wise. }
- Begin
- SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
- end;
- end;
- Procedure GetVESARGBPalette(ColorNum: integer; Var
- RedValue, GreenValue, BlueValue : integer);
- var
- pal: PalRec;
- {$ifndef fpc}
- palptr : ^PalRec;
- {$endif fpc}
- regs : TDPMIRegisters;
- RealSeg: word;
- ptr: longint;
- begin
- if DirectColor then
- Begin
- _GraphResult := grError;
- exit;
- end;
- { use the set/get palette function }
- if VESAInfo.Version >= $0200 then
- Begin
- { Alllocate real mode buffer }
- {$ifndef fpc}
- Ptr:=GlobalDosAlloc(sizeof(palrec));
- { get the selector value }
- PalPtr := pointer(longint(Ptr and $0000ffff) shl 16);
- if not assigned(PalPtr) then
- RunError(203);
- {$else fpc}
- Ptr:=Global_Dos_Alloc(sizeof(palrec));
- {$endif fpc}
- { get the segment value }
- RealSeg := word(Ptr shr 16);
- { setup interrupt registers }
- FillChar(regs, sizeof(regs), #0);
- regs.eax := $4F09;
- regs.ebx := $01; { get palette data }
- regs.ecx := $01;
- regs.edx := ColorNum;
- regs.es := RealSeg;
- regs.edi := 0; { offset is always zero }
- RealIntr($10, regs);
- { copy to protected mode buffer ... }
- {$ifndef fpc}
- Move(PalPtr^, Pal, sizeof(pal));
- {$else fpc}
- DosMemGet(RealSeg,0,Pal,sizeof(pal));
- {$endif fpc}
- { free real mode memory }
- {$ifndef fpc}
- GlobalDosFree(word(Ptr and $ffff));
- {$else fpc}
- If not Global_Dos_Free(word(Ptr and $ffff)) then
- RunError(216);
- {$endif fpc}
- if word(regs.eax) <> $004F then
- begin
- _GraphResult := grError;
- exit;
- end
- else
- begin
- RedValue := Integer(pal.Red);
- GreenValue := Integer(pal.Green);
- BlueValue := Integer(pal.Blue);
- end;
- end
- else
- GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
- end;
- {$ELSE}
- Procedure SetVESARGBPalette(ColorNum, RedValue, GreenValue,
- BlueValue : Integer); far;
- var
- FunctionNr : byte; { use blankbit or normal RAMDAC programming? }
- pal: ^palrec;
- Error : boolean; { VBE call error }
- begin
- if DirectColor then
- Begin
- _GraphResult := grError;
- exit;
- end;
- Error := FALSE;
- new(pal);
- if not assigned(pal) then RunError(203);
- pal^.align := 0;
- pal^.red := byte(RedValue);
- pal^.green := byte(GreenValue);
- pal^.blue := byte(BlueValue);
- { use the set/get palette function }
- if VESAInfo.Version >= $0200 then
- Begin
- { check if blanking bit must be set when programming }
- { the RAMDAC. }
- if (VESAInfo.caps and attrSnowCheck) <> 0 then
- FunctionNr := $80
- else
- FunctionNr := $00;
- asm
- mov ax, 4F09h { Set/Get Palette data }
- mov bl, [FunctionNr] { Set palette data }
- mov cx, 01h { update one palette reg. }
- mov dx, [ColorNum] { register number to update }
- les di, [pal] { get palette address }
- int 10h
- cmp ax, 004Fh { check if success }
- jz @noerror
- mov [Error], TRUE
- @noerror:
- end;
- if not Error then
- Dispose(pal)
- else
- begin
- _GraphResult := grError;
- exit;
- end;
- end
- else
- { assume it's fully VGA compatible palette-wise. }
- Begin
- SetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
- end;
- end;
- Procedure GetVESARGBPalette(ColorNum: integer; Var RedValue, GreenValue,
- BlueValue : integer); far;
- var
- Error: boolean;
- pal: ^palrec;
- begin
- if DirectColor then
- Begin
- _GraphResult := grError;
- exit;
- end;
- Error := FALSE;
- new(pal);
- if not assigned(pal) then RunError(203);
- FillChar(pal^, sizeof(palrec), #0);
- { use the set/get palette function }
- if VESAInfo.Version >= $0200 then
- Begin
- asm
- mov ax, 4F09h { Set/Get Palette data }
- mov bl, 01h { Set palette data }
- mov cx, 01h { update one palette reg. }
- mov dx, [ColorNum] { register number to update }
- les di, [pal] { get palette address }
- int 10h
- cmp ax, 004Fh { check if success }
- jz @noerror
- mov [Error], TRUE
- @noerror:
- end;
- if not Error then
- begin
- RedValue := Integer(pal^.Red);
- GreenValue := Integer(pal^.Green);
- BlueValue := Integer(pal^.Blue);
- Dispose(pal);
- end
- else
- begin
- _GraphResult := grError;
- exit;
- end;
- end
- else
- GetVGARGBPalette(ColorNum, RedValue, GreenValue, BlueValue);
- end;
- {$ENDIF}
- function SetupLinear(var ModeInfo: TVESAModeInfo;mode : word) : boolean;
- begin
- {$ifndef FPC}
- { !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! }
- SetUpLinear:=false;
- {$else FPC}
- case mode of
- m320x200x32k,
- m320x200x64k,
- m640x480x32k,
- m640x480x64k,
- m800x600x32k,
- m800x600x64k,
- m1024x768x32k,
- m1024x768x64k,
- m1280x1024x32k,
- m1280x1024x64k :
- begin
- DirectPutPixel:=@DirectPutPixVESA32kor64kLinear;
- PutPixel:=@PutPixVESA32kor64kLinear;
- GetPixel:=@GetPixVESA32kor64kLinear;
- { linear mode for lines not yet implemented PM }
- HLine:=@HLineDefault;
- VLine:=@VLineDefault;
- end;
- m640x400x256,
- m640x480x256,
- m800x600x256,
- m1024x768x256,
- m1280x1024x256:
- begin
- DirectPutPixel:=@DirectPutPixVESA256Linear;
- PutPixel:=@PutPixVESA256Linear;
- GetPixel:=@GetPixVESA256Linear;
- { linear mode for lines not yet implemented PM }
- HLine:=@HLineDefault;
- VLine:=@VLineDefault;
- end;
- else
- begin
- SetUpLinear:=false;
- exit;
- end;
- end;
- FrameBufferLinearAddress:=Get_linear_addr(VESAModeInfo.PhysAddress and $FFFF0000,
- VESAInfo.TotalMem shl 16);
- if int31error<>0 then
- writeln(stderr,'Unable to get linear address for ',hexstr(VESAModeInfo.PhysAddress,8));
- set_segment_base_address(WinWriteSeg,FrameBufferLinearAddress);
- set_segment_limit(WinWriteSeg,(VESAInfo.TotalMem shl 16)-1);
- set_segment_base_address(WinReadSeg,FrameBufferLinearAddress);
- set_segment_limit(WinReadSeg,(VESAInfo.TotalMem shl 16)-1);
- InLinear:=true;
- SetUpLinear:=true;
- { WinSize:=(VGAInfo.TotalMem shl 16);
- WinLoMask:=(VGAInfo.TotalMem shl 16)-1;
- WinShift:=15;
- Temp:=VGAInfo.TotalMem;
- while Temp>0 do
- begin
- inc(WinShift);
- Temp:=Temp shr 1;
- end; }
- {$endif FPC}
- end;
- procedure SetupWindows(var ModeInfo: TVESAModeInfo);
- begin
- InLinear:=false;
- { now we check the windowing scheme ...}
- if (ModeInfo.WinAAttr and WinSupported) <> 0 then
- { is this window supported ... }
- begin
- { now check if the window is R/W }
- if (ModeInfo.WinAAttr and WinReadable) <> 0 then
- begin
- ReadWindow := 0;
- WinReadSeg := ModeInfo.WinASeg;
- end;
- if (ModeInfo.WinAAttr and WinWritable) <> 0 then
- begin
- WriteWindow := 0;
- WinWriteSeg := ModeInfo.WinASeg;
- end;
- end;
- if (ModeInfo.WinBAttr and WinSupported) <> 0 then
- { is this window supported ... }
- begin
- { OPTIMIZATION ... }
- { if window A supports both read/write, then we try to optimize }
- { everything, by using a different window for Read and/or write.}
- if (WinReadSeg <> 0) and (WinWriteSeg <> 0) then
- begin
- { check if winB supports read }
- if (ModeInfo.WinBAttr and winReadable) <> 0 then
- begin
- WinReadSeg := ModeInfo.WinBSeg;
- ReadWindow := 1;
- end
- else
- { check if WinB supports write }
- if (ModeInfo.WinBAttr and WinWritable) <> 0 then
- begin
- WinWriteSeg := ModeInfo.WinBSeg;
- WriteWindow := 1;
- end;
- end
- else
- { Window A only supported Read OR Write, no we have to make }
- { sure that window B supports the other mode. }
- if (WinReadSeg = 0) and (WinWriteSeg<>0) then
- begin
- if (ModeInfo.WinBAttr and WinReadable <> 0) then
- begin
- ReadWindow := 1;
- WinReadSeg := ModeInfo.WinBSeg;
- end
- else
- { impossible, this VESA mode is WRITE only! }
- begin
- WriteLn('Invalid VESA Window attribute.');
- Halt(255);
- end;
- end
- else
- if (winWriteSeg = 0) and (WinReadSeg<>0) then
- begin
- if (ModeInfo.WinBAttr and WinWritable) <> 0 then
- begin
- WriteWindow := 1;
- WinWriteSeg := ModeInfo.WinBSeg;
- end
- else
- { impossible, this VESA mode is READ only! }
- begin
- WriteLn('Invalid VESA Window attribute.');
- Halt(255);
- end;
- end
- else
- if (winReadSeg = 0) and (winWriteSeg = 0) then
- { no read/write in this mode! }
- begin
- WriteLn('Invalid VESA Window attribute.');
- Halt(255);
- end;
- end;
- { if both windows are not supported, then we can assume }
- { that there is ONE single NON relocatable window. }
- if (WinWriteSeg = 0) and (WinReadSeg = 0) then
- begin
- WinWriteSeg := ModeInfo.WinASeg;
- WinReadSeg := ModeInfo.WinASeg;
- end;
- { 16-bit Protected mode checking code... }
- { change segment values to protected mode }
- { selectors. }
- if WinReadSeg = $A000 then
- WinReadSeg := SegA000
- else
- if WinReadSeg = $B000 then
- WinReadSeg := SegB000
- else
- if WinReadSeg = $B800 then
- WinReadSeg := SegB800
- else
- begin
- WriteLn('Invalid segment address.');
- Halt(255);
- end;
- if WinWriteSeg = $A000 then
- WinWriteSeg := SegA000
- else
- if WinWriteSeg = $B000 then
- WinWriteSeg := SegB000
- else
- if WinWriteSeg = $B800 then
- WinWriteSeg := SegB800
- else
- begin
- WriteLn('Invalid segment address.');
- Halt(255);
- end;
- end;
- function setVESAMode(mode:word):boolean;
- var i:word;
- begin
- { Init mode information, for compatibility with VBE < 1.1 }
- FillChar(VESAModeInfo, sizeof(TVESAModeInfo), #0);
- { get the video mode information }
- if getVESAModeInfo(VESAmodeinfo, mode) then
- begin
- { checks if the hardware supports the video mode. }
- if (VESAModeInfo.attr and modeAvail) = 0 then
- begin
- SetVESAmode := FALSE;
- _GraphResult := grError;
- exit;
- end;
- SetVESAMode := TRUE;
- BankShift := 0;
- while (64 shr BankShift) <> VESAModeInfo.WinGranularity do
- Inc(BankShift);
- CurrentWriteBank := -1;
- CurrentReadBank := -1;
- BytesPerLine := VESAModeInfo.BytesPerScanLine;
- { These are the window adresses ... }
- WinWriteSeg := 0; { This is the segment to use for writes }
- WinReadSeg := 0; { This is the segment to use for reads }
- ReadWindow := 0;
- WriteWindow := 0;
- { VBE 2.0 and higher supports >= non VGA linear buffer types...}
- { this is backward compatible. }
- if ((VESAModeInfo.Attr and ModeNoWindowed) <> 0) and
- ((VESAModeInfo.Attr and ModeLinearBuffer) <> 0) then
- begin
- if not SetupLinear(VESAModeInfo,mode) then
- SetUpWindows(VESAModeInfo);
- end
- else
- { if linear and windowed is supported, then use windowed }
- { method. }
- SetUpWindows(VESAModeInfo);
- {$ifdef logging}
- LogLn('Entering vesa mode '+strf(mode));
- LogLn('Read segment: $'+hexstr(winreadseg,4));
- LogLn('Write segment: $'+hexstr(winwriteseg,4));
- LogLn('Window granularity: '+strf(VESAModeInfo.WinGranularity)+'kb');
- LogLn('Window size: '+strf(VESAModeInfo.winSize)+'kb');
- LogLn('Bytes per line: '+strf(bytesperline));
- {$endif logging}
- asm
- mov ax,4F02h
- mov bx,mode
- {$ifdef fpc}
- push ebp
- {$endif fpc}
- int 10h
- {$ifdef fpc}
- pop ebp
- {$endif fpc}
- sub ax,004Fh
- cmp ax,1
- sbb al,al
- {$ifndef ver0_99_12}
- mov @RESULT,al
- {$endif ver0_99_12}
- end;
- end;
- end;
- (*
- function getVESAMode:word;assembler;
- asm {return -1 if error}
- mov ax,4F03h
- {$ifdef fpc}
- push ebp
- {$endif fpc}
- int 10h
- {$ifdef fpc}
- pop ebp
- {$endif fpc}
- cmp ax,004Fh
- je @@OK
- mov ax,-1
- jmp @@X
- @@OK:
- mov ax,bx
- @@X:
- end;
- *)
- {************************************************************************}
- {* VESA Modes inits *}
- {************************************************************************}
- {$IFDEF DPMI}
- {******************************************************** }
- { Function GetMaxScanLines() }
- {-------------------------------------------------------- }
- { This routine returns the maximum number of scan lines }
- { possible for this mode. This is done using the Get }
- { Scan Line length VBE function. }
- {******************************************************** }
- function GetMaxScanLines: word;
- var
- regs : TDPMIRegisters;
- begin
- FillChar(regs, sizeof(regs), #0);
- { play it safe, call the real mode int, the 32-bit entry point }
- { may not be defined as stated in VBE v3.0 }
- regs.eax := $4f06; {_ setup function }
- regs.ebx := $0001; { get scan line length }
- RealIntr($10, regs);
- GetMaxScanLines := (regs.edx and $0000ffff);
- end;
- {$ELSE}
- function GetMaxScanLines: word; assembler;
- asm
- mov ax, 4f06h
- mov bx, 0001h
- int 10h
- mov ax, dx
- end;
- {$ENDIF}
- procedure Init1280x1024x64k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVesaMode(m1280x1024x64k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init1280x1024x32k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m1280x1024x32k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init1280x1024x256; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m1280x1024x256);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init1280x1024x16; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m1280x1024x16);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init1024x768x64k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m1024x768x64k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init640x480x32k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m640x480x32k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init1024x768x256; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m1024x768x256);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init1024x768x16; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m1024x768x16);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init800x600x64k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m800x600x64k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init800x600x32k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m800x600x32k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init800x600x256; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m800x600x256);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init800x600x16; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVesaMode(m800x600x16);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init640x480x64k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m640x480x64k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init640x480x256; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m640x480x256);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init640x400x256; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m640x400x256);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init320x200x64k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m320x200x64k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- procedure Init320x200x32k; {$ifndef fpc}far;{$endif fpc}
- begin
- SetVESAMode(m320x200x32k);
- { Get maximum number of scanlines for page flipping }
- ScanLines := GetMaxScanLines;
- end;
- {$IFDEF DPMI}
- Procedure SaveStateVESA; {$ifndef fpc}far;{$endif fpc}
- var
- PtrLong: longint;
- regs: TDPMIRegisters;
- begin
- SaveSupported := FALSE;
- SavePtr := nil;
- {$ifdef logging}
- LogLn('Get the video mode...');
- {$endif logging}
- { Get the video mode }
- asm
- mov ah,0fh
- {$ifdef fpc}
- push ebp
- {$endif fpc}
- int 10h
- {$ifdef fpc}
- pop ebp
- {$endif fpc}
- mov [VideoMode], al
- end;
- {$ifdef logging}
- LogLn('Prepare to save VESA video state');
- {$endif logging}
- { Prepare to save video state...}
- asm
- mov ax, 4F04h { get buffer size to save state }
- mov dx, 00h
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- {$ifdef fpc}
- push ebp
- {$endif fpc}
- int 10h
- {$ifdef fpc}
- pop ebp
- {$endif fpc}
- mov [StateSize], bx
- cmp al,04fh
- jnz @notok
- mov [SaveSupported],TRUE
- @notok:
- end;
- regs.eax := $4f04;
- regs.edx := $0000;
- regs.ecx := $000F;
- RealIntr($10, regs);
- StateSize := word(regs.ebx);
- if byte(regs.eax) = $4f then
- SaveSupported := TRUE;
- if SaveSupported then
- begin
- {$ifdef logging}
- LogLn('allocating VESA save buffer of '+strf(64*StateSize));
- {$endif logging}
- {$ifndef fpc}
- PtrLong:=GlobalDosAlloc(64*StateSize); { values returned in 64-byte blocks }
- {$else fpc}
- PtrLong:=Global_Dos_Alloc(64*StateSize); { values returned in 64-byte blocks }
- {$endif fpc}
- if PtrLong = 0 then
- RunError(203);
- SavePtr := pointer(longint(PtrLong and $0000ffff) shl 16);
- {$ifndef fpc}
- { In FPC mode, we can't do anything with this (no far pointers) }
- { However, we still need to keep it to be able to free the }
- { memory afterwards. Since this data is not accessed in PM code, }
- { there's no need to save it in a seperate buffer (JM) }
- if not assigned(SavePtr) then
- RunError(203);
- {$endif fpc}
- RealStateSeg := word(PtrLong shr 16);
- FillChar(regs, sizeof(regs), #0);
- { call the real mode interrupt ... }
- regs.eax := $4F04; { save the state buffer }
- regs.ecx := $0F; { Save DAC / Data areas / Hardware states }
- regs.edx := $01; { save state }
- regs.es := RealStateSeg;
- regs.ebx := 0;
- RealIntr($10,regs);
- FillChar(regs, sizeof(regs), #0);
- { restore state, according to Ralph Brown Interrupt list }
- { some BIOS corrupt the hardware after a save... }
- regs.eax := $4F04; { restore the state buffer }
- regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
- regs.edx := $02;
- regs.es := RealStateSeg;
- regs.ebx := 0;
- RealIntr($10,regs);
- end;
- end;
- procedure RestoreStateVESA; {$ifndef fpc}far;{$endif fpc}
- var
- regs:TDPMIRegisters;
- begin
- { go back to the old video mode...}
- asm
- mov ah,00
- mov al,[VideoMode]
- {$ifdef fpc}
- push ebp
- {$endif fpc}
- int 10h
- {$ifdef fpc}
- pop ebp
- {$endif fpc}
- end;
- { then restore all state information }
- {$ifndef fpc}
- if assigned(SavePtr) and (SaveSupported=TRUE) then
- {$else fpc}
- { No far pointer support, so it's possible that that assigned(SavePtr) }
- { would return false under FPC. Just check if it's different from nil. }
- if (SavePtr <> nil) and (SaveSupported=TRUE) then
- {$endif fpc}
- begin
- FillChar(regs, sizeof(regs), #0);
- { restore state, according to Ralph Brown Interrupt list }
- { some BIOS corrupt the hardware after a save... }
- regs.eax := $4F04; { restore the state buffer }
- regs.ecx := $0F; { rest DAC / Data areas / Hardware states }
- regs.edx := $02; { restore state }
- regs.es := RealStateSeg;
- regs.ebx := 0;
- RealIntr($10,regs);
- {$ifndef fpc}
- if GlobalDosFree(longint(SavePtr) shr 16)<>0 then
- {$else fpc}
- if Not(Global_Dos_Free(longint(SavePtr) shr 16)) then
- {$endif fpc}
- RunError(216);
- SavePtr := nil;
- end;
- end;
- {$ELSE}
- {**************************************************************}
- {* Real mode routines *}
- {**************************************************************}
- Procedure SaveStateVESA; far;
- begin
- SavePtr := nil;
- SaveSupported := FALSE;
- { Get the video mode }
- asm
- mov ah,0fh
- int 10h
- mov [VideoMode], al
- end;
- { Prepare to save video state...}
- asm
- mov ax, 4f04h { get buffer size to save state }
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- mov dx, 00h
- int 10h
- mov [StateSize], bx
- cmp al,04fh
- jnz @notok
- mov [SaveSupported],TRUE
- @notok:
- end;
- if SaveSupported then
- Begin
- GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
- if not assigned(SavePtr) then
- RunError(203);
- asm
- mov ax, 4F04h { save the state buffer }
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- mov dx, 01h
- mov es, WORD PTR [SavePtr+2]
- mov bx, WORD PTR [SavePtr]
- int 10h
- end;
- { restore state, according to Ralph Brown Interrupt list }
- { some BIOS corrupt the hardware after a save... }
- asm
- mov ax, 4F04h { save the state buffer }
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- mov dx, 02h
- mov es, WORD PTR [SavePtr+2]
- mov bx, WORD PTR [SavePtr]
- int 10h
- end;
- end;
- end;
- procedure RestoreStateVESA; far;
- begin
- { go back to the old video mode...}
- asm
- mov ah,00
- mov al,[VideoMode]
- int 10h
- end;
- { then restore all state information }
- if assigned(SavePtr) and (SaveSupported=TRUE) then
- begin
- { restore state, according to Ralph Brown Interrupt list }
- asm
- mov ax, 4F04h { save the state buffer }
- mov cx, 00001111b { Save DAC / Data areas / Hardware states }
- mov dx, 02h { restore state }
- mov es, WORD PTR [SavePtr+2]
- mov bx, WORD PTR [SavePtr]
- int 10h
- end;
- FreeMem(SavePtr, 64*StateSize);
- SavePtr := nil;
- end;
- end;
- {$ENDIF DPMI}
- {************************************************************************}
- {* VESA Page flipping routines *}
- {************************************************************************}
- { Note: These routines, according to the VBE3 specification, will NOT }
- { work with the 24 bpp modes, because of the alignment. }
- {************************************************************************}
- {******************************************************** }
- { Procedure SetVisualVESA() }
- {-------------------------------------------------------- }
- { This routine changes the page which will be displayed }
- { on the screen, since the method has changed somewhat }
- { between VBE versions , we will use the old method where }
- { the new pixel offset is used to display different pages }
- {******************************************************** }
- procedure SetVisualVESA(page: word); {$ifndef fpc}far;{$endif fpc}
- var
- newStartVisible : word;
- begin
- if page > HardwarePages then exit;
- newStartVisible := (MaxY+1)*page;
- if newStartVisible > ScanLines then exit;
- asm
- mov ax, 4f07h
- mov bx, 0000h { set display start }
- mov cx, 0000h { pixel zero ! }
- mov dx, [NewStartVisible] { new scanline }
- {$ifdef fpc}
- push ebp
- {$endif}
- int 10h
- {$ifdef fpc}
- pop ebp
- {$endif}
- end;
- end;
- procedure SetActiveVESA(page: word); {$ifndef fpc}far;{$endif fpc}
- begin
- { video offset is in pixels under VESA VBE! }
- { This value is reset after a mode set to page ZERO = YOffset = 0 ) }
- YOffset := (MaxY+1)*page;
- end;
- (*
- $Log$
- Revision 1.18 2000-01-07 16:41:32 daniel
- * copyright 2000
- Revision 1.17 2000/01/07 16:32:24 daniel
- * copyright 2000 added
- Revision 1.16 2000/01/06 15:19:42 jonas
- * fixed bug in getscanlinevesa256 and hlinevesa256 for short lines (<8 pixels)
- Revision 1.15 2000/01/02 18:51:05 jonas
- * again small fix to patternline-, hline- and getscanlinevesa256
- Revision 1.14 1999/12/29 12:15:41 jonas
- * fixed small bug in hlinevesa256, getscanlinevesa25 and patternlinevesa256
- * small speed-up in the above procedures
- Revision 1.13 1999/12/27 12:10:57 jonas
- * fixed VESA palrec structure
- Revision 1.12 1999/12/26 10:36:00 jonas
- * finished patternlineVESA256 and enabled it
- * folded (direct)put/getpixVESA32k and 64k into one procedure since
- they were exactly the same code
- Revision 1.11 1999/12/25 22:31:09 jonas
- + patternlineVESA256, not yet used because I'm not yet sure it's
- already working 100%
- * changed {$ifdef logging} to {$ifdef logging2} for vlineVESA256 and
- hlineVESA256 (they're used a lot a working properly afaik)
- Revision 1.10 1999/12/21 17:42:17 jonas
- * changed vesa.inc so it doesn't try to use linear modes anymore (doesn't work
- yet!!)
- * fixed mode detection so the low modenumber of a driver doesn't have to be zero
- anymore (so VESA autodetection now works)
- Revision 1.9 1999/12/12 13:34:20 jonas
- * putimage now performs the lipping itself and uses directputpixel
- (note: this REQUIRES or/and/notput support in directputpixel,
- this is not yet the case in the assembler versions!)
- * YOffset addition moved in hlinevesa256 and vlinevesa256
- because it uses still putpixel afterwards
- Revision 1.8 1999/12/11 23:41:39 jonas
- * changed definition of getscanlineproc to "getscanline(x1,x2,y:
- integer; var data);" so it can be used by getimage too
- * changed getimage so it uses getscanline
- * changed floodfill, getscanline16 and definitions in Linux
- include files so they use this new format
- + getscanlineVESA256 for 256 color VESA modes (banked)
- Revision 1.7 1999/12/10 12:52:54 pierre
- * some LinearFrameBuffer code, not finished
- Revision 1.6 1999/12/09 02:06:00 carl
- + page flipping for all VESA modes.
- (important note: The VESAModeInfo structure returns the MAXIMUM
- number of image pages, and not the actual available number of
- pages (cf. VBE 3.0 specification), that is the reason why
- SetVisualPage() has so much checking).
- Revision 1.5 1999/12/02 22:34:14 pierre
- * avoid FPC problem in array of char comp
- Revision 1.4 1999/11/30 02:25:15 carl
- * GetPixVESA16 bugfix with read segment.
- Revision 1.3 1999/11/28 12:18:39 jonas
- + all available mode numbers are logged if you compile the unit with
- -dlogging
- Revision 1.2 1999/11/27 21:48:01 jonas
- * fixed VlineVESA256 and re-enabled it in graph.inc
- * added procedure detectgraph to interface of graph unit
- Revision 1.1 1999/11/08 11:15:21 peter
- * move graph.inc to the target dir
- Revision 1.21 1999/11/03 20:23:01 florian
- + first release of win32 gui support
- Revision 1.20 1999/10/24 15:50:23 carl
- * Bugfix in TP mode SaveStateVESA
- Revision 1.19 1999/10/24 03:37:15 carl
- + GetPixVESA16 (not tested yet...)
- Revision 1.18 1999/09/28 13:56:31 jonas
- * reordered some local variables (first 4 byte vars, then 2 byte vars
- etc)
- * font data is now disposed in exitproc, exitproc is now called
- GraphExitProc (was CleanModes) and resides in graph.pp instead of in
- modes.inc
- Revision 1.17 1999/09/27 23:34:42 peter
- * new graph unit is default for go32v2
- * removed warnings/notes
- Revision 1.16 1999/09/26 13:31:07 jonas
- * changed name of modeinfo variable to vesamodeinfo and fixed
- associated errors (fillchar(modeinfo,sizeof(tmodeinfo),#0) instead
- of sizeof(TVesamodeinfo) etc)
- * changed several sizeof(type) to sizeof(varname) to avoid similar
- errors in the future
- Revision 1.15 1999/09/24 22:52:39 jonas
- * optimized patternline a bit (always use hline when possible)
- * isgraphmode stuff cleanup
- * vesainfo.modelist now gets disposed in cleanmode instead of in
- closegraph (required moving of some declarations from vesa.inc to
- new vesah.inc)
- * queryadapter gets no longer called from initgraph (is called from
- initialization of graph unit)
- * bugfix for notput in 32k and 64k vesa modes
- * a div replaced by / in fillpoly
- Revision 1.14 1999/09/23 14:00:42 jonas
- * -dlogging no longer required to fuction correctly
- * some typo's fixed
- Revision 1.13 1999/09/20 09:34:30 florian
- * conflicts solved
- Revision 1.12 1999/09/18 22:21:11 jonas
- + hlinevesa256 and vlinevesa256
- + support for not/xor/or/andput in vesamodes with 32k/64k colors
- * lots of changes to avoid warnings under FPC
- Revision 1.11 1999/09/15 11:40:30 jonas
- * fixed PutPixVESA256
- Revision 1.10 1999/09/11 19:43:02 jonas
- * FloodFill: did not take into account current viewport settings
- * GetScanLine: only get line inside viewport, data outside of it
- is not used anyway
- * InternalEllipseDefault: fix for when xradius or yradius = 0 and
- increase xradius and yradius always by one (TP does this too)
- * fixed conlict in vesa.inc from last update
- * some conditionals to avoid range check and overflow errors in
- places where it doesn't matter
- Revision 1.9 1999/08/01 14:51:07 jonas
- * removed and/or/xorput support from vesaputpix256 (not in TP either)
- * added notput support to directputpix256
- Revision 1.8 1999/07/18 15:07:21 jonas
- + xor-, and- and orput support for VESA256 modes
- * compile with -dlogging if you wnt some info to be logged to grlog.txt
- Revision 1.7 1999/07/14 15:21:49 jonas
- * fixed initialization of bankshift var ('64 shr banshift' instead of shl)
- Revision 1.6 1999/07/14 13:17:29 jonas
- * bugfix in getmodeinfo (SizeOf(TModeInfo) -> SizeOf(TVESAModeInfo))
- * as the result of the above bugfix, the graph unit doesn't crash
- anymore under FPC if compiler with -dsupportVESA, but it doesn't
- work yet either...
- Revision 1.5 1999/07/12 13:28:33 jonas
- * forgot log tag in previous commit
- *)
|