graph.pp 110 KB

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