+++ /dev/null
-// WL_SCALE.C\r
-\r
-#include "WL_DEF.H"\r
-#pragma hdrstop\r
-\r
-#define OP_RETF 0xcb\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBALS\r
-\r
-=============================================================================\r
-*/\r
-\r
-t_compscale _seg *scaledirectory[MAXSCALEHEIGHT+1];\r
-long fullscalefarcall[MAXSCALEHEIGHT+1];\r
-\r
-int maxscale,maxscaleshl2;\r
-\r
-boolean insetupscaling;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCALS\r
-\r
-=============================================================================\r
-*/\r
-\r
-t_compscale _seg *work;\r
-unsigned BuildCompScale (int height, memptr *finalspot);\r
-\r
-int stepbytwo;\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==============\r
-=\r
-= BadScale\r
-=\r
-==============\r
-*/\r
-\r
-void far BadScale (void)\r
-{\r
- Quit ("BadScale called!");\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= SetupScaling\r
-=\r
-==========================\r
-*/\r
-\r
-void SetupScaling (int maxscaleheight)\r
-{\r
- int i,x,y;\r
- byte far *dest;\r
-\r
- insetupscaling = true;\r
-\r
- maxscaleheight/=2; // one scaler every two pixels\r
-\r
- maxscale = maxscaleheight-1;\r
- maxscaleshl2 = maxscale<<2;\r
-\r
-//\r
-// free up old scalers\r
-//\r
- for (i=1;i<MAXSCALEHEIGHT;i++)\r
- {\r
- if (scaledirectory[i])\r
- MM_FreePtr (&(memptr)scaledirectory[i]);\r
- if (i>=stepbytwo)\r
- i += 2;\r
- }\r
- memset (scaledirectory,0,sizeof(scaledirectory));\r
-\r
- MM_SortMem ();\r
-\r
-//\r
-// build the compiled scalers\r
-//\r
- stepbytwo = viewheight/2; // save space by double stepping\r
- MM_GetPtr (&(memptr)work,20000);\r
-\r
- for (i=1;i<=maxscaleheight;i++)\r
- {\r
- BuildCompScale (i*2,&(memptr)scaledirectory[i]);\r
- if (i>=stepbytwo)\r
- i+= 2;\r
- }\r
- MM_FreePtr (&(memptr)work);\r
-\r
-//\r
-// compact memory and lock down scalers\r
-//\r
- MM_SortMem ();\r
- for (i=1;i<=maxscaleheight;i++)\r
- {\r
- MM_SetLock (&(memptr)scaledirectory[i],true);\r
- fullscalefarcall[i] = (unsigned)scaledirectory[i];\r
- fullscalefarcall[i] <<=16;\r
- fullscalefarcall[i] += scaledirectory[i]->codeofs[0];\r
- if (i>=stepbytwo)\r
- {\r
- scaledirectory[i+1] = scaledirectory[i];\r
- fullscalefarcall[i+1] = fullscalefarcall[i];\r
- scaledirectory[i+2] = scaledirectory[i];\r
- fullscalefarcall[i+2] = fullscalefarcall[i];\r
- i+=2;\r
- }\r
- }\r
- scaledirectory[0] = scaledirectory[1];\r
- fullscalefarcall[0] = fullscalefarcall[1];\r
-\r
-//\r
-// check for oversize wall drawing\r
-//\r
- for (i=maxscaleheight;i<MAXSCALEHEIGHT;i++)\r
- fullscalefarcall[i] = (long)BadScale;\r
-\r
- insetupscaling = false;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-========================\r
-=\r
-= BuildCompScale\r
-=\r
-= Builds a compiled scaler object that will scale a 64 tall object to\r
-= the given height (centered vertically on the screen)\r
-=\r
-= height should be even\r
-=\r
-= Call with\r
-= ---------\r
-= DS:SI Source for scale\r
-= ES:DI Dest for scale\r
-=\r
-= Calling the compiled scaler only destroys AL\r
-=\r
-========================\r
-*/\r
-\r
-unsigned BuildCompScale (int height, memptr *finalspot)\r
-{\r
- byte far *code;\r
-\r
- int i;\r
- long fix,step;\r
- unsigned src,totalscaled,totalsize;\r
- int startpix,endpix,toppix;\r
-\r
-\r
- step = ((long)height<<16) / 64;\r
- code = &work->code[0];\r
- toppix = (viewheight-height)/2;\r
- fix = 0;\r
-\r
- for (src=0;src<=64;src++)\r
- {\r
- startpix = fix>>16;\r
- fix += step;\r
- endpix = fix>>16;\r
-\r
- if (endpix>startpix)\r
- work->width[src] = endpix-startpix;\r
- else\r
- work->width[src] = 0;\r
-\r
-//\r
-// mark the start of the code\r
-//\r
- work->codeofs[src] = FP_OFF(code);\r
-\r
-//\r
-// compile some code if the source pixel generates any screen pixels\r
-//\r
- startpix+=toppix;\r
- endpix+=toppix;\r
-\r
- if (startpix == endpix || endpix < 0 || startpix >= viewheight || src == 64)\r
- continue;\r
-\r
- //\r
- // mov al,[si+src]\r
- //\r
- *code++ = 0x8a;\r
- *code++ = 0x44;\r
- *code++ = src;\r
-\r
- for (;startpix<endpix;startpix++)\r
- {\r
- if (startpix >= viewheight)\r
- break; // off the bottom of the view area\r
- if (startpix < 0)\r
- continue; // not into the view area\r
-\r
- //\r
- // mov [es:di+heightofs],al\r
- //\r
- *code++ = 0x26;\r
- *code++ = 0x88;\r
- *code++ = 0x85;\r
- *((unsigned far *)code)++ = startpix*SCREENBWIDE;\r
- }\r
-\r
- }\r
-\r
-//\r
-// retf\r
-//\r
- *code++ = 0xcb;\r
-\r
- totalsize = FP_OFF(code);\r
- MM_GetPtr (finalspot,totalsize);\r
- _fmemcpy ((byte _seg *)(*finalspot),(byte _seg *)work,totalsize);\r
-\r
- return totalsize;\r
-}\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= ScaleLine\r
-=\r
-= linescale should have the high word set to the segment of the scaler\r
-=\r
-=======================\r
-*/\r
-\r
-extern int slinex,slinewidth;\r
-extern unsigned far *linecmds;\r
-extern long linescale;\r
-extern unsigned maskword;\r
-\r
-byte mask1,mask2,mask3;\r
-\r
-\r
-void near ScaleLine (void)\r
-{\r
-asm mov cx,WORD PTR [linescale+2]\r
-asm mov es,cx // segment of scaler\r
-\r
-asm mov bp,WORD PTR [linecmds]\r
-asm mov dx,SC_INDEX+1 // to set SC_MAPMASK\r
-\r
-asm mov bx,[slinex]\r
-asm mov di,bx\r
-asm shr di,1 // X in bytes\r
-asm shr di,1\r
-asm add di,[bufferofs]\r
-asm and bx,3\r
-/* begin 8086 hack\r
-asm shl bx,3\r
-*/\r
-asm push cx\r
-asm mov cl,3\r
-asm shl bx,cl\r
-asm pop cx\r
-/* end 8086 hack */\r
-asm add bx,[slinewidth] // bx = (pixel*8+pixwidth)\r
-asm mov al,BYTE [mapmasks3-1+bx] // -1 because pixwidth of 1 is first\r
-asm mov ds,WORD PTR [linecmds+2]\r
-asm or al,al\r
-asm jz notthreebyte // scale across three bytes\r
-asm jmp threebyte\r
-notthreebyte:\r
-asm mov al,BYTE PTR ss:[mapmasks2-1+bx] // -1 because pixwidth of 1 is first\r
-asm or al,al\r
-asm jnz twobyte // scale across two bytes\r
-\r
-//\r
-// one byte scaling\r
-//\r
-asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first\r
-asm out dx,al // set map mask register\r
-\r
-scalesingle:\r
-\r
-asm mov bx,[ds:bp] // table location of rtl to patch\r
-asm or bx,bx\r
-asm jz linedone // 0 signals end of segment list\r
-asm mov bx,[es:bx]\r
-asm mov dl,[es:bx] // save old value\r
-asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in\r
-asm mov si,[ds:bp+4] // table location of entry spot\r
-asm mov ax,[es:si]\r
-asm mov WORD PTR ss:[linescale],ax // call here to start scaling\r
-asm mov si,[ds:bp+2] // corrected top of shape for this segment\r
-asm add bp,6 // next segment list\r
-\r
-asm mov ax,SCREENSEG\r
-asm mov es,ax\r
-asm call ss:[linescale] // scale the segment of pixels\r
-\r
-asm mov es,cx // segment of scaler\r
-asm mov BYTE PTR es:[bx],dl // unpatch the RETF\r
-asm jmp scalesingle // do the next segment\r
-\r
-\r
-//\r
-// done\r
-//\r
-linedone:\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-return;\r
-\r
-//\r
-// two byte scaling\r
-//\r
-twobyte:\r
-asm mov ss:[mask2],al\r
-asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first\r
-asm mov ss:[mask1],al\r
-\r
-scaledouble:\r
-\r
-asm mov bx,[ds:bp] // table location of rtl to patch\r
-asm or bx,bx\r
-asm jz linedone // 0 signals end of segment list\r
-asm mov bx,[es:bx]\r
-asm mov cl,[es:bx] // save old value\r
-asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in\r
-asm mov si,[ds:bp+4] // table location of entry spot\r
-asm mov ax,[es:si]\r
-asm mov WORD PTR ss:[linescale],ax // call here to start scaling\r
-asm mov si,[ds:bp+2] // corrected top of shape for this segment\r
-asm add bp,6 // next segment list\r
-\r
-asm mov ax,SCREENSEG\r
-asm mov es,ax\r
-asm mov al,ss:[mask1]\r
-asm out dx,al // set map mask register\r
-asm call ss:[linescale] // scale the segment of pixels\r
-asm inc di\r
-asm mov al,ss:[mask2]\r
-asm out dx,al // set map mask register\r
-asm call ss:[linescale] // scale the segment of pixels\r
-asm dec di\r
-\r
-asm mov es,WORD PTR ss:[linescale+2] // segment of scaler\r
-asm mov BYTE PTR es:[bx],cl // unpatch the RETF\r
-asm jmp scaledouble // do the next segment\r
-\r
-\r
-//\r
-// three byte scaling\r
-//\r
-threebyte:\r
-asm mov ss:[mask3],al\r
-asm mov al,BYTE PTR ss:[mapmasks2-1+bx] // -1 because pixwidth of 1 is first\r
-asm mov ss:[mask2],al\r
-asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first\r
-asm mov ss:[mask1],al\r
-\r
-scaletriple:\r
-\r
-asm mov bx,[ds:bp] // table location of rtl to patch\r
-asm or bx,bx\r
-asm jz linedone // 0 signals end of segment list\r
-asm mov bx,[es:bx]\r
-asm mov cl,[es:bx] // save old value\r
-asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in\r
-asm mov si,[ds:bp+4] // table location of entry spot\r
-asm mov ax,[es:si]\r
-asm mov WORD PTR ss:[linescale],ax // call here to start scaling\r
-asm mov si,[ds:bp+2] // corrected top of shape for this segment\r
-asm add bp,6 // next segment list\r
-\r
-asm mov ax,SCREENSEG\r
-asm mov es,ax\r
-asm mov al,ss:[mask1]\r
-asm out dx,al // set map mask register\r
-asm call ss:[linescale] // scale the segment of pixels\r
-asm inc di\r
-asm mov al,ss:[mask2]\r
-asm out dx,al // set map mask register\r
-asm call ss:[linescale] // scale the segment of pixels\r
-asm inc di\r
-asm mov al,ss:[mask3]\r
-asm out dx,al // set map mask register\r
-asm call ss:[linescale] // scale the segment of pixels\r
-asm dec di\r
-asm dec di\r
-\r
-asm mov es,WORD PTR ss:[linescale+2] // segment of scaler\r
-asm mov BYTE PTR es:[bx],cl // unpatch the RETF\r
-asm jmp scaletriple // do the next segment\r
-\r
-\r
-}\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= ScaleShape\r
-=\r
-= Draws a compiled shape at [scale] pixels high\r
-=\r
-= each vertical line of the shape has a pointer to segment data:\r
-= end of segment pixel*2 (0 terminates line) used to patch rtl in scaler\r
-= top of virtual line with segment in proper place\r
-= start of segment pixel*2, used to jsl into compiled scaler\r
-= <repeat>\r
-=\r
-= Setup for call\r
-= --------------\r
-= GC_MODE read mode 1, write mode 2\r
-= GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff\r
-= GC_INDEX pointing at GC_BITMASK\r
-=\r
-=======================\r
-*/\r
-\r
-static long longtemp;\r
-\r
-void ScaleShape (int xcenter, int shapenum, unsigned height)\r
-{\r
- t_compshape _seg *shape;\r
- t_compscale _seg *comptable;\r
- unsigned scale,srcx,stopx,tempx;\r
- int t;\r
- unsigned far *cmdptr;\r
- boolean leftvis,rightvis;\r
-\r
-\r
- shape = PM_GetSpritePage (shapenum);\r
-\r
- scale = height>>3; // low three bits are fractional\r
- if (!scale || scale>maxscale)\r
- return; // too close or far away\r
- comptable = scaledirectory[scale];\r
-\r
- *(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call\r
- *(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape\r
-\r
-//\r
-// scale to the left (from pixel 31 to shape->leftpix)\r
-//\r
- srcx = 32;\r
- slinex = xcenter;\r
- stopx = shape->leftpix;\r
- cmdptr = &shape->dataofs[31-stopx];\r
-\r
- while ( --srcx >=stopx && slinex>0)\r
- {\r
- (unsigned)linecmds = *cmdptr--;\r
- if ( !(slinewidth = comptable->width[srcx]) )\r
- continue;\r
-\r
- if (slinewidth == 1)\r
- {\r
- slinex--;\r
- if (slinex<viewwidth)\r
- {\r
- if (wallheight[slinex] >= height)\r
- continue; // obscured by closer wall\r
- ScaleLine ();\r
- }\r
- continue;\r
- }\r
-\r
- //\r
- // handle multi pixel lines\r
- //\r
- if (slinex>viewwidth)\r
- {\r
- slinex -= slinewidth;\r
- slinewidth = viewwidth-slinex;\r
- if (slinewidth<1)\r
- continue; // still off the right side\r
- }\r
- else\r
- {\r
- if (slinewidth>slinex)\r
- slinewidth = slinex;\r
- slinex -= slinewidth;\r
- }\r
-\r
-\r
- leftvis = (wallheight[slinex] < height);\r
- rightvis = (wallheight[slinex+slinewidth-1] < height);\r
-\r
- if (leftvis)\r
- {\r
- if (rightvis)\r
- ScaleLine ();\r
- else\r
- {\r
- while (wallheight[slinex+slinewidth-1] >= height)\r
- slinewidth--;\r
- ScaleLine ();\r
- }\r
- }\r
- else\r
- {\r
- if (!rightvis)\r
- continue; // totally obscured\r
-\r
- while (wallheight[slinex] >= height)\r
- {\r
- slinex++;\r
- slinewidth--;\r
- }\r
- ScaleLine ();\r
- break; // the rest of the shape is gone\r
- }\r
- }\r
-\r
-\r
-//\r
-// scale to the right\r
-//\r
- slinex = xcenter;\r
- stopx = shape->rightpix;\r
- if (shape->leftpix<31)\r
- {\r
- srcx = 31;\r
- cmdptr = &shape->dataofs[32-shape->leftpix];\r
- }\r
- else\r
- {\r
- srcx = shape->leftpix-1;\r
- cmdptr = &shape->dataofs[0];\r
- }\r
- slinewidth = 0;\r
-\r
- while ( ++srcx <= stopx && (slinex+=slinewidth)<viewwidth)\r
- {\r
- (unsigned)linecmds = *cmdptr++;\r
- if ( !(slinewidth = comptable->width[srcx]) )\r
- continue;\r
-\r
- if (slinewidth == 1)\r
- {\r
- if (slinex>=0 && wallheight[slinex] < height)\r
- {\r
- ScaleLine ();\r
- }\r
- continue;\r
- }\r
-\r
- //\r
- // handle multi pixel lines\r
- //\r
- if (slinex<0)\r
- {\r
- if (slinewidth <= -slinex)\r
- continue; // still off the left edge\r
-\r
- slinewidth += slinex;\r
- slinex = 0;\r
- }\r
- else\r
- {\r
- if (slinex + slinewidth > viewwidth)\r
- slinewidth = viewwidth-slinex;\r
- }\r
-\r
-\r
- leftvis = (wallheight[slinex] < height);\r
- rightvis = (wallheight[slinex+slinewidth-1] < height);\r
-\r
- if (leftvis)\r
- {\r
- if (rightvis)\r
- {\r
- ScaleLine ();\r
- }\r
- else\r
- {\r
- while (wallheight[slinex+slinewidth-1] >= height)\r
- slinewidth--;\r
- ScaleLine ();\r
- break; // the rest of the shape is gone\r
- }\r
- }\r
- else\r
- {\r
- if (rightvis)\r
- {\r
- while (wallheight[slinex] >= height)\r
- {\r
- slinex++;\r
- slinewidth--;\r
- }\r
- ScaleLine ();\r
- }\r
- else\r
- continue; // totally obscured\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= SimpleScaleShape\r
-=\r
-= NO CLIPPING, height in pixels\r
-=\r
-= Draws a compiled shape at [scale] pixels high\r
-=\r
-= each vertical line of the shape has a pointer to segment data:\r
-= end of segment pixel*2 (0 terminates line) used to patch rtl in scaler\r
-= top of virtual line with segment in proper place\r
-= start of segment pixel*2, used to jsl into compiled scaler\r
-= <repeat>\r
-=\r
-= Setup for call\r
-= --------------\r
-= GC_MODE read mode 1, write mode 2\r
-= GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff\r
-= GC_INDEX pointing at GC_BITMASK\r
-=\r
-=======================\r
-*/\r
-\r
-void SimpleScaleShape (int xcenter, int shapenum, unsigned height)\r
-{\r
- t_compshape _seg *shape;\r
- t_compscale _seg *comptable;\r
- unsigned scale,srcx,stopx,tempx;\r
- int t;\r
- unsigned far *cmdptr;\r
- boolean leftvis,rightvis;\r
-\r
-\r
- shape = PM_GetSpritePage (shapenum);\r
-\r
- scale = height>>1;\r
- comptable = scaledirectory[scale];\r
-\r
- *(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call\r
- *(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape\r
-\r
-//\r
-// scale to the left (from pixel 31 to shape->leftpix)\r
-//\r
- srcx = 32;\r
- slinex = xcenter;\r
- stopx = shape->leftpix;\r
- cmdptr = &shape->dataofs[31-stopx];\r
-\r
- while ( --srcx >=stopx )\r
- {\r
- (unsigned)linecmds = *cmdptr--;\r
- if ( !(slinewidth = comptable->width[srcx]) )\r
- continue;\r
-\r
- slinex -= slinewidth;\r
- ScaleLine ();\r
- }\r
-\r
-\r
-//\r
-// scale to the right\r
-//\r
- slinex = xcenter;\r
- stopx = shape->rightpix;\r
- if (shape->leftpix<31)\r
- {\r
- srcx = 31;\r
- cmdptr = &shape->dataofs[32-shape->leftpix];\r
- }\r
- else\r
- {\r
- srcx = shape->leftpix-1;\r
- cmdptr = &shape->dataofs[0];\r
- }\r
- slinewidth = 0;\r
-\r
- while ( ++srcx <= stopx )\r
- {\r
- (unsigned)linecmds = *cmdptr++;\r
- if ( !(slinewidth = comptable->width[srcx]) )\r
- continue;\r
-\r
- ScaleLine ();\r
- slinex+=slinewidth;\r
- }\r
-}\r
-\r
-\r
-\r
-\r
-//\r
-// bit mask tables for drawing scaled strips up to eight pixels wide\r
-//\r
-// down here so the STUPID inline assembler doesn't get confused!\r
-//\r
-\r
-\r
-byte mapmasks1[4][8] = {\r
-{1 ,3 ,7 ,15,15,15,15,15},\r
-{2 ,6 ,14,14,14,14,14,14},\r
-{4 ,12,12,12,12,12,12,12},\r
-{8 ,8 ,8 ,8 ,8 ,8 ,8 ,8} };\r
-\r
-byte mapmasks2[4][8] = {\r
-{0 ,0 ,0 ,0 ,1 ,3 ,7 ,15},\r
-{0 ,0 ,0 ,1 ,3 ,7 ,15,15},\r
-{0 ,0 ,1 ,3 ,7 ,15,15,15},\r
-{0 ,1 ,3 ,7 ,15,15,15,15} };\r
-\r
-byte mapmasks3[4][8] = {\r
-{0 ,0 ,0 ,0 ,0 ,0 ,0 ,0},\r
-{0 ,0 ,0 ,0 ,0 ,0 ,0 ,1},\r
-{0 ,0 ,0 ,0 ,0 ,0 ,1 ,3},\r
-{0 ,0 ,0 ,0 ,0 ,1 ,3 ,7} };\r
-\r
-\r
-unsigned wordmasks[8][8] = {\r
-{0x0080,0x00c0,0x00e0,0x00f0,0x00f8,0x00fc,0x00fe,0x00ff},\r
-{0x0040,0x0060,0x0070,0x0078,0x007c,0x007e,0x007f,0x807f},\r
-{0x0020,0x0030,0x0038,0x003c,0x003e,0x003f,0x803f,0xc03f},\r
-{0x0010,0x0018,0x001c,0x001e,0x001f,0x801f,0xc01f,0xe01f},\r
-{0x0008,0x000c,0x000e,0x000f,0x800f,0xc00f,0xe00f,0xf00f},\r
-{0x0004,0x0006,0x0007,0x8007,0xc007,0xe007,0xf007,0xf807},\r
-{0x0002,0x0003,0x8003,0xc003,0xe003,0xf003,0xf803,0xfc03},\r
-{0x0001,0x8001,0xc001,0xe001,0xf001,0xf801,0xfc01,0xfe01} };\r
-\r
-int slinex,slinewidth;\r
-unsigned far *linecmds;\r
-long linescale;\r
-unsigned maskword;\r
-\r