+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_VW.C\r
-\r
-#include "ID_HEADS.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define VIEWWIDTH 40\r
-\r
-#define PIXTOBLOCK 4 // 16 pixels to an update block\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-cardtype videocard; // set by VW_Startup\r
-grtype grmode; // CGAgr, EGAgr, VGAgr\r
-\r
-unsigned bufferofs; // hidden area to draw to before displaying\r
-unsigned displayofs; // origin of the visable screen\r
-unsigned panx,pany; // panning adjustments inside port in pixels\r
-unsigned pansx,pansy; // panning adjustments inside port in screen\r
- // block limited pixel values (ie 0/8 for ega x)\r
-unsigned panadjust; // panx/pany adjusted by screen resolution\r
-\r
-unsigned screenseg; // normally 0xa000 / 0xb800\r
-unsigned linewidth;\r
-unsigned ylookup[VIRTUALHEIGHT];\r
-\r
-unsigned fontnumber; // 0 based font number for drawing\r
-\r
-boolean screenfaded;\r
-\r
-pictabletype _seg *pictable;\r
-pictabletype _seg *picmtable;\r
-spritetabletype _seg *spritetable;\r
-\r
-int bordercolor;\r
-boolean nopan;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void VWL_MeasureString (char far *string, word *width, word *height,\r
- fontstruct _seg *font);\r
-void VWL_DrawCursor (void);\r
-void VWL_EraseCursor (void);\r
-void VWL_DBSetup (void);\r
-void VWL_UpdateScreenBlocks (void);\r
-\r
-\r
-int bordercolor;\r
-int cursorvisible;\r
-int cursornumber,cursorwidth,cursorheight,cursorx,cursory;\r
-memptr cursorsave;\r
-unsigned cursorspot;\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_Startup\r
-=\r
-=======================\r
-*/\r
-\r
-static char *ParmStrings[] = {"HIDDENCARD","NOPAN",""};\r
-\r
-void VW_Startup (void)\r
-{\r
- int i,n;\r
-\r
- asm cld;\r
-\r
- videocard = 0;\r
-\r
- for (i = 1;i < _argc;i++)\r
- {\r
- n = US_CheckParm(_argv[i],ParmStrings);\r
- if (n == 0)\r
- {\r
- videocard = EGAcard;\r
- }\r
- else if (n == 1)\r
- {\r
- nopan = true;\r
- }\r
- }\r
-\r
- if (!videocard)\r
- videocard = VW_VideoID ();\r
-\r
-#if GRMODE == EGAGR\r
- grmode = EGAGR;\r
- if (videocard != EGAcard && videocard != VGAcard)\r
-#ifdef KEEN\r
-Quit ("Improper video card! If you really have an EGA/VGA card that I am not\n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
-#else\r
-Quit ("Improper video card! If you really have an EGA/VGA card that I am not \n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
-#endif\r
- EGAWRITEMODE(0);\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- grmode = CGAGR;\r
- if (videocard < CGAcard || videocard > VGAcard)\r
-#ifdef KEEN\r
-Quit ("Improper video card! If you really have a CGA card that I am not\n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
-#else\r
-Quit ("Improper video card! If you really have a CGA card that I am not \n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
-#endif\r
- MM_GetPtr (&(memptr)screenseg,0x10000l); // grab 64k for floating screen\r
-#endif\r
-\r
- cursorvisible = 0;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_Shutdown\r
-=\r
-=======================\r
-*/\r
-\r
-void VW_Shutdown (void)\r
-{\r
- VW_SetScreenMode (TEXTGR);\r
-#if GRMODE == EGAGR\r
- VW_SetLineWidth (80);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-========================\r
-=\r
-= VW_SetScreenMode\r
-= Call BIOS to set TEXT / CGAgr / EGAgr / VGAgr\r
-=\r
-========================\r
-*/\r
-\r
-void VW_SetScreenMode (int grmode)\r
-{\r
- switch (grmode)\r
- {\r
- case TEXTGR: _AX = 3;\r
- geninterrupt (0x10);\r
-#ifdef CAT3D\r
- screenseg=0xb000;\r
-#endif\r
- break;\r
- case CGAGR: _AX = 4;\r
- geninterrupt (0x10); // screenseg is actually a main mem buffer\r
- break;\r
- case EGAGR: _AX = 0xd;\r
- geninterrupt (0x10);\r
- screenseg=0xa000;\r
- break;\r
-#ifdef VGAGAME\r
- case VGAGR:{\r
- char extern VGAPAL; // deluxepaint vga pallet .OBJ file\r
- void far *vgapal = &VGAPAL;\r
- SetCool256 (); // custom 256 color mode\r
- screenseg=0xa000;\r
- _ES = FP_SEG(vgapal);\r
- _DX = FP_OFF(vgapal);\r
- _BX = 0;\r
- _CX = 0x100;\r
- _AX = 0x1012;\r
- geninterrupt(0x10); // set the deluxepaint pallet\r
-\r
- break;\r
-#endif\r
- }\r
- VW_SetLineWidth(SCREENWIDTH);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SCREEN FADES\r
-\r
-=============================================================================\r
-*/\r
-\r
-char colors[7][17]=\r
-{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},\r
- {0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,0},\r
- {0,0,0,0,0,0,0,0,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0},\r
- {0,1,2,3,4,5,6,7,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0},\r
- {0,1,2,3,4,5,6,7,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0},\r
- {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f}};\r
-\r
-\r
-void VW_ColorBorder (int color)\r
-{\r
- _AH=0x10;\r
- _AL=1;\r
- _BH=color;\r
- geninterrupt (0x10);\r
- bordercolor = color;\r
-}\r
-\r
-void VW_SetPalette(byte *palette)\r
-{\r
- byte p;\r
- word i;\r
-\r
- for (i = 0;i < 15;i++)\r
- {\r
- p = palette[i];\r
- colors[0][i] = 0;\r
- colors[1][i] = (p > 0x10)? (p & 0x0f) : 0;\r
- colors[2][i] = (p > 0x10)? p : 0;\r
- colors[3][i] = p;\r
- colors[4][i] = (p > 0x10)? 0x1f : p;\r
- colors[5][i] = 0x1f;\r
- }\r
-}\r
-\r
-void VW_SetDefaultColors(void)\r
-{\r
-#if GRMODE == EGAGR\r
- colors[3][16] = bordercolor;\r
- _ES=FP_SEG(&colors[3]);\r
- _DX=FP_OFF(&colors[3]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-\r
-void VW_FadeOut(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=3;i>=0;i--)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = true;\r
-#endif\r
-}\r
-\r
-\r
-void VW_FadeIn(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=0;i<4;i++)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-void VW_FadeUp(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=3;i<6;i++)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = true;\r
-#endif\r
-}\r
-\r
-void VW_FadeDown(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=5;i>2;i--)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= VW_SetAtrReg\r
-=\r
-= Sets an attribute (pallete / border) register\r
-= Does NOT vsync!\r
-=\r
-========================\r
-*/\r
-\r
-void VW_SetAtrReg (int reg, int value)\r
-{\r
- asm cli\r
- asm mov dx,STATUS_REGISTER_1\r
- asm in al,dx\r
- asm mov dx,ATR_INDEX\r
-\r
- asm mov al,BYTE PTR [reg]\r
- asm out dx,al\r
- asm mov al,BYTE PTR [value]\r
- asm out dx,al\r
- asm mov dx,0x3da\r
- asm in al,dx\r
- asm mov dx,ATR_INDEX\r
- asm mov al,0x20\r
- asm out dx,al\r
- asm sti\r
-}\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetLineWidth\r
-=\r
-= Must be an even number of bytes\r
-=\r
-====================\r
-*/\r
-\r
-void VW_SetLineWidth (int width)\r
-{\r
- int i,offset;\r
-\r
-#if GRMODE == EGAGR\r
-//\r
-// set wide virtual screen\r
-//\r
-asm mov dx,CRTC_INDEX\r
-asm mov al,CRTC_OFFSET\r
-asm mov ah,[BYTE PTR width]\r
-asm shr ah,1\r
-asm out dx,ax\r
-#endif\r
-\r
-//\r
-// set up lookup tables\r
-//\r
- linewidth = width;\r
-\r
- offset = 0;\r
-\r
- for (i=0;i<VIRTUALHEIGHT;i++)\r
- {\r
- ylookup[i]=offset;\r
- offset += width;\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetSplitScreen\r
-=\r
-====================\r
-*/\r
-#ifdef CAT3D\r
-void VW_SetSplitScreen (int linenum)\r
-{\r
- VW_WaitVBL (1);\r
- if (videocard==VGAcard)\r
- linenum=linenum*2-1;\r
- outportb (CRTC_INDEX,CRTC_LINECOMPARE);\r
- outportb (CRTC_INDEX+1,linenum % 256);\r
- outportb (CRTC_INDEX,CRTC_OVERFLOW);\r
- outportb (CRTC_INDEX+1, 1+16*(linenum/256));\r
- if (videocard==VGAcard)\r
- {\r
- outportb (CRTC_INDEX,CRTC_MAXSCANLINE);\r
- outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));\r
- }\r
-}\r
-#endif\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_ClearVideo\r
-=\r
-====================\r
-*/\r
-\r
-void VW_ClearVideo (int color)\r
-{\r
-#if GRMODE == EGAGR\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
- color = (color << 8) & color; //BUG: color is always 0 after this\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- color = (color << 12) & (color << 8) & (color << 4) & color; //BUG: color is always 0 after this\r
-#endif\r
-\r
- VW_WaitVBL(1);\r
-\r
-asm mov es, screenseg;\r
-asm mov di, displayofs;\r
-asm and di, not 1;\r
-asm mov cx, 8000h;\r
-asm mov ax, color;\r
-asm rep stosw;\r
-\r
-#if GRMODE == EGAGR\r
- EGAWRITEMODE(0);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if NUMPICS>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawPic\r
-=\r
-= X in bytes, y in pixels, chunknum is the #defined picnum\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawPic(unsigned x, unsigned y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICS;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = pictable[picnum].width;\r
- height = pictable[picnum].height;\r
-\r
- VW_MemToScreen(source,dest,width,height);\r
-}\r
-\r
-\r
-#endif\r
-\r
-#if NUMPICM>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawMPic\r
-=\r
-= X in bytes, y in pixels, chunknum is the #defined picnum\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawMPic(unsigned x, unsigned y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
-\r
- VW_MaskBlock(source,0,dest,width,height,width*height);\r
-}\r
-\r
-void VW_ClipDrawMPic(unsigned x, int y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,ofs,plane;\r
- int height;\r
-\r
- source = grsegs[chunknum];\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
- plane = width*height;\r
-\r
- ofs = 0;\r
- if (y<0)\r
- {\r
- ofs= -y*width;\r
- height+=y;\r
- y=0;\r
- }\r
- else if (y+height>216)\r
- {\r
- height-=(y-216);\r
- }\r
- dest = ylookup[y]+x+bufferofs;\r
- if (height<1)\r
- return;\r
-\r
- VW_MaskBlock(source,ofs,dest,width,height,plane);\r
-}\r
-\r
-\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-#if NUMSPRITES>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawSprite\r
-=\r
-= X and Y in pixels, it will match the closest shift possible\r
-=\r
-= To do:\r
-= Add vertical clipping!\r
-= Make the shifts act as center points, rather than break points\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawSprite(int x, int y, unsigned chunknum)\r
-{\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned dest,shift;\r
-\r
- spr = &spritetable[chunknum-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[chunknum];\r
-\r
- y+=spr->orgy>>G_P_SHIFT;\r
- x+=spr->orgx>>G_P_SHIFT;\r
-\r
-#if GRMODE == EGAGR\r
- shift = (x&7)/2;\r
-#endif\r
-#if GRMODE == CGAGR\r
- shift = 0;\r
-#endif\r
-\r
- dest = bufferofs + ylookup[y];\r
- if (x>=0)\r
- dest += x/SCREENXDIV;\r
- else\r
- dest += (x+1)/SCREENXDIV;\r
-\r
- VW_MaskBlock (block,block->sourceoffset[shift],dest,\r
- block->width[shift],spr->height,block->planesize[shift]);\r
-}\r
-\r
-#endif\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= VW_Hlin\r
-=\r
-==================\r
-*/\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-unsigned char leftmask[8] = {0xff,0x7f,0x3f,0x1f,0xf,7,3,1};\r
-unsigned char rightmask[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};\r
-\r
-void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)\r
-{\r
- unsigned dest,xlb,xhb,maskleft,maskright,mid;\r
-\r
- xlb=xl/8;\r
- xhb=xh/8;\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
- maskleft = leftmask[xl&7];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
-\r
- asm mov dx,GC_INDEX\r
- asm mov al,GC_BITMASK\r
- asm mov ah,[BYTE PTR maskleft]\r
- asm out dx,ax // mask off pixels\r
-\r
- asm mov al,[BYTE PTR color]\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
- goto done;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov dx,GC_INDEX\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskleft]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm mov bl,[es:di] // load latches\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov ax,GC_BITMASK + 255*256\r
-asm out dx,ax // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskright]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm xchg bh,[es:di] // load latches and write pixels\r
-\r
-done:\r
- EGABITMASK(255);\r
- EGAWRITEMODE(0);\r
-}\r
-#endif\r
-\r
-\r
-#if GRMODE == CGAGR\r
-\r
-unsigned char pixmask[4] = {0xc0,0x30,0x0c,0x03};\r
-unsigned char leftmask[4] = {0xff,0x3f,0x0f,0x03};\r
-unsigned char rightmask[4] = {0xc0,0xf0,0xfc,0xff};\r
-unsigned char colorbyte[4] = {0,0x55,0xaa,0xff};\r
-\r
-//\r
-// could be optimized for rep stosw\r
-//\r
-void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)\r
-{\r
- unsigned dest,xlb,xhb,mid;\r
- byte maskleft,maskright;\r
-\r
- color = colorbyte[color]; // expand 2 color bits to 8\r
-\r
- xlb=xl/4;\r
- xhb=xh/4;\r
-\r
- maskleft = leftmask[xl&3];\r
- maskright = rightmask[xh&3];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-asm mov es,[screenseg]\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
- maskleft&=maskright;\r
-\r
- asm mov ah,[maskleft]\r
- asm mov bl,[BYTE PTR color]\r
- asm and bl,[maskleft]\r
- asm not ah\r
-\r
- asm mov di,[dest]\r
-\r
- asm mov al,[es:di]\r
- asm and al,ah // mask out pixels\r
- asm or al,bl // or in color\r
- asm mov [es:di],al\r
- return;\r
- }\r
-\r
-asm mov di,[dest]\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov ah,[maskleft]\r
-asm mov bl,bh\r
-asm and bl,[maskleft]\r
-asm not ah\r
-asm mov al,[es:di]\r
-asm and al,ah // mask out pixels\r
-asm or al,bl // or in color\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov ah,[maskright]\r
-asm mov bl,bh\r
-asm and bl,[maskright]\r
-asm not ah\r
-asm mov al,[es:di]\r
-asm and al,ah // mask out pixels\r
-asm or al,bl // or in color\r
-asm stosb\r
-}\r
-#endif\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= VW_Bar\r
-=\r
-= Pixel addressable block fill routine\r
-=\r
-==================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,\r
- unsigned color)\r
-{\r
- unsigned xh = x+width-1;\r
-\r
- while (height--)\r
- VW_Hlin (x,xh,y++,color);\r
-}\r
-\r
-#endif\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,\r
- unsigned color)\r
-{\r
- unsigned dest,xh,xlb,xhb,maskleft,maskright,mid;\r
-\r
- xh = x+width-1;\r
- xlb=x/8;\r
- xhb=xh/8;\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
- maskleft = leftmask[x&7];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
-\r
- asm mov dx,GC_INDEX\r
- asm mov al,GC_BITMASK\r
- asm mov ah,[BYTE PTR maskleft]\r
- asm out dx,ax // mask off pixels\r
-\r
- asm mov ah,[BYTE PTR color]\r
- asm mov dx,[linewidth]\r
-yloop1:\r
- asm mov al,ah\r
- asm xchg al,[es:di] // load latches and write pixels\r
- asm add di,dx // down to next line\r
- asm dec [height]\r
- asm jnz yloop1\r
-\r
- goto done;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov bh,[BYTE PTR color]\r
-asm mov dx,GC_INDEX\r
-asm mov si,[linewidth]\r
-asm sub si,[mid] // add to di at end of line to get to next scan\r
-asm dec si\r
-\r
-//\r
-// draw left side\r
-//\r
-yloop2:\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskleft]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm mov bl,[es:di] // load latches\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov ax,GC_BITMASK + 255*256\r
-asm out dx,ax // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskright]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm xchg al,[es:di] // load latches and write pixels\r
-\r
-asm add di,si // move to start of next line\r
-asm dec [height]\r
-asm jnz yloop2\r
-\r
-done:\r
- EGABITMASK(255);\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= VW_MeasureString\r
-=\r
-==================\r
-*/\r
-\r
-#if NUMFONT+NUMFONTM>0\r
-void\r
-VWL_MeasureString (char far *string, word *width, word *height, fontstruct _seg *font)\r
-{\r
- *height = font->height;\r
- for (*width = 0;*string;string++)\r
- *width += font->width[*((byte far *)string)]; // proportional width\r
-}\r
-\r
-void VW_MeasurePropString (char far *string, word *width, word *height)\r
-{\r
- VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONT+fontnumber]);\r
-}\r
-\r
-void VW_MeasureMPropString (char far *string, word *width, word *height)\r
-{\r
- VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONTM+fontnumber]);\r
-}\r
-\r
-\r
-#endif\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- CGA stuff\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define CGACRTCWIDTH 40\r
-\r
-/*\r
-==========================\r
-=\r
-= VW_CGAFullUpdate\r
-=\r
-==========================\r
-*/\r
-\r
-void VW_CGAFullUpdate (void)\r
-{\r
- byte *update;\r
- boolean halftile;\r
- unsigned x,y,middlerows,middlecollumns;\r
-\r
- displayofs = bufferofs+panadjust;\r
-\r
-asm mov ax,0xb800\r
-asm mov es,ax\r
-\r
-asm mov si,[displayofs]\r
-asm xor di,di\r
-\r
-asm mov bx,100 // pairs of scan lines to copy\r
-asm mov dx,[linewidth]\r
-asm sub dx,80\r
-\r
-asm mov ds,[screenseg]\r
-asm test si,1\r
-asm jz evenblock\r
-\r
-//\r
-// odd source\r
-//\r
-asm mov ax,39 // words accross screen\r
-copytwolineso:\r
-asm movsb\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm movsb\r
-asm add si,dx\r
-asm add di,0x2000-80 // go to the interlaced bank\r
-asm movsb\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm movsb\r
-asm add si,dx\r
-asm sub di,0x2000 // go to the non interlaced bank\r
-\r
-asm dec bx\r
-asm jnz copytwolineso\r
-asm jmp blitdone\r
-\r
-//\r
-// even source\r
-//\r
-evenblock:\r
-asm mov ax,40 // words accross screen\r
-copytwolines:\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm add si,dx\r
-asm add di,0x2000-80 // go to the interlaced bank\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm add si,dx\r
-asm sub di,0x2000 // go to the non interlaced bank\r
-\r
-asm dec bx\r
-asm jnz copytwolines\r
-\r
-blitdone:\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-asm mov es,ax\r
-\r
-asm xor ax,ax // clear out the update matrix\r
-asm mov cx,UPDATEWIDE*UPDATEHIGH/2\r
-\r
-asm mov di,[baseupdateptr]\r
-asm rep stosw\r
-\r
- updateptr = baseupdateptr;\r
- *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;\r
-}\r
-\r
-\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- CURSOR ROUTINES\r
-\r
-These only work in the context of the double buffered update routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-====================\r
-=\r
-= VWL_DrawCursor\r
-=\r
-= Background saves, then draws the cursor at cursorspot\r
-=\r
-====================\r
-*/\r
-\r
-void VWL_DrawCursor (void)\r
-{\r
- cursorspot = bufferofs + ylookup[cursory+pansy]+(cursorx+pansx)/SCREENXDIV;\r
- VW_ScreenToMem(cursorspot,cursorsave,cursorwidth,cursorheight);\r
- VWB_DrawSprite(cursorx,cursory,cursornumber);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VWL_EraseCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VWL_EraseCursor (void)\r
-{\r
- VW_MemToScreen(cursorsave,cursorspot,cursorwidth,cursorheight);\r
- VW_MarkUpdateBlock ((cursorx+pansx)&SCREENXMASK,cursory+pansy,\r
- ( (cursorx+pansx)&SCREENXMASK)+cursorwidth*SCREENXDIV-1,\r
- cursory+pansy+cursorheight-1);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VW_ShowCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VW_ShowCursor (void)\r
-{\r
- cursorvisible++;\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_HideCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VW_HideCursor (void)\r
-{\r
- cursorvisible--;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_MoveCursor\r
-=\r
-====================\r
-*/\r
-#define MAXCURSORX (319-24)\r
-#define MAXCURSORY (199-24)\r
-\r
-void VW_MoveCursor (int x, int y)\r
-{\r
-#ifdef CAT3D\r
- if (x>MAXCURSORX)\r
- x=MAXCURSORX;\r
- if (y>MAXCURSORY)\r
- y=MAXCURSORY; // catacombs hack to keep cursor on screen\r
-#endif\r
-\r
- cursorx = x;\r
- cursory = y;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetCursor\r
-=\r
-= Load in a sprite to be used as a cursor, and allocate background save space\r
-=\r
-====================\r
-*/\r
-\r
-void VW_SetCursor (int spritenum)\r
-{\r
- VW_FreeCursor ();\r
-\r
- cursornumber = spritenum;\r
-\r
- CA_CacheGrChunk (spritenum);\r
- MM_SetLock (&grsegs[spritenum],true);\r
-\r
- cursorwidth = spritetable[spritenum-STARTSPRITES].width+1;\r
- cursorheight = spritetable[spritenum-STARTSPRITES].height;\r
-\r
- MM_GetPtr (&cursorsave,cursorwidth*cursorheight*5);\r
- MM_SetLock (&cursorsave,true);\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VW_FreeCursor\r
-=\r
-= Frees the memory used by the cursor and its background save\r
-=\r
-====================\r
-*/\r
-\r
-void VW_FreeCursor (void)\r
-{\r
- if (cursornumber)\r
- {\r
- MM_SetLock (&grsegs[cursornumber],false);\r
- MM_SetPurge (&grsegs[cursornumber],3);\r
- MM_SetLock (&cursorsave,false);\r
- MM_FreePtr (&cursorsave);\r
- cursornumber = 0;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- Double buffer management routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-======================\r
-=\r
-= VW_InitDoubleBuffer\r
-=\r
-======================\r
-*/\r
-\r
-void VW_InitDoubleBuffer (void)\r
-{\r
-#if GRMODE == EGAGR\r
- VW_SetScreen (displayofs+panadjust,0); // no pel pan\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= VW_FixRefreshBuffer\r
-=\r
-= Copies the view page to the buffer page on page flipped refreshes to\r
-= avoid a one frame shear around pop up windows\r
-=\r
-======================\r
-*/\r
-\r
-void VW_FixRefreshBuffer (void)\r
-{\r
-#if GRMODE == EGAGR\r
- VW_ScreenToScreen (displayofs,bufferofs,PORTTILESWIDE*4*CHARWIDTH,\r
- (PORTTILESHIGH-1)*16);\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= VW_QuitDoubleBuffer\r
-=\r
-======================\r
-*/\r
-\r
-void VW_QuitDoubleBuffer (void)\r
-{\r
-}\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_MarkUpdateBlock\r
-=\r
-= Takes a pixel bounded block and marks the tiles in bufferblocks\r
-= Returns 0 if the entire block is off the buffer screen\r
-=\r
-=======================\r
-*/\r
-\r
-int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2)\r
-{\r
- int x,y,xt1,yt1,xt2,yt2,nextline;\r
- byte *mark;\r
-\r
- xt1 = x1>>PIXTOBLOCK;\r
- yt1 = y1>>PIXTOBLOCK;\r
-\r
- xt2 = x2>>PIXTOBLOCK;\r
- yt2 = y2>>PIXTOBLOCK;\r
-\r
- if (xt1<0)\r
- xt1=0;\r
- else if (xt1>=UPDATEWIDE-1)\r
- return 0;\r
-\r
- if (yt1<0)\r
- yt1=0;\r
- else if (yt1>UPDATEHIGH)\r
- return 0;\r
-\r
- if (xt2<0)\r
- return 0;\r
- else if (xt2>=UPDATEWIDE-1)\r
- xt2 = UPDATEWIDE-2;\r
-\r
- if (yt2<0)\r
- return 0;\r
- else if (yt2>=UPDATEHIGH)\r
- yt2 = UPDATEHIGH-1;\r
-\r
- mark = updateptr + uwidthtable[yt1] + xt1;\r
- nextline = UPDATEWIDE - (xt2-xt1) - 1;\r
-\r
- for (y=yt1;y<=yt2;y++)\r
- {\r
- for (x=xt1;x<=xt2;x++)\r
- *mark++ = 1; // this tile will need to be updated\r
-\r
- mark += nextline;\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-\r
-/*\r
-===========================\r
-=\r
-= VW_UpdateScreen\r
-=\r
-= Updates any changed areas of the double buffer and displays the cursor\r
-=\r
-===========================\r
-*/\r
-\r
-void VW_UpdateScreen (void)\r
-{\r
- if (cursorvisible>0)\r
- VWL_DrawCursor();\r
-\r
-#if GRMODE == EGAGR\r
- VWL_UpdateScreenBlocks();\r
-#endif\r
-#if GRMODE == CGAGR\r
- VW_CGAFullUpdate();\r
-#endif\r
-\r
- if (cursorvisible>0)\r
- VWL_EraseCursor();\r
-}\r
-\r
-\r
-\r
-void VWB_DrawTile8 (int x, int y, int tile)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7))\r
- VW_DrawTile8 (x/SCREENXDIV,y,tile);\r
-}\r
-\r
-void VWB_DrawTile8M (int x, int y, int tile)\r
-{\r
- int xb;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- xb = x/SCREENXDIV; // use intermediate because VW_DT8M is macro\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7))\r
- VW_DrawTile8M (xb,y,tile);\r
-}\r
-\r
-void VWB_DrawTile16 (int x, int y, int tile)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))\r
- VW_DrawTile16 (x/SCREENXDIV,y,tile);\r
-}\r
-\r
-void VWB_DrawTile16M (int x, int y, int tile)\r
-{\r
- int xb;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- xb = x/SCREENXDIV; // use intermediate because VW_DT16M is macro\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))\r
- VW_DrawTile16M (xb,y,tile);\r
-}\r
-\r
-#if NUMPICS\r
-void VWB_DrawPic (int x, int y, int chunknum)\r
-{\r
-// mostly copied from drawpic\r
- int picnum = chunknum - STARTPICS;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- x/= SCREENXDIV;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = pictable[picnum].width;\r
- height = pictable[picnum].height;\r
-\r
- if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))\r
- VW_MemToScreen(source,dest,width,height);\r
-}\r
-#endif\r
-\r
-#if NUMPICM>0\r
-void VWB_DrawMPic(int x, int y, int chunknum)\r
-{\r
-// mostly copied from drawmpic\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- x/=SCREENXDIV;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
-\r
- if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))\r
- VW_MaskBlock(source,0,dest,width,height,width*height);\r
-}\r
-#endif\r
-\r
-\r
-void VWB_Bar (int x, int y, int width, int height, int color)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x,y,x+width,y+height-1) )\r
- VW_Bar (x,y,width,height,color);\r
-}\r
-\r
-\r
-#if NUMFONT\r
-void VWB_DrawPropString (char far *string)\r
-{\r
- int x,y;\r
- x = px+pansx;\r
- y = py+pansy;\r
- VW_DrawPropString (string);\r
- VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);\r
-}\r
-#endif\r
-\r
-\r
-#if NUMFONTM\r
-void VWB_DrawMPropString (char far *string)\r
-{\r
- int x,y;\r
- x = px+pansx;\r
- y = py+pansy;\r
- VW_DrawMPropString (string);\r
- VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);\r
-}\r
-#endif\r
-\r
-#if NUMSPRITES\r
-void VWB_DrawSprite(int x, int y, int chunknum)\r
-{\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned dest,shift,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
-\r
- spr = &spritetable[chunknum-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[chunknum];\r
-\r
- y+=spr->orgy>>G_P_SHIFT;\r
- x+=spr->orgx>>G_P_SHIFT;\r
-\r
-\r
-#if GRMODE == EGAGR\r
- shift = (x&7)/2;\r
-#endif\r
-#if GRMODE == CGAGR\r
- shift = 0;\r
-#endif\r
-\r
- dest = bufferofs + ylookup[y];\r
- if (x>=0)\r
- dest += x/SCREENXDIV;\r
- else\r
- dest += (x+1)/SCREENXDIV;\r
-\r
- width = block->width[shift];\r
- height = spr->height;\r
-\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+width*SCREENXDIV-1\r
- ,y+height-1))\r
- VW_MaskBlock (block,block->sourceoffset[shift],dest,\r
- width,height,block->planesize[shift]);\r
-}\r
-#endif\r
-\r
-void VWB_Plot (int x, int y, int color)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x,y,x,y))\r
- VW_Plot(x,y,color);\r
-}\r
-\r
-void VWB_Hlin (int x1, int x2, int y, int color)\r
-{\r
- x1+=pansx;\r
- x2+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x1,y,x2,y))\r
- VW_Hlin(x1,x2,y,color);\r
-}\r
-\r
-void VWB_Vlin (int y1, int y2, int x, int color)\r
-{\r
- x+=pansx;\r
- y1+=pansy;\r
- y2+=pansy;\r
- if (VW_MarkUpdateBlock (x,y1,x,y2))\r
- VW_Vlin(y1,y2,x,color);\r
-}\r
-\r
-\r
-//===========================================================================\r