1 /* Reconstructed Commander Keen 4-6 Source Code
\r
2 * Copyright (C) 2021 K1n9_Duk3
\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
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
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
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
25 #include "ID_HEADS.H"
\r
28 =============================================================================
\r
32 =============================================================================
\r
35 #define VIEWWIDTH 40
\r
37 #define PIXTOBLOCK 4 // 16 pixels to an update block
\r
40 =============================================================================
\r
44 =============================================================================
\r
47 cardtype videocard; // set by VW_Startup
\r
48 grtype grmode; // CGAgr, EGAgr, VGAgr
\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
57 unsigned screenseg; // normally 0xa000 / 0xb800
\r
59 unsigned ylookup[VIRTUALHEIGHT];
\r
61 unsigned fontnumber; // 0 based font number for drawing
\r
63 boolean screenfaded;
\r
65 pictabletype _seg *pictable;
\r
66 pictabletype _seg *picmtable;
\r
67 spritetabletype _seg *spritetable;
\r
73 =============================================================================
\r
77 =============================================================================
\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
90 int cursornumber,cursorwidth,cursorheight,cursorx,cursory;
\r
92 unsigned cursorspot;
\r
94 //===========================================================================
\r
98 =======================
\r
102 =======================
\r
105 static char *ParmStrings[] = {"HIDDENCARD","NOPAN",""};
\r
107 void VW_Startup (void)
\r
115 for (i = 1;i < _argc;i++)
\r
117 n = US_CheckParm(_argv[i],ParmStrings);
\r
120 videocard = EGAcard;
\r
129 videocard = VW_VideoID ();
\r
131 #if GRMODE == EGAGR
\r
133 if (videocard != EGAcard && videocard != VGAcard)
\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
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
144 #if GRMODE == CGAGR
\r
146 if (videocard < CGAcard || videocard > VGAcard)
\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
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
154 MM_GetPtr (&(memptr)screenseg,0x10000l); // grab 64k for floating screen
\r
160 //===========================================================================
\r
163 =======================
\r
167 =======================
\r
170 void VW_Shutdown (void)
\r
172 VW_SetScreenMode (TEXTGR);
\r
173 #if GRMODE == EGAGR
\r
174 VW_SetLineWidth (80);
\r
178 //===========================================================================
\r
181 ========================
\r
184 = Call BIOS to set TEXT / CGAgr / EGAgr / VGAgr
\r
186 ========================
\r
189 void VW_SetScreenMode (int grmode)
\r
193 case TEXTGR: _AX = 3;
\r
194 geninterrupt (0x10);
\r
199 case CGAGR: _AX = 4;
\r
200 geninterrupt (0x10); // screenseg is actually a main mem buffer
\r
202 case EGAGR: _AX = 0xd;
\r
203 geninterrupt (0x10);
\r
208 char extern VGAPAL; // deluxepaint vga pallet .OBJ file
\r
209 void far *vgapal = &VGAPAL;
\r
210 SetCool256 (); // custom 256 color mode
\r
212 _ES = FP_SEG(vgapal);
\r
213 _DX = FP_OFF(vgapal);
\r
217 geninterrupt(0x10); // set the deluxepaint pallet
\r
222 VW_SetLineWidth(SCREENWIDTH);
\r
226 =============================================================================
\r
230 =============================================================================
\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
242 void VW_ColorBorder (int color)
\r
247 geninterrupt (0x10);
\r
248 bordercolor = color;
\r
251 void VW_SetPalette(byte *palette)
\r
256 for (i = 0;i < 15;i++)
\r
260 colors[1][i] = (p > 0x10)? (p & 0x0f) : 0;
\r
261 colors[2][i] = (p > 0x10)? p : 0;
\r
263 colors[4][i] = (p > 0x10)? 0x1f : p;
\r
264 colors[5][i] = 0x1f;
\r
268 void VW_SetDefaultColors(void)
\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
275 geninterrupt(0x10);
\r
276 screenfaded = false;
\r
281 void VW_FadeOut(void)
\r
283 #if GRMODE == EGAGR
\r
288 colors[i][16] = bordercolor;
\r
289 _ES=FP_SEG(&colors[i]);
\r
290 _DX=FP_OFF(&colors[i]);
\r
292 geninterrupt(0x10);
\r
295 screenfaded = true;
\r
300 void VW_FadeIn(void)
\r
302 #if GRMODE == EGAGR
\r
307 colors[i][16] = bordercolor;
\r
308 _ES=FP_SEG(&colors[i]);
\r
309 _DX=FP_OFF(&colors[i]);
\r
311 geninterrupt(0x10);
\r
314 screenfaded = false;
\r
318 void VW_FadeUp(void)
\r
320 #if GRMODE == EGAGR
\r
325 colors[i][16] = bordercolor;
\r
326 _ES=FP_SEG(&colors[i]);
\r
327 _DX=FP_OFF(&colors[i]);
\r
329 geninterrupt(0x10);
\r
332 screenfaded = true;
\r
336 void VW_FadeDown(void)
\r
338 #if GRMODE == EGAGR
\r
343 colors[i][16] = bordercolor;
\r
344 _ES=FP_SEG(&colors[i]);
\r
345 _DX=FP_OFF(&colors[i]);
\r
347 geninterrupt(0x10);
\r
350 screenfaded = false;
\r
356 ========================
\r
360 = Sets an attribute (pallete / border) register
\r
363 ========================
\r
366 void VW_SetAtrReg (int reg, int value)
\r
369 asm mov dx,STATUS_REGISTER_1
\r
371 asm mov dx,ATR_INDEX
\r
373 asm mov al,BYTE PTR [reg]
\r
375 asm mov al,BYTE PTR [value]
\r
379 asm mov dx,ATR_INDEX
\r
387 //===========================================================================
\r
390 ====================
\r
394 = Must be an even number of bytes
\r
396 ====================
\r
399 void VW_SetLineWidth (int width)
\r
403 #if GRMODE == EGAGR
\r
405 // set wide virtual screen
\r
407 asm mov dx,CRTC_INDEX
\r
408 asm mov al,CRTC_OFFSET
\r
409 asm mov ah,[BYTE PTR width]
\r
415 // set up lookup tables
\r
421 for (i=0;i<VIRTUALHEIGHT;i++)
\r
429 //===========================================================================
\r
432 ====================
\r
434 = VW_SetSplitScreen
\r
436 ====================
\r
439 void VW_SetSplitScreen (int linenum)
\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
450 outportb (CRTC_INDEX,CRTC_MAXSCANLINE);
\r
451 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));
\r
455 //===========================================================================
\r
458 ====================
\r
462 ====================
\r
465 void VW_ClearVideo (int color)
\r
467 #if GRMODE == EGAGR
\r
471 color = (color << 8) & color; //BUG: color is always 0 after this
\r
474 #if GRMODE == CGAGR
\r
475 color = (color << 12) & (color << 8) & (color << 4) & color; //BUG: color is always 0 after this
\r
480 asm mov es, screenseg;
\r
481 asm mov di, displayofs;
\r
487 #if GRMODE == EGAGR
\r
492 //===========================================================================
\r
497 ====================
\r
501 = X in bytes, y in pixels, chunknum is the #defined picnum
\r
503 ====================
\r
506 void VW_DrawPic(unsigned x, unsigned y, unsigned chunknum)
\r
508 int picnum = chunknum - STARTPICS;
\r
510 unsigned dest,width,height;
\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
517 VW_MemToScreen(source,dest,width,height);
\r
526 ====================
\r
530 = X in bytes, y in pixels, chunknum is the #defined picnum
\r
532 ====================
\r
535 void VW_DrawMPic(unsigned x, unsigned y, unsigned chunknum)
\r
537 int picnum = chunknum - STARTPICM;
\r
539 unsigned dest,width,height;
\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
546 VW_MaskBlock(source,0,dest,width,height,width*height);
\r
549 void VW_ClipDrawMPic(unsigned x, int y, unsigned chunknum)
\r
551 int picnum = chunknum - STARTPICM;
\r
553 unsigned dest,width,ofs,plane;
\r
556 source = grsegs[chunknum];
\r
557 width = picmtable[picnum].width;
\r
558 height = picmtable[picnum].height;
\r
559 plane = width*height;
\r
568 else if (y+height>216)
\r
572 dest = ylookup[y]+x+bufferofs;
\r
576 VW_MaskBlock(source,ofs,dest,width,height,plane);
\r
582 //===========================================================================
\r
587 ====================
\r
591 = X and Y in pixels, it will match the closest shift possible
\r
594 = Add vertical clipping!
\r
595 = Make the shifts act as center points, rather than break points
\r
597 ====================
\r
600 void VW_DrawSprite(int x, int y, unsigned chunknum)
\r
602 spritetabletype far *spr;
\r
603 spritetype _seg *block;
\r
604 unsigned dest,shift;
\r
606 spr = &spritetable[chunknum-STARTSPRITES];
\r
607 block = (spritetype _seg *)grsegs[chunknum];
\r
609 y+=spr->orgy>>G_P_SHIFT;
\r
610 x+=spr->orgx>>G_P_SHIFT;
\r
612 #if GRMODE == EGAGR
\r
615 #if GRMODE == CGAGR
\r
619 dest = bufferofs + ylookup[y];
\r
621 dest += x/SCREENXDIV;
\r
623 dest += (x+1)/SCREENXDIV;
\r
625 VW_MaskBlock (block,block->sourceoffset[shift],dest,
\r
626 block->width[shift],spr->height,block->planesize[shift]);
\r
641 #if GRMODE == EGAGR
\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
646 void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)
\r
648 unsigned dest,xlb,xhb,maskleft,maskright,mid;
\r
656 maskleft = leftmask[xl&7];
\r
657 maskright = rightmask[xh&7];
\r
660 dest = bufferofs+ylookup[y]+xlb;
\r
665 // entire line is in one byte
\r
668 maskleft&=maskright;
\r
670 asm mov es,[screenseg]
\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
678 asm mov al,[BYTE PTR color]
\r
679 asm xchg al,[es:di] // load latches and write pixels
\r
684 asm mov es,[screenseg]
\r
686 asm mov dx,GC_INDEX
\r
687 asm mov bh,[BYTE PTR color]
\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
697 asm mov bl,[es:di] // load latches
\r
703 asm mov ax,GC_BITMASK + 255*256
\r
704 asm out dx,ax // no masking
\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
717 asm xchg bh,[es:di] // load latches and write pixels
\r
726 #if GRMODE == CGAGR
\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
734 // could be optimized for rep stosw
\r
736 void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)
\r
738 unsigned dest,xlb,xhb,mid;
\r
739 byte maskleft,maskright;
\r
741 color = colorbyte[color]; // expand 2 color bits to 8
\r
746 maskleft = leftmask[xl&3];
\r
747 maskright = rightmask[xh&3];
\r
750 dest = bufferofs+ylookup[y]+xlb;
\r
751 asm mov es,[screenseg]
\r
756 // entire line is in one byte
\r
758 maskleft&=maskright;
\r
760 asm mov ah,[maskleft]
\r
761 asm mov bl,[BYTE PTR color]
\r
762 asm and bl,[maskleft]
\r
768 asm and al,ah // mask out pixels
\r
769 asm or al,bl // or in color
\r
775 asm mov bh,[BYTE PTR color]
\r
780 asm mov ah,[maskleft]
\r
782 asm and bl,[maskleft]
\r
785 asm and al,ah // mask out pixels
\r
786 asm or al,bl // or in color
\r
799 asm mov ah,[maskright]
\r
801 asm and bl,[maskright]
\r
804 asm and al,ah // mask out pixels
\r
805 asm or al,bl // or in color
\r
816 = Pixel addressable block fill routine
\r
821 #if GRMODE == CGAGR
\r
823 void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,
\r
826 unsigned xh = x+width-1;
\r
829 VW_Hlin (x,xh,y++,color);
\r
835 #if GRMODE == EGAGR
\r
837 void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,
\r
840 unsigned dest,xh,xlb,xhb,maskleft,maskright,mid;
\r
849 maskleft = leftmask[x&7];
\r
850 maskright = rightmask[xh&7];
\r
853 dest = bufferofs+ylookup[y]+xlb;
\r
858 // entire line is in one byte
\r
861 maskleft&=maskright;
\r
863 asm mov es,[screenseg]
\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
871 asm mov ah,[BYTE PTR color]
\r
872 asm mov dx,[linewidth]
\r
875 asm xchg al,[es:di] // load latches and write pixels
\r
876 asm add di,dx // down to next line
\r
883 asm mov es,[screenseg]
\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
895 asm mov al,GC_BITMASK
\r
896 asm mov ah,[BYTE PTR maskleft]
\r
897 asm out dx,ax // mask off pixels
\r
900 asm mov bl,[es:di] // load latches
\r
906 asm mov ax,GC_BITMASK + 255*256
\r
907 asm out dx,ax // no masking
\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
921 asm xchg al,[es:di] // load latches and write pixels
\r
923 asm add di,si // move to start of next line
\r
934 //==========================================================================
\r
944 #if NUMFONT+NUMFONTM>0
\r
946 VWL_MeasureString (char far *string, word *width, word *height, fontstruct _seg *font)
\r
948 *height = font->height;
\r
949 for (*width = 0;*string;string++)
\r
950 *width += font->width[*((byte far *)string)]; // proportional width
\r
953 void VW_MeasurePropString (char far *string, word *width, word *height)
\r
955 VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONT+fontnumber]);
\r
958 void VW_MeasureMPropString (char far *string, word *width, word *height)
\r
960 VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONTM+fontnumber]);
\r
968 =============================================================================
\r
972 =============================================================================
\r
975 #if GRMODE == CGAGR
\r
977 #define CGACRTCWIDTH 40
\r
980 ==========================
\r
984 ==========================
\r
987 void VW_CGAFullUpdate (void)
\r
991 unsigned x,y,middlerows,middlecollumns;
\r
993 displayofs = bufferofs+panadjust;
\r
998 asm mov si,[displayofs]
\r
1001 asm mov bx,100 // pairs of scan lines to copy
\r
1002 asm mov dx,[linewidth]
\r
1005 asm mov ds,[screenseg]
\r
1012 asm mov ax,39 // words accross screen
\r
1019 asm add di,0x2000-80 // go to the interlaced bank
\r
1025 asm sub di,0x2000 // go to the non interlaced bank
\r
1028 asm jnz copytwolineso
\r
1035 asm mov ax,40 // words accross screen
\r
1040 asm add di,0x2000-80 // go to the interlaced bank
\r
1044 asm sub di,0x2000 // go to the non interlaced bank
\r
1047 asm jnz copytwolines
\r
1054 asm xor ax,ax // clear out the update matrix
\r
1055 asm mov cx,UPDATEWIDE*UPDATEHIGH/2
\r
1057 asm mov di,[baseupdateptr]
\r
1060 updateptr = baseupdateptr;
\r
1061 *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;
\r
1068 =============================================================================
\r
1072 These only work in the context of the double buffered update routines
\r
1074 =============================================================================
\r
1078 ====================
\r
1082 = Background saves, then draws the cursor at cursorspot
\r
1084 ====================
\r
1087 void VWL_DrawCursor (void)
\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
1095 //==========================================================================
\r
1099 ====================
\r
1103 ====================
\r
1106 void VWL_EraseCursor (void)
\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
1115 //==========================================================================
\r
1119 ====================
\r
1123 ====================
\r
1126 void VW_ShowCursor (void)
\r
1132 //==========================================================================
\r
1135 ====================
\r
1139 ====================
\r
1142 void VW_HideCursor (void)
\r
1147 //==========================================================================
\r
1150 ====================
\r
1154 ====================
\r
1156 #define MAXCURSORX (319-24)
\r
1157 #define MAXCURSORY (199-24)
\r
1159 void VW_MoveCursor (int x, int y)
\r
1165 y=MAXCURSORY; // catacombs hack to keep cursor on screen
\r
1172 //==========================================================================
\r
1175 ====================
\r
1179 = Load in a sprite to be used as a cursor, and allocate background save space
\r
1181 ====================
\r
1184 void VW_SetCursor (int spritenum)
\r
1188 cursornumber = spritenum;
\r
1190 CA_CacheGrChunk (spritenum);
\r
1191 MM_SetLock (&grsegs[spritenum],true);
\r
1193 cursorwidth = spritetable[spritenum-STARTSPRITES].width+1;
\r
1194 cursorheight = spritetable[spritenum-STARTSPRITES].height;
\r
1196 MM_GetPtr (&cursorsave,cursorwidth*cursorheight*5);
\r
1197 MM_SetLock (&cursorsave,true);
\r
1202 ====================
\r
1206 = Frees the memory used by the cursor and its background save
\r
1208 ====================
\r
1211 void VW_FreeCursor (void)
\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
1225 =============================================================================
\r
1227 Double buffer management routines
\r
1229 =============================================================================
\r
1233 ======================
\r
1235 = VW_InitDoubleBuffer
\r
1237 ======================
\r
1240 void VW_InitDoubleBuffer (void)
\r
1242 #if GRMODE == EGAGR
\r
1243 VW_SetScreen (displayofs+panadjust,0); // no pel pan
\r
1249 ======================
\r
1251 = VW_FixRefreshBuffer
\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
1256 ======================
\r
1259 void VW_FixRefreshBuffer (void)
\r
1261 #if GRMODE == EGAGR
\r
1262 VW_ScreenToScreen (displayofs,bufferofs,PORTTILESWIDE*4*CHARWIDTH,
\r
1263 (PORTTILESHIGH-1)*16);
\r
1269 ======================
\r
1271 = VW_QuitDoubleBuffer
\r
1273 ======================
\r
1276 void VW_QuitDoubleBuffer (void)
\r
1282 =======================
\r
1284 = VW_MarkUpdateBlock
\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
1289 =======================
\r
1292 int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2)
\r
1294 int x,y,xt1,yt1,xt2,yt2,nextline;
\r
1297 xt1 = x1>>PIXTOBLOCK;
\r
1298 yt1 = y1>>PIXTOBLOCK;
\r
1300 xt2 = x2>>PIXTOBLOCK;
\r
1301 yt2 = y2>>PIXTOBLOCK;
\r
1305 else if (xt1>=UPDATEWIDE-1)
\r
1310 else if (yt1>UPDATEHIGH)
\r
1315 else if (xt2>=UPDATEWIDE-1)
\r
1316 xt2 = UPDATEWIDE-2;
\r
1320 else if (yt2>=UPDATEHIGH)
\r
1321 yt2 = UPDATEHIGH-1;
\r
1323 mark = updateptr + uwidthtable[yt1] + xt1;
\r
1324 nextline = UPDATEWIDE - (xt2-xt1) - 1;
\r
1326 for (y=yt1;y<=yt2;y++)
\r
1328 for (x=xt1;x<=xt2;x++)
\r
1329 *mark++ = 1; // this tile will need to be updated
\r
1339 ===========================
\r
1343 = Updates any changed areas of the double buffer and displays the cursor
\r
1345 ===========================
\r
1348 void VW_UpdateScreen (void)
\r
1350 if (cursorvisible>0)
\r
1353 #if GRMODE == EGAGR
\r
1354 VWL_UpdateScreenBlocks();
\r
1356 #if GRMODE == CGAGR
\r
1357 VW_CGAFullUpdate();
\r
1360 if (cursorvisible>0)
\r
1361 VWL_EraseCursor();
\r
1366 void VWB_DrawTile8 (int x, int y, int tile)
\r
1370 if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7))
\r
1371 VW_DrawTile8 (x/SCREENXDIV,y,tile);
\r
1374 void VWB_DrawTile8M (int x, int y, int tile)
\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
1385 void VWB_DrawTile16 (int x, int y, int tile)
\r
1389 if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))
\r
1390 VW_DrawTile16 (x/SCREENXDIV,y,tile);
\r
1393 void VWB_DrawTile16M (int x, int y, int tile)
\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
1405 void VWB_DrawPic (int x, int y, int chunknum)
\r
1407 // mostly copied from drawpic
\r
1408 int picnum = chunknum - STARTPICS;
\r
1410 unsigned dest,width,height;
\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
1421 if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))
\r
1422 VW_MemToScreen(source,dest,width,height);
\r
1427 void VWB_DrawMPic(int x, int y, int chunknum)
\r
1429 // mostly copied from drawmpic
\r
1430 int picnum = chunknum - STARTPICM;
\r
1432 unsigned dest,width,height;
\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
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
1449 void VWB_Bar (int x, int y, int width, int height, int color)
\r
1453 if (VW_MarkUpdateBlock (x,y,x+width,y+height-1) )
\r
1454 VW_Bar (x,y,width,height,color);
\r
1459 void VWB_DrawPropString (char far *string)
\r
1464 VW_DrawPropString (string);
\r
1465 VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);
\r
1471 void VWB_DrawMPropString (char far *string)
\r
1476 VW_DrawMPropString (string);
\r
1477 VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);
\r
1482 void VWB_DrawSprite(int x, int y, int chunknum)
\r
1484 spritetabletype far *spr;
\r
1485 spritetype _seg *block;
\r
1486 unsigned dest,shift,width,height;
\r
1491 spr = &spritetable[chunknum-STARTSPRITES];
\r
1492 block = (spritetype _seg *)grsegs[chunknum];
\r
1494 y+=spr->orgy>>G_P_SHIFT;
\r
1495 x+=spr->orgx>>G_P_SHIFT;
\r
1498 #if GRMODE == EGAGR
\r
1501 #if GRMODE == CGAGR
\r
1505 dest = bufferofs + ylookup[y];
\r
1507 dest += x/SCREENXDIV;
\r
1509 dest += (x+1)/SCREENXDIV;
\r
1511 width = block->width[shift];
\r
1512 height = spr->height;
\r
1514 if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+width*SCREENXDIV-1
\r
1516 VW_MaskBlock (block,block->sourceoffset[shift],dest,
\r
1517 width,height,block->planesize[shift]);
\r
1521 void VWB_Plot (int x, int y, int color)
\r
1525 if (VW_MarkUpdateBlock (x,y,x,y))
\r
1526 VW_Plot(x,y,color);
\r
1529 void VWB_Hlin (int x1, int x2, int y, int color)
\r
1534 if (VW_MarkUpdateBlock (x1,y,x2,y))
\r
1535 VW_Hlin(x1,x2,y,color);
\r
1538 void VWB_Vlin (int y1, int y2, int x, int color)
\r
1543 if (VW_MarkUpdateBlock (x,y1,x,y2))
\r
1544 VW_Vlin(y1,y2,x,color);
\r
1548 //===========================================================================
\r