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