--- /dev/null
+// ID_VH.C\r
+\r
+#include "ID_HEADS.H"\r
+\r
+#define SCREENWIDTH 80\r
+#define CHARWIDTH 2\r
+#define TILEWIDTH 4\r
+#define GRPLANES 4\r
+#define BYTEPIXELS 4\r
+\r
+#define SCREENXMASK (~3)\r
+#define SCREENXPLUS (3)\r
+#define SCREENXDIV (4)\r
+\r
+#define VIEWWIDTH 80\r
+\r
+#define PIXTOBLOCK 4 // 16 pixels to an update block\r
+\r
+#define UNCACHEGRCHUNK(chunk) {MM_FreePtr(&grsegs[chunk]);grneeded[chunk]&=~ca_levelbit;}\r
+\r
+byte update[UPDATEHIGH][UPDATEWIDE];\r
+\r
+//==========================================================================\r
+\r
+pictabletype _seg *pictable;\r
+\r
+\r
+int px,py;\r
+byte fontcolor,backcolor;\r
+int fontnumber;\r
+int bufferwidth,bufferheight;\r
+\r
+\r
+//==========================================================================\r
+\r
+void VWL_UpdateScreenBlocks (void);\r
+\r
+//==========================================================================\r
+\r
+void VW_DrawPropString (char far *string)\r
+{\r
+ fontstruct far *font;\r
+ int width,step,height,i;\r
+ byte far *source, far *dest, far *origdest;\r
+ byte ch,mask;\r
+\r
+ font = (fontstruct far *)grsegs[STARTFONT+fontnumber];\r
+ height = bufferheight = font->height;\r
+ dest = origdest = MK_FP(SCREENSEG,bufferofs+ylookup[py]+(px>>2));\r
+ mask = 1<<(px&3);\r
+\r
+\r
+ while ((ch = *string++)!=0)\r
+ {\r
+ width = step = font->width[ch];\r
+ source = ((byte far *)font)+font->location[ch];\r
+ while (width--)\r
+ {\r
+ VGAMAPMASK(mask);\r
+\r
+asm mov ah,[BYTE PTR fontcolor]\r
+asm mov bx,[step]\r
+asm mov cx,[height]\r
+asm mov dx,[linewidth]\r
+asm lds si,[source]\r
+asm les di,[dest]\r
+\r
+vertloop:\r
+asm mov al,[si]\r
+asm or al,al\r
+asm je next\r
+asm mov [es:di],ah // draw color\r
+\r
+next:\r
+asm add si,bx\r
+asm add di,dx\r
+asm loop vertloop\r
+asm mov ax,ss\r
+asm mov ds,ax\r
+\r
+ source++;\r
+ px++;\r
+ mask <<= 1;\r
+ if (mask == 16)\r
+ {\r
+ mask = 1;\r
+ dest++;\r
+ }\r
+ }\r
+ }\r
+bufferheight = height;\r
+bufferwidth = ((dest+1)-origdest)*4;\r
+}\r
+\r
+\r
+void VW_DrawColorPropString (char far *string)\r
+{\r
+ fontstruct far *font;\r
+ int width,step,height,i;\r
+ byte far *source, far *dest, far *origdest;\r
+ byte ch,mask;\r
+\r
+ font = (fontstruct far *)grsegs[STARTFONT+fontnumber];\r
+ height = bufferheight = font->height;\r
+ dest = origdest = MK_FP(SCREENSEG,bufferofs+ylookup[py]+(px>>2));\r
+ mask = 1<<(px&3);\r
+\r
+\r
+ while ((ch = *string++)!=0)\r
+ {\r
+ width = step = font->width[ch];\r
+ source = ((byte far *)font)+font->location[ch];\r
+ while (width--)\r
+ {\r
+ VGAMAPMASK(mask);\r
+\r
+asm mov ah,[BYTE PTR fontcolor]\r
+asm mov bx,[step]\r
+asm mov cx,[height]\r
+asm mov dx,[linewidth]\r
+asm lds si,[source]\r
+asm les di,[dest]\r
+\r
+vertloop:\r
+asm mov al,[si]\r
+asm or al,al\r
+asm je next\r
+asm mov [es:di],ah // draw color\r
+\r
+next:\r
+asm add si,bx\r
+asm add di,dx\r
+\r
+asm rcr cx,1 // inc font color\r
+asm jc cont\r
+asm inc ah\r
+\r
+cont:\r
+asm rcl cx,1\r
+asm loop vertloop\r
+asm mov ax,ss\r
+asm mov ds,ax\r
+\r
+ source++;\r
+ px++;\r
+ mask <<= 1;\r
+ if (mask == 16)\r
+ {\r
+ mask = 1;\r
+ dest++;\r
+ }\r
+ }\r
+ }\r
+bufferheight = height;\r
+bufferwidth = ((dest+1)-origdest)*4;\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= VL_MungePic\r
+=\r
+=================\r
+*/\r
+\r
+void VL_MungePic (byte far *source, unsigned width, unsigned height)\r
+{\r
+ unsigned x,y,plane,size,pwidth;\r
+ byte _seg *temp, far *dest, far *srcline;\r
+\r
+ size = width*height;\r
+\r
+ if (width&3)\r
+ MS_Quit ("VL_MungePic: Not divisable by 4!");\r
+\r
+//\r
+// copy the pic to a temp buffer\r
+//\r
+ MM_GetPtr (&(memptr)temp,size);\r
+ _fmemcpy (temp,source,size);\r
+\r
+//\r
+// munge it back into the original buffer\r
+//\r
+ dest = source;\r
+ pwidth = width/4;\r
+\r
+ for (plane=0;plane<4;plane++)\r
+ {\r
+ srcline = temp;\r
+ for (y=0;y<height;y++)\r
+ {\r
+ for (x=0;x<pwidth;x++)\r
+ *dest++ = *(srcline+x*4+plane);\r
+ srcline+=width;\r
+ }\r
+ }\r
+\r
+ MM_FreePtr (&(memptr)temp);\r
+}\r
+\r
+void VWL_MeasureString (char far *string, word *width, word *height\r
+ , 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
+\r
+/*\r
+=============================================================================\r
+\r
+ Double buffer management routines\r
+\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)\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)\r
+ xt2 = UPDATEWIDE-1;\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
+void VWB_DrawTile8 (int x, int y, int tile)\r
+{\r
+ if (VW_MarkUpdateBlock (x,y,x+7,y+7))\r
+ LatchDrawChar(x,y,tile);\r
+}\r
+\r
+void VWB_DrawTile8M (int x, int y, int tile)\r
+{\r
+ if (VW_MarkUpdateBlock (x,y,x+7,y+7))\r
+ VL_MemToScreen (((byte far *)grsegs[STARTTILE8M])+tile*64,8,8,x,y);\r
+}\r
+\r
+\r
+void VWB_DrawPic (int x, int y, int chunknum)\r
+{\r
+ int picnum = chunknum - STARTPICS;\r
+ unsigned width,height;\r
+\r
+ x &= ~7;\r
+\r
+ width = pictable[picnum].width;\r
+ height = pictable[picnum].height;\r
+\r
+ if (VW_MarkUpdateBlock (x,y,x+width-1,y+height-1))\r
+ VL_MemToScreen (grsegs[chunknum],width,height,x,y);\r
+}\r
+\r
+\r
+\r
+void VWB_DrawPropString (char far *string)\r
+{\r
+ int x;\r
+ x=px;\r
+ VW_DrawPropString (string);\r
+ VW_MarkUpdateBlock(x,py,px-1,py+bufferheight-1);\r
+}\r
+\r
+\r
+void VWB_Bar (int x, int y, int width, int height, int color)\r
+{\r
+ if (VW_MarkUpdateBlock (x,y,x+width,y+height-1) )\r
+ VW_Bar (x,y,width,height,color);\r
+}\r
+\r
+void VWB_Plot (int x, int y, int color)\r
+{\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
+ 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
+ if (VW_MarkUpdateBlock (x,y1,x,y2))\r
+ VW_Vlin(y1,y2,x,color);\r
+}\r
+\r
+void VW_UpdateScreen (void)\r
+{\r
+ VH_UpdateScreen ();\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WOLFENSTEIN STUFF\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+=====================\r
+=\r
+= LatchDrawPic\r
+=\r
+=====================\r
+*/\r
+\r
+void LatchDrawPic (unsigned x, unsigned y, unsigned picnum)\r
+{\r
+ unsigned wide, height, source;\r
+\r
+ wide = pictable[picnum-STARTPICS].width;\r
+ height = pictable[picnum-STARTPICS].height;\r
+ source = latchpics[2+picnum-LATCHPICS_LUMP_START];\r
+\r
+ VL_LatchToScreen (source,wide/4,height,x*8,y);\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= LoadLatchMem\r
+=\r
+===================\r
+*/\r
+\r
+void LoadLatchMem (void)\r
+{\r
+ int i,j,p,m,width,height,start,end;\r
+ byte far *src;\r
+ unsigned destoff;\r
+\r
+//\r
+// tile 8s\r
+//\r
+ latchpics[0] = freelatch;\r
+ CA_CacheGrChunk (STARTTILE8);\r
+ src = (byte _seg *)grsegs[STARTTILE8];\r
+ destoff = freelatch;\r
+\r
+ for (i=0;i<NUMTILE8;i++)\r
+ {\r
+ VL_MemToLatch (src,8,8,destoff);\r
+ src += 64;\r
+ destoff +=16;\r
+ }\r
+ UNCACHEGRCHUNK (STARTTILE8);\r
+\r
+#if 0 // ran out of latch space!\r
+//\r
+// tile 16s\r
+//\r
+ src = (byte _seg *)grsegs[STARTTILE16];\r
+ latchpics[1] = destoff;\r
+\r
+ for (i=0;i<NUMTILE16;i++)\r
+ {\r
+ CA_CacheGrChunk (STARTTILE16+i);\r
+ src = (byte _seg *)grsegs[STARTTILE16+i];\r
+ VL_MemToLatch (src,16,16,destoff);\r
+ destoff+=64;\r
+ if (src)\r
+ UNCACHEGRCHUNK (STARTTILE16+i);\r
+ }\r
+#endif\r
+\r
+//\r
+// pics\r
+//\r
+ start = LATCHPICS_LUMP_START;\r
+ end = LATCHPICS_LUMP_END;\r
+\r
+ for (i=start;i<=end;i++)\r
+ {\r
+ latchpics[2+i-start] = destoff;\r
+ CA_CacheGrChunk (i);\r
+ width = pictable[i-STARTPICS].width;\r
+ height = pictable[i-STARTPICS].height;\r
+ VL_MemToLatch (grsegs[i],width,height,destoff);\r
+ destoff += width/4 *height;\r
+ UNCACHEGRCHUNK(i);\r
+ }\r
+\r
+ EGAMAPMASK(15);\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= FizzleFade\r
+=\r
+= returns true if aborted\r
+=\r
+===================\r
+*/\r
+\r
+extern ControlInfo c;\r
+\r
+boolean FizzleFade (unsigned source, unsigned dest,\r
+ unsigned width,unsigned height, unsigned frames, boolean abortable)\r
+{\r
+ int pixperframe;\r
+ unsigned drawofs,pagedelta;\r
+ byte mask,maskb[8] = {1,2,4,8};\r
+ unsigned x,y,p,frame;\r
+ long rndval;\r
+\r
+ pagedelta = dest-source;\r
+ rndval = 1;\r
+ y = 0;\r
+ pixperframe = 64000/frames;\r
+\r
+ IN_StartAck ();\r
+\r
+ TimeCount=frame=0;\r
+ do // while (1)\r
+ {\r
+ if (abortable && IN_CheckAck () )\r
+ return true;\r
+\r
+ asm mov es,[screenseg]\r
+\r
+ for (p=0;p<pixperframe;p++)\r
+ {\r
+ //\r
+ // seperate random value into x/y pair\r
+ //\r
+ asm mov ax,[WORD PTR rndval]\r
+ asm mov dx,[WORD PTR rndval+2]\r
+ asm mov bx,ax\r
+ asm dec bl\r
+ asm mov [BYTE PTR y],bl // low 8 bits - 1 = y xoordinate\r
+ asm mov bx,ax\r
+ asm mov cx,dx\r
+ asm mov [BYTE PTR x],ah // next 9 bits = x xoordinate\r
+ asm mov [BYTE PTR x+1],dl\r
+ //\r
+ // advance to next random element\r
+ //\r
+ asm shr dx,1\r
+ asm rcr ax,1\r
+ asm jnc noxor\r
+ asm xor dx,0x0001\r
+ asm xor ax,0x2000\r
+noxor:\r
+ asm mov [WORD PTR rndval],ax\r
+ asm mov [WORD PTR rndval+2],dx\r
+\r
+ if (x>width || y>height)\r
+ continue;\r
+ drawofs = source+ylookup[y] + (x>>2);\r
+\r
+ //\r
+ // copy one pixel\r
+ //\r
+ mask = x&3;\r
+ VGAREADMAP(mask);\r
+ mask = maskb[mask];\r
+ VGAMAPMASK(mask);\r
+\r
+ asm mov di,[drawofs]\r
+ asm mov al,[es:di]\r
+ asm add di,[pagedelta]\r
+ asm mov [es:di],al\r
+\r
+ if (rndval == 1) // entire sequence has been completed\r
+ return false;\r
+ }\r
+ frame++;\r
+ while (TimeCount<frame) // don't go too fast\r
+ ;\r
+ } while (1);\r
+\r
+\r
+}\r