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