ID_VW.C 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592
  1. /* Catacomb Armageddon Source Code
  2. * Copyright (C) 1993-2014 Flat Rock Software
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. // ID_VW.C
  19. #include "ID_HEADS.H"
  20. /*
  21. =============================================================================
  22. LOCAL CONSTANTS
  23. =============================================================================
  24. */
  25. #define VIEWWIDTH 40
  26. #define PIXTOBLOCK 4 // 16 pixels to an update block
  27. /*
  28. =============================================================================
  29. GLOBAL VARIABLES
  30. =============================================================================
  31. */
  32. cardtype videocard; // set by VW_Startup
  33. grtype grmode; // CGAgr, EGAgr, VGAgr
  34. unsigned bufferofs; // hidden area to draw to before displaying
  35. unsigned displayofs; // origin of the visable screen
  36. unsigned panx,pany; // panning adjustments inside port in pixels
  37. unsigned pansx,pansy; // panning adjustments inside port in screen
  38. // block limited pixel values (ie 0/8 for ega x)
  39. unsigned panadjust; // panx/pany adjusted by screen resolution
  40. unsigned screenseg; // normally 0xa000 / 0xb800
  41. unsigned linewidth;
  42. unsigned ylookup[VIRTUALHEIGHT];
  43. unsigned fontnumber; // 0 based font number for drawing
  44. boolean screenfaded;
  45. pictabletype _seg *pictable;
  46. pictabletype _seg *picmtable;
  47. spritetabletype _seg *spritetable;
  48. int bordercolor;
  49. /*
  50. =============================================================================
  51. LOCAL VARIABLES
  52. =============================================================================
  53. */
  54. void VWL_MeasureString (char far *string, word *width, word *height,
  55. fontstruct _seg *font);
  56. void VWL_DrawCursor (void);
  57. void VWL_EraseCursor (void);
  58. void VWL_DBSetup (void);
  59. void VWL_UpdateScreenBlocks (void);
  60. int bordercolor;
  61. int cursorvisible;
  62. int cursornumber,cursorwidth,cursorheight,cursorx,cursory;
  63. memptr cursorsave;
  64. unsigned cursorspot;
  65. //===========================================================================
  66. /*
  67. =======================
  68. =
  69. = VW_Startup
  70. =
  71. =======================
  72. */
  73. static char *ParmStrings[] = {"HIDDENCARD",""};
  74. void VW_Startup (void)
  75. {
  76. int i;
  77. asm cld;
  78. videocard = 0;
  79. for (i = 1;i < _argc;i++)
  80. if (US_CheckParm(_argv[i],ParmStrings) == 0)
  81. {
  82. videocard = EGAcard;
  83. break;
  84. }
  85. if (!videocard)
  86. videocard = VW_VideoID ();
  87. #if GRMODE == EGAGR
  88. grmode = EGAGR;
  89. if (videocard != EGAcard && videocard != VGAcard)
  90. Quit ("Improper video card! If you really have an EGA/VGA card that I am not \n"
  91. "detecting, use the -HIDDENCARD command line parameter!");
  92. EGAWRITEMODE(0);
  93. #endif
  94. #if GRMODE == CGAGR
  95. grmode = CGAGR;
  96. if (videocard < CGAcard || videocard > VGAcard)
  97. Quit ("Improper video card! If you really have a CGA card that I am not \n"
  98. "detecting, use the -HIDDENCARD command line parameter!");
  99. MM_GetPtr (&(memptr)screenseg,0x10000l); // grab 64k for floating screen
  100. #endif
  101. cursorvisible = 0;
  102. }
  103. //===========================================================================
  104. /*
  105. =======================
  106. =
  107. = VW_Shutdown
  108. =
  109. =======================
  110. */
  111. void VW_Shutdown (void)
  112. {
  113. VW_SetScreenMode (TEXTGR);
  114. #if GRMODE == EGAGR
  115. VW_SetLineWidth (80);
  116. #endif
  117. }
  118. //===========================================================================
  119. /*
  120. ========================
  121. =
  122. = VW_SetScreenMode
  123. = Call BIOS to set TEXT / CGAgr / EGAgr / VGAgr
  124. =
  125. ========================
  126. */
  127. void VW_SetScreenMode (int grmode)
  128. {
  129. switch (grmode)
  130. {
  131. case TEXTGR: _AX = 3;
  132. geninterrupt (0x10);
  133. screenseg=0xb000;
  134. break;
  135. case CGAGR: _AX = 4;
  136. geninterrupt (0x10); // screenseg is actually a main mem buffer
  137. break;
  138. case EGA320GR: // MDM start (GAMERS EDGE)
  139. MaxX=320;
  140. MaxY=200;
  141. _AX = 0xd|128;
  142. geninterrupt (0x10);
  143. screenseg=0xa000;
  144. break;
  145. case EGA640GR:
  146. MaxX=640;
  147. MaxY=200;
  148. _AX = 0xe|128;
  149. geninterrupt (0x10);
  150. screenseg=0xa000;
  151. break; // MDM end (GAMERS EDGE)
  152. case EGAGR: _AX = 0xd;
  153. MaxX=320;
  154. MaxY=200;
  155. geninterrupt (0x10);
  156. screenseg=0xa000;
  157. break;
  158. #ifdef VGAGAME
  159. case VGAGR:{
  160. char extern VGAPAL; // deluxepaint vga pallet .OBJ file
  161. void far *vgapal = &VGAPAL;
  162. SetCool256 (); // custom 256 color mode
  163. screenseg=0xa000;
  164. _ES = FP_SEG(vgapal);
  165. _DX = FP_OFF(vgapal);
  166. _BX = 0;
  167. _CX = 0x100;
  168. _AX = 0x1012;
  169. geninterrupt(0x10); // set the deluxepaint pallet
  170. break;
  171. #endif
  172. }
  173. VW_SetLineWidth(SCREENWIDTH);
  174. }
  175. /*
  176. =============================================================================
  177. SCREEN FADES
  178. =============================================================================
  179. */
  180. char colors[7][17]=
  181. {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  182. {0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,0},
  183. {0,0,0,0,0,0,0,0,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0},
  184. {0,1,2,3,4,5,6,7,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0},
  185. {0,1,2,3,4,5,6,7,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0},
  186. {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f}};
  187. void VW_ColorBorder (int color)
  188. {
  189. _AH=0x10;
  190. _AL=1;
  191. _BH=color;
  192. geninterrupt (0x10);
  193. bordercolor = color;
  194. }
  195. void VW_SetPalette(byte *palette)
  196. {
  197. byte p;
  198. word i;
  199. for (i = 0;i < 15;i++)
  200. {
  201. p = palette[i];
  202. colors[0][i] = 0;
  203. colors[1][i] = (p > 0x10)? (p & 0x0f) : 0;
  204. colors[2][i] = (p > 0x10)? p : 0;
  205. colors[3][i] = p;
  206. colors[4][i] = (p > 0x10)? 0x1f : p;
  207. colors[5][i] = 0x1f;
  208. }
  209. }
  210. void VW_SetDefaultColors(void)
  211. {
  212. #if GRMODE == EGAGR
  213. colors[3][16] = bordercolor;
  214. _ES=FP_SEG(&colors[3]);
  215. _DX=FP_OFF(&colors[3]);
  216. _AX=0x1002;
  217. geninterrupt(0x10);
  218. screenfaded = false;
  219. #endif
  220. }
  221. void VW_FadeOut(void)
  222. {
  223. #if GRMODE == EGAGR
  224. int i;
  225. for (i=3;i>=0;i--)
  226. {
  227. colors[i][16] = bordercolor;
  228. _ES=FP_SEG(&colors[i]);
  229. _DX=FP_OFF(&colors[i]);
  230. _AX=0x1002;
  231. geninterrupt(0x10);
  232. VW_WaitVBL(6);
  233. }
  234. screenfaded = true;
  235. #endif
  236. }
  237. void VW_FadeIn(void)
  238. {
  239. #if GRMODE == EGAGR
  240. int i;
  241. for (i=0;i<4;i++)
  242. {
  243. colors[i][16] = bordercolor;
  244. _ES=FP_SEG(&colors[i]);
  245. _DX=FP_OFF(&colors[i]);
  246. _AX=0x1002;
  247. geninterrupt(0x10);
  248. VW_WaitVBL(6);
  249. }
  250. screenfaded = false;
  251. #endif
  252. }
  253. void VW_FadeUp(void)
  254. {
  255. #if GRMODE == EGAGR
  256. int i;
  257. for (i=3;i<6;i++)
  258. {
  259. colors[i][16] = bordercolor;
  260. _ES=FP_SEG(&colors[i]);
  261. _DX=FP_OFF(&colors[i]);
  262. _AX=0x1002;
  263. geninterrupt(0x10);
  264. VW_WaitVBL(6);
  265. }
  266. screenfaded = true;
  267. #endif
  268. }
  269. void VW_FadeDown(void)
  270. {
  271. #if GRMODE == EGAGR
  272. int i;
  273. for (i=5;i>2;i--)
  274. {
  275. colors[i][16] = bordercolor;
  276. _ES=FP_SEG(&colors[i]);
  277. _DX=FP_OFF(&colors[i]);
  278. _AX=0x1002;
  279. geninterrupt(0x10);
  280. VW_WaitVBL(6);
  281. }
  282. screenfaded = false;
  283. #endif
  284. }
  285. /*
  286. ========================
  287. =
  288. = VW_SetAtrReg
  289. =
  290. = Sets an attribute (pallete / border) register
  291. = Does NOT vsync!
  292. =
  293. ========================
  294. */
  295. void VW_SetAtrReg (int reg, int value)
  296. {
  297. asm cli
  298. asm mov dx,STATUS_REGISTER_1
  299. asm in al,dx
  300. asm mov dx,ATR_INDEX
  301. asm mov al,BYTE PTR [reg]
  302. asm out dx,al
  303. asm mov al,BYTE PTR [value]
  304. asm out dx,al
  305. asm mov dx,0x3da
  306. asm in al,dx
  307. asm mov dx,ATR_INDEX
  308. asm mov al,0x20
  309. asm out dx,al
  310. asm sti
  311. }
  312. //===========================================================================
  313. /*
  314. ====================
  315. =
  316. = VW_SetLineWidth
  317. =
  318. = Must be an even number of bytes
  319. =
  320. ====================
  321. */
  322. void VW_SetLineWidth (int width)
  323. {
  324. int i,offset;
  325. #if GRMODE == EGAGR
  326. //
  327. // set wide virtual screen
  328. //
  329. asm mov dx,CRTC_INDEX
  330. asm mov al,CRTC_OFFSET
  331. asm mov ah,[BYTE PTR width]
  332. asm shr ah,1
  333. asm out dx,ax
  334. #endif
  335. //
  336. // set up lookup tables
  337. //
  338. linewidth = width;
  339. offset = 0;
  340. for (i=0;i<VIRTUALHEIGHT;i++)
  341. {
  342. ylookup[i]=offset;
  343. offset += width;
  344. }
  345. }
  346. //===========================================================================
  347. /*
  348. ====================
  349. =
  350. = VW_SetSplitScreen
  351. =
  352. ====================
  353. */
  354. void VW_SetSplitScreen (int linenum)
  355. {
  356. VW_WaitVBL (1);
  357. if (videocard==VGAcard)
  358. linenum=linenum*2-1;
  359. outportb (CRTC_INDEX,CRTC_LINECOMPARE);
  360. outportb (CRTC_INDEX+1,linenum % 256);
  361. outportb (CRTC_INDEX,CRTC_OVERFLOW);
  362. outportb (CRTC_INDEX+1, 1+16*(linenum/256));
  363. if (videocard==VGAcard)
  364. {
  365. outportb (CRTC_INDEX,CRTC_MAXSCANLINE);
  366. outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));
  367. }
  368. }
  369. //===========================================================================
  370. /*
  371. ====================
  372. =
  373. = VW_ClearVideo
  374. =
  375. ====================
  376. */
  377. void VW_ClearVideo (int color)
  378. {
  379. #if GRMODE == EGAGR
  380. EGAWRITEMODE(2);
  381. EGAMAPMASK(15);
  382. #endif
  383. asm mov es,[screenseg]
  384. asm xor di,di
  385. asm mov cx,0xffff
  386. asm mov al,[BYTE PTR color]
  387. asm rep stosb
  388. asm stosb
  389. #if GRMODE == EGAGR
  390. EGAWRITEMODE(0);
  391. #endif
  392. }
  393. //===========================================================================
  394. #if NUMPICS>0
  395. /*
  396. ====================
  397. =
  398. = VW_DrawPic
  399. =
  400. = X in bytes, y in pixels, chunknum is the #defined picnum
  401. =
  402. ====================
  403. */
  404. void VW_DrawPic(unsigned x, unsigned y, unsigned chunknum)
  405. {
  406. int picnum = chunknum - STARTPICS;
  407. memptr source;
  408. unsigned dest,width,height;
  409. source = grsegs[chunknum];
  410. dest = ylookup[y]+x+bufferofs;
  411. width = pictable[picnum].width;
  412. height = pictable[picnum].height;
  413. VW_MemToScreen(source,dest,width,height);
  414. }
  415. // MDM (GAMERS EDGE) begin
  416. /*
  417. ====================
  418. =
  419. = VW_DrawPic2x - Same as VW_DrawPic, but doubles pixels horizontally
  420. = (Great for drawing 320 graphics on 640 screen!)
  421. =
  422. = X in bytes, y in pixels, chunknum is the #defined picnum
  423. =
  424. ====================
  425. */
  426. void VW_DrawPic2x(unsigned x, unsigned y, unsigned chunknum)
  427. {
  428. int picnum = chunknum - STARTPICS;
  429. memptr source;
  430. unsigned dest,width,height;
  431. source = grsegs[chunknum];
  432. dest = ylookup[y]+x+bufferofs;
  433. width = pictable[picnum].width;
  434. height = pictable[picnum].height;
  435. VW_MemToScreen2x(source,dest,width,height);
  436. }
  437. // MDM (GAMERS EDGE) end
  438. #endif
  439. #if NUMPICM>0
  440. /*
  441. ====================
  442. =
  443. = VW_DrawMPic
  444. =
  445. = X in bytes, y in pixels, chunknum is the #defined picnum
  446. =
  447. ====================
  448. */
  449. void VW_DrawMPic(unsigned x, unsigned y, unsigned chunknum)
  450. {
  451. int picnum = chunknum - STARTPICM;
  452. memptr source;
  453. unsigned dest,width,height;
  454. source = grsegs[chunknum];
  455. dest = ylookup[y]+x+bufferofs;
  456. width = picmtable[picnum].width;
  457. height = picmtable[picnum].height;
  458. VW_MaskBlock(source,0,dest,width,height,width*height);
  459. }
  460. void VW_ClipDrawMPic(unsigned x, int y, unsigned chunknum)
  461. {
  462. int picnum = chunknum - STARTPICM;
  463. memptr source;
  464. unsigned dest,width,ofs,plane;
  465. int height;
  466. source = grsegs[chunknum];
  467. width = picmtable[picnum].width;
  468. height = picmtable[picnum].height;
  469. plane = width*height;
  470. ofs = 0;
  471. if (y<0)
  472. {
  473. ofs= -y*width;
  474. height+=y;
  475. y=0;
  476. }
  477. else if (y+height>216)
  478. {
  479. height-=(y-216);
  480. }
  481. dest = ylookup[y]+x+bufferofs;
  482. if (height<1)
  483. return;
  484. VW_MaskBlock(source,ofs,dest,width,height,plane);
  485. }
  486. #endif
  487. //===========================================================================
  488. #if NUMSPRITES>0
  489. /*
  490. ====================
  491. =
  492. = VW_DrawSprite
  493. =
  494. = X and Y in pixels, it will match the closest shift possible
  495. =
  496. = To do:
  497. = Add vertical clipping!
  498. = Make the shifts act as center points, rather than break points
  499. =
  500. ====================
  501. */
  502. void VW_DrawSprite(int x, int y, unsigned chunknum)
  503. {
  504. spritetabletype far *spr;
  505. spritetype _seg *block;
  506. unsigned dest,shift;
  507. spr = &spritetable[chunknum-STARTSPRITES];
  508. block = (spritetype _seg *)grsegs[chunknum];
  509. y+=spr->orgy>>G_P_SHIFT;
  510. x+=spr->orgx>>G_P_SHIFT;
  511. #if GRMODE == EGAGR
  512. shift = (x&7)/2;
  513. #endif
  514. #if GRMODE == CGAGR
  515. shift = 0;
  516. #endif
  517. dest = bufferofs + ylookup[y];
  518. if (x>=0)
  519. dest += x/SCREENXDIV;
  520. else
  521. dest += (x+1)/SCREENXDIV;
  522. VW_MaskBlock (block,block->sourceoffset[shift],dest,
  523. block->width[shift],spr->height,block->planesize[shift]);
  524. }
  525. #endif
  526. /*
  527. ==================
  528. =
  529. = VW_Hlin
  530. =
  531. ==================
  532. */
  533. #if GRMODE == EGAGR
  534. unsigned char leftmask[8] = {0xff,0x7f,0x3f,0x1f,0xf,7,3,1};
  535. unsigned char rightmask[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
  536. void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)
  537. {
  538. unsigned dest,xlb,xhb,maskleft,maskright,mid;
  539. xlb=xl/8;
  540. xhb=xh/8;
  541. EGAWRITEMODE(2);
  542. EGAMAPMASK(15);
  543. maskleft = leftmask[xl&7];
  544. maskright = rightmask[xh&7];
  545. mid = xhb-xlb-1;
  546. dest = bufferofs+ylookup[y]+xlb;
  547. if (xlb==xhb)
  548. {
  549. //
  550. // entire line is in one byte
  551. //
  552. maskleft&=maskright;
  553. asm mov es,[screenseg]
  554. asm mov di,[dest]
  555. asm mov dx,GC_INDEX
  556. asm mov al,GC_BITMASK
  557. asm mov ah,[BYTE PTR maskleft]
  558. asm out dx,ax // mask off pixels
  559. asm mov al,[BYTE PTR color]
  560. asm xchg al,[es:di] // load latches and write pixels
  561. goto done;
  562. }
  563. asm mov es,[screenseg]
  564. asm mov di,[dest]
  565. asm mov dx,GC_INDEX
  566. asm mov bh,[BYTE PTR color]
  567. //
  568. // draw left side
  569. //
  570. asm mov al,GC_BITMASK
  571. asm mov ah,[BYTE PTR maskleft]
  572. asm out dx,ax // mask off pixels
  573. asm mov al,bh
  574. asm mov bl,[es:di] // load latches
  575. asm stosb
  576. //
  577. // draw middle
  578. //
  579. asm mov ax,GC_BITMASK + 255*256
  580. asm out dx,ax // no masking
  581. asm mov al,bh
  582. asm mov cx,[mid]
  583. asm rep stosb
  584. //
  585. // draw right side
  586. //
  587. asm mov al,GC_BITMASK
  588. asm mov ah,[BYTE PTR maskright]
  589. asm out dx,ax // mask off pixels
  590. asm xchg bh,[es:di] // load latches and write pixels
  591. done:
  592. EGABITMASK(255);
  593. EGAWRITEMODE(0);
  594. }
  595. #endif
  596. #if GRMODE == CGAGR
  597. unsigned char pixmask[4] = {0xc0,0x30,0x0c,0x03};
  598. unsigned char leftmask[4] = {0xff,0x3f,0x0f,0x03};
  599. unsigned char rightmask[4] = {0xc0,0xf0,0xfc,0xff};
  600. unsigned char colorbyte[4] = {0,0x55,0xaa,0xff};
  601. //
  602. // could be optimized for rep stosw
  603. //
  604. void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)
  605. {
  606. unsigned dest,xlb,xhb,mid;
  607. byte maskleft,maskright;
  608. color = colorbyte[color]; // expand 2 color bits to 8
  609. xlb=xl/4;
  610. xhb=xh/4;
  611. maskleft = leftmask[xl&3];
  612. maskright = rightmask[xh&3];
  613. mid = xhb-xlb-1;
  614. dest = bufferofs+ylookup[y]+xlb;
  615. asm mov es,[screenseg]
  616. if (xlb==xhb)
  617. {
  618. //
  619. // entire line is in one byte
  620. //
  621. maskleft&=maskright;
  622. asm mov ah,[maskleft]
  623. asm mov bl,[BYTE PTR color]
  624. asm and bl,[maskleft]
  625. asm not ah
  626. asm mov di,[dest]
  627. asm mov al,[es:di]
  628. asm and al,ah // mask out pixels
  629. asm or al,bl // or in color
  630. asm mov [es:di],al
  631. return;
  632. }
  633. asm mov di,[dest]
  634. asm mov bh,[BYTE PTR color]
  635. //
  636. // draw left side
  637. //
  638. asm mov ah,[maskleft]
  639. asm mov bl,bh
  640. asm and bl,[maskleft]
  641. asm not ah
  642. asm mov al,[es:di]
  643. asm and al,ah // mask out pixels
  644. asm or al,bl // or in color
  645. asm stosb
  646. //
  647. // draw middle
  648. //
  649. asm mov al,bh
  650. asm mov cx,[mid]
  651. asm rep stosb
  652. //
  653. // draw right side
  654. //
  655. asm mov ah,[maskright]
  656. asm mov bl,bh
  657. asm and bl,[maskright]
  658. asm not ah
  659. asm mov al,[es:di]
  660. asm and al,ah // mask out pixels
  661. asm or al,bl // or in color
  662. asm stosb
  663. }
  664. #endif
  665. /*
  666. ==================
  667. =
  668. = VW_Bar
  669. =
  670. = Pixel addressable block fill routine
  671. =
  672. ==================
  673. */
  674. #if GRMODE == CGAGR
  675. void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,
  676. unsigned color)
  677. {
  678. unsigned xh = x+width-1;
  679. while (height--)
  680. VW_Hlin (x,xh,y++,color);
  681. }
  682. #endif
  683. #if GRMODE == EGAGR
  684. void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,
  685. unsigned color)
  686. {
  687. unsigned dest,xh,xlb,xhb,maskleft,maskright,mid;
  688. xh = x+width-1;
  689. xlb=x/8;
  690. xhb=xh/8;
  691. EGAWRITEMODE(2);
  692. EGAMAPMASK(15);
  693. maskleft = leftmask[x&7];
  694. maskright = rightmask[xh&7];
  695. mid = xhb-xlb-1;
  696. dest = bufferofs+ylookup[y]+xlb;
  697. if (xlb==xhb)
  698. {
  699. //
  700. // entire line is in one byte
  701. //
  702. maskleft&=maskright;
  703. asm mov es,[screenseg]
  704. asm mov di,[dest]
  705. asm mov dx,GC_INDEX
  706. asm mov al,GC_BITMASK
  707. asm mov ah,[BYTE PTR maskleft]
  708. asm out dx,ax // mask off pixels
  709. asm mov ah,[BYTE PTR color]
  710. asm mov dx,[linewidth]
  711. yloop1:
  712. asm mov al,ah
  713. asm xchg al,[es:di] // load latches and write pixels
  714. asm add di,dx // down to next line
  715. asm dec [height]
  716. asm jnz yloop1
  717. goto done;
  718. }
  719. asm mov es,[screenseg]
  720. asm mov di,[dest]
  721. asm mov bh,[BYTE PTR color]
  722. asm mov dx,GC_INDEX
  723. asm mov si,[linewidth]
  724. asm sub si,[mid] // add to di at end of line to get to next scan
  725. asm dec si
  726. //
  727. // draw left side
  728. //
  729. yloop2:
  730. asm mov al,GC_BITMASK
  731. asm mov ah,[BYTE PTR maskleft]
  732. asm out dx,ax // mask off pixels
  733. asm mov al,bh
  734. asm mov bl,[es:di] // load latches
  735. asm stosb
  736. //
  737. // draw middle
  738. //
  739. asm mov ax,GC_BITMASK + 255*256
  740. asm out dx,ax // no masking
  741. asm mov al,bh
  742. asm mov cx,[mid]
  743. asm rep stosb
  744. //
  745. // draw right side
  746. //
  747. asm mov al,GC_BITMASK
  748. asm mov ah,[BYTE PTR maskright]
  749. asm out dx,ax // mask off pixels
  750. asm mov al,bh
  751. asm xchg al,[es:di] // load latches and write pixels
  752. asm add di,si // move to start of next line
  753. asm dec [height]
  754. asm jnz yloop2
  755. done:
  756. EGABITMASK(255);
  757. EGAWRITEMODE(0);
  758. }
  759. #endif
  760. //==========================================================================
  761. /*
  762. ==================
  763. =
  764. = VW_MeasureString
  765. =
  766. ==================
  767. */
  768. #if NUMFONT+NUMFONTM>0
  769. void
  770. VWL_MeasureString (char far *string, word *width, word *height, fontstruct _seg *font)
  771. {
  772. *height = font->height-1; // MDM (GAMERS EDGE) - squeeze font vertically...
  773. for (*width = 0;*string;string++)
  774. *width += font->width[*((byte far *)string)]; // proportional width
  775. }
  776. void VW_MeasurePropString (char far *string, word *width, word *height)
  777. {
  778. VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONT+fontnumber]);
  779. }
  780. void VW_MeasureMPropString (char far *string, word *width, word *height)
  781. {
  782. VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONTM+fontnumber]);
  783. }
  784. #endif
  785. /*
  786. =============================================================================
  787. CGA stuff
  788. =============================================================================
  789. */
  790. #if GRMODE == CGAGR
  791. #define CGACRTCWIDTH 40
  792. /*
  793. ==========================
  794. =
  795. = VW_CGAFullUpdate
  796. =
  797. ==========================
  798. */
  799. void VW_CGAFullUpdate (void)
  800. {
  801. byte *update;
  802. boolean halftile;
  803. unsigned x,y,middlerows,middlecollumns;
  804. displayofs = bufferofs+panadjust;
  805. asm mov ax,0xb800
  806. asm mov es,ax
  807. asm mov si,[displayofs]
  808. asm xor di,di
  809. asm mov bx,100 // pairs of scan lines to copy
  810. asm mov dx,[linewidth]
  811. asm sub dx,80
  812. asm mov ds,[screenseg]
  813. asm test si,1
  814. asm jz evenblock
  815. //
  816. // odd source
  817. //
  818. asm mov ax,39 // words accross screen
  819. copytwolineso:
  820. asm movsb
  821. asm mov cx,ax
  822. asm rep movsw
  823. asm movsb
  824. asm add si,dx
  825. asm add di,0x2000-80 // go to the interlaced bank
  826. asm movsb
  827. asm mov cx,ax
  828. asm rep movsw
  829. asm movsb
  830. asm add si,dx
  831. asm sub di,0x2000 // go to the non interlaced bank
  832. asm dec bx
  833. asm jnz copytwolineso
  834. asm jmp blitdone
  835. //
  836. // even source
  837. //
  838. evenblock:
  839. asm mov ax,40 // words accross screen
  840. copytwolines:
  841. asm mov cx,ax
  842. asm rep movsw
  843. asm add si,dx
  844. asm add di,0x2000-80 // go to the interlaced bank
  845. asm mov cx,ax
  846. asm rep movsw
  847. asm add si,dx
  848. asm sub di,0x2000 // go to the non interlaced bank
  849. asm dec bx
  850. asm jnz copytwolines
  851. blitdone:
  852. asm mov ax,ss
  853. asm mov ds,ax
  854. asm mov es,ax
  855. asm xor ax,ax // clear out the update matrix
  856. asm mov cx,UPDATEWIDE*UPDATEHIGH/2
  857. asm mov di,[baseupdateptr]
  858. asm rep stosw
  859. updateptr = baseupdateptr;
  860. *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;
  861. }
  862. #endif
  863. /*
  864. =============================================================================
  865. CURSOR ROUTINES
  866. These only work in the context of the double buffered update routines
  867. =============================================================================
  868. */
  869. /*
  870. ====================
  871. =
  872. = VWL_DrawCursor
  873. =
  874. = Background saves, then draws the cursor at cursorspot
  875. =
  876. ====================
  877. */
  878. void VWL_DrawCursor (void)
  879. {
  880. cursorspot = bufferofs + ylookup[cursory+pansy]+(cursorx+pansx)/SCREENXDIV;
  881. VW_ScreenToMem(cursorspot,cursorsave,cursorwidth,cursorheight);
  882. VWB_DrawSprite(cursorx,cursory,cursornumber);
  883. }
  884. //==========================================================================
  885. /*
  886. ====================
  887. =
  888. = VWL_EraseCursor
  889. =
  890. ====================
  891. */
  892. void VWL_EraseCursor (void)
  893. {
  894. VW_MemToScreen(cursorsave,cursorspot,cursorwidth,cursorheight);
  895. VW_MarkUpdateBlock ((cursorx+pansx)&SCREENXMASK,cursory+pansy,
  896. ( (cursorx+pansx)&SCREENXMASK)+cursorwidth*SCREENXDIV-1,
  897. cursory+pansy+cursorheight-1);
  898. }
  899. //==========================================================================
  900. /*
  901. ====================
  902. =
  903. = VW_ShowCursor
  904. =
  905. ====================
  906. */
  907. void VW_ShowCursor (void)
  908. {
  909. cursorvisible++;
  910. }
  911. //==========================================================================
  912. /*
  913. ====================
  914. =
  915. = VW_HideCursor
  916. =
  917. ====================
  918. */
  919. void VW_HideCursor (void)
  920. {
  921. cursorvisible--;
  922. }
  923. //==========================================================================
  924. /*
  925. ====================
  926. =
  927. = VW_MoveCursor
  928. =
  929. ====================
  930. */
  931. #define MAXCURSORX (319-24)
  932. #define MAXCURSORY (199-24)
  933. void VW_MoveCursor (int x, int y)
  934. {
  935. if (x>MAXCURSORX)
  936. x=MAXCURSORX;
  937. if (y>MAXCURSORY)
  938. y=MAXCURSORY; // catacombs hack to keep cursor on screen
  939. cursorx = x;
  940. cursory = y;
  941. }
  942. //==========================================================================
  943. /*
  944. ====================
  945. =
  946. = VW_SetCursor
  947. =
  948. = Load in a sprite to be used as a cursor, and allocate background save space
  949. =
  950. ====================
  951. */
  952. void VW_SetCursor (int spritenum)
  953. {
  954. VW_FreeCursor ();
  955. cursornumber = spritenum;
  956. CA_CacheGrChunk (spritenum);
  957. MM_SetLock (&grsegs[spritenum],true);
  958. cursorwidth = spritetable[spritenum-STARTSPRITES].width+1;
  959. cursorheight = spritetable[spritenum-STARTSPRITES].height;
  960. MM_GetPtr (&cursorsave,cursorwidth*cursorheight*5);
  961. MM_SetLock (&cursorsave,true);
  962. }
  963. /*
  964. ====================
  965. =
  966. = VW_FreeCursor
  967. =
  968. = Frees the memory used by the cursor and its background save
  969. =
  970. ====================
  971. */
  972. void VW_FreeCursor (void)
  973. {
  974. if (cursornumber)
  975. {
  976. MM_SetLock (&grsegs[cursornumber],false);
  977. MM_SetPurge (&grsegs[cursornumber],3);
  978. MM_SetLock (&cursorsave,false);
  979. MM_FreePtr (&cursorsave);
  980. cursornumber = 0;
  981. }
  982. }
  983. /*
  984. =============================================================================
  985. Double buffer management routines
  986. =============================================================================
  987. */
  988. /*
  989. ======================
  990. =
  991. = VW_InitDoubleBuffer
  992. =
  993. ======================
  994. */
  995. void VW_InitDoubleBuffer (void)
  996. {
  997. #if GRMODE == EGAGR
  998. VW_SetScreen (displayofs+panadjust,0); // no pel pan
  999. #endif
  1000. }
  1001. /*
  1002. ======================
  1003. =
  1004. = VW_FixRefreshBuffer
  1005. =
  1006. = Copies the view page to the buffer page on page flipped refreshes to
  1007. = avoid a one frame shear around pop up windows
  1008. =
  1009. ======================
  1010. */
  1011. void VW_FixRefreshBuffer (void)
  1012. {
  1013. #if GRMODE == EGAGR
  1014. VW_ScreenToScreen (displayofs,bufferofs,PORTTILESWIDE*4*CHARWIDTH,
  1015. (PORTTILESHIGH-1)*16);
  1016. #endif
  1017. }
  1018. /*
  1019. ======================
  1020. =
  1021. = VW_QuitDoubleBuffer
  1022. =
  1023. ======================
  1024. */
  1025. void VW_QuitDoubleBuffer (void)
  1026. {
  1027. }
  1028. /*
  1029. =======================
  1030. =
  1031. = VW_MarkUpdateBlock
  1032. =
  1033. = Takes a pixel bounded block and marks the tiles in bufferblocks
  1034. = Returns 0 if the entire block is off the buffer screen
  1035. =
  1036. =======================
  1037. */
  1038. int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2)
  1039. {
  1040. // MDM (GAMERS EDGE) begin - NOT NEEDED FOR 3D ENGINE
  1041. #if 0
  1042. int x,y,xt1,yt1,xt2,yt2,nextline;
  1043. byte *mark;
  1044. xt1 = x1>>PIXTOBLOCK;
  1045. yt1 = y1>>PIXTOBLOCK;
  1046. xt2 = x2>>PIXTOBLOCK;
  1047. yt2 = y2>>PIXTOBLOCK;
  1048. if (xt1<0)
  1049. xt1=0;
  1050. else if (xt1>=UPDATEWIDE-1)
  1051. return 0;
  1052. if (yt1<0)
  1053. yt1=0;
  1054. else if (yt1>UPDATEHIGH)
  1055. return 0;
  1056. if (xt2<0)
  1057. return 0;
  1058. else if (xt2>=UPDATEWIDE-1)
  1059. xt2 = UPDATEWIDE-2;
  1060. if (yt2<0)
  1061. return 0;
  1062. else if (yt2>=UPDATEHIGH)
  1063. yt2 = UPDATEHIGH-1;
  1064. mark = updateptr + uwidthtable[yt1] + xt1;
  1065. nextline = UPDATEWIDE - (xt2-xt1) - 1;
  1066. for (y=yt1;y<=yt2;y++)
  1067. {
  1068. for (x=xt1;x<=xt2;x++)
  1069. *mark++ = 1; // this tile will need to be updated
  1070. mark += nextline;
  1071. }
  1072. #endif
  1073. // MDM (GAMERS EDGE) end
  1074. return 1;
  1075. }
  1076. /*
  1077. ===========================
  1078. =
  1079. = VW_UpdateScreen
  1080. =
  1081. = Updates any changed areas of the double buffer and displays the cursor
  1082. =
  1083. ===========================
  1084. */
  1085. void VW_UpdateScreen (void)
  1086. {
  1087. if (cursorvisible>0)
  1088. VWL_DrawCursor();
  1089. #if GRMODE == EGAGR
  1090. VWL_UpdateScreenBlocks();
  1091. asm mov ax,ds
  1092. asm mov es,ax
  1093. asm mov di,[updateptr] // cat3d patch
  1094. asm xor ax,ax // clear out the update matrix
  1095. asm mov cx,UPDATEWIDE*UPDATEHIGH/2
  1096. asm rep stosw
  1097. *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;
  1098. asm cli
  1099. asm mov cx,[displayofs]
  1100. asm add cx,[panadjust]
  1101. asm mov dx,CRTC_INDEX
  1102. asm mov al,0ch // start address high register
  1103. asm out dx,al
  1104. asm inc dx
  1105. asm mov al,ch
  1106. asm out dx,al
  1107. asm dec dx
  1108. asm mov al,0dh // start address low register
  1109. asm out dx,al
  1110. asm mov al,cl
  1111. asm inc dx
  1112. asm out dx,al
  1113. asm sti
  1114. #endif
  1115. #if GRMODE == CGAGR
  1116. VW_CGAFullUpdate();
  1117. #endif
  1118. if (cursorvisible>0)
  1119. VWL_EraseCursor();
  1120. }
  1121. void VWB_DrawTile8 (int x, int y, int tile)
  1122. {
  1123. x+=pansx;
  1124. y+=pansy;
  1125. if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7))
  1126. VW_DrawTile8 (x/SCREENXDIV,y,tile);
  1127. }
  1128. void VWB_DrawTile8M (int x, int y, int tile)
  1129. {
  1130. int xb;
  1131. x+=pansx;
  1132. y+=pansy;
  1133. xb = x/SCREENXDIV; // use intermediate because VW_DT8M is macro
  1134. // if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7)) // MDM (GAMER EDGE)
  1135. VW_DrawTile8M (xb,y,tile); // statement prevents drawing chars past 42
  1136. }
  1137. void VWB_DrawTile16 (int x, int y, int tile)
  1138. {
  1139. x+=pansx;
  1140. y+=pansy;
  1141. if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))
  1142. VW_DrawTile16 (x/SCREENXDIV,y,tile);
  1143. }
  1144. void VWB_DrawTile16M (int x, int y, int tile)
  1145. {
  1146. int xb;
  1147. x+=pansx;
  1148. y+=pansy;
  1149. xb = x/SCREENXDIV; // use intermediate because VW_DT16M is macro
  1150. if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))
  1151. VW_DrawTile16M (xb,y,tile);
  1152. }
  1153. #if NUMPICS
  1154. void VWB_DrawPic (int x, int y, int chunknum)
  1155. {
  1156. // mostly copied from drawpic
  1157. int picnum = chunknum - STARTPICS;
  1158. memptr source;
  1159. unsigned dest,width,height;
  1160. x+=pansx;
  1161. y+=pansy;
  1162. x/= SCREENXDIV;
  1163. source = grsegs[chunknum];
  1164. dest = ylookup[y]+x+bufferofs;
  1165. width = pictable[picnum].width;
  1166. height = pictable[picnum].height;
  1167. if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))
  1168. VW_MemToScreen(source,dest,width,height);
  1169. }
  1170. #endif
  1171. #if NUMPICM>0
  1172. void VWB_DrawMPic(int x, int y, int chunknum)
  1173. {
  1174. // mostly copied from drawmpic
  1175. int picnum = chunknum - STARTPICM;
  1176. memptr source;
  1177. unsigned dest,width,height;
  1178. x+=pansx;
  1179. y+=pansy;
  1180. x/=SCREENXDIV;
  1181. source = grsegs[chunknum];
  1182. dest = ylookup[y]+x+bufferofs;
  1183. width = picmtable[picnum].width;
  1184. height = picmtable[picnum].height;
  1185. if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))
  1186. VW_MaskBlock(source,0,dest,width,height,width*height);
  1187. }
  1188. #endif
  1189. void VWB_Bar (int x, int y, int width, int height, int color)
  1190. {
  1191. x+=pansx;
  1192. y+=pansy;
  1193. if (VW_MarkUpdateBlock (x,y,x+width,y+height-1) )
  1194. VW_Bar (x,y,width,height,color);
  1195. }
  1196. #if NUMFONT
  1197. void VWB_DrawPropString (char far *string)
  1198. {
  1199. int x,y;
  1200. x = px+pansx;
  1201. y = py+pansy;
  1202. VW_DrawPropString (string);
  1203. VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);
  1204. }
  1205. #endif
  1206. #if NUMFONTM
  1207. void VWB_DrawMPropString (char far *string)
  1208. {
  1209. int x,y;
  1210. x = px+pansx;
  1211. y = py+pansy;
  1212. VW_DrawMPropString (string);
  1213. VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);
  1214. }
  1215. #endif
  1216. #if NUMSPRITES
  1217. void VWB_DrawSprite(int x, int y, int chunknum)
  1218. {
  1219. spritetabletype far *spr;
  1220. spritetype _seg *block;
  1221. unsigned dest,shift,width,height;
  1222. x+=pansx;
  1223. y+=pansy;
  1224. spr = &spritetable[chunknum-STARTSPRITES];
  1225. block = (spritetype _seg *)grsegs[chunknum];
  1226. y+=spr->orgy>>G_P_SHIFT;
  1227. x+=spr->orgx>>G_P_SHIFT;
  1228. #if GRMODE == EGAGR
  1229. shift = (x&7)/2;
  1230. #endif
  1231. #if GRMODE == CGAGR
  1232. shift = 0;
  1233. #endif
  1234. dest = bufferofs + ylookup[y];
  1235. if (x>=0)
  1236. dest += x/SCREENXDIV;
  1237. else
  1238. dest += (x+1)/SCREENXDIV;
  1239. width = block->width[shift];
  1240. height = spr->height;
  1241. if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+width*SCREENXDIV-1
  1242. ,y+height-1))
  1243. VW_MaskBlock (block,block->sourceoffset[shift],dest,
  1244. width,height,block->planesize[shift]);
  1245. }
  1246. #endif
  1247. void VWB_Plot (int x, int y, int color)
  1248. {
  1249. x+=pansx;
  1250. y+=pansy;
  1251. if (VW_MarkUpdateBlock (x,y,x,y))
  1252. VW_Plot(x,y,color);
  1253. }
  1254. void VWB_Hlin (int x1, int x2, int y, int color)
  1255. {
  1256. x1+=pansx;
  1257. x2+=pansx;
  1258. y+=pansy;
  1259. if (VW_MarkUpdateBlock (x1,y,x2,y))
  1260. VW_Hlin(x1,x2,y,color);
  1261. }
  1262. void VWB_Vlin (int y1, int y2, int x, int color)
  1263. {
  1264. x+=pansx;
  1265. y1+=pansy;
  1266. y2+=pansy;
  1267. if (VW_MarkUpdateBlock (x,y1,x,y2))
  1268. VW_Vlin(y1,y2,x,color);
  1269. }
  1270. //===========================================================================