graph.pp 107 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. This file implements the go32v2 support for the graph unit
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit Graph;
  12. interface
  13. { the code of the unit fits in 64kb in the medium memory model, but exceeds 64kb
  14. in the large and huge memory models, so enable huge code in these models. }
  15. {$if defined(FPC_MM_LARGE) or defined(FPC_MM_HUGE)}
  16. {$hugecode on}
  17. {$endif}
  18. {$define asmgraph}
  19. {$i graphh.inc}
  20. {$i vesah.inc}
  21. CONST
  22. m640x200x16 = VGALo;
  23. m640x400x16 = VGAMed;
  24. m640x480x16 = VGAHi;
  25. { VESA Specific video modes. }
  26. m320x200x32k = $10D;
  27. m320x200x64k = $10E;
  28. {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
  29. m320x200x16m = $10F;
  30. {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
  31. m640x400x256 = $100;
  32. m640x480x256 = $101;
  33. m640x480x32k = $110;
  34. m640x480x64k = $111;
  35. {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
  36. m640x480x16m = $112;
  37. {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
  38. m800x600x16 = $102;
  39. m800x600x256 = $103;
  40. m800x600x32k = $113;
  41. m800x600x64k = $114;
  42. {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
  43. m800x600x16m = $115;
  44. {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
  45. m1024x768x16 = $104;
  46. m1024x768x256 = $105;
  47. m1024x768x32k = $116;
  48. m1024x768x64k = $117;
  49. {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
  50. m1024x768x16m = $118;
  51. {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
  52. m1280x1024x16 = $106;
  53. m1280x1024x256 = $107;
  54. m1280x1024x32k = $119;
  55. m1280x1024x64k = $11A;
  56. {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
  57. m1280x1024x16m = $11B;
  58. {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
  59. { Helpful variable to get save/restore support in IDE PM }
  60. const
  61. DontClearGraphMemory : boolean = false;
  62. implementation
  63. uses
  64. dos,ports;
  65. const
  66. InternalDriverName = 'DOSGX';
  67. {$i graph.inc}
  68. const
  69. VideoOfs : word = 0; { Segment to draw to }
  70. FirstPlane = $0102; (* 02 = Index to Color plane Select, *)
  71. (* 01 = Enable color plane 1 *)
  72. { ; ===== VGA Register Values ===== }
  73. SCREEN_WIDTH = 80 ; { MODE-X 320 SCREEN WIDTH }
  74. { CHANGE THE VALUE IF OTHER MODES }
  75. { OTHER THEN 320 ARE USED. }
  76. ATTRIB_Ctrl = $03C0 ; { VGA Attribute Controller }
  77. GC_Index = $03CE ; { VGA Graphics Controller }
  78. SC_Index = $03C4 ; { VGA Sequencer Controller }
  79. SC_Data = $03C5 ; { VGA Sequencer Data Port }
  80. CRTC_Index = $03D4 ; { VGA CRT Controller }
  81. CRTC_Data = $03D5 ; { VGA CRT Controller Data }
  82. MISC_OUTPUT = $03C2 ; { VGA Misc Register }
  83. INPUT_1 = $03DA ; { Input Status #1 Register }
  84. DAC_WRITE_ADDR = $03C8 ; { VGA DAC Write Addr Register }
  85. DAC_READ_ADDR = $03C7 ; { VGA DAC Read Addr Register }
  86. PEL_DATA_REG = $03C9 ; { VGA DAC/PEL data Register R/W }
  87. PIXEL_PAN_REG = $033 ; { Attrib Index: Pixel Pan Reg }
  88. MAP_MASK = $002 ; { S= $Index: Write Map Mask reg }
  89. READ_MAP = $004 ; { GC Index: Read Map Register }
  90. START_DISP_HI = $00C ; { CRTC Index: Display Start Hi }
  91. START_DISP_LO = $00D ; { CRTC Index: Display Start Lo }
  92. MAP_MASK_PLANE1 = $00102 ; { Map Register + Plane 1 }
  93. MAP_MASK_PLANE2 = $01102 ; { Map Register + Plane 1 }
  94. ALL_PLANES_ON = $00F02 ; { Map Register + All Bit Planes }
  95. CHAIN4_OFF = $00604 ; { Chain 4 mode Off }
  96. ASYNC_RESET = $00100 ; { (A)synchronous Reset }
  97. SEQU_RESTART = $00300 ; { Sequencer Restart }
  98. LATCHES_ON = $00008 ; { Bit Mask + Data from Latches }
  99. LATCHES_OFF = $0FF08 ; { Bit Mask + Data from CPU }
  100. VERT_RETRACE = $08 ; { INPUT_1: Vertical Retrace Bit }
  101. PLANE_BITS = $03 ; { Bits 0-1 of Xpos = Plane # }
  102. ALL_PLANES = $0F ; { All Bit Planes Selected }
  103. CHAR_BITS = $0F ; { Bits 0-3 of Character Data }
  104. GET_CHAR_PTR = $01130 ; { VGA BIOS Func: Get Char Set }
  105. ROM_8x8_Lo = $03 ; { ROM 8x8 Char Set Lo Pointer }
  106. ROM_8x8_Hi = $04 ; { ROM 8x8 Char Set Hi Pointer }
  107. { Constants Specific for these routines }
  108. NUM_MODES = $8 ; { # of Mode X Variations }
  109. { in 16 color modes, the actual colors used are not 0..15, but: }
  110. ToRealCols16: Array[0..15] of word =
  111. (0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63);
  112. var
  113. ScrWidth : word absolute $40:$4a;
  114. inWindows: boolean;
  115. {$ifndef tp}
  116. Procedure seg_bytemove(sseg : word;source : word;dseg : word;dest : word;count : word); assembler;
  117. asm
  118. push ds
  119. cld
  120. mov es, dseg
  121. mov si, source
  122. mov di, dest
  123. mov cx, count
  124. mov ds,sseg
  125. rep movsb
  126. pop ds
  127. end;
  128. {$endif tp}
  129. Procedure CallInt10(val_ax : word); assembler;
  130. asm
  131. mov ax,val_ax
  132. push ds
  133. push bp
  134. int 10h
  135. pop bp
  136. pop ds
  137. end;
  138. Procedure InitInt10hMode(mode : byte);
  139. begin
  140. if DontClearGraphMemory then
  141. CallInt10(mode or $80)
  142. else
  143. CallInt10(mode);
  144. end;
  145. {************************************************************************}
  146. {* 720x348x2 Hercules mode routines *}
  147. {************************************************************************}
  148. var
  149. DummyHGCBkColor: Word;
  150. procedure InitHGC720;
  151. const
  152. RegValues: array [0..11] of byte =
  153. ($35, $2D, $2E, $07, $5B, $02, $57, $57, $02, $03, $00, $00);
  154. var
  155. I: Integer;
  156. begin
  157. Port[$3BF] := 3; { graphic and page 2 possible }
  158. Port[$3B8] := 2; { display page 0, graphic mode, display off }
  159. for I := 0 to 11 do
  160. PortW[$3B4] := I or (RegValues[I] shl 8);
  161. Port[$3B8] := 10; { display page 0, graphic mode, display on }
  162. asm
  163. {$ifdef FPC_MM_HUGE}
  164. mov ax, SEG SegB000
  165. mov es, ax
  166. mov es, es:[SegB000]
  167. {$else FPC_MM_HUGE}
  168. mov es, [SegB000]
  169. {$endif FPC_MM_HUGE}
  170. mov cx, 32768
  171. xor di, di
  172. xor ax, ax
  173. cld
  174. rep stosw
  175. end ['ax','cx','di'];
  176. VideoOfs := 0;
  177. DummyHGCBkColor := 0;
  178. end;
  179. { compatible with TP7's HERC.BGI }
  180. procedure SetBkColorHGC720(ColorNum: ColorType);
  181. begin
  182. if ColorNum > 15 then
  183. exit;
  184. DummyHGCBkColor := ColorNum;
  185. end;
  186. { compatible with TP7's HERC.BGI }
  187. function GetBkColorHGC720: ColorType;
  188. begin
  189. GetBkColorHGC720 := DummyHGCBkColor;
  190. end;
  191. procedure SetHGCRGBPalette(ColorNum, RedValue, GreenValue,
  192. BlueValue : smallint);
  193. begin
  194. end;
  195. procedure GetHGCRGBPalette(ColorNum: smallint; Var
  196. RedValue, GreenValue, BlueValue : smallint);
  197. begin
  198. end;
  199. procedure PutPixelHGC720(X, Y: SmallInt; Pixel: ColorType);
  200. var
  201. Offset: Word;
  202. B, Mask, Shift: Byte;
  203. begin
  204. { verify clipping and then convert to absolute coordinates...}
  205. if ClipPixels then
  206. begin
  207. if (X < 0) or (X > ViewWidth) then
  208. exit;
  209. if (Y < 0) or (Y > ViewHeight) then
  210. exit;
  211. end;
  212. X:= X + StartXViewPort;
  213. Y:= Y + StartYViewPort;
  214. Offset := (Y shr 2) * 90 + (X shr 3) + VideoOfs;
  215. case Y and 3 of
  216. 1: Inc(Offset, $2000);
  217. 2: Inc(Offset, $4000);
  218. 3: Inc(Offset, $6000);
  219. end;
  220. Shift := 7 - (X and 7);
  221. Mask := 1 shl Shift;
  222. B := Mem[SegB000:Offset];
  223. B := B and (not Mask) or (Pixel shl Shift);
  224. Mem[SegB000:Offset] := B;
  225. end;
  226. function GetPixelHGC720(X, Y: SmallInt): ColorType;
  227. var
  228. Offset: Word;
  229. B, Shift: Byte;
  230. begin
  231. X:= X + StartXViewPort;
  232. Y:= Y + StartYViewPort;
  233. Offset := (Y shr 2) * 90 + (X shr 3) + VideoOfs;
  234. case Y and 3 of
  235. 1: Inc(Offset, $2000);
  236. 2: Inc(Offset, $4000);
  237. 3: Inc(Offset, $6000);
  238. end;
  239. Shift := 7 - (X and 7);
  240. B := Mem[SegB000:Offset];
  241. GetPixelHGC720 := (B shr Shift) and 1;
  242. end;
  243. procedure DirectPutPixelHGC720(X, Y: SmallInt);
  244. { x,y -> must be in global coordinates. No clipping. }
  245. var
  246. Offset: Word;
  247. B, Mask, Shift: Byte;
  248. begin
  249. Offset := (Y shr 2) * 90 + (X shr 3) + VideoOfs;
  250. case Y and 3 of
  251. 1: Inc(Offset, $2000);
  252. 2: Inc(Offset, $4000);
  253. 3: Inc(Offset, $6000);
  254. end;
  255. Shift := 7 - (X and 7);
  256. case CurrentWriteMode of
  257. XORPut:
  258. begin
  259. { optimization }
  260. if CurrentColor = 0 then
  261. exit;
  262. Mem[SegB000:Offset] := Mem[SegB000:Offset] xor (CurrentColor shl Shift);
  263. end;
  264. OrPut:
  265. begin
  266. { optimization }
  267. if CurrentColor = 0 then
  268. exit;
  269. Mem[SegB000:Offset] := Mem[SegB000:Offset] or (CurrentColor shl Shift);
  270. end;
  271. AndPut:
  272. begin
  273. { optimization }
  274. if CurrentColor = 1 then
  275. exit;
  276. { therefore, CurrentColor must be 0 }
  277. Mem[SegB000:Offset] := Mem[SegB000:Offset] and (not (1 shl Shift));
  278. end;
  279. NotPut:
  280. begin
  281. Mask := 1 shl Shift;
  282. B := Mem[SegB000:Offset];
  283. B := B and (not Mask) or ((CurrentColor xor $01) shl Shift);
  284. Mem[SegB000:Offset] := B;
  285. end
  286. else
  287. begin
  288. Mask := 1 shl Shift;
  289. B := Mem[SegB000:Offset];
  290. B := B and (not Mask) or (CurrentColor shl Shift);
  291. Mem[SegB000:Offset] := B;
  292. end;
  293. end;
  294. end;
  295. procedure HLineHGC720(X, X2, Y: SmallInt);
  296. var
  297. Color: Word;
  298. YOffset, LOffset, ROffset, CurrentOffset, MiddleAreaLength: Word;
  299. B, ForeMask, LForeMask, LBackMask, RForeMask, RBackMask: Byte;
  300. xtmp: SmallInt;
  301. begin
  302. { must we swap the values? }
  303. if x > x2 then
  304. begin
  305. xtmp := x2;
  306. x2 := x;
  307. x:= xtmp;
  308. end;
  309. { First convert to global coordinates }
  310. X := X + StartXViewPort;
  311. X2 := X2 + StartXViewPort;
  312. Y := Y + StartYViewPort;
  313. if ClipPixels then
  314. begin
  315. if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  316. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  317. exit;
  318. end;
  319. YOffset := (Y shr 2) * 90 + VideoOfs;
  320. case Y and 3 of
  321. 1: Inc(YOffset, $2000);
  322. 2: Inc(YOffset, $4000);
  323. 3: Inc(YOffset, $6000);
  324. end;
  325. LOffset := YOffset + (X shr 3);
  326. ROffset := YOffset + (X2 shr 3);
  327. if CurrentWriteMode = NotPut then
  328. Color := CurrentColor xor $01
  329. else
  330. Color := CurrentColor;
  331. if Color = 1 then
  332. ForeMask := $FF
  333. else
  334. ForeMask := $00;
  335. LBackMask := Byte($FF00 shr (X and $07));
  336. LForeMask := (not LBackMask) and ForeMask;
  337. RBackMask := Byte(not ($FF shl (7 - (X2 and $07))));
  338. RForeMask := (not RBackMask) and ForeMask;
  339. if LOffset = ROffset then
  340. begin
  341. LBackMask := LBackMask or RBackMask;
  342. LForeMask := LForeMask and RForeMask;
  343. end;
  344. CurrentOffset := LOffset;
  345. { check if the first byte is only partially full
  346. (otherwise, it's completely full and is handled as a part of the middle area) }
  347. if LBackMask <> 0 then
  348. begin
  349. { draw the first byte }
  350. case CurrentWriteMode of
  351. XORPut:
  352. begin
  353. { optimization }
  354. if CurrentColor = 0 then
  355. exit;
  356. Mem[SegB000:CurrentOffset] := Mem[SegB000:CurrentOffset] xor LForeMask;
  357. end;
  358. OrPut:
  359. begin
  360. { optimization }
  361. if CurrentColor = 0 then
  362. exit;
  363. Mem[SegB000:CurrentOffset] := Mem[SegB000:CurrentOffset] or LForeMask;
  364. end;
  365. AndPut:
  366. begin
  367. { optimization }
  368. if CurrentColor = 1 then
  369. exit;
  370. { therefore, CurrentColor must be 0 }
  371. Mem[SegB000:CurrentOffset] := Mem[SegB000:CurrentOffset] and LBackMask;
  372. end;
  373. else
  374. begin
  375. { note: NotPut is also handled here }
  376. B := Mem[SegB000:CurrentOffset];
  377. B := B and LBackMask or LForeMask;
  378. Mem[SegB000:CurrentOffset] := B;
  379. end;
  380. end;
  381. Inc(CurrentOffset);
  382. end;
  383. if CurrentOffset > ROffset then
  384. exit;
  385. MiddleAreaLength := ROffset + 1 - CurrentOffset;
  386. if RBackMask <> 0 then
  387. Dec(MiddleAreaLength);
  388. { draw the middle area }
  389. if MiddleAreaLength > 0 then
  390. begin
  391. case CurrentWriteMode of
  392. XORPut:
  393. begin
  394. { optimization }
  395. if CurrentColor = 0 then
  396. exit;
  397. while MiddleAreaLength > 0 do
  398. begin
  399. Mem[SegB000:CurrentOffset] := Mem[SegB000:CurrentOffset] xor $FF;
  400. Inc(CurrentOffset);
  401. Dec(MiddleAreaLength);
  402. end;
  403. end;
  404. OrPut:
  405. begin
  406. { optimization }
  407. if CurrentColor = 0 then
  408. exit;
  409. while MiddleAreaLength > 0 do
  410. begin
  411. Mem[SegB000:CurrentOffset] := $FF;
  412. Inc(CurrentOffset);
  413. Dec(MiddleAreaLength);
  414. end;
  415. end;
  416. AndPut:
  417. begin
  418. { optimization }
  419. if CurrentColor = 1 then
  420. exit;
  421. { therefore, CurrentColor must be 0 }
  422. while MiddleAreaLength > 0 do
  423. begin
  424. Mem[SegB000:CurrentOffset] := 0;
  425. Inc(CurrentOffset);
  426. Dec(MiddleAreaLength);
  427. end;
  428. end;
  429. else
  430. begin
  431. { note: NotPut is also handled here }
  432. while MiddleAreaLength > 0 do
  433. begin
  434. Mem[SegB000:CurrentOffset] := ForeMask;
  435. Inc(CurrentOffset);
  436. Dec(MiddleAreaLength);
  437. end;
  438. end;
  439. end;
  440. end;
  441. { draw the final right byte, if less than 100% full }
  442. if RBackMask <> 0 then
  443. begin
  444. { draw the last byte }
  445. case CurrentWriteMode of
  446. XORPut:
  447. begin
  448. { optimization }
  449. if CurrentColor = 0 then
  450. exit;
  451. Mem[SegB000:CurrentOffset] := Mem[SegB000:CurrentOffset] xor RForeMask;
  452. end;
  453. OrPut:
  454. begin
  455. { optimization }
  456. if CurrentColor = 0 then
  457. exit;
  458. Mem[SegB000:CurrentOffset] := Mem[SegB000:CurrentOffset] or RForeMask;
  459. end;
  460. AndPut:
  461. begin
  462. { optimization }
  463. if CurrentColor = 1 then
  464. exit;
  465. { therefore, CurrentColor must be 0 }
  466. Mem[SegB000:CurrentOffset] := Mem[SegB000:CurrentOffset] and RBackMask;
  467. end;
  468. else
  469. begin
  470. { note: NotPut is also handled here }
  471. B := Mem[SegB000:CurrentOffset];
  472. B := B and RBackMask or RForeMask;
  473. Mem[SegB000:CurrentOffset] := B;
  474. end;
  475. end;
  476. end;
  477. end;
  478. procedure SetVisualHGC720(page: word);
  479. { two page supPort... }
  480. begin
  481. if page > HardwarePages then exit;
  482. case page of
  483. 0 : Port[$3B8] := 10; { display page 0, graphic mode, display on }
  484. 1 : Port[$3B8] := 10+128; { display page 1, graphic mode, display on }
  485. end;
  486. end;
  487. procedure SetActiveHGC720(page: word);
  488. { two page supPort... }
  489. begin
  490. case page of
  491. 0 : VideoOfs := 0;
  492. 1 : VideoOfs := 32768;
  493. else
  494. VideoOfs := 0;
  495. end;
  496. end;
  497. {************************************************************************}
  498. {* 320x200x4 CGA mode routines *}
  499. {************************************************************************}
  500. var
  501. CurrentCGABorder: Word;
  502. procedure SetCGAPalette(CGAPaletteID: Byte); assembler;
  503. asm
  504. mov ax,CGAPaletteID
  505. mov bl, al
  506. mov bh, 1
  507. mov ah, 0Bh
  508. push ds
  509. push bp
  510. int 10h
  511. pop bp
  512. pop ds
  513. end;
  514. procedure SetCGABorder(CGABorder: Byte); assembler;
  515. asm
  516. mov ax,CGABorder
  517. mov bl, al
  518. mov bh, 0
  519. mov ah, 0Bh
  520. push ds
  521. push bp
  522. int 10h
  523. pop bp
  524. pop ds
  525. end;
  526. procedure SetBkColorCGA320(ColorNum: ColorType);
  527. begin
  528. if ColorNum > 15 then
  529. exit;
  530. CurrentCGABorder := (CurrentCGABorder and 16) or ColorNum;
  531. SetCGABorder(CurrentCGABorder);
  532. end;
  533. function GetBkColorCGA320: ColorType;
  534. begin
  535. GetBkColorCGA320 := CurrentCGABorder and 15;
  536. end;
  537. procedure InitCGA320C0;
  538. begin
  539. InitInt10hMode($04);
  540. VideoOfs := 0;
  541. SetCGAPalette(0);
  542. SetCGABorder(16);
  543. CurrentCGABorder := 16;
  544. end;
  545. procedure InitCGA320C1;
  546. begin
  547. InitInt10hMode($04);
  548. VideoOfs := 0;
  549. SetCGAPalette(1);
  550. SetCGABorder(16);
  551. CurrentCGABorder := 16;
  552. end;
  553. procedure InitCGA320C2;
  554. begin
  555. InitInt10hMode($04);
  556. VideoOfs := 0;
  557. SetCGAPalette(2);
  558. SetCGABorder(0);
  559. CurrentCGABorder := 0;
  560. end;
  561. procedure InitCGA320C3;
  562. begin
  563. InitInt10hMode($04);
  564. VideoOfs := 0;
  565. SetCGAPalette(3);
  566. SetCGABorder(0);
  567. CurrentCGABorder := 0;
  568. end;
  569. procedure PutPixelCGA320(X, Y: SmallInt; Pixel: ColorType);
  570. var
  571. Offset: Word;
  572. B, Mask, Shift: Byte;
  573. begin
  574. { verify clipping and then convert to absolute coordinates...}
  575. if ClipPixels then
  576. begin
  577. if (X < 0) or (X > ViewWidth) then
  578. exit;
  579. if (Y < 0) or (Y > ViewHeight) then
  580. exit;
  581. end;
  582. X:= X + StartXViewPort;
  583. Y:= Y + StartYViewPort;
  584. Offset := (Y shr 1) * 80 + (X shr 2);
  585. if (Y and 1) <> 0 then
  586. Inc(Offset, 8192);
  587. Shift := 6 - ((X and 3) shl 1);
  588. Mask := $03 shl Shift;
  589. B := Mem[SegB800:Offset];
  590. B := B and (not Mask) or (Pixel shl Shift);
  591. Mem[SegB800:Offset] := B;
  592. end;
  593. function GetPixelCGA320(X, Y: SmallInt): ColorType;
  594. var
  595. Offset: Word;
  596. B, Shift: Byte;
  597. begin
  598. X:= X + StartXViewPort;
  599. Y:= Y + StartYViewPort;
  600. Offset := (Y shr 1) * 80 + (X shr 2);
  601. if (Y and 1) <> 0 then
  602. Inc(Offset, 8192);
  603. Shift := 6 - ((X and 3) shl 1);
  604. B := Mem[SegB800:Offset];
  605. GetPixelCGA320 := (B shr Shift) and $03;
  606. end;
  607. procedure DirectPutPixelCGA320(X, Y: SmallInt);
  608. { x,y -> must be in global coordinates. No clipping. }
  609. var
  610. Offset: Word;
  611. B, Mask, Shift: Byte;
  612. begin
  613. Offset := (Y shr 1) * 80 + (X shr 2);
  614. if (Y and 1) <> 0 then
  615. Inc(Offset, 8192);
  616. Shift := 6 - ((X and 3) shl 1);
  617. case CurrentWriteMode of
  618. XORPut:
  619. begin
  620. { optimization }
  621. if CurrentColor = 0 then
  622. exit;
  623. Mem[SegB800:Offset] := Mem[SegB800:Offset] xor (CurrentColor shl Shift);
  624. end;
  625. OrPut:
  626. begin
  627. { optimization }
  628. if CurrentColor = 0 then
  629. exit;
  630. Mem[SegB800:Offset] := Mem[SegB800:Offset] or (CurrentColor shl Shift);
  631. end;
  632. AndPut:
  633. begin
  634. { optimization }
  635. if CurrentColor = 3 then
  636. exit;
  637. Mask := $03 shl Shift;
  638. Mem[SegB800:Offset] := Mem[SegB800:Offset] and ((CurrentColor shl Shift) or (not Mask));
  639. end;
  640. NotPut:
  641. begin
  642. Mask := $03 shl Shift;
  643. B := Mem[SegB800:Offset];
  644. B := B and (not Mask) or ((CurrentColor xor $03) shl Shift);
  645. Mem[SegB800:Offset] := B;
  646. end
  647. else
  648. begin
  649. Mask := $03 shl Shift;
  650. B := Mem[SegB800:Offset];
  651. B := B and (not Mask) or (CurrentColor shl Shift);
  652. Mem[SegB800:Offset] := B;
  653. end;
  654. end;
  655. end;
  656. procedure HLineCGA320(X, X2, Y: SmallInt);
  657. var
  658. Color: Word;
  659. YOffset, LOffset, ROffset, CurrentOffset, MiddleAreaLength: Word;
  660. B, ForeMask, LForeMask, LBackMask, RForeMask, RBackMask: Byte;
  661. xtmp: SmallInt;
  662. begin
  663. { must we swap the values? }
  664. if x > x2 then
  665. begin
  666. xtmp := x2;
  667. x2 := x;
  668. x:= xtmp;
  669. end;
  670. { First convert to global coordinates }
  671. X := X + StartXViewPort;
  672. X2 := X2 + StartXViewPort;
  673. Y := Y + StartYViewPort;
  674. if ClipPixels then
  675. begin
  676. if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  677. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  678. exit;
  679. end;
  680. YOffset := (Y shr 1) * 80;
  681. if (Y and 1) <> 0 then
  682. Inc(YOffset, 8192);
  683. LOffset := YOffset + (X shr 2);
  684. ROffset := YOffset + (X2 shr 2);
  685. if CurrentWriteMode = NotPut then
  686. Color := CurrentColor xor $03
  687. else
  688. Color := CurrentColor;
  689. case Color of
  690. 0: ForeMask := $00;
  691. 1: ForeMask := $55;
  692. 2: ForeMask := $AA;
  693. 3: ForeMask := $FF;
  694. end;
  695. LBackMask := Byte($FF00 shr ((X and $03) shl 1));
  696. LForeMask := (not LBackMask) and ForeMask;
  697. RBackMask := Byte(not ($FF shl (6 - ((X2 and $03) shl 1))));
  698. RForeMask := (not RBackMask) and ForeMask;
  699. if LOffset = ROffset then
  700. begin
  701. LBackMask := LBackMask or RBackMask;
  702. LForeMask := LForeMask and RForeMask;
  703. end;
  704. CurrentOffset := LOffset;
  705. { check if the first byte is only partially full
  706. (otherwise, it's completely full and is handled as a part of the middle area) }
  707. if LBackMask <> 0 then
  708. begin
  709. { draw the first byte }
  710. case CurrentWriteMode of
  711. XORPut:
  712. begin
  713. { optimization }
  714. if CurrentColor = 0 then
  715. exit;
  716. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] xor LForeMask;
  717. end;
  718. OrPut:
  719. begin
  720. { optimization }
  721. if CurrentColor = 0 then
  722. exit;
  723. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] or LForeMask;
  724. end;
  725. AndPut:
  726. begin
  727. { optimization }
  728. if CurrentColor = 3 then
  729. exit;
  730. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] and (LBackMask or LForeMask);
  731. end;
  732. else
  733. begin
  734. { note: NotPut is also handled here }
  735. B := Mem[SegB800:CurrentOffset];
  736. B := B and LBackMask or LForeMask;
  737. Mem[SegB800:CurrentOffset] := B;
  738. end;
  739. end;
  740. Inc(CurrentOffset);
  741. end;
  742. if CurrentOffset > ROffset then
  743. exit;
  744. MiddleAreaLength := ROffset + 1 - CurrentOffset;
  745. if RBackMask <> 0 then
  746. Dec(MiddleAreaLength);
  747. { draw the middle area }
  748. if MiddleAreaLength > 0 then
  749. begin
  750. case CurrentWriteMode of
  751. XORPut:
  752. begin
  753. { optimization }
  754. if CurrentColor = 0 then
  755. exit;
  756. while MiddleAreaLength > 0 do
  757. begin
  758. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] xor ForeMask;
  759. Inc(CurrentOffset);
  760. Dec(MiddleAreaLength);
  761. end;
  762. end;
  763. OrPut:
  764. begin
  765. { optimization }
  766. if CurrentColor = 0 then
  767. exit;
  768. while MiddleAreaLength > 0 do
  769. begin
  770. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] or ForeMask;
  771. Inc(CurrentOffset);
  772. Dec(MiddleAreaLength);
  773. end;
  774. end;
  775. AndPut:
  776. begin
  777. { optimization }
  778. if CurrentColor = 3 then
  779. exit;
  780. while MiddleAreaLength > 0 do
  781. begin
  782. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] and ForeMask;
  783. Inc(CurrentOffset);
  784. Dec(MiddleAreaLength);
  785. end;
  786. end;
  787. else
  788. begin
  789. { note: NotPut is also handled here }
  790. while MiddleAreaLength > 0 do
  791. begin
  792. Mem[SegB800:CurrentOffset] := ForeMask;
  793. Inc(CurrentOffset);
  794. Dec(MiddleAreaLength);
  795. end;
  796. end;
  797. end;
  798. end;
  799. { draw the final right byte, if less than 100% full }
  800. if RBackMask <> 0 then
  801. begin
  802. { draw the last byte }
  803. case CurrentWriteMode of
  804. XORPut:
  805. begin
  806. { optimization }
  807. if CurrentColor = 0 then
  808. exit;
  809. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] xor RForeMask;
  810. end;
  811. OrPut:
  812. begin
  813. { optimization }
  814. if CurrentColor = 0 then
  815. exit;
  816. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] or RForeMask;
  817. end;
  818. AndPut:
  819. begin
  820. { optimization }
  821. if CurrentColor = 3 then
  822. exit;
  823. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] and (RBackMask or RForeMask);
  824. end;
  825. else
  826. begin
  827. { note: NotPut is also handled here }
  828. B := Mem[SegB800:CurrentOffset];
  829. B := B and RBackMask or RForeMask;
  830. Mem[SegB800:CurrentOffset] := B;
  831. end;
  832. end;
  833. end;
  834. end;
  835. {************************************************************************}
  836. {* 640x200x2 CGA mode routines *}
  837. {************************************************************************}
  838. procedure InitCGA640;
  839. begin
  840. InitInt10hMode($06);
  841. VideoOfs := 0;
  842. CurrentCGABorder := 0; {yes, TP7 CGA.BGI behaves *exactly* like that}
  843. end;
  844. {yes, TP7 CGA.BGI behaves *exactly* like that}
  845. procedure SetBkColorCGA640(ColorNum: ColorType);
  846. begin
  847. if ColorNum > 15 then
  848. exit;
  849. CurrentCGABorder := ColorNum;
  850. if ColorNum = 0 then
  851. exit;
  852. SetCGABorder(CurrentCGABorder);
  853. end;
  854. function GetBkColorCGA640: ColorType;
  855. begin
  856. GetBkColorCGA640 := CurrentCGABorder and 15;
  857. end;
  858. procedure PutPixelCGA640(X, Y: SmallInt; Pixel: ColorType);
  859. var
  860. Offset: Word;
  861. B, Mask, Shift: Byte;
  862. begin
  863. { verify clipping and then convert to absolute coordinates...}
  864. if ClipPixels then
  865. begin
  866. if (X < 0) or (X > ViewWidth) then
  867. exit;
  868. if (Y < 0) or (Y > ViewHeight) then
  869. exit;
  870. end;
  871. X:= X + StartXViewPort;
  872. Y:= Y + StartYViewPort;
  873. Offset := (Y shr 1) * 80 + (X shr 3);
  874. if (Y and 1) <> 0 then
  875. Inc(Offset, 8192);
  876. Shift := 7 - (X and 7);
  877. Mask := 1 shl Shift;
  878. B := Mem[SegB800:Offset];
  879. B := B and (not Mask) or (Pixel shl Shift);
  880. Mem[SegB800:Offset] := B;
  881. end;
  882. function GetPixelCGA640(X, Y: SmallInt): ColorType;
  883. var
  884. Offset: Word;
  885. B, Shift: Byte;
  886. begin
  887. X:= X + StartXViewPort;
  888. Y:= Y + StartYViewPort;
  889. Offset := (Y shr 1) * 80 + (X shr 3);
  890. if (Y and 1) <> 0 then
  891. Inc(Offset, 8192);
  892. Shift := 7 - (X and 7);
  893. B := Mem[SegB800:Offset];
  894. GetPixelCGA640 := (B shr Shift) and 1;
  895. end;
  896. procedure DirectPutPixelCGA640(X, Y: SmallInt);
  897. { x,y -> must be in global coordinates. No clipping. }
  898. var
  899. Offset: Word;
  900. B, Mask, Shift: Byte;
  901. begin
  902. Offset := (Y shr 1) * 80 + (X shr 3);
  903. if (Y and 1) <> 0 then
  904. Inc(Offset, 8192);
  905. Shift := 7 - (X and 7);
  906. case CurrentWriteMode of
  907. XORPut:
  908. begin
  909. { optimization }
  910. if CurrentColor = 0 then
  911. exit;
  912. Mem[SegB800:Offset] := Mem[SegB800:Offset] xor (CurrentColor shl Shift);
  913. end;
  914. OrPut:
  915. begin
  916. { optimization }
  917. if CurrentColor = 0 then
  918. exit;
  919. Mem[SegB800:Offset] := Mem[SegB800:Offset] or (CurrentColor shl Shift);
  920. end;
  921. AndPut:
  922. begin
  923. { optimization }
  924. if CurrentColor = 1 then
  925. exit;
  926. { therefore, CurrentColor must be 0 }
  927. Mem[SegB800:Offset] := Mem[SegB800:Offset] and (not (1 shl Shift));
  928. end;
  929. NotPut:
  930. begin
  931. Mask := 1 shl Shift;
  932. B := Mem[SegB800:Offset];
  933. B := B and (not Mask) or ((CurrentColor xor $01) shl Shift);
  934. Mem[SegB800:Offset] := B;
  935. end
  936. else
  937. begin
  938. Mask := 1 shl Shift;
  939. B := Mem[SegB800:Offset];
  940. B := B and (not Mask) or (CurrentColor shl Shift);
  941. Mem[SegB800:Offset] := B;
  942. end;
  943. end;
  944. end;
  945. procedure HLineCGA640(X, X2, Y: SmallInt);
  946. var
  947. Color: Word;
  948. YOffset, LOffset, ROffset, CurrentOffset, MiddleAreaLength: Word;
  949. B, ForeMask, LForeMask, LBackMask, RForeMask, RBackMask: Byte;
  950. xtmp: SmallInt;
  951. begin
  952. { must we swap the values? }
  953. if x > x2 then
  954. begin
  955. xtmp := x2;
  956. x2 := x;
  957. x:= xtmp;
  958. end;
  959. { First convert to global coordinates }
  960. X := X + StartXViewPort;
  961. X2 := X2 + StartXViewPort;
  962. Y := Y + StartYViewPort;
  963. if ClipPixels then
  964. begin
  965. if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  966. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  967. exit;
  968. end;
  969. YOffset := (Y shr 1) * 80;
  970. if (Y and 1) <> 0 then
  971. Inc(YOffset, 8192);
  972. LOffset := YOffset + (X shr 3);
  973. ROffset := YOffset + (X2 shr 3);
  974. if CurrentWriteMode = NotPut then
  975. Color := CurrentColor xor $01
  976. else
  977. Color := CurrentColor;
  978. if Color = 1 then
  979. ForeMask := $FF
  980. else
  981. ForeMask := $00;
  982. LBackMask := Byte($FF00 shr (X and $07));
  983. LForeMask := (not LBackMask) and ForeMask;
  984. RBackMask := Byte(not ($FF shl (7 - (X2 and $07))));
  985. RForeMask := (not RBackMask) and ForeMask;
  986. if LOffset = ROffset then
  987. begin
  988. LBackMask := LBackMask or RBackMask;
  989. LForeMask := LForeMask and RForeMask;
  990. end;
  991. CurrentOffset := LOffset;
  992. { check if the first byte is only partially full
  993. (otherwise, it's completely full and is handled as a part of the middle area) }
  994. if LBackMask <> 0 then
  995. begin
  996. { draw the first byte }
  997. case CurrentWriteMode of
  998. XORPut:
  999. begin
  1000. { optimization }
  1001. if CurrentColor = 0 then
  1002. exit;
  1003. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] xor LForeMask;
  1004. end;
  1005. OrPut:
  1006. begin
  1007. { optimization }
  1008. if CurrentColor = 0 then
  1009. exit;
  1010. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] or LForeMask;
  1011. end;
  1012. AndPut:
  1013. begin
  1014. { optimization }
  1015. if CurrentColor = 1 then
  1016. exit;
  1017. { therefore, CurrentColor must be 0 }
  1018. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] and LBackMask;
  1019. end;
  1020. else
  1021. begin
  1022. { note: NotPut is also handled here }
  1023. B := Mem[SegB800:CurrentOffset];
  1024. B := B and LBackMask or LForeMask;
  1025. Mem[SegB800:CurrentOffset] := B;
  1026. end;
  1027. end;
  1028. Inc(CurrentOffset);
  1029. end;
  1030. if CurrentOffset > ROffset then
  1031. exit;
  1032. MiddleAreaLength := ROffset + 1 - CurrentOffset;
  1033. if RBackMask <> 0 then
  1034. Dec(MiddleAreaLength);
  1035. { draw the middle area }
  1036. if MiddleAreaLength > 0 then
  1037. begin
  1038. case CurrentWriteMode of
  1039. XORPut:
  1040. begin
  1041. { optimization }
  1042. if CurrentColor = 0 then
  1043. exit;
  1044. while MiddleAreaLength > 0 do
  1045. begin
  1046. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] xor $FF;
  1047. Inc(CurrentOffset);
  1048. Dec(MiddleAreaLength);
  1049. end;
  1050. end;
  1051. OrPut:
  1052. begin
  1053. { optimization }
  1054. if CurrentColor = 0 then
  1055. exit;
  1056. while MiddleAreaLength > 0 do
  1057. begin
  1058. Mem[SegB800:CurrentOffset] := $FF;
  1059. Inc(CurrentOffset);
  1060. Dec(MiddleAreaLength);
  1061. end;
  1062. end;
  1063. AndPut:
  1064. begin
  1065. { optimization }
  1066. if CurrentColor = 1 then
  1067. exit;
  1068. { therefore, CurrentColor must be 0 }
  1069. while MiddleAreaLength > 0 do
  1070. begin
  1071. Mem[SegB800:CurrentOffset] := 0;
  1072. Inc(CurrentOffset);
  1073. Dec(MiddleAreaLength);
  1074. end;
  1075. end;
  1076. else
  1077. begin
  1078. { note: NotPut is also handled here }
  1079. while MiddleAreaLength > 0 do
  1080. begin
  1081. Mem[SegB800:CurrentOffset] := ForeMask;
  1082. Inc(CurrentOffset);
  1083. Dec(MiddleAreaLength);
  1084. end;
  1085. end;
  1086. end;
  1087. end;
  1088. { draw the final right byte, if less than 100% full }
  1089. if RBackMask <> 0 then
  1090. begin
  1091. { draw the last byte }
  1092. case CurrentWriteMode of
  1093. XORPut:
  1094. begin
  1095. { optimization }
  1096. if CurrentColor = 0 then
  1097. exit;
  1098. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] xor RForeMask;
  1099. end;
  1100. OrPut:
  1101. begin
  1102. { optimization }
  1103. if CurrentColor = 0 then
  1104. exit;
  1105. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] or RForeMask;
  1106. end;
  1107. AndPut:
  1108. begin
  1109. { optimization }
  1110. if CurrentColor = 1 then
  1111. exit;
  1112. { therefore, CurrentColor must be 0 }
  1113. Mem[SegB800:CurrentOffset] := Mem[SegB800:CurrentOffset] and RBackMask;
  1114. end;
  1115. else
  1116. begin
  1117. { note: NotPut is also handled here }
  1118. B := Mem[SegB800:CurrentOffset];
  1119. B := B and RBackMask or RForeMask;
  1120. Mem[SegB800:CurrentOffset] := B;
  1121. end;
  1122. end;
  1123. end;
  1124. end;
  1125. {************************************************************************}
  1126. {* 640x480x2 MCGA mode routines *}
  1127. {************************************************************************}
  1128. procedure InitMCGA640;
  1129. begin
  1130. InitInt10hMode($11);
  1131. VideoOfs := 0;
  1132. CurrentCGABorder := 0; {yes, TP7 CGA.BGI behaves *exactly* like that}
  1133. end;
  1134. procedure SetBkColorMCGA640(ColorNum: ColorType);
  1135. begin
  1136. if ColorNum > 15 then
  1137. exit;
  1138. CurrentCGABorder := (CurrentCGABorder and 16) or ColorNum;
  1139. SetCGABorder(CurrentCGABorder);
  1140. end;
  1141. function GetBkColorMCGA640: ColorType;
  1142. begin
  1143. GetBkColorMCGA640 := CurrentCGABorder and 15;
  1144. end;
  1145. procedure PutPixelMCGA640(X, Y: SmallInt; Pixel: ColorType);
  1146. var
  1147. Offset: Word;
  1148. B, Mask, Shift: Byte;
  1149. begin
  1150. { verify clipping and then convert to absolute coordinates...}
  1151. if ClipPixels then
  1152. begin
  1153. if (X < 0) or (X > ViewWidth) then
  1154. exit;
  1155. if (Y < 0) or (Y > ViewHeight) then
  1156. exit;
  1157. end;
  1158. X:= X + StartXViewPort;
  1159. Y:= Y + StartYViewPort;
  1160. Offset := Y * 80 + (X shr 3);
  1161. Shift := 7 - (X and 7);
  1162. Mask := 1 shl Shift;
  1163. B := Mem[SegA000:Offset];
  1164. B := B and (not Mask) or (Pixel shl Shift);
  1165. Mem[SegA000:Offset] := B;
  1166. end;
  1167. function GetPixelMCGA640(X, Y: SmallInt): ColorType;
  1168. var
  1169. Offset: Word;
  1170. B, Shift: Byte;
  1171. begin
  1172. X:= X + StartXViewPort;
  1173. Y:= Y + StartYViewPort;
  1174. Offset := Y * 80 + (X shr 3);
  1175. Shift := 7 - (X and 7);
  1176. B := Mem[SegA000:Offset];
  1177. GetPixelMCGA640 := (B shr Shift) and 1;
  1178. end;
  1179. procedure DirectPutPixelMCGA640(X, Y: SmallInt);
  1180. { x,y -> must be in global coordinates. No clipping. }
  1181. var
  1182. Offset: Word;
  1183. B, Mask, Shift: Byte;
  1184. begin
  1185. Offset := Y * 80 + (X shr 3);
  1186. Shift := 7 - (X and 7);
  1187. case CurrentWriteMode of
  1188. XORPut:
  1189. begin
  1190. { optimization }
  1191. if CurrentColor = 0 then
  1192. exit;
  1193. Mem[SegA000:Offset] := Mem[SegA000:Offset] xor (CurrentColor shl Shift);
  1194. end;
  1195. OrPut:
  1196. begin
  1197. { optimization }
  1198. if CurrentColor = 0 then
  1199. exit;
  1200. Mem[SegA000:Offset] := Mem[SegA000:Offset] or (CurrentColor shl Shift);
  1201. end;
  1202. AndPut:
  1203. begin
  1204. { optimization }
  1205. if CurrentColor = 1 then
  1206. exit;
  1207. { therefore, CurrentColor must be 0 }
  1208. Mem[SegA000:Offset] := Mem[SegA000:Offset] and (not (1 shl Shift));
  1209. end;
  1210. NotPut:
  1211. begin
  1212. Mask := 1 shl Shift;
  1213. B := Mem[SegA000:Offset];
  1214. B := B and (not Mask) or ((CurrentColor xor $01) shl Shift);
  1215. Mem[SegA000:Offset] := B;
  1216. end
  1217. else
  1218. begin
  1219. Mask := 1 shl Shift;
  1220. B := Mem[SegA000:Offset];
  1221. B := B and (not Mask) or (CurrentColor shl Shift);
  1222. Mem[SegA000:Offset] := B;
  1223. end;
  1224. end;
  1225. end;
  1226. procedure HLineMCGA640(X, X2, Y: SmallInt);
  1227. var
  1228. Color: Word;
  1229. YOffset, LOffset, ROffset, CurrentOffset, MiddleAreaLength: Word;
  1230. B, ForeMask, LForeMask, LBackMask, RForeMask, RBackMask: Byte;
  1231. xtmp: SmallInt;
  1232. begin
  1233. { must we swap the values? }
  1234. if x > x2 then
  1235. begin
  1236. xtmp := x2;
  1237. x2 := x;
  1238. x:= xtmp;
  1239. end;
  1240. { First convert to global coordinates }
  1241. X := X + StartXViewPort;
  1242. X2 := X2 + StartXViewPort;
  1243. Y := Y + StartYViewPort;
  1244. if ClipPixels then
  1245. begin
  1246. if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  1247. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  1248. exit;
  1249. end;
  1250. YOffset := Y * 80;
  1251. LOffset := YOffset + (X shr 3);
  1252. ROffset := YOffset + (X2 shr 3);
  1253. if CurrentWriteMode = NotPut then
  1254. Color := CurrentColor xor $01
  1255. else
  1256. Color := CurrentColor;
  1257. if Color = 1 then
  1258. ForeMask := $FF
  1259. else
  1260. ForeMask := $00;
  1261. LBackMask := Byte($FF00 shr (X and $07));
  1262. LForeMask := (not LBackMask) and ForeMask;
  1263. RBackMask := Byte(not ($FF shl (7 - (X2 and $07))));
  1264. RForeMask := (not RBackMask) and ForeMask;
  1265. if LOffset = ROffset then
  1266. begin
  1267. LBackMask := LBackMask or RBackMask;
  1268. LForeMask := LForeMask and RForeMask;
  1269. end;
  1270. CurrentOffset := LOffset;
  1271. { check if the first byte is only partially full
  1272. (otherwise, it's completely full and is handled as a part of the middle area) }
  1273. if LBackMask <> 0 then
  1274. begin
  1275. { draw the first byte }
  1276. case CurrentWriteMode of
  1277. XORPut:
  1278. begin
  1279. { optimization }
  1280. if CurrentColor = 0 then
  1281. exit;
  1282. Mem[SegA000:CurrentOffset] := Mem[SegA000:CurrentOffset] xor LForeMask;
  1283. end;
  1284. OrPut:
  1285. begin
  1286. { optimization }
  1287. if CurrentColor = 0 then
  1288. exit;
  1289. Mem[SegA000:CurrentOffset] := Mem[SegA000:CurrentOffset] or LForeMask;
  1290. end;
  1291. AndPut:
  1292. begin
  1293. { optimization }
  1294. if CurrentColor = 1 then
  1295. exit;
  1296. { therefore, CurrentColor must be 0 }
  1297. Mem[SegA000:CurrentOffset] := Mem[SegA000:CurrentOffset] and LBackMask;
  1298. end;
  1299. else
  1300. begin
  1301. { note: NotPut is also handled here }
  1302. B := Mem[SegA000:CurrentOffset];
  1303. B := B and LBackMask or LForeMask;
  1304. Mem[SegA000:CurrentOffset] := B;
  1305. end;
  1306. end;
  1307. Inc(CurrentOffset);
  1308. end;
  1309. if CurrentOffset > ROffset then
  1310. exit;
  1311. MiddleAreaLength := ROffset + 1 - CurrentOffset;
  1312. if RBackMask <> 0 then
  1313. Dec(MiddleAreaLength);
  1314. { draw the middle area }
  1315. if MiddleAreaLength > 0 then
  1316. begin
  1317. case CurrentWriteMode of
  1318. XORPut:
  1319. begin
  1320. { optimization }
  1321. if CurrentColor = 0 then
  1322. exit;
  1323. while MiddleAreaLength > 0 do
  1324. begin
  1325. Mem[SegA000:CurrentOffset] := Mem[SegA000:CurrentOffset] xor $FF;
  1326. Inc(CurrentOffset);
  1327. Dec(MiddleAreaLength);
  1328. end;
  1329. end;
  1330. OrPut:
  1331. begin
  1332. { optimization }
  1333. if CurrentColor = 0 then
  1334. exit;
  1335. while MiddleAreaLength > 0 do
  1336. begin
  1337. Mem[SegA000:CurrentOffset] := $FF;
  1338. Inc(CurrentOffset);
  1339. Dec(MiddleAreaLength);
  1340. end;
  1341. end;
  1342. AndPut:
  1343. begin
  1344. { optimization }
  1345. if CurrentColor = 1 then
  1346. exit;
  1347. { therefore, CurrentColor must be 0 }
  1348. while MiddleAreaLength > 0 do
  1349. begin
  1350. Mem[SegA000:CurrentOffset] := 0;
  1351. Inc(CurrentOffset);
  1352. Dec(MiddleAreaLength);
  1353. end;
  1354. end;
  1355. else
  1356. begin
  1357. { note: NotPut is also handled here }
  1358. while MiddleAreaLength > 0 do
  1359. begin
  1360. Mem[SegA000:CurrentOffset] := ForeMask;
  1361. Inc(CurrentOffset);
  1362. Dec(MiddleAreaLength);
  1363. end;
  1364. end;
  1365. end;
  1366. end;
  1367. if RBackMask <> 0 then
  1368. begin
  1369. { draw the last byte }
  1370. case CurrentWriteMode of
  1371. XORPut:
  1372. begin
  1373. { optimization }
  1374. if CurrentColor = 0 then
  1375. exit;
  1376. Mem[SegA000:CurrentOffset] := Mem[SegA000:CurrentOffset] xor RForeMask;
  1377. end;
  1378. OrPut:
  1379. begin
  1380. { optimization }
  1381. if CurrentColor = 0 then
  1382. exit;
  1383. Mem[SegA000:CurrentOffset] := Mem[SegA000:CurrentOffset] or RForeMask;
  1384. end;
  1385. AndPut:
  1386. begin
  1387. { optimization }
  1388. if CurrentColor = 1 then
  1389. exit;
  1390. { therefore, CurrentColor must be 0 }
  1391. Mem[SegA000:CurrentOffset] := Mem[SegA000:CurrentOffset] and RBackMask;
  1392. end;
  1393. else
  1394. begin
  1395. { note: NotPut is also handled here }
  1396. B := Mem[SegA000:CurrentOffset];
  1397. B := B and RBackMask or RForeMask;
  1398. Mem[SegA000:CurrentOffset] := B;
  1399. end;
  1400. end;
  1401. end;
  1402. end;
  1403. {************************************************************************}
  1404. {* 4-bit planar VGA mode routines *}
  1405. {************************************************************************}
  1406. Procedure Init640x200x16;
  1407. begin
  1408. InitInt10hMode($e);
  1409. VideoOfs := 0;
  1410. end;
  1411. Procedure Init640x350x16;
  1412. begin
  1413. InitInt10hMode($10);
  1414. VideoOfs := 0;
  1415. end;
  1416. Procedure Init640x480x16;
  1417. begin
  1418. InitInt10hMode($12);
  1419. VideoOfs := 0;
  1420. end;
  1421. {$ifndef asmgraph}
  1422. Procedure PutPixel16(X,Y : smallint; Pixel: ColorType);
  1423. var offset: word;
  1424. dummy: byte;
  1425. Begin
  1426. { verify clipping and then convert to absolute coordinates...}
  1427. if ClipPixels then
  1428. begin
  1429. if (X < 0) or (X > ViewWidth) then
  1430. exit;
  1431. if (Y < 0) or (Y > ViewHeight) then
  1432. exit;
  1433. end;
  1434. X:= X + StartXViewPort;
  1435. Y:= Y + StartYViewPort;
  1436. offset := y * 80 + (x shr 3) + VideoOfs;
  1437. PortW[$3ce] := $0f01; { Index 01 : Enable ops on all 4 planes }
  1438. PortW[$3ce] := (Pixel and $ff) shl 8; { Index 00 : Enable correct plane and write color }
  1439. PortW[$3ce] := ($8000 shr (x and $7)) or 8; { Select correct bits to modify }
  1440. dummy := Mem[SegA000: offset]; { Latch the data into host space. }
  1441. Mem[Sega000: offset] := dummy; { Write the data into video memory }
  1442. PortW[$3ce] := $ff08; { Enable all bit planes. }
  1443. PortW[$3ce] := $0001; { Index 01 : Disable ops on all four planes. }
  1444. end;
  1445. {$else asmgraph}
  1446. Procedure PutPixel16(X,Y : smallint; Pixel: ColorType); assembler;
  1447. asm
  1448. mov si, [X]
  1449. mov bx, [Y]
  1450. cmp byte ptr [ClipPixels], 0
  1451. je @@ClipDone
  1452. test si, si
  1453. js @@Done
  1454. test bx, bx
  1455. js @@Done
  1456. cmp si, [ViewWidth]
  1457. jg @@Done
  1458. cmp bx, [ViewHeight]
  1459. jg @@Done
  1460. @@ClipDone:
  1461. add si, [StartXViewPort]
  1462. add bx, [StartYViewPort]
  1463. {$ifdef FPC_MM_HUGE}
  1464. mov ax, SEG SegA000
  1465. mov es, ax
  1466. mov es, es:[SegA000]
  1467. {$else FPC_MM_HUGE}
  1468. mov es, [SegA000]
  1469. {$endif FPC_MM_HUGE}
  1470. { enable the set / reset function and load the color }
  1471. mov dx, 3ceh
  1472. mov ax, 0f01h
  1473. out dx, ax
  1474. { setup set/reset register }
  1475. mov ah, byte ptr [Pixel]
  1476. xor al, al
  1477. out dx, ax
  1478. { setup the bit mask register }
  1479. mov al, 8
  1480. { load the bitmask register }
  1481. mov cx, si
  1482. and cl, 07h
  1483. mov ah, 80h
  1484. shr ah, cl
  1485. out dx, ax
  1486. { get the x index and divide by 8 for 16-color }
  1487. mov cl, 3
  1488. shr si, cl
  1489. { determine the address }
  1490. inc cx { CL=4 }
  1491. shl bx, cl
  1492. mov di, bx
  1493. shl di, 1
  1494. shl di, 1
  1495. add di, bx
  1496. add di, si
  1497. add di, [VideoOfs]
  1498. { send the data through the display memory through set/reset }
  1499. mov bl,es:[di]
  1500. stosb
  1501. { reset for formal vga operation }
  1502. mov ax,0ff08h
  1503. out dx,ax
  1504. { restore enable set/reset register }
  1505. mov ax,0001h
  1506. out dx,ax
  1507. @@Done:
  1508. end;
  1509. {$endif asmgraph}
  1510. {$ifndef asmgraph}
  1511. Function GetPixel16(X,Y: smallint):ColorType;
  1512. Var dummy, offset: Word;
  1513. shift: byte;
  1514. Begin
  1515. X:= X + StartXViewPort;
  1516. Y:= Y + StartYViewPort;
  1517. offset := Y * 80 + (x shr 3) + VideoOfs;
  1518. PortW[$3ce] := $0004;
  1519. shift := 7 - (X and 7);
  1520. dummy := (Mem[Sega000:offset] shr shift) and 1;
  1521. Port[$3cf] := 1;
  1522. dummy := dummy or (((Mem[Sega000:offset] shr shift) and 1) shl 1);
  1523. Port[$3cf] := 2;
  1524. dummy := dummy or (((Mem[Sega000:offset] shr shift) and 1) shl 2);
  1525. Port[$3cf] := 3;
  1526. dummy := dummy or (((Mem[Sega000:offset] shr shift) and 1) shl 3);
  1527. GetPixel16 := dummy;
  1528. end;
  1529. {$else asmgraph}
  1530. Function GetPixel16(X,Y: smallint):ColorType;assembler;
  1531. asm
  1532. {$ifdef FPC_MM_HUGE}
  1533. mov ax, SEG SegA000
  1534. mov es, ax
  1535. mov es, es:[SegA000]
  1536. {$else FPC_MM_HUGE}
  1537. mov es, [SegA000]
  1538. {$endif FPC_MM_HUGE}
  1539. mov dx,03ceh
  1540. mov ax,0304h
  1541. out dx,ax
  1542. inc dx
  1543. mov di, [X] { Get X address }
  1544. add di, [StartXViewPort]
  1545. mov ax, di
  1546. mov cl, 3
  1547. shr di, cl
  1548. mov bx, [Y]
  1549. add bx, [StartYViewPort]
  1550. inc cx { CL=4 }
  1551. shl bx, cl { BX=16*(Y+StartYViewPort)*16 }
  1552. mov si, bx { SI=16*(Y+StartYViewPort)*16 }
  1553. shl si, 1 { SI=32*(Y+StartYViewPort)*32 }
  1554. shl si, 1 { SI=64*(Y+StartYViewPort)*64 }
  1555. add si, bx { SI=(64+16)*(Y+StartYViewPort)=80*(Y+StartYViewPort) }
  1556. add si, di { SI=correct offset into video segment }
  1557. add si, [VideoOfs] { Point to correct page offset... }
  1558. xchg ax, cx { 1 byte shorter than 'mov cx, ax' }
  1559. and cl,7
  1560. mov bh, 080h
  1561. shr bh, cl
  1562. { read plane 3 }
  1563. mov ah,es:[si] { read display memory }
  1564. and ah,bh { save bit in AH }
  1565. { read plane 2 }
  1566. mov al,2 { Select plane to read }
  1567. out dx,al
  1568. mov bl,es:[si]
  1569. and bl,bh
  1570. rol ah,1
  1571. or ah,bl { save bit in AH }
  1572. { read plane 1 }
  1573. dec ax { Select plane to read }
  1574. out dx,al
  1575. mov bl,es:[si]
  1576. and bl,bh
  1577. rol ah,1
  1578. or ah,bl { save bit in AH }
  1579. { read plane 0 }
  1580. dec ax { Select plane to read }
  1581. out dx,al
  1582. seges lodsb
  1583. and al,bh
  1584. rol ah,1
  1585. or al,ah { add previous bits from AH into AL }
  1586. inc cx
  1587. rol al,cl { 16-bit pixel in AX }
  1588. { 1 byte shorter than 'xor ah, ah'; will always set ah to 0, because sign(al)=0 }
  1589. cbw
  1590. {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
  1591. { 1 byte shorter than 'xor dx, dx'; will always set dx to 0, because sign(ah)=0 }
  1592. cwd
  1593. {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
  1594. end;
  1595. {$endif asmgraph}
  1596. Procedure GetScanLine16(x1, x2, y: smallint; var data);
  1597. var dummy: word;
  1598. Offset, count, count2, amount, index: word;
  1599. plane: byte;
  1600. Begin
  1601. inc(x1,StartXViewPort);
  1602. inc(x2,StartXViewPort);
  1603. {$ifdef logging}
  1604. LogLn('GetScanLine16 start, length to get: '+strf(x2-x1+1)+' at y = '+strf(y));
  1605. {$Endif logging}
  1606. offset := (Y + StartYViewPort) * 80 + (x1 shr 3) + VideoOfs;
  1607. {$ifdef logging}
  1608. LogLn('Offset: '+HexStr(offset,4)+' - ' + strf(offset));
  1609. {$Endif logging}
  1610. { first get enough pixels so offset is 16bit aligned }
  1611. amount := 0;
  1612. index := 0;
  1613. If ((x1 and 15) <> 0) Or
  1614. ((x2-x1+1) < 16) Then
  1615. Begin
  1616. If ((x2-x1+1) >= 16+16-(x1 and 15)) Then
  1617. amount := 16-(x1 and 15)
  1618. Else amount := x2-x1+1;
  1619. {$ifdef logging}
  1620. LogLn('amount to align to 16bits or to get all: ' + strf(amount));
  1621. {$Endif logging}
  1622. For count := 0 to amount-1 do
  1623. WordArray(Data)[Count] := getpixel16(x1-StartXViewPort+Count,y);
  1624. index := amount;
  1625. Inc(Offset,(amount+7) shr 3);
  1626. {$ifdef logging}
  1627. LogLn('offset now: '+HexStr(offset,4)+' - ' + strf(offset));
  1628. LogLn('index now: '+strf(index));
  1629. {$Endif logging}
  1630. End;
  1631. amount := x2-x1+1 - amount;
  1632. {$ifdef logging}
  1633. LogLn('amount left: ' + strf(amount));
  1634. {$Endif logging}
  1635. If amount = 0 Then Exit;
  1636. { first get everything from plane 3 (4th plane) }
  1637. PortW[$3ce] := $0304;
  1638. Count := 0;
  1639. For Count := 1 to (amount shr 4) Do
  1640. Begin
  1641. dummy := MemW[SegA000:offset+(Count-1)*2];
  1642. dummy :=
  1643. ((dummy and $ff) shl 8) or
  1644. ((dummy and $ff00) shr 8);
  1645. For Count2 := 15 downto 0 Do
  1646. Begin
  1647. WordArray(Data)[index+Count2] := Dummy and 1;
  1648. Dummy := Dummy shr 1;
  1649. End;
  1650. Inc(Index, 16);
  1651. End;
  1652. { Now get the data from the 3 other planes }
  1653. plane := 3;
  1654. Repeat
  1655. Dec(Index,Count*16);
  1656. Dec(plane);
  1657. Port[$3cf] := plane;
  1658. Count := 0;
  1659. For Count := 1 to (amount shr 4) Do
  1660. Begin
  1661. dummy := MemW[SegA000:offset+(Count-1)*2];
  1662. dummy :=
  1663. ((dummy and $ff) shl 8) or
  1664. ((dummy and $ff00) shr 8);
  1665. For Count2 := 15 downto 0 Do
  1666. Begin
  1667. WordArray(Data)[index+Count2] :=
  1668. (WordArray(Data)[index+Count2] shl 1) or (Dummy and 1);
  1669. Dummy := Dummy shr 1;
  1670. End;
  1671. Inc(Index, 16);
  1672. End;
  1673. Until plane = 0;
  1674. amount := amount and 15;
  1675. Dec(index);
  1676. {$ifdef Logging}
  1677. LogLn('Last array index written to: '+strf(index));
  1678. LogLn('amount left: '+strf(amount)+' starting at x = '+strf(index+1));
  1679. {$Endif logging}
  1680. dec(x1,startXViewPort);
  1681. For Count := 1 to amount Do
  1682. WordArray(Data)[index+Count] := getpixel16(x1+index+Count,y);
  1683. {$ifdef logging}
  1684. inc(x1,startXViewPort);
  1685. LogLn('First 16 bytes gotten with getscanline16: ');
  1686. If x2-x1+1 >= 16 Then
  1687. Count2 := 16
  1688. Else Count2 := x2-x1+1;
  1689. For Count := 0 to Count2-1 Do
  1690. Log(strf(WordArray(Data)[Count])+' ');
  1691. LogLn('');
  1692. If x2-x1+1 >= 16 Then
  1693. Begin
  1694. LogLn('Last 16 bytes gotten with getscanline16: ');
  1695. For Count := 15 downto 0 Do
  1696. Log(strf(WordArray(Data)[x2-x1-Count])+' ');
  1697. End;
  1698. LogLn('');
  1699. GetScanLineDefault(x1-StartXViewPort,x2-StartXViewPort,y,Data);
  1700. LogLn('First 16 bytes gotten with getscanlinedef: ');
  1701. If x2-x1+1 >= 16 Then
  1702. Count2 := 16
  1703. Else Count2 := x2-x1+1;
  1704. For Count := 0 to Count2-1 Do
  1705. Log(strf(WordArray(Data)[Count])+' ');
  1706. LogLn('');
  1707. If x2-x1+1 >= 16 Then
  1708. Begin
  1709. LogLn('Last 16 bytes gotten with getscanlinedef: ');
  1710. For Count := 15 downto 0 Do
  1711. Log(strf(WordArray(Data)[x2-x1-Count])+' ');
  1712. End;
  1713. LogLn('');
  1714. LogLn('GetScanLine16 end');
  1715. {$Endif logging}
  1716. End;
  1717. {$ifndef asmgraph}
  1718. Procedure DirectPutPixel16(X,Y : smallint);
  1719. { x,y -> must be in global coordinates. No clipping. }
  1720. var
  1721. color: word;
  1722. offset: word;
  1723. dummy: byte;
  1724. begin
  1725. If CurrentWriteMode <> NotPut Then
  1726. Color := CurrentColor
  1727. else Color := not CurrentColor;
  1728. case CurrentWriteMode of
  1729. XORPut:
  1730. PortW[$3ce]:=((3 shl 3) shl 8) or 3;
  1731. ANDPut:
  1732. PortW[$3ce]:=((1 shl 3) shl 8) or 3;
  1733. ORPut:
  1734. PortW[$3ce]:=((2 shl 3) shl 8) or 3;
  1735. {not needed, this is the default state (e.g. PutPixel16 requires it)}
  1736. {NormalPut, NotPut:
  1737. PortW[$3ce]:=$0003
  1738. else
  1739. PortW[$3ce]:=$0003}
  1740. end;
  1741. offset := Y * 80 + (X shr 3) + VideoOfs;
  1742. PortW[$3ce] := $f01;
  1743. PortW[$3ce] := Color shl 8;
  1744. PortW[$3ce] := ($8000 shr (X and 7)) or 8;
  1745. dummy := Mem[SegA000: offset];
  1746. Mem[Sega000: offset] := dummy;
  1747. PortW[$3ce] := $ff08;
  1748. PortW[$3ce] := $0001;
  1749. if (CurrentWriteMode = XORPut) or
  1750. (CurrentWriteMode = ANDPut) or
  1751. (CurrentWriteMode = ORPut) then
  1752. PortW[$3ce] := $0003;
  1753. end;
  1754. {$else asmgraph}
  1755. Procedure DirectPutPixel16(X,Y : smallint); assembler;
  1756. const
  1757. DataRotateRegTbl: array [NormalPut..NotPut] of Byte=($00,$18,$10,$08,$00);
  1758. { x,y -> must be in global coordinates. No clipping. }
  1759. asm
  1760. {$ifdef FPC_MM_HUGE}
  1761. mov ax, SEG SegA000
  1762. mov es, ax
  1763. mov es, es:[SegA000]
  1764. {$else FPC_MM_HUGE}
  1765. mov es, [SegA000]
  1766. {$endif FPC_MM_HUGE}
  1767. mov dx, 3ceh
  1768. xor ch, ch { Color mask = 0 }
  1769. mov bx, [CurrentWriteMode]
  1770. test bl, 4 { NotPut? }
  1771. jz @@NoNotPut
  1772. { NotPut }
  1773. mov ch, 15 { Color mask for NotPut }
  1774. @@NoNotPut:
  1775. mov ah, byte ptr [DataRotateRegTbl + bx]
  1776. test ah, ah
  1777. jz @@NormalPut
  1778. mov al, 3
  1779. out dx, ax
  1780. @@NormalPut:
  1781. { enable the set / reset function and load the color }
  1782. mov ax, 0f01h
  1783. out dx, ax
  1784. { setup set/reset register }
  1785. mov ah, byte ptr [CurrentColor]
  1786. xor ah, ch { Maybe apply the NotPut mask }
  1787. xor al, al
  1788. out dx, ax
  1789. { setup the bit mask register }
  1790. mov al, 8
  1791. { load the bitmask register }
  1792. mov si, [X]
  1793. mov cx, si
  1794. and cl, 07h
  1795. mov ah, 80h
  1796. shr ah, cl
  1797. out dx, ax
  1798. { get the x index and divide by 8 for 16-color }
  1799. mov cl, 3
  1800. shr si, cl
  1801. { determine the address }
  1802. mov bx, [Y]
  1803. inc cx { CL=4 }
  1804. shl bx, cl
  1805. mov di, bx
  1806. shl di, 1
  1807. shl di, 1
  1808. add di, bx
  1809. add di, si
  1810. add di, [VideoOfs] { add correct page }
  1811. { send the data through the display memory through set/reset }
  1812. mov al,es:[di]
  1813. stosb
  1814. { reset for formal vga operation }
  1815. mov ax,0ff08h
  1816. out dx,ax
  1817. { restore enable set/reset register }
  1818. mov ax,0001h
  1819. out dx,ax
  1820. test bl, 3 { NormalPut or NotPut? }
  1821. jz @@Done { If yes, skip }
  1822. mov ax,0003h
  1823. out dx,ax
  1824. @@Done:
  1825. end;
  1826. {$endif asmgraph}
  1827. procedure HLine16(x,x2,y: smallint);
  1828. var
  1829. xtmp: smallint;
  1830. ScrOfs,HLength : word;
  1831. LMask,RMask : byte;
  1832. Begin
  1833. { must we swap the values? }
  1834. if x > x2 then
  1835. Begin
  1836. xtmp := x2;
  1837. x2 := x;
  1838. x:= xtmp;
  1839. end;
  1840. { First convert to global coordinates }
  1841. X := X + StartXViewPort;
  1842. X2 := X2 + StartXViewPort;
  1843. Y := Y + StartYViewPort;
  1844. if ClipPixels then
  1845. Begin
  1846. if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  1847. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  1848. exit;
  1849. end;
  1850. ScrOfs:=y*ScrWidth+x div 8 + VideoOfs;
  1851. HLength:=x2 div 8-x div 8;
  1852. LMask:=$ff shr (x and 7);
  1853. {$push}
  1854. {$r-}
  1855. {$q-}
  1856. RMask:=$ff shl (7-(x2 and 7));
  1857. {$pop}
  1858. if HLength=0 then
  1859. LMask:=LMask and RMask;
  1860. If CurrentWriteMode <> NotPut Then
  1861. PortW[$3ce]:= CurrentColor shl 8
  1862. else PortW[$3ce]:= (not CurrentColor) shl 8;
  1863. PortW[$3ce]:=$0f01;
  1864. case CurrentWriteMode of
  1865. XORPut:
  1866. PortW[$3ce]:=((3 shl 3) shl 8) or 3;
  1867. ANDPut:
  1868. PortW[$3ce]:=((1 shl 3) shl 8) or 3;
  1869. ORPut:
  1870. PortW[$3ce]:=((2 shl 3) shl 8) or 3;
  1871. NormalPut, NotPut:
  1872. PortW[$3ce]:=$0003
  1873. else
  1874. PortW[$3ce]:=$0003
  1875. end;
  1876. PortW[$3ce]:=(LMask shl 8) or 8;
  1877. {$push}
  1878. {$r-}
  1879. {$q-}
  1880. Mem[SegA000:ScrOfs]:=Mem[SegA000:ScrOfs]+1;
  1881. {$pop}
  1882. {Port[$3ce]:=8;}{not needed, the register is already selected}
  1883. if HLength>0 then
  1884. begin
  1885. dec(HLength);
  1886. inc(ScrOfs);
  1887. if HLength>0 then
  1888. begin
  1889. Port[$3cf]:=$ff;
  1890. {$ifndef tp}
  1891. seg_bytemove(SegA000,ScrOfs,SegA000,ScrOfs,HLength);
  1892. {$else}
  1893. move(Ptr(SegA000,ScrOfs)^, Ptr(SegA000,ScrOfs)^, HLength);
  1894. {$endif}
  1895. ScrOfs:=ScrOfs+HLength;
  1896. end;
  1897. Port[$3cf]:=RMask;
  1898. {$push}
  1899. {$r-}
  1900. {$q-}
  1901. Mem[Sega000:ScrOfs]:=Mem[SegA000:ScrOfs]+1;
  1902. {$pop}
  1903. end;
  1904. { clean up }
  1905. {Port[$3cf]:=0;}{not needed, the register is reset by the next operation:}
  1906. PortW[$3ce]:=$ff08;
  1907. PortW[$3ce]:=$0001;
  1908. PortW[$3ce]:=$0003;
  1909. end;
  1910. procedure VLine16(x,y,y2: smallint);
  1911. var
  1912. ytmp,i: smallint;
  1913. ScrOfs: word;
  1914. BitMask : byte;
  1915. Begin
  1916. { must we swap the values? }
  1917. if y > y2 then
  1918. Begin
  1919. ytmp := y2;
  1920. y2 := y;
  1921. y:= ytmp;
  1922. end;
  1923. { First convert to global coordinates }
  1924. X := X + StartXViewPort;
  1925. Y2 := Y2 + StartYViewPort;
  1926. Y := Y + StartYViewPort;
  1927. if ClipPixels then
  1928. Begin
  1929. if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
  1930. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  1931. exit;
  1932. end;
  1933. ScrOfs:=y*ScrWidth+x div 8 + VideoOfs;
  1934. BitMask:=$80 shr (x and 7);
  1935. If CurrentWriteMode <> NotPut Then
  1936. PortW[$3ce]:= (CurrentColor shl 8)
  1937. else PortW[$3ce]:= (not CurrentColor) shl 8;
  1938. PortW[$3ce]:=$0f01;
  1939. PortW[$3ce]:=(BitMask shl 8) or 8;
  1940. case CurrentWriteMode of
  1941. XORPut:
  1942. PortW[$3ce]:=((3 shl 3) shl 8) or 3;
  1943. ANDPut:
  1944. PortW[$3ce]:=((1 shl 3) shl 8) or 3;
  1945. ORPut:
  1946. PortW[$3ce]:=((2 shl 3) shl 8) or 3;
  1947. NormalPut, NotPut:
  1948. PortW[$3ce]:=$0003
  1949. else
  1950. PortW[$3ce]:=$0003
  1951. end;
  1952. for i:=y to y2 do
  1953. begin
  1954. {$push}
  1955. {$r-}
  1956. {$q-}
  1957. Mem[SegA000:ScrOfs]:=Mem[Sega000:ScrOfs]+1;
  1958. {$pop}
  1959. ScrOfs:=ScrOfs+ScrWidth;
  1960. end;
  1961. { clean up }
  1962. {Port[$3cf]:=0;}{not needed, the register is reset by the next operation}
  1963. PortW[$3ce]:=$ff08;
  1964. PortW[$3ce]:=$0001;
  1965. PortW[$3ce]:=$0003;
  1966. End;
  1967. procedure SetVisual200_350(page: word);
  1968. begin
  1969. if page > HardwarePages then exit;
  1970. asm
  1971. mov al, byte ptr [page] { only lower byte is supported. }
  1972. mov ah,05h
  1973. push ds
  1974. push bp
  1975. int 10h
  1976. pop bp
  1977. pop ds
  1978. end ['DX','CX','BX','AX','SI','DI'];
  1979. end;
  1980. procedure SetActive200(page: word);
  1981. { four page support... }
  1982. begin
  1983. case page of
  1984. 0 : VideoOfs := 0;
  1985. 1 : VideoOfs := 16384;
  1986. 2 : VideoOfs := 32768;
  1987. 3 : VideoOfs := 49152;
  1988. else
  1989. VideoOfs := 0;
  1990. end;
  1991. end;
  1992. procedure SetActive350(page: word);
  1993. { one page supPort... }
  1994. begin
  1995. case page of
  1996. 0 : VideoOfs := 0;
  1997. 1 : VideoOfs := 32768;
  1998. else
  1999. VideoOfs := 0;
  2000. end;
  2001. end;
  2002. {************************************************************************}
  2003. {* 320x200x256c Routines *}
  2004. {************************************************************************}
  2005. Procedure Init320;
  2006. begin
  2007. InitInt10hMode($13);
  2008. end;
  2009. {$ifndef asmgraph}
  2010. Procedure PutPixel320(X,Y : smallint; Pixel: ColorType);
  2011. { x,y -> must be in local coordinates. Clipping if required. }
  2012. Begin
  2013. { verify clipping and then convert to absolute coordinates...}
  2014. if ClipPixels then
  2015. begin
  2016. if (X < 0) or (X > ViewWidth) then
  2017. exit;
  2018. if (Y < 0) or (Y > ViewHeight) then
  2019. exit;
  2020. end;
  2021. X:= X + StartXViewPort;
  2022. Y:= Y + StartYViewPort;
  2023. Mem[SegA000:Y*320+X] := Pixel;
  2024. end;
  2025. {$else asmgraph}
  2026. Procedure PutPixel320(X,Y : smallint; Pixel: ColorType); assembler;
  2027. asm
  2028. mov ax, [Y]
  2029. mov di, [X]
  2030. cmp byte ptr [ClipPixels], 0
  2031. je @@ClipDone
  2032. test ax, ax
  2033. js @@Done
  2034. test di, di
  2035. js @@Done
  2036. cmp ax, [ViewHeight]
  2037. jg @@Done
  2038. cmp di, [ViewWidth]
  2039. jg @@Done
  2040. @@ClipDone:
  2041. {$ifdef FPC_MM_HUGE}
  2042. mov bx, SEG SegA000
  2043. mov es, bx
  2044. mov es, es:[SegA000]
  2045. {$else FPC_MM_HUGE}
  2046. mov es, [SegA000]
  2047. {$endif FPC_MM_HUGE}
  2048. add ax, [StartYViewPort]
  2049. add di, [StartXViewPort]
  2050. xchg ah, al { The value of Y must be in AH }
  2051. add di, ax
  2052. shr ax, 1
  2053. shr ax, 1
  2054. add di, ax
  2055. mov al, byte ptr [Pixel]
  2056. stosb
  2057. @@Done:
  2058. end;
  2059. {$endif asmgraph}
  2060. {$ifndef asmgraph}
  2061. Function GetPixel320(X,Y: smallint):ColorType;
  2062. Begin
  2063. X:= X + StartXViewPort;
  2064. Y:= Y + StartYViewPort;
  2065. GetPixel320 := Mem[SegA000:Y*320+X];
  2066. end;
  2067. {$else asmgraph}
  2068. Function GetPixel320(X,Y: smallint):ColorType; assembler;
  2069. asm
  2070. {$ifdef FPC_MM_HUGE}
  2071. mov ax, SEG SegA000
  2072. mov es, ax
  2073. mov es, es:[SegA000]
  2074. {$else FPC_MM_HUGE}
  2075. mov es, [SegA000]
  2076. {$endif FPC_MM_HUGE}
  2077. mov ax, [Y]
  2078. add ax, [StartYViewPort]
  2079. mov si, [X]
  2080. add si, [StartXViewPort]
  2081. xchg ah, al { The value of Y must be in AH }
  2082. add si, ax
  2083. shr ax, 1
  2084. shr ax, 1
  2085. add si, ax
  2086. seges lodsb
  2087. xor ah, ah
  2088. {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
  2089. { 1 byte shorter than 'xor dx, dx'; will always set dx to 0, because sign(ah)=0 }
  2090. cwd
  2091. {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
  2092. end;
  2093. {$endif asmgraph}
  2094. {$ifndef asmgraph}
  2095. Procedure DirectPutPixel320(X,Y : smallint);
  2096. { x,y -> must be in global coordinates. No clipping. }
  2097. var offset: word;
  2098. dummy: Byte;
  2099. begin
  2100. dummy := CurrentColor;
  2101. offset := y * 320 + x;
  2102. case CurrentWriteMode of
  2103. XorPut: dummy := dummy xor Mem[Sega000:offset];
  2104. OrPut: dummy := dummy or Mem[Sega000:offset];
  2105. AndPut: dummy := dummy and Mem[SegA000:offset];
  2106. NotPut: dummy := Not dummy;
  2107. end;
  2108. Mem[SegA000:offset] := dummy;
  2109. end;
  2110. {$else asmgraph}
  2111. Procedure DirectPutPixel320(X,Y : smallint); assembler;
  2112. asm
  2113. {$ifdef FPC_MM_HUGE}
  2114. mov ax, SEG SegA000
  2115. mov es, ax
  2116. mov es, es:[SegA000]
  2117. {$else FPC_MM_HUGE}
  2118. mov es, [SegA000]
  2119. {$endif FPC_MM_HUGE}
  2120. mov ax, [Y]
  2121. mov di, [X]
  2122. xchg ah, al { The value of Y must be in AH }
  2123. add di, ax
  2124. shr ax, 1
  2125. shr ax, 1
  2126. add di, ax
  2127. mov al, byte ptr [CurrentColor]
  2128. { check write mode }
  2129. mov bl, byte ptr [CurrentWriteMode]
  2130. cmp bl, NormalPut
  2131. jne @@1
  2132. stosb
  2133. jmp @Done
  2134. @@1:
  2135. cmp bl, XorPut
  2136. jne @@2
  2137. xor es:[di], al
  2138. jmp @Done
  2139. @@2:
  2140. cmp bl, OrPut
  2141. jne @@3
  2142. or es:[di], al
  2143. jmp @Done
  2144. @@3:
  2145. cmp bl, AndPut
  2146. jne @NotPutMode
  2147. and es:[di], al
  2148. jmp @Done
  2149. @NotPutMode:
  2150. not al
  2151. stosb
  2152. @Done:
  2153. end;
  2154. {$endif asmgraph}
  2155. procedure SetVisual320(page: word);
  2156. { no page supPort... }
  2157. begin
  2158. end;
  2159. procedure SetActive320(page: word);
  2160. { no page supPort... }
  2161. begin
  2162. end;
  2163. {************************************************************************}
  2164. {* Mode-X related routines *}
  2165. {************************************************************************}
  2166. const CrtAddress: word = 0;
  2167. {$ifndef asmgraph}
  2168. procedure InitModeX;
  2169. begin
  2170. {see if we are using color-/monochrome display}
  2171. if (Port[$3CC] and 1) <> 0 then
  2172. CrtAddress := $3D4 { color }
  2173. else
  2174. CrtAddress := $3B4; { monochrome }
  2175. InitInt10hMode($13);
  2176. Port[$3C4] := $04; {select memory-mode-register at sequencer port }
  2177. { bit 3 := 0: don't chain the 4 planes }
  2178. { bit 2 := 1: no odd/even mechanism }
  2179. Port[$3C5] := (Port[$3C5] and $F7) or $04;
  2180. Port[$3C4] := $02; {s.a.: address sequencer reg. 2 (=map-mask),... }
  2181. Port[$3C5] := $0F; {...and allow access to all 4 bit maps }
  2182. { starting with segment A000h, set 8000h logical words = 4*8000h
  2183. physical words (because of 4 bitplanes) to 0 }
  2184. asm
  2185. {$ifdef FPC_MM_HUGE}
  2186. MOV AX,SEG SegA000
  2187. MOV ES,AX
  2188. MOV ES,ES:[SegA000]
  2189. {$else FPC_MM_HUGE}
  2190. MOV ES, [SegA000]
  2191. {$endif FPC_MM_HUGE}
  2192. XOR DI,DI
  2193. XOR AX,AX
  2194. MOV CX,8000h
  2195. CLD
  2196. REP STOSW
  2197. end ['AX','CX','DI'];
  2198. {address the underline-location-register at the CRT-controller
  2199. port, read out the according data register: }
  2200. Port[CRTAddress] := $14;
  2201. {bit 6:=0: no double word addressing scheme in video RAM }
  2202. Port[CRTAddress+1] := Port[CRTAddress+1] and $BF;
  2203. Port[CRTAddress] := $17; {select mode control register }
  2204. {bit 6 := 1: memory access scheme=linear bit array }
  2205. Port[CRTAddress+1] := Port[CRTAddress+1] or $40;
  2206. end;
  2207. {$else asmgraph}
  2208. procedure InitModeX; assembler;
  2209. asm
  2210. {see if we are using color-/monochrome display}
  2211. MOV DX,3CCh {use output register: }
  2212. IN AL,DX
  2213. TEST AL,1 {is it a color display? }
  2214. MOV DX,3D4h
  2215. JNZ @L1 {yes }
  2216. MOV DX,3B4h {no }
  2217. @L1: {DX = 3B4h / 3D4h = CRTAddress-register for monochrome/color}
  2218. MOV CRTAddress,DX
  2219. MOV AX, 0013h
  2220. CMP BYTE PTR [DontClearGraphMemory],0
  2221. JE @L2
  2222. OR AL, 080h
  2223. @L2:
  2224. push ds
  2225. push bp
  2226. INT 10h
  2227. pop bp
  2228. pop ds
  2229. MOV DX,03C4h {select memory-mode-register at sequencer Port }
  2230. MOV AL,04
  2231. OUT DX,AL
  2232. INC DX {read in data via the according data register }
  2233. IN AL,DX
  2234. AND AL,0F7h {bit 3 := 0: don't chain the 4 planes}
  2235. OR AL,04 {bit 2 := 1: no odd/even mechanism }
  2236. OUT DX,AL {activate new settings }
  2237. DEC DX {s.a.: address sequencer reg. 2 (=map-mask),... }
  2238. MOV AL,02
  2239. OUT DX,AL
  2240. INC DX
  2241. MOV AL,0Fh {...and allow access to all 4 bit maps }
  2242. OUT DX,AL
  2243. {starting with segment A000h, set 8000h logical }
  2244. {words = 4*8000h physical words (because of 4 }
  2245. {bitplanes) to 0 }
  2246. {$ifdef FPC_MM_HUGE}
  2247. MOV AX,SEG SegA000
  2248. MOV ES,AX
  2249. MOV ES,ES:[SegA000]
  2250. {$else FPC_MM_HUGE}
  2251. MOV ES, [SegA000]
  2252. {$endif FPC_MM_HUGE}
  2253. XOR DI,DI
  2254. XOR AX,AX
  2255. MOV CX,8000h
  2256. CLD
  2257. REP STOSW
  2258. MOV DX,CRTAddress {address the underline-location-register at }
  2259. MOV AL,14h {the CRT-controller Port, read out the according }
  2260. OUT DX,AL {data register: }
  2261. INC DX
  2262. IN AL,DX
  2263. AND AL,0BFh {bit 6:=0: no double word addressing scheme in}
  2264. OUT DX,AL {video RAM }
  2265. DEC DX
  2266. MOV AL,17h {select mode control register }
  2267. OUT DX,AL
  2268. INC DX
  2269. IN AL,DX
  2270. OR AL,40h {bit 6 := 1: memory access scheme=linear bit array }
  2271. OUT DX,AL
  2272. end;
  2273. {$endif asmgraph}
  2274. {$undef asmgraph}
  2275. {$ifndef asmgraph}
  2276. function GetPixelX(X,Y: smallint): ColorType;
  2277. var offset: word;
  2278. begin
  2279. X := X + StartXViewPort;
  2280. Y := Y + StartYViewPort;
  2281. offset := y * 80 + x shr 2 + VideoOfs;
  2282. PortW[$3ce] := ((x and 3) shl 8) + 4;
  2283. GetPixelX := Mem[SegA000:offset];
  2284. end;
  2285. {$else asmgraph}
  2286. function GetPixelX(X,Y: smallint): ColorType; assembler;
  2287. asm
  2288. {$ifdef FPC_MM_HUGE}
  2289. mov ax, SEG SegA000
  2290. mov es, ax
  2291. mov es, es:[SegA000]
  2292. {$else FPC_MM_HUGE}
  2293. mov es, [SegA000]
  2294. {$endif FPC_MM_HUGE}
  2295. mov di,[Y] ; (* DI = Y coordinate *)
  2296. add di,[StartYViewPort]
  2297. (* Multiply by 80 start *)
  2298. mov cl, 4
  2299. shl di, cl
  2300. mov bx, di
  2301. shl di, 1
  2302. shl di, 1
  2303. add di, bx ; (* Multiply Value by 80 *)
  2304. (* End multiply by 80 *)
  2305. mov cx, [X]
  2306. add cx, [StartXViewPort]
  2307. mov ax, cx
  2308. {DI = Y * LINESIZE, BX = X, coordinates admissible}
  2309. shr ax, 1 ; (* Faster on 286/86 machines *)
  2310. shr ax, 1
  2311. add di, ax ; {DI = Y * LINESIZE + (X SHR 2) }
  2312. add di, [VideoOfs] ; (* Pointing at start of Active page *)
  2313. (* Select plane to use *)
  2314. mov dx, 03c4h
  2315. mov ax, FirstPlane ; (* Map Mask & Plane Select Register *)
  2316. and cl, 03h ; (* Get Plane Bits *)
  2317. shl ah, cl ; (* Get Plane Select Value *)
  2318. out dx, ax
  2319. (* End selection of plane *)
  2320. mov al, ES:[DI]
  2321. xor ah, ah
  2322. {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
  2323. { 1 byte shorter than 'xor dx, dx'; will always set dx to 0, because sign(ah)=0 }
  2324. cwd
  2325. {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
  2326. end;
  2327. {$endif asmgraph}
  2328. procedure SetVisualX(page: word);
  2329. { 4 page supPort... }
  2330. Procedure SetVisibleStart(AOffset: word); Assembler;
  2331. (* Select where the left corner of the screen will be *)
  2332. { By Matt Pritchard }
  2333. asm
  2334. { Wait if we are currently in a Vertical Retrace }
  2335. MOV DX, INPUT_1 { Input Status #1 Register }
  2336. @DP_WAIT0:
  2337. IN AL, DX { Get VGA status }
  2338. AND AL, VERT_RETRACE { In Display mode yet? }
  2339. JNZ @DP_WAIT0 { If Not, wait for it }
  2340. { Set the Start Display Address to the new page }
  2341. MOV DX, CRTC_Index { We Change the VGA Sequencer }
  2342. MOV AL, START_DISP_LO { Display Start Low Register }
  2343. MOV AH, BYTE PTR [AOffset] { Low 8 Bits of Start Addr }
  2344. OUT DX, AX { Set Display Addr Low }
  2345. MOV AL, START_DISP_HI { Display Start High Register }
  2346. MOV AH, BYTE PTR [AOffset+1] { High 8 Bits of Start Addr }
  2347. OUT DX, AX { Set Display Addr High }
  2348. { Wait for a Vertical Retrace to smooth out things }
  2349. MOV DX, INPUT_1 { Input Status #1 Register }
  2350. @DP_WAIT1:
  2351. IN AL, DX { Get VGA status }
  2352. AND AL, VERT_RETRACE { Vertical Retrace Start? }
  2353. JZ @DP_WAIT1 { If Not, wait for it }
  2354. { Now Set Display Starting Address }
  2355. end;
  2356. {$ifdef fpc}
  2357. {$undef asmgraph}
  2358. {$endif fpc}
  2359. begin
  2360. Case page of
  2361. 0: SetVisibleStart(0);
  2362. 1: SetVisibleStart(16000);
  2363. 2: SetVisibleStart(32000);
  2364. 3: SetVisibleStart(48000);
  2365. else
  2366. SetVisibleStart(0);
  2367. end;
  2368. end;
  2369. procedure SetActiveX(page: word);
  2370. { 4 page supPort... }
  2371. begin
  2372. case page of
  2373. 0: VideoOfs := 0;
  2374. 1: VideoOfs := 16000;
  2375. 2: VideoOfs := 32000;
  2376. 3: VideoOfs := 48000;
  2377. else
  2378. VideoOfs:=0;
  2379. end;
  2380. end;
  2381. Procedure PutPixelX(X,Y: smallint; color:ColorType);
  2382. {$ifndef asmgraph}
  2383. var offset: word;
  2384. {$endif asmgraph}
  2385. begin
  2386. { verify clipping and then convert to absolute coordinates...}
  2387. if ClipPixels then
  2388. begin
  2389. if (X < 0) or (X > ViewWidth) then
  2390. exit;
  2391. if (Y < 0) or (Y > ViewHeight) then
  2392. exit;
  2393. end;
  2394. X:= X + StartXViewPort;
  2395. Y:= Y + StartYViewPort;
  2396. {$ifndef asmgraph}
  2397. offset := y * 80 + x shr 2 + VideoOfs;
  2398. PortW[$3c4] := (hi(word(FirstPlane)) shl 8) shl (x and 3)+ lo(word(FirstPlane));
  2399. Mem[SegA000:offset] := color;
  2400. {$else asmgraph}
  2401. asm
  2402. push ax
  2403. push bx
  2404. push cx
  2405. push dx
  2406. push es
  2407. push di
  2408. mov di,[Y] ; (* DI = Y coordinate *)
  2409. (* Multiply by 80 start *)
  2410. mov bx, di
  2411. shl di, 6 ; (* Faster on 286/386/486 machines *)
  2412. shl bx, 4
  2413. add di, bx ; (* Multiply Value by 80 *)
  2414. (* End multiply by 80 *)
  2415. mov cx, [X]
  2416. mov ax, cx
  2417. {DI = Y * LINESIZE, BX = X, coordinates admissible}
  2418. shr ax, 2
  2419. add di, ax ; {DI = Y * LINESIZE + (X SHR 2) }
  2420. add di, [VideoOfs] ; (* Pointing at start of Active page *)
  2421. (* Select plane to use *)
  2422. mov dx, 03c4h
  2423. mov ax, FirstPlane ; (* Map Mask & Plane Select Register *)
  2424. and cl, 03h ; (* Get Plane Bits *)
  2425. shl ah, cl ; (* Get Plane Select Value *)
  2426. out dx, ax
  2427. (* End selection of plane *)
  2428. mov es,[SegA000]
  2429. mov ax,[Color] ; { only lower byte is used. }
  2430. cmp [CurrentWriteMode],XORPut { check write mode }
  2431. jne @MOVMode
  2432. mov ah,es:[di] { read the byte... }
  2433. xor al,ah { xor it and return value into AL }
  2434. @MovMode:
  2435. mov es:[di], al
  2436. pop di
  2437. pop es
  2438. pop dx
  2439. pop cx
  2440. pop bx
  2441. pop ax
  2442. end;
  2443. {$endif asmgraph}
  2444. end;
  2445. Procedure DirectPutPixelX(X,Y: smallint);
  2446. { x,y -> must be in global coordinates. No clipping. }
  2447. {$ifndef asmgraph}
  2448. Var offset: Word;
  2449. dummy: Byte;
  2450. begin
  2451. offset := y * 80 + x shr 2 + VideoOfs;
  2452. case CurrentWriteMode of
  2453. XorPut:
  2454. begin
  2455. PortW[$3ce] := ((x and 3) shl 8) + 4;
  2456. dummy := CurrentColor xor Mem[Sega000: offset];
  2457. end;
  2458. OrPut:
  2459. begin
  2460. PortW[$3ce] := ((x and 3) shl 8) + 4;
  2461. dummy := CurrentColor or Mem[Sega000: offset];
  2462. end;
  2463. AndPut:
  2464. begin
  2465. PortW[$3ce] := ((x and 3) shl 8) + 4;
  2466. dummy := CurrentColor and Mem[Sega000: offset];
  2467. end;
  2468. NotPut: dummy := Not CurrentColor;
  2469. else dummy := CurrentColor;
  2470. end;
  2471. PortW[$3c4] := (hi(word(FirstPlane)) shl 8) shl (x and 3)+ lo(word(FirstPlane));
  2472. Mem[Sega000: offset] := Dummy;
  2473. end;
  2474. {$else asmgraph}
  2475. { note: still needs or/and/notput support !!!!! (JM) }
  2476. Assembler;
  2477. asm
  2478. push ax
  2479. push bx
  2480. push cx
  2481. push dx
  2482. push es
  2483. push di
  2484. {$IFDEF REGCALL}
  2485. mov cl, al
  2486. mov di, dx
  2487. {$ELSE REGCALL}
  2488. mov cx, [X]
  2489. mov ax, cx
  2490. mov di, [Y] ; (* DI = Y coordinate *)
  2491. {$ENDIF REGCALL}
  2492. (* Multiply by 80 start *)
  2493. mov bx, di
  2494. shl di, 6 ; (* Faster on 286/386/486 machines *)
  2495. shl bx, 4
  2496. add di, bx ; (* Multiply Value by 80 *)
  2497. (* End multiply by 80 *)
  2498. {DI = Y * LINESIZE, BX = X, coordinates admissible}
  2499. shr ax, 2
  2500. add di, ax ; {DI = Y * LINESIZE + (X SHR 2) }
  2501. add di, [VideoOfs] ; (* Pointing at start of Active page *)
  2502. (* Select plane to use *)
  2503. mov dx, 03c4h
  2504. mov ax, FirstPlane ; (* Map Mask & Plane Select Register *)
  2505. and cl, 03h ; (* Get Plane Bits *)
  2506. shl ah, cl ; (* Get Plane Select Value *)
  2507. out dx, ax
  2508. (* End selection of plane *)
  2509. mov es,[SegA000]
  2510. mov ax,[CurrentColor] ; { only lower byte is used. }
  2511. cmp [CurrentWriteMode],XORPut { check write mode }
  2512. jne @MOVMode
  2513. mov ah,es:[di] { read the byte... }
  2514. xor al,ah { xor it and return value into AL }
  2515. @MovMode:
  2516. mov es:[di], al
  2517. pop di
  2518. pop es
  2519. pop dx
  2520. pop cx
  2521. pop bx
  2522. pop ax
  2523. end;
  2524. {$endif asmgraph}
  2525. {************************************************************************}
  2526. {* General routines *}
  2527. {************************************************************************}
  2528. var
  2529. SavePtr : pointer; { pointer to video state }
  2530. { CrtSavePtr: pointer;} { pointer to video state when CrtMode gets called }
  2531. StateSize: word; { size in 64 byte blocks for video state }
  2532. VideoMode: byte; { old video mode before graph mode }
  2533. SaveSupPorted : Boolean; { Save/Restore video state supPorted? }
  2534. Procedure SaveStateVGA;
  2535. var
  2536. regs: Registers;
  2537. begin
  2538. SaveSupPorted := FALSE;
  2539. SavePtr := nil;
  2540. { Get the video mode }
  2541. regs.ah:=$0f;
  2542. intr($10,regs);
  2543. VideoMode:=regs.al;
  2544. { saving/restoring video state screws up Windows (JM) }
  2545. if inWindows then
  2546. exit;
  2547. { Prepare to save video state...}
  2548. regs.ax:=$1C00; { get buffer size to save state }
  2549. regs.cx:=%00000111; { Save DAC / Data areas / Hardware states }
  2550. intr($10,regs);
  2551. StateSize:=regs.bx;
  2552. SaveSupPorted:=(regs.al=$1c);
  2553. if SaveSupPorted then
  2554. begin
  2555. GetMem(SavePtr, 64*StateSize); { values returned in 64-byte blocks }
  2556. if not assigned(SavePtr) then
  2557. RunError(203);
  2558. { call the real mode interrupt ... }
  2559. regs.ax := $1C01; { save the state buffer }
  2560. regs.cx := $07; { Save DAC / Data areas / Hardware states }
  2561. regs.es := Seg(SavePtr^);
  2562. regs.bx := Ofs(SavePtr^);
  2563. Intr($10,regs);
  2564. { restore state, according to Ralph Brown Interrupt list }
  2565. { some BIOS corrupt the hardware after a save... }
  2566. regs.ax := $1C02; { restore the state buffer }
  2567. regs.cx := $07; { rest DAC / Data areas / Hardware states }
  2568. regs.es := Seg(SavePtr^);
  2569. regs.bx := Ofs(SavePtr^);
  2570. Intr($10,regs);
  2571. end;
  2572. end;
  2573. procedure RestoreStateVGA;
  2574. var
  2575. regs:Registers;
  2576. SavePtrCopy: Pointer;
  2577. begin
  2578. { go back to the old video mode...}
  2579. regs.ax:=VideoMode;
  2580. intr($10,regs);
  2581. { then restore all state information }
  2582. if assigned(SavePtr) and SaveSupPorted then
  2583. begin
  2584. regs.ax := $1C02; { restore the state buffer }
  2585. regs.cx := $07; { rest DAC / Data areas / Hardware states }
  2586. regs.es := Seg(SavePtr^);
  2587. regs.bx := Ofs(SavePtr^);
  2588. Intr($10,regs);
  2589. SavePtrCopy := SavePtr;
  2590. SavePtr := nil;
  2591. FreeMem(SavePtrCopy, 64*StateSize);
  2592. end;
  2593. end;
  2594. Procedure SetVGARGBAllPalette(const Palette:PaletteType);
  2595. var
  2596. c: byte;
  2597. begin
  2598. { wait for vertical retrace start/end}
  2599. while (port[$3da] and $8) <> 0 do;
  2600. while (port[$3da] and $8) = 0 do;
  2601. If MaxColor = 16 Then
  2602. begin
  2603. for c := 0 to 15 do
  2604. begin
  2605. { translate the color number for 16 color mode }
  2606. portb[$3c8] := toRealCols16[c];
  2607. portb[$3c9] := palette.colors[c].red shr 2;
  2608. portb[$3c9] := palette.colors[c].green shr 2;
  2609. portb[$3c9] := palette.colors[c].blue shr 2;
  2610. end
  2611. end
  2612. else
  2613. begin
  2614. portb[$3c8] := 0;
  2615. for c := 0 to 255 do
  2616. begin
  2617. { no need to set port[$3c8] every time if you set the entries }
  2618. { for successive colornumbers (JM) }
  2619. portb[$3c9] := palette.colors[c].red shr 2;
  2620. portb[$3c9] := palette.colors[c].green shr 2;
  2621. portb[$3c9] := palette.colors[c].blue shr 2;
  2622. end
  2623. end;
  2624. End;
  2625. { VGA is never a direct color mode, so no need to check ... }
  2626. Procedure SetVGARGBPalette(ColorNum, RedValue, GreenValue,
  2627. BlueValue : smallint);
  2628. begin
  2629. { translate the color number for 16 color mode }
  2630. If MaxColor = 16 Then
  2631. ColorNum := ToRealCols16[ColorNum];
  2632. asm
  2633. { on some hardware - there is a snow like effect }
  2634. { when changing the palette register directly }
  2635. { so we wait for a vertical retrace start period. }
  2636. push ax
  2637. push dx
  2638. mov dx, $03da
  2639. @1:
  2640. in al, dx { Get input status register }
  2641. test al, $08 { check if in vertical retrace }
  2642. jnz @1 { yes, complete it }
  2643. { we have to wait for the next }
  2644. { retrace to assure ourselves }
  2645. { that we have time to complete }
  2646. { the DAC operation within }
  2647. { the vertical retrace period }
  2648. @2:
  2649. in al, dx
  2650. test al, $08
  2651. jz @2 { repeat until vertical retrace start }
  2652. mov dx, $03c8 { Set color register address to use }
  2653. mov ax, [ColorNum]
  2654. out dx, al
  2655. inc dx { Point to DAC registers }
  2656. mov ax, [RedValue] { Get RedValue }
  2657. shr ax, 1
  2658. shr ax, 1
  2659. out dx, al
  2660. mov ax, [GreenValue]{ Get RedValue }
  2661. shr ax, 1
  2662. shr ax, 1
  2663. out dx, al
  2664. mov ax, [BlueValue] { Get RedValue }
  2665. shr ax, 1
  2666. shr ax, 1
  2667. out dx, al
  2668. pop dx
  2669. pop ax
  2670. end
  2671. End;
  2672. { VGA is never a direct color mode, so no need to check ... }
  2673. Procedure GetVGARGBPalette(ColorNum: smallint; Var
  2674. RedValue, GreenValue, BlueValue : smallint);
  2675. begin
  2676. If MaxColor = 16 Then
  2677. ColorNum := ToRealCols16[ColorNum];
  2678. Port[$03C7] := ColorNum;
  2679. { we must convert to lsb values... because the vga uses the 6 msb bits }
  2680. { which is not compatible with anything. }
  2681. RedValue := smallint(Port[$3C9]) shl 2;
  2682. GreenValue := smallint(Port[$3C9]) shl 2;
  2683. BlueValue := smallint(Port[$3C9]) shl 2;
  2684. end;
  2685. {************************************************************************}
  2686. {* VESA related routines *}
  2687. {************************************************************************}
  2688. {$I vesa.inc}
  2689. {************************************************************************}
  2690. {* General routines *}
  2691. {************************************************************************}
  2692. procedure CloseGraph;
  2693. Begin
  2694. If not isgraphmode then
  2695. begin
  2696. _graphresult := grnoinitgraph;
  2697. exit
  2698. end;
  2699. if not assigned(RestoreVideoState) then
  2700. RunError(216);
  2701. RestoreVideoState;
  2702. isgraphmode := false;
  2703. end;
  2704. (*
  2705. procedure LoadFont8x8;
  2706. var
  2707. r : registers;
  2708. x,y,c : longint;
  2709. data : array[0..127,0..7] of byte;
  2710. begin
  2711. r.ah:=$11;
  2712. r.al:=$30;
  2713. r.bh:=1;
  2714. RealIntr($10,r);
  2715. dosmemget(r.es,r.bp,data,sizeof(data));
  2716. for c:=0 to 127 do
  2717. for y:=0 to 7 do
  2718. for x:=0 to 7 do
  2719. if (data[c,y] and ($80 shr x))<>0 then
  2720. DefaultFontData[chr(c),y,x]:=1
  2721. else
  2722. DefaultFontData[chr(c),y,x]:=0;
  2723. { second part }
  2724. r.ah:=$11;
  2725. r.al:=$30;
  2726. r.bh:=0;
  2727. RealIntr($10,r);
  2728. dosmemget(r.es,r.bp,data,sizeof(data));
  2729. for c:=0 to 127 do
  2730. for y:=0 to 7 do
  2731. for x:=0 to 7 do
  2732. if (data[c,y] and ($80 shr x))<>0 then
  2733. DefaultFontData[chr(c+128),y,x]:=1
  2734. else
  2735. DefaultFontData[chr(c+128),y,x]:=0;
  2736. end;
  2737. *)
  2738. function QueryAdapterInfo:PModeInfo;
  2739. { This routine returns the head pointer to the list }
  2740. { of supPorted graphics modes. }
  2741. { Returns nil if no graphics mode supported. }
  2742. { This list is READ ONLY! }
  2743. function Test6845(CRTCPort: Word): Boolean;
  2744. const
  2745. TestRegister = $0F;
  2746. var
  2747. OldValue, TestValue, ReadValue: Byte;
  2748. begin
  2749. { save the old value }
  2750. Port[CRTCPort] := TestRegister;
  2751. OldValue := Port[CRTCPort + 1];
  2752. TestValue := OldValue xor $56;
  2753. { try writing a new value to the CRTC register }
  2754. Port[CRTCPort] := TestRegister;
  2755. Port[CRTCPort + 1] := TestValue;
  2756. { check if the value has been written }
  2757. Port[CRTCPort] := TestRegister;
  2758. ReadValue := Port[CRTCPort + 1];
  2759. if ReadValue = TestValue then
  2760. begin
  2761. Test6845 := True;
  2762. { restore old value }
  2763. Port[CRTCPort] := TestRegister;
  2764. Port[CRTCPort + 1] := OldValue;
  2765. end
  2766. else
  2767. Test6845 := False;
  2768. end;
  2769. procedure FillCommonCGA320(var mode: TModeInfo);
  2770. begin
  2771. mode.HardwarePages := 0;
  2772. mode.MaxColor := 4;
  2773. mode.PaletteSize := 16;
  2774. mode.DirectColor := FALSE;
  2775. mode.MaxX := 319;
  2776. mode.MaxY := 199;
  2777. mode.DirectPutPixel:=@DirectPutPixelCGA320;
  2778. mode.PutPixel:=@PutPixelCGA320;
  2779. mode.GetPixel:=@GetPixelCGA320;
  2780. mode.SetRGBPalette := @SetVGARGBPalette;
  2781. mode.GetRGBPalette := @GetVGARGBPalette;
  2782. mode.SetAllPalette := @SetVGARGBAllPalette;
  2783. mode.HLine := @HLineCGA320;
  2784. mode.SetBkColor := @SetBkColorCGA320;
  2785. mode.GetBkColor := @GetBkColorCGA320;
  2786. mode.XAspect := 8333;
  2787. mode.YAspect := 10000;
  2788. end;
  2789. procedure FillCommonCGA640(var mode: TModeInfo);
  2790. begin
  2791. mode.HardwarePages := 0;
  2792. mode.MaxColor := 2;
  2793. mode.PaletteSize := 16;
  2794. mode.DirectColor := FALSE;
  2795. mode.MaxX := 639;
  2796. mode.MaxY := 199;
  2797. mode.DirectPutPixel:=@DirectPutPixelCGA640;
  2798. mode.PutPixel:=@PutPixelCGA640;
  2799. mode.GetPixel:=@GetPixelCGA640;
  2800. mode.SetRGBPalette := @SetVGARGBPalette;
  2801. mode.GetRGBPalette := @GetVGARGBPalette;
  2802. mode.SetAllPalette := @SetVGARGBAllPalette;
  2803. mode.HLine := @HLineCGA640;
  2804. mode.SetBkColor := @SetBkColorCGA640;
  2805. mode.GetBkColor := @GetBkColorCGA640;
  2806. mode.XAspect := 4167;
  2807. mode.YAspect := 10000;
  2808. end;
  2809. procedure FillCommonEGAVGA16(var mode: TModeInfo);
  2810. begin
  2811. mode.MaxColor := 16;
  2812. mode.DirectColor := FALSE;
  2813. mode.PaletteSize := mode.MaxColor;
  2814. mode.DirectPutPixel:=@DirectPutPixel16;
  2815. mode.PutPixel:=@PutPixel16;
  2816. mode.GetPixel:=@GetPixel16;
  2817. mode.SetRGBPalette := @SetVGARGBPalette;
  2818. mode.GetRGBPalette := @GetVGARGBPalette;
  2819. mode.SetAllPalette := @SetVGARGBAllPalette;
  2820. mode.HLine := @HLine16;
  2821. mode.VLine := @VLine16;
  2822. mode.GetScanLine := @GetScanLine16;
  2823. end;
  2824. procedure FillCommonVESA16(var mode: TModeInfo);
  2825. begin
  2826. mode.MaxColor := 16;
  2827. { the ModeInfo is automatically set if the mode is supPorted }
  2828. { by the call to SearchVESAMode. }
  2829. mode.HardwarePages := VESAModeInfo.NumberOfPages;
  2830. mode.DirectColor := FALSE;
  2831. mode.PaletteSize := mode.MaxColor;
  2832. mode.DirectPutPixel:=@DirectPutPixVESA16;
  2833. mode.SetRGBPalette := @SetVESARGBPalette;
  2834. mode.GetRGBPalette := @GetVESARGBPalette;
  2835. {$ifdef fpc}
  2836. mode.SetAllPalette := @SetVESARGBAllPalette;
  2837. {$endif fpc}
  2838. mode.PutPixel:=@PutPixVESA16;
  2839. mode.GetPixel:=@GetPixVESA16;
  2840. mode.SetVisualPage := @SetVisualVESA;
  2841. mode.SetActivePage := @SetActiveVESA;
  2842. mode.HLine := @HLineVESA16;
  2843. end;
  2844. procedure FillCommonVESA256(var mode: TModeInfo);
  2845. begin
  2846. mode.MaxColor := 256;
  2847. { the ModeInfo is automatically set if the mode is supPorted }
  2848. { by the call to SearchVESAMode. }
  2849. mode.HardwarePages := VESAModeInfo.NumberOfPages;
  2850. mode.PaletteSize := mode.MaxColor;
  2851. mode.DirectColor := FALSE;
  2852. mode.DirectPutPixel:=@DirectPutPixVESA256;
  2853. mode.PutPixel:=@PutPixVESA256;
  2854. mode.GetPixel:=@GetPixVESA256;
  2855. mode.SetRGBPalette := @SetVESARGBPalette;
  2856. mode.GetRGBPalette := @GetVESARGBPalette;
  2857. {$ifdef fpc}
  2858. mode.SetAllPalette := @SetVESARGBAllPalette;
  2859. {$endif fpc}
  2860. mode.SetVisualPage := @SetVisualVESA;
  2861. mode.SetActivePage := @SetActiveVESA;
  2862. mode.hline := @HLineVESA256;
  2863. mode.vline := @VLineVESA256;
  2864. mode.GetScanLine := @GetScanLineVESA256;
  2865. mode.PatternLine := @PatternLineVESA256;
  2866. end;
  2867. procedure FillCommonVESA32kOr64k(var mode: TModeInfo);
  2868. begin
  2869. { the ModeInfo is automatically set if the mode is supPorted }
  2870. { by the call to SearchVESAMode. }
  2871. mode.HardwarePages := VESAModeInfo.NumberOfPages;
  2872. mode.DirectColor := TRUE;
  2873. mode.DirectPutPixel:=@DirectPutPixVESA32kOr64k;
  2874. mode.PutPixel:=@PutPixVESA32kOr64k;
  2875. mode.GetPixel:=@GetPixVESA32kOr64k;
  2876. mode.SetRGBPalette := @SetVESARGBPalette;
  2877. mode.GetRGBPalette := @GetVESARGBPalette;
  2878. mode.SetVisualPage := @SetVisualVESA;
  2879. mode.SetActivePage := @SetActiveVESA;
  2880. mode.HLine := @HLineVESA32kOr64k;
  2881. end;
  2882. procedure FillCommonVESA32k(var mode: TModeInfo);
  2883. begin
  2884. FillCommonVESA32kOr64k(mode);
  2885. mode.MaxColor := 32768;
  2886. mode.PaletteSize := mode.MaxColor;
  2887. end;
  2888. procedure FillCommonVESA64k(var mode: TModeInfo);
  2889. begin
  2890. FillCommonVESA32kOr64k(mode);
  2891. mode.MaxColor := 65536;
  2892. mode.PaletteSize := mode.MaxColor;
  2893. end;
  2894. procedure FillCommonVESA320x200(var mode: TModeInfo);
  2895. begin
  2896. mode.DriverNumber := VESA;
  2897. mode.ModeName:='320 x 200 VESA';
  2898. mode.MaxX := 319;
  2899. mode.MaxY := 199;
  2900. mode.XAspect := 8333;
  2901. mode.YAspect := 10000;
  2902. end;
  2903. procedure FillCommonVESA640x480(var mode: TModeInfo);
  2904. begin
  2905. mode.DriverNumber := VESA;
  2906. mode.ModeName:='640 x 480 VESA';
  2907. mode.MaxX := 639;
  2908. mode.MaxY := 479;
  2909. mode.XAspect := 10000;
  2910. mode.YAspect := 10000;
  2911. end;
  2912. procedure FillCommonVESA800x600(var mode: TModeInfo);
  2913. begin
  2914. mode.DriverNumber := VESA;
  2915. mode.ModeName:='800 x 600 VESA';
  2916. mode.MaxX := 799;
  2917. mode.MaxY := 599;
  2918. mode.XAspect := 10000;
  2919. mode.YAspect := 10000;
  2920. end;
  2921. procedure FillCommonVESA1024x768(var mode: TModeInfo);
  2922. begin
  2923. mode.DriverNumber := VESA;
  2924. mode.ModeName:='1024 x 768 VESA';
  2925. mode.MaxX := 1023;
  2926. mode.MaxY := 767;
  2927. mode.XAspect := 10000;
  2928. mode.YAspect := 10000;
  2929. end;
  2930. procedure FillCommonVESA1280x1024(var mode: TModeInfo);
  2931. begin
  2932. mode.DriverNumber := VESA;
  2933. mode.ModeName:='1280 x 1024 VESA';
  2934. mode.MaxX := 1279;
  2935. mode.MaxY := 1023;
  2936. mode.XAspect := 10000;
  2937. mode.YAspect := 10000;
  2938. end;
  2939. var
  2940. HGCDetected : Boolean = FALSE;
  2941. CGADetected : Boolean = FALSE; { TRUE means real CGA, *not* EGA or VGA }
  2942. EGAColorDetected : Boolean = FALSE; { TRUE means true EGA with a color monitor }
  2943. EGAMonoDetected : Boolean = FALSE; { TRUE means true EGA with a monochrome (MDA) monitor }
  2944. MCGADetected : Boolean = FALSE;
  2945. VGADetected : Boolean = FALSE;
  2946. mode: TModeInfo;
  2947. regs: Registers;
  2948. begin
  2949. QueryAdapterInfo := ModeList;
  2950. { If the mode listing already exists... }
  2951. { simply return it, without changing }
  2952. { anything... }
  2953. if assigned(ModeList) then
  2954. exit;
  2955. { check if VGA/MCGA adapter supported... }
  2956. regs.ax:=$1a00;
  2957. intr($10,regs); { get display combination code...}
  2958. if regs.al=$1a then
  2959. begin
  2960. while regs.bx <> 0 do
  2961. begin
  2962. case regs.bl of
  2963. 1: { monochrome adapter (MDA or HGC) }
  2964. begin
  2965. { check if Hercules adapter supported ... }
  2966. HGCDetected:=Test6845($3B4);
  2967. end;
  2968. 2: CGADetected:=TRUE;
  2969. 4: EGAColorDetected:=TRUE;
  2970. 5: EGAMonoDetected:=TRUE;
  2971. {6: PGA, this is rare stuff, how do we handle it? }
  2972. 7, 8: VGADetected:=TRUE;
  2973. 10, 11, 12: MCGADetected:=TRUE;
  2974. end;
  2975. { check both primary and secondary display adapter }
  2976. regs.bx:=regs.bx shr 8;
  2977. end;
  2978. end;
  2979. if VGADetected then
  2980. begin
  2981. { now check if this is the ATI EGA }
  2982. regs.ax:=$1c00; { get state size for save... }
  2983. { ... all important data }
  2984. regs.cx:=$07;
  2985. intr($10,regs);
  2986. VGADetected:=regs.al=$1c;
  2987. end;
  2988. if not VGADetected and not MCGADetected and
  2989. not EGAColorDetected and not EGAMonoDetected and
  2990. not CGADetected and not HGCDetected then
  2991. begin
  2992. { check if EGA adapter supported... }
  2993. regs.ah:=$12;
  2994. regs.bx:=$FF10;
  2995. intr($10,regs); { get EGA information }
  2996. if regs.bh<>$FF then
  2997. case regs.cl of
  2998. 0..3, { primary: MDA/HGC, secondary: EGA color }
  2999. 6..9: { primary: EGA color, secondary: MDA/HGC (optional) }
  3000. begin
  3001. EGAColorDetected:=TRUE;
  3002. { check if Hercules adapter supported ... }
  3003. HGCDetected:=Test6845($3B4);
  3004. end;
  3005. 4..5, { primary: CGA, secondary: EGA mono }
  3006. 10..11: { primary: EGA mono, secondary: CGA (optional) }
  3007. begin
  3008. EGAMonoDetected:=TRUE;
  3009. { check if CGA adapter supported ... }
  3010. CGADetected := Test6845($3D4);
  3011. end;
  3012. end;
  3013. end;
  3014. { older than EGA? }
  3015. if not VGADetected and not MCGADetected and
  3016. not EGAColorDetected and not EGAMonoDetected and
  3017. not CGADetected and not HGCDetected then
  3018. begin
  3019. { check if Hercules adapter supported ... }
  3020. HGCDetected := Test6845($3B4);
  3021. { check if CGA adapter supported ... }
  3022. CGADetected := Test6845($3D4);
  3023. end;
  3024. {$ifdef logging}
  3025. LogLn('HGC detected: '+strf(Longint(HGCDetected)));
  3026. LogLn('CGA detected: '+strf(Longint(CGADetected)));
  3027. LogLn('EGA color detected: '+strf(Longint(EGAColorDetected)));
  3028. LogLn('EGA mono detected: '+strf(Longint(EGAMonoDetected)));
  3029. LogLn('MCGA detected: '+strf(Longint(MCGADetected)));
  3030. LogLn('VGA detected: '+strf(Longint(VGADetected)));
  3031. {$endif logging}
  3032. if HGCDetected then
  3033. begin
  3034. { HACK:
  3035. until we create Save/RestoreStateHGC, we use Save/RestoreStateVGA
  3036. with the inWindows flag enabled (so we only save the mode number
  3037. and nothing else) }
  3038. if not VGADetected then
  3039. inWindows := true;
  3040. SaveVideoState := @SaveStateVGA;
  3041. RestoreVideoState := @RestoreStateVGA;
  3042. InitMode(mode);
  3043. mode.DriverNumber := HercMono;
  3044. mode.HardwarePages := 1;
  3045. mode.ModeNumber := HercMonoHi;
  3046. mode.ModeName:='720 x 348 HERCULES';
  3047. mode.MaxColor := 2;
  3048. mode.PaletteSize := 16;
  3049. mode.DirectColor := FALSE;
  3050. mode.MaxX := 719;
  3051. mode.MaxY := 347;
  3052. mode.DirectPutPixel:=@DirectPutPixelHGC720;
  3053. mode.PutPixel:=@PutPixelHGC720;
  3054. mode.GetPixel:=@GetPixelHGC720;
  3055. mode.SetRGBPalette := @SetHGCRGBPalette;
  3056. mode.GetRGBPalette := @GetHGCRGBPalette;
  3057. mode.SetVisualPage := @SetVisualHGC720;
  3058. mode.SetActivePage := @SetActiveHGC720;
  3059. mode.InitMode := @InitHGC720;
  3060. mode.HLine := @HLineHGC720;
  3061. mode.SetBkColor := @SetBkColorHGC720;
  3062. mode.GetBkColor := @GetBkColorHGC720;
  3063. mode.XAspect := 7500;
  3064. mode.YAspect := 10000;
  3065. AddMode(mode);
  3066. end;
  3067. if CGADetected or EGAColorDetected or MCGADetected or VGADetected then
  3068. begin
  3069. { HACK:
  3070. until we create Save/RestoreStateCGA, we use Save/RestoreStateVGA
  3071. with the inWindows flag enabled (so we only save the mode number
  3072. and nothing else) }
  3073. if not VGADetected then
  3074. inWindows := true;
  3075. SaveVideoState := @SaveStateVGA;
  3076. RestoreVideoState := @RestoreStateVGA;
  3077. { now add all standard CGA modes... }
  3078. InitMode(mode);
  3079. FillCommonCGA320(mode);
  3080. mode.DriverNumber := CGA;
  3081. mode.ModeNumber := CGAC0;
  3082. mode.ModeName:='320 x 200 CGA C0';
  3083. mode.InitMode := @InitCGA320C0;
  3084. AddMode(mode);
  3085. InitMode(mode);
  3086. FillCommonCGA320(mode);
  3087. mode.DriverNumber := CGA;
  3088. mode.ModeNumber := CGAC1;
  3089. mode.ModeName:='320 x 200 CGA C1';
  3090. mode.InitMode := @InitCGA320C1;
  3091. AddMode(mode);
  3092. InitMode(mode);
  3093. FillCommonCGA320(mode);
  3094. mode.DriverNumber := CGA;
  3095. mode.ModeNumber := CGAC2;
  3096. mode.ModeName:='320 x 200 CGA C2';
  3097. mode.InitMode := @InitCGA320C2;
  3098. AddMode(mode);
  3099. InitMode(mode);
  3100. FillCommonCGA320(mode);
  3101. mode.DriverNumber := CGA;
  3102. mode.ModeNumber := CGAC3;
  3103. mode.ModeName:='320 x 200 CGA C3';
  3104. mode.InitMode := @InitCGA320C3;
  3105. AddMode(mode);
  3106. InitMode(mode);
  3107. FillCommonCGA640(mode);
  3108. mode.DriverNumber := CGA;
  3109. mode.ModeNumber := CGAHi;
  3110. mode.ModeName:='640 x 200 CGA';
  3111. mode.InitMode := @InitCGA640;
  3112. AddMode(mode);
  3113. end;
  3114. if EGAColorDetected or VGADetected then
  3115. begin
  3116. { HACK:
  3117. until we create Save/RestoreStateEGA, we use Save/RestoreStateVGA
  3118. with the inWindows flag enabled (so we only save the mode number
  3119. and nothing else) }
  3120. if not VGADetected then
  3121. inWindows := true;
  3122. SaveVideoState := @SaveStateVGA;
  3123. RestoreVideoState := @RestoreStateVGA;
  3124. InitMode(mode);
  3125. FillCommonEGAVGA16(mode);
  3126. mode.ModeNumber:=EGALo;
  3127. mode.DriverNumber := EGA;
  3128. mode.ModeName:='640 x 200 EGA';
  3129. mode.MaxX := 639;
  3130. mode.MaxY := 199;
  3131. mode.HardwarePages := 3;
  3132. mode.SetVisualPage := @SetVisual200_350;
  3133. mode.SetActivePage := @SetActive200;
  3134. mode.InitMode := @Init640x200x16;
  3135. mode.XAspect := 4500;
  3136. mode.YAspect := 10000;
  3137. AddMode(mode);
  3138. InitMode(mode);
  3139. FillCommonEGAVGA16(mode);
  3140. mode.ModeNumber:=EGAHi;
  3141. mode.DriverNumber := EGA;
  3142. mode.ModeName:='640 x 350 EGA';
  3143. mode.MaxX := 639;
  3144. mode.MaxY := 349;
  3145. mode.HardwarePages := 1;
  3146. mode.SetVisualPage := @SetVisual200_350;
  3147. mode.SetActivePage := @SetActive350;
  3148. mode.InitMode := @Init640x350x16;
  3149. mode.XAspect := 7750;
  3150. mode.YAspect := 10000;
  3151. AddMode(mode);
  3152. end;
  3153. if MCGADetected or VGADetected then
  3154. begin
  3155. { HACK:
  3156. until we create Save/RestoreStateEGA, we use Save/RestoreStateVGA
  3157. with the inWindows flag enabled (so we only save the mode number
  3158. and nothing else) }
  3159. if not VGADetected then
  3160. inWindows := true;
  3161. SaveVideoState := @SaveStateVGA;
  3162. {$ifdef logging}
  3163. LogLn('Setting VGA SaveVideoState to '+strf(longint(SaveVideoState)));
  3164. {$endif logging}
  3165. RestoreVideoState := @RestoreStateVGA;
  3166. {$ifdef logging}
  3167. LogLn('Setting VGA RestoreVideoState to '+strf(longint(RestoreVideoState)));
  3168. {$endif logging}
  3169. { now add all standard MCGA modes... }
  3170. { yes, most of these are the same as the CGA modes; this is TP7
  3171. compatible }
  3172. InitMode(mode);
  3173. FillCommonCGA320(mode);
  3174. mode.DriverNumber := MCGA;
  3175. mode.ModeNumber := MCGAC0;
  3176. mode.ModeName:='320 x 200 CGA C0'; { yes, it says 'CGA' even for the MCGA driver; this is TP7 compatible }
  3177. mode.InitMode := @InitCGA320C0;
  3178. AddMode(mode);
  3179. InitMode(mode);
  3180. FillCommonCGA320(mode);
  3181. mode.DriverNumber := MCGA;
  3182. mode.ModeNumber := MCGAC1;
  3183. mode.ModeName:='320 x 200 CGA C1'; { yes, it says 'CGA' even for the MCGA driver; this is TP7 compatible }
  3184. mode.InitMode := @InitCGA320C1;
  3185. AddMode(mode);
  3186. InitMode(mode);
  3187. FillCommonCGA320(mode);
  3188. mode.DriverNumber := MCGA;
  3189. mode.ModeNumber := MCGAC2;
  3190. mode.ModeName:='320 x 200 CGA C2'; { yes, it says 'CGA' even for the MCGA driver; this is TP7 compatible }
  3191. mode.InitMode := @InitCGA320C2;
  3192. AddMode(mode);
  3193. InitMode(mode);
  3194. FillCommonCGA320(mode);
  3195. mode.DriverNumber := MCGA;
  3196. mode.ModeNumber := MCGAC3;
  3197. mode.ModeName:='320 x 200 CGA C3'; { yes, it says 'CGA' even for the MCGA driver; this is TP7 compatible }
  3198. mode.InitMode := @InitCGA320C3;
  3199. AddMode(mode);
  3200. InitMode(mode);
  3201. FillCommonCGA640(mode);
  3202. mode.DriverNumber := MCGA;
  3203. mode.ModeNumber := MCGAMed;
  3204. mode.ModeName:='640 x 200 CGA'; { yes, it says 'CGA' even for the MCGA driver; this is TP7 compatible }
  3205. mode.InitMode := @InitCGA640;
  3206. AddMode(mode);
  3207. InitMode(mode);
  3208. mode.DriverNumber := MCGA;
  3209. mode.HardwarePages := 0;
  3210. mode.ModeNumber := MCGAHi;
  3211. mode.ModeName:='640 x 480 MCGA';
  3212. mode.MaxColor := 2;
  3213. mode.PaletteSize := 16;
  3214. mode.DirectColor := FALSE;
  3215. mode.MaxX := 639;
  3216. mode.MaxY := 479;
  3217. mode.DirectPutPixel:=@DirectPutPixelMCGA640;
  3218. mode.PutPixel:=@PutPixelMCGA640;
  3219. mode.GetPixel:=@GetPixelMCGA640;
  3220. mode.SetRGBPalette := @SetVGARGBPalette;
  3221. mode.GetRGBPalette := @GetVGARGBPalette;
  3222. mode.SetAllPalette := @SetVGARGBAllPalette;
  3223. mode.InitMode := @InitMCGA640;
  3224. mode.HLine := @HLineMCGA640;
  3225. mode.SetBkColor := @SetBkColorMCGA640;
  3226. mode.GetBkColor := @GetBkColorMCGA640;
  3227. mode.XAspect := 10000;
  3228. mode.YAspect := 10000;
  3229. AddMode(mode);
  3230. InitMode(mode);
  3231. { now add all standard VGA modes... }
  3232. mode.DriverNumber:= LowRes;
  3233. mode.HardwarePages:= 0;
  3234. mode.ModeNumber:=0;
  3235. mode.ModeName:='320 x 200 VGA';
  3236. mode.MaxColor := 256;
  3237. mode.PaletteSize := mode.MaxColor;
  3238. mode.DirectColor := FALSE;
  3239. mode.MaxX := 319;
  3240. mode.MaxY := 199;
  3241. mode.DirectPutPixel:=@DirectPutPixel320;
  3242. mode.PutPixel:=@PutPixel320;
  3243. mode.GetPixel:=@GetPixel320;
  3244. mode.SetRGBPalette := @SetVGARGBPalette;
  3245. mode.GetRGBPalette := @GetVGARGBPalette;
  3246. mode.SetAllPalette := @SetVGARGBAllPalette;
  3247. mode.InitMode := @Init320;
  3248. mode.XAspect := 8333;
  3249. mode.YAspect := 10000;
  3250. AddMode(mode);
  3251. end;
  3252. if VGADetected then
  3253. begin
  3254. SaveVideoState := @SaveStateVGA;
  3255. {$ifdef logging}
  3256. LogLn('Setting VGA SaveVideoState to '+strf(longint(SaveVideoState)));
  3257. {$endif logging}
  3258. RestoreVideoState := @RestoreStateVGA;
  3259. {$ifdef logging}
  3260. LogLn('Setting VGA RestoreVideoState to '+strf(longint(RestoreVideoState)));
  3261. {$endif logging}
  3262. { now add all standard VGA modes... }
  3263. InitMode(mode);
  3264. mode.DriverNumber:= LowRes;
  3265. mode.ModeNumber:=1;
  3266. mode.HardwarePages := 3; { 0..3 }
  3267. mode.ModeName:='320 x 200 ModeX';
  3268. mode.MaxColor := 256;
  3269. mode.DirectColor := FALSE;
  3270. mode.PaletteSize := mode.MaxColor;
  3271. mode.MaxX := 319;
  3272. mode.MaxY := 199;
  3273. mode.DirectPutPixel:=@DirectPutPixelX;
  3274. mode.PutPixel:=@PutPixelX;
  3275. mode.GetPixel:=@GetPixelX;
  3276. mode.SetRGBPalette := @SetVGARGBPalette;
  3277. mode.GetRGBPalette := @GetVGARGBPalette;
  3278. mode.SetAllPalette := @SetVGARGBAllPalette;
  3279. mode.SetVisualPage := @SetVisualX;
  3280. mode.SetActivePage := @SetActiveX;
  3281. mode.InitMode := @InitModeX;
  3282. mode.XAspect := 8333;
  3283. mode.YAspect := 10000;
  3284. AddMode(mode);
  3285. InitMode(mode);
  3286. FillCommonEGAVGA16(mode);
  3287. mode.ModeNumber:=VGALo;
  3288. mode.DriverNumber := VGA;
  3289. mode.ModeName:='640 x 200 EGA'; { yes, it says 'EGA' even for the VGA driver; this is TP7 compatible }
  3290. mode.MaxX := 639;
  3291. mode.MaxY := 199;
  3292. mode.HardwarePages := 3;
  3293. mode.SetVisualPage := @SetVisual200_350;
  3294. mode.SetActivePage := @SetActive200;
  3295. mode.InitMode := @Init640x200x16;
  3296. mode.XAspect := 4500;
  3297. mode.YAspect := 10000;
  3298. AddMode(mode);
  3299. InitMode(mode);
  3300. FillCommonEGAVGA16(mode);
  3301. mode.ModeNumber:=VGAMed;
  3302. mode.DriverNumber := VGA;
  3303. mode.ModeName:='640 x 350 EGA'; { yes, it says 'EGA' even for the VGA driver; this is TP7 compatible }
  3304. mode.MaxX := 639;
  3305. mode.MaxY := 349;
  3306. mode.HardwarePages := 1;
  3307. mode.SetVisualPage := @SetVisual200_350;
  3308. mode.SetActivePage := @SetActive350;
  3309. mode.InitMode := @Init640x350x16;
  3310. mode.XAspect := 7750;
  3311. mode.YAspect := 10000;
  3312. AddMode(mode);
  3313. InitMode(mode);
  3314. FillCommonEGAVGA16(mode);
  3315. mode.ModeNumber:=VGAHi;
  3316. mode.DriverNumber := VGA;
  3317. mode.ModeName:='640 x 480 VGA';
  3318. mode.MaxX := 639;
  3319. mode.MaxY := 479;
  3320. mode.HardwarePages := 0;
  3321. mode.InitMode := @Init640x480x16;
  3322. mode.XAspect := 10000;
  3323. mode.YAspect := 10000;
  3324. AddMode(mode);
  3325. end;
  3326. { check if VESA adapter supPorted... }
  3327. {$ifndef noSupPortVESA}
  3328. hasVesa := getVesaInfo(VESAInfo);
  3329. { VBE Version v1.00 is unstable, therefore }
  3330. { only VBE v1.1 and later are supported. }
  3331. if (hasVESA=TRUE) and (VESAInfo.Version <= $0100) then
  3332. hasVESA := False;
  3333. {$else noSupPortVESA}
  3334. hasVESA := false;
  3335. {$endif noSupPortVESA}
  3336. if hasVesa then
  3337. begin
  3338. { We have to set and restore the entire VESA state }
  3339. { otherwise, if we use the VGA BIOS only function }
  3340. { there might be a crash under DPMI, such as in the}
  3341. { ATI Mach64 }
  3342. SaveVideoState := @SaveStateVESA;
  3343. {$ifdef logging}
  3344. LogLn('Setting SaveVideoState to '+strf(longint(SaveVideoState)));
  3345. {$endif logging}
  3346. RestoreVideoState := @RestoreStateVESA;
  3347. {$ifdef logging}
  3348. LogLn('Setting RestoreVideoState to '+strf(longint(RestoreVideoState)));
  3349. {$endif logging}
  3350. { now check all supported modes...}
  3351. if SearchVESAModes(m320x200x32k) then
  3352. begin
  3353. InitMode(mode);
  3354. FillCommonVESA32k(mode);
  3355. FillCommonVESA320x200(mode);
  3356. mode.ModeNumber:=m320x200x32k;
  3357. mode.InitMode := @Init320x200x32k;
  3358. AddMode(mode);
  3359. end;
  3360. if SearchVESAModes(m320x200x64k) then
  3361. begin
  3362. InitMode(mode);
  3363. FillCommonVESA64k(mode);
  3364. FillCommonVESA320x200(mode);
  3365. mode.ModeNumber:=m320x200x64k;
  3366. mode.InitMode := @Init320x200x64k;
  3367. AddMode(mode);
  3368. end;
  3369. if SearchVESAModes(m640x400x256) then
  3370. begin
  3371. InitMode(mode);
  3372. FillCommonVESA256(mode);
  3373. mode.ModeNumber:=m640x400x256;
  3374. mode.DriverNumber := VESA;
  3375. mode.ModeName:='640 x 400 VESA';
  3376. mode.MaxX := 639;
  3377. mode.MaxY := 399;
  3378. mode.InitMode := @Init640x400x256;
  3379. mode.XAspect := 8333;
  3380. mode.YAspect := 10000;
  3381. AddMode(mode);
  3382. end;
  3383. if SearchVESAModes(m640x480x256) then
  3384. begin
  3385. InitMode(mode);
  3386. FillCommonVESA256(mode);
  3387. FillCommonVESA640x480(mode);
  3388. mode.ModeNumber:=m640x480x256;
  3389. mode.InitMode := @Init640x480x256;
  3390. AddMode(mode);
  3391. end;
  3392. if SearchVESAModes(m640x480x32k) then
  3393. begin
  3394. InitMode(mode);
  3395. FillCommonVESA32k(mode);
  3396. FillCommonVESA640x480(mode);
  3397. mode.ModeNumber:=m640x480x32k;
  3398. mode.InitMode := @Init640x480x32k;
  3399. AddMode(mode);
  3400. end;
  3401. if SearchVESAModes(m640x480x64k) then
  3402. begin
  3403. InitMode(mode);
  3404. FillCommonVESA64k(mode);
  3405. FillCommonVESA640x480(mode);
  3406. mode.ModeNumber:=m640x480x64k;
  3407. mode.InitMode := @Init640x480x64k;
  3408. AddMode(mode);
  3409. end;
  3410. if SearchVESAModes(m800x600x16) then
  3411. begin
  3412. InitMode(mode);
  3413. FillCommonVESA16(mode);
  3414. FillCommonVESA800x600(mode);
  3415. mode.ModeNumber:=m800x600x16;
  3416. mode.InitMode := @Init800x600x16;
  3417. AddMode(mode);
  3418. end;
  3419. if SearchVESAModes(m800x600x256) then
  3420. begin
  3421. InitMode(mode);
  3422. FillCommonVESA256(mode);
  3423. FillCommonVESA800x600(mode);
  3424. mode.ModeNumber:=m800x600x256;
  3425. mode.InitMode := @Init800x600x256;
  3426. AddMode(mode);
  3427. end;
  3428. if SearchVESAModes(m800x600x32k) then
  3429. begin
  3430. InitMode(mode);
  3431. FillCommonVESA32k(mode);
  3432. FillCommonVESA800x600(mode);
  3433. mode.ModeNumber:=m800x600x32k;
  3434. mode.InitMode := @Init800x600x32k;
  3435. AddMode(mode);
  3436. end;
  3437. if SearchVESAModes(m800x600x64k) then
  3438. begin
  3439. InitMode(mode);
  3440. FillCommonVESA64k(mode);
  3441. FillCommonVESA800x600(mode);
  3442. mode.ModeNumber:=m800x600x64k;
  3443. mode.InitMode := @Init800x600x64k;
  3444. AddMode(mode);
  3445. end;
  3446. if SearchVESAModes(m1024x768x16) then
  3447. begin
  3448. InitMode(mode);
  3449. FillCommonVESA16(mode);
  3450. FillCommonVESA1024x768(mode);
  3451. mode.ModeNumber:=m1024x768x16;
  3452. mode.InitMode := @Init1024x768x16;
  3453. AddMode(mode);
  3454. end;
  3455. if SearchVESAModes(m1024x768x256) then
  3456. begin
  3457. InitMode(mode);
  3458. FillCommonVESA256(mode);
  3459. FillCommonVESA1024x768(mode);
  3460. mode.ModeNumber:=m1024x768x256;
  3461. mode.InitMode := @Init1024x768x256;
  3462. AddMode(mode);
  3463. end;
  3464. if SearchVESAModes(m1024x768x32k) then
  3465. begin
  3466. InitMode(mode);
  3467. FillCommonVESA32k(mode);
  3468. FillCommonVESA1024x768(mode);
  3469. mode.ModeNumber:=m1024x768x32k;
  3470. mode.InitMode := @Init1024x768x32k;
  3471. AddMode(mode);
  3472. end;
  3473. if SearchVESAModes(m1024x768x64k) then
  3474. begin
  3475. InitMode(mode);
  3476. FillCommonVESA64k(mode);
  3477. FillCommonVESA1024x768(mode);
  3478. mode.ModeNumber:=m1024x768x64k;
  3479. mode.InitMode := @Init1024x768x64k;
  3480. AddMode(mode);
  3481. end;
  3482. if SearchVESAModes(m1280x1024x16) then
  3483. begin
  3484. InitMode(mode);
  3485. FillCommonVESA16(mode);
  3486. FillCommonVESA1280x1024(mode);
  3487. mode.ModeNumber:=m1280x1024x16;
  3488. mode.InitMode := @Init1280x1024x16;
  3489. AddMode(mode);
  3490. end;
  3491. if SearchVESAModes(m1280x1024x256) then
  3492. begin
  3493. InitMode(mode);
  3494. FillCommonVESA256(mode);
  3495. FillCommonVESA1280x1024(mode);
  3496. mode.ModeNumber:=m1280x1024x256;
  3497. mode.InitMode := @Init1280x1024x256;
  3498. AddMode(mode);
  3499. end;
  3500. if SearchVESAModes(m1280x1024x32k) then
  3501. begin
  3502. InitMode(mode);
  3503. FillCommonVESA32k(mode);
  3504. FillCommonVESA1280x1024(mode);
  3505. mode.ModeNumber:=m1280x1024x32k;
  3506. mode.InitMode := @Init1280x1024x32k;
  3507. AddMode(mode);
  3508. end;
  3509. if SearchVESAModes(m1280x1024x64k) then
  3510. begin
  3511. InitMode(mode);
  3512. FillCommonVESA64k(mode);
  3513. FillCommonVESA1280x1024(mode);
  3514. mode.ModeNumber:=m1280x1024x64k;
  3515. mode.InitMode := @Init1280x1024x64k;
  3516. AddMode(mode);
  3517. end;
  3518. end;
  3519. end;
  3520. var
  3521. go32exitsave: codepointer;
  3522. procedure freeSaveStateBuffer;
  3523. begin
  3524. if savePtr <> nil then
  3525. begin
  3526. FreeMem(SavePtr, 64*StateSize);
  3527. SavePtr := nil;
  3528. end;
  3529. exitproc := go32exitsave;
  3530. end;
  3531. var
  3532. regs: Registers;
  3533. begin
  3534. { must be done *before* initialize graph is called, because the save }
  3535. { buffer can be used in the normal exit_proc (which is hooked in }
  3536. { initializegraph and as such executed first) (JM) }
  3537. go32exitsave := exitproc;
  3538. exitproc := @freeSaveStateBuffer;
  3539. { windows screws up the display if the savestate/restore state }
  3540. { stuff is used (or uses an abnormal amount of cpu time after }
  3541. { such a problem has exited), so detect its presense and do not }
  3542. { use those functions if it's running. I'm really tired of }
  3543. { working around Windows bugs :( (JM) }
  3544. regs.ax:=$160a;
  3545. intr($2f,regs);
  3546. inWindows:=regs.ax=0;
  3547. InitializeGraph;
  3548. end.