+++ /dev/null
-/* 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
-// C3_SCALE.C\r
-\r
-#include "C3_DEF.H"\r
-#pragma hdrstop\r
-\r
-//const unsigned viewheight = 144;\r
-const unsigned screenbwide = 40;\r
-const byte BACKGROUNDPIX = 5;\r
-\r
-unsigned shapesize[MAXSCALE+1];\r
-t_compscale _seg *scaledirectory[MAXSCALE+1];\r
-t_compshape _seg *shapedirectory[NUMSCALEPICS];\r
-memptr walldirectory[NUMSCALEWALLS];\r
-\r
-/*\r
-===========================\r
-=\r
-= DeplanePic\r
-=\r
-= Takes a raw bit map of width bytes by height and creates a scaleable shape\r
-=\r
-= Returns the length of the shape in bytes\r
-=\r
-= Fills in spotvis (a convenient 64*64 array) with the color values\r
-=\r
-===========================\r
-*/\r
-\r
-void DeplanePic (int picnum)\r
-{\r
- byte far *plane0,far *plane1,far *plane2,far *plane3;\r
- byte by0,by1,by2,by3;\r
- unsigned x,y,b,color,shift,width,height;\r
- byte *dest;\r
-\r
-//\r
-// convert ega pixels to byte color values in a temp buffer\r
-//\r
- width = pictable[picnum-STARTPICS].width;\r
- height = pictable[picnum-STARTPICS].height;\r
-\r
- if (width>64 || height!=64)\r
- Quit ("DePlanePic: Bad size shape");\r
-\r
- memset (spotvis,BACKGROUNDPIX,sizeof(spotvis));\r
-\r
- plane0 = (byte _seg *)grsegs[picnum];\r
- plane1 = plane0 + width*height;\r
- plane2 = plane1 + width*height;\r
- plane3 = plane2 + width*height;\r
-\r
- for (y=0;y<height;y++)\r
- {\r
- dest = &spotvis[y][0];\r
- for (x=0;x<width;x++)\r
- {\r
- by0 = *plane0++;\r
- by1 = *plane1++;\r
- by2 = *plane2++;\r
- by3 = *plane3++;\r
-\r
- for (b=0;b<8;b++)\r
- {\r
- shift=8-b;\r
-\r
- color = 0;\r
- asm mov cl,[BYTE PTR shift]\r
- asm mov al,[BYTE PTR by3]\r
- asm rcr al,cl;\r
- asm rcl [BYTE PTR color],1;\r
-\r
- asm mov cl,[BYTE PTR shift]\r
- asm mov al,[BYTE PTR by2]\r
- asm rcr al,cl;\r
- asm rcl [BYTE PTR color],1;\r
-\r
- asm mov cl,[BYTE PTR shift]\r
- asm mov al,[BYTE PTR by1]\r
- asm rcr al,cl;\r
- asm rcl [BYTE PTR color],1;\r
-\r
- asm mov cl,[BYTE PTR shift]\r
- asm mov al,[BYTE PTR by0]\r
- asm rcr al,cl;\r
- asm rcl [BYTE PTR color],1;\r
-\r
- *dest++ = color;\r
- } // B\r
- } // X\r
- } // Y\r
-}\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
- t_compscale _seg *work;\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
- MM_GetPtr (&(memptr)work,20000);\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
- work->start[src] = startpix;\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
- // and [es:di+heightofs],al\r
- //\r
- *code++ = 0x26;\r
- *code++ = 0x20;\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
- MM_FreePtr (&(memptr)work);\r
-\r
- return totalsize;\r
-}\r
-\r
-\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= BuildCompShape\r
-=\r
-= typedef struct\r
-= {\r
-= unsigned width;\r
-= unsigned codeofs[64];\r
-= } t_compshape;\r
-=\r
-= Width is the number of compiled line draws in the shape. The shape\r
-= drawing code will assume that the midpoint of the shape is in the\r
-= middle of the width.\r
-=\r
-= The non background pixel data will start at codeofs[width], so codeofs\r
-= greater than width will be invalid.\r
-=\r
-= Each code offset will draw one vertical line of the shape, consisting\r
-= of 0 or more segments of scaled pixels.\r
-=\r
-= The scaled shapes use ss:0-4 as a scratch variable for the far call to\r
-= the compiled scaler, so zero it back out after the shape is scaled, or\r
-= a "null pointer assignment" will result upon termination.\r
-=\r
-= Setup for a call to a compiled shape\r
-= -----------------------------------\r
-= ax toast\r
-= bx toast\r
-= cx toast\r
-= dx segment of compiled shape\r
-= si toast\r
-= di byte at top of view area to draw the line in\r
-= bp 0\r
-= ss:2 and ds the segment of the compiled scaler to use\r
-= es screenseg\r
-=\r
-= Upon return, ds IS NOT SET to the data segment. Do:\r
-= mov ax,ss\r
-= mov ds,ax\r
-=\r
-=\r
-= GC_BITMASK set to the pixels to be drawn in the row of bytes under DI\r
-= GC_MODE read mode 1, write mode 2\r
-= GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff\r
-=\r
-=\r
-= Code generated for each segment\r
-= -------------------------------\r
-= mov bx,[(segend+1)*2]\r
-= mov cx,[bx]\r
-= mov [BYTE PTR bx],0xc8 // far return\r
-= mov ax,[segstart*2]\r
-= mov [ss:0],ax // entry point into the compiled scaler\r
-= mov ds,dx // (mov ds,cs) the data is after the compiled code\r
-= mov si,ofs data\r
-= call [bp] // scale some pixels\r
-= mov ds,[bp+2]\r
-= mov [bx],cx // un patch return\r
-=\r
-= Code generated after all segments on a line\r
-= -------------------------------------------\r
-= retf\r
-=\r
-========================\r
-*/\r
-\r
-unsigned BuildCompShape (t_compshape _seg **finalspot)\r
-{\r
- t_compshape _seg *work;\r
- byte far *code;\r
- int firstline,lastline,x,y;\r
- unsigned firstpix,lastpix,width;\r
- unsigned totalsize,pixelofs;\r
- unsigned buff;\r
-\r
-\r
-// MM_GetPtr (&(memptr)work,20000);\r
- EGAWRITEMODE(0);\r
- EGAREADMAP(0); // use ega screen memory for temp buffer\r
- EGAMAPMASK(1);\r
- buff = screenloc[1];\r
- work = (t_compshape _seg *)(0xa000+(buff+15)/16);\r
-\r
-//\r
-// find the width of the shape\r
-//\r
- firstline = -1;\r
- x=0;\r
- do\r
- {\r
- for (y=0;y<64;y++)\r
- if (spotvis[y][x] != BACKGROUNDPIX)\r
- {\r
- firstline = x;\r
- break;\r
- }\r
- if (++x == 64)\r
- Quit ("BuildCompShape: No shape data!");\r
- } while (firstline == -1);\r
-\r
- lastline = -1;\r
- x=63;\r
- do\r
- {\r
- for (y=0;y<64;y++)\r
- if (spotvis[y][x] != BACKGROUNDPIX)\r
- {\r
- lastline = x;\r
- break;\r
- }\r
- x--;\r
- } while (lastline == -1);\r
-\r
- width = lastline-firstline+1;\r
-\r
- work->width = width;\r
- code = (byte far *)&work->codeofs[width];\r
-\r
-//\r
-// copy all non background pixels to the work space\r
-//\r
- pixelofs = FP_OFF(code);\r
-\r
- for (x=firstline;x<=lastline;x++)\r
- for (y=0;y<64;y++)\r
- if (spotvis[y][x] != BACKGROUNDPIX)\r
- *code++ = spotvis[y][x];\r
-\r
-//\r
-// start compiling the vertical lines\r
-//\r
- for (x=firstline;x<=lastline;x++)\r
- {\r
- work->codeofs[x-firstline] = FP_OFF(code);\r
-\r
- y=0;\r
- do\r
- {\r
- //\r
- // scan past black background pixels\r
- //\r
- while (spotvis[y][x] == BACKGROUNDPIX && y<64)\r
- y++;\r
-\r
- if (y>63) // no more segments\r
- break;\r
-\r
- firstpix = y+1; // +1 because width is before codeofs\r
-\r
- //\r
- // scan past scalable pixels\r
- //\r
- while (spotvis[y][x] != BACKGROUNDPIX && y<64)\r
- y++;\r
-\r
- if (y>63)\r
- lastpix = 65;\r
- else\r
- lastpix = y+1; // actually one pixel past the last displayed\r
-\r
- //\r
- // compile the scale call\r
- //\r
- *code++ = 0x8b; // mov bx,[lastpix*2]\r
- *code++ = 0x1e;\r
- *((unsigned far *)code)++ = lastpix*2;\r
-\r
- *code++ = 0x8b; // mov cx,[bx]\r
- *code++ = 0x0f;\r
-\r
- *code++ = 0xc6; // move [BYTE bx],0xcb\r
- *code++ = 0x07;\r
- *code++ = 0xcb;\r
-\r
- *code++ = 0xa1; // mov ax,[firstpix*2] /*************\r
- *((unsigned far *)code)++ = firstpix*2;\r
-\r
- *code++ = 0x36; // mov [ss:0],ax\r
- *code++ = 0xa3;\r
- *code++ = 0x00;\r
- *code++ = 0x00;\r
-\r
- *code++ = 0x8e; // mov ds,dx (mov ds,cs)\r
- *code++ = 0xda;\r
-\r
- *code++ = 0xbe; // mov si,OFFSET pixelofs-firstpixel\r
- *((unsigned far *)code)++ = pixelofs-firstpix;\r
-\r
- *code++ = 0xff; // call [DWORD bp]\r
- *code++ = 0x5e;\r
- *code++ = 0x00;\r
-\r
- *code++ = 0x8e; // mov ds,[bp+2]\r
- *code++ = 0x5e;\r
- *code++ = 0x02;\r
-\r
- *code++ = 0x89; // mov [bx],cx\r
- *code++ = 0x0f;\r
-\r
- pixelofs += (lastpix-firstpix);\r
- } while (y<63);\r
-\r
- //\r
- // retf\r
- //\r
- *code++ = 0xcb;\r
- }\r
-\r
-\r
-//\r
-// copy the final shape to a properly sized buffer\r
-//\r
- totalsize = FP_OFF(code);\r
- MM_GetPtr ((memptr *)finalspot,totalsize);\r
- _fmemcpy ((byte _seg *)(*finalspot),(byte _seg *)work,totalsize);\r
-// MM_FreePtr (&(memptr)work);\r
-\r
- return totalsize;\r
-}\r
-\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= ScaleShape\r
-=\r
-= Draws a compiled shape at [scale] pixels high\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, t_compshape _seg *compshape, unsigned scale)\r
-{\r
- t_compscale _seg *comptable;\r
- unsigned width,scalewidth;\r
- int x,pixel,lastpixel,pixwidth,min;\r
- unsigned far *codehandle, far *widthptr;\r
- unsigned badcodeptr;\r
- int rightclip;\r
-\r
- if (!compshape)\r
- Quit ("ScaleShape: NULL compshape ptr!");\r
-\r
- scale = (scale+1)/2;\r
- if (!scale)\r
- return; // too far away\r
- if (scale>MAXSCALE)\r
- scale = MAXSCALE;\r
- comptable = scaledirectory[scale];\r
-\r
- width = compshape->width;\r
- scalewidth = comptable->start[width];\r
-\r
- pixel = xcenter - scalewidth/2;\r
- lastpixel = pixel+scalewidth-1;\r
- if (pixel >= VIEWWIDTH || lastpixel < 0)\r
- return; // totally off screen\r
-\r
-//\r
-// scan backwards from the right edge until pixels are visable\r
-// rightclip is the first NON VISABLE pixel\r
-//\r
- if (lastpixel>=VIEWWIDTH-1)\r
- rightclip = VIEWWIDTH-1;\r
- else\r
- rightclip = lastpixel;\r
-\r
- if (zbuffer[rightclip]>scale)\r
- {\r
- if (pixel>0)\r
- min = pixel;\r
- else\r
- min = 0;\r
- do\r
- {\r
- if (--rightclip < min)\r
- return; // totally covered or before 0\r
- if (zbuffer[rightclip]<=scale)\r
- break;\r
- } while (1);\r
- }\r
- rightclip++;\r
-\r
-//\r
-// scan from the left until it is on screen, leaving\r
-// [pixel],[pixwidth],[codehandle],and [widthptr] set correctly\r
-//\r
- *(((unsigned *)&longtemp)+1) = (unsigned)compshape; // seg of shape\r
- codehandle = &compshape->codeofs[0];\r
- badcodeptr = compshape->codeofs[width];\r
- widthptr = &comptable->width[0];\r
- asm mov ax,[comptable]\r
- asm mov WORD PTR [2],ax // ds:0-4 is used as a far call pointer\r
- // by the compiled shapes\r
- pixwidth = *widthptr; // scaled width of this pixel\r
- while (!pixwidth)\r
- {\r
- pixwidth = *++widthptr; // find the first visable pixel\r
- codehandle++;\r
- }\r
-\r
- if (pixel<0)\r
- {\r
- do\r
- {\r
- if (pixel+pixwidth>0)\r
- {\r
- pixwidth += pixel;\r
- pixel = 0;\r
- break;\r
- }\r
- do\r
- {\r
- pixwidth = *++widthptr;\r
- codehandle++;\r
- } while (!pixwidth);\r
- pixel+=pixwidth;\r
- } while (1);\r
- }\r
-\r
-//\r
-// scan until it is visable, leaving\r
-// [pixel],[pixwidth],[codehandle],and [widthptr] set correctly\r
-//\r
- do\r
- {\r
- if (zbuffer[pixel] <= scale)\r
- break; // start drawing here\r
- pixel++;\r
- if (!--pixwidth)\r
- {\r
- do\r
- {\r
- pixwidth = *++widthptr;\r
- codehandle++;\r
- } while (!pixwidth);\r
- }\r
- } while (1);\r
-\r
- if (pixel+pixwidth>rightclip)\r
- pixwidth = rightclip-pixel;\r
-//\r
-// draw lines\r
-//\r
- do // while (1)\r
- {\r
- //\r
- // scale a vertical segment [pixwidth] pixels wide at [pixel]\r
- //\r
- (unsigned)longtemp = *codehandle; // offset of compiled code\r
- if ((unsigned)longtemp == badcodeptr)\r
- Quit ("ScaleShape: codehandle past end!");\r
-\r
- asm mov bx,[pixel]\r
- asm mov di,bx\r
- asm shr di,1\r
- asm shr di,1\r
- asm shr di,1 // X in bytes\r
- asm add di,[bufferofs]\r
- asm and bx,7\r
- asm shl bx,1\r
- asm shl bx,1\r
- asm shl bx,1\r
- asm add bx,[pixwidth] // bx = pixel*8+pixwidth-1\r
- asm dec bx\r
- asm push bx\r
- asm mov al,BYTE PTR [bitmasks1+bx]\r
- asm mov dx,GC_INDEX+1\r
- asm out dx,al // set bit mask register\r
-\r
- asm mov es,[screenseg]\r
- asm push si\r
- asm push di\r
- asm push bp\r
- asm xor bp,bp\r
- asm mov dx,[WORD PTR longtemp+2]\r
- asm mov ds,[2]\r
- asm call ss:[DWORD PTR longtemp] // scale the line of pixels\r
- asm mov ax,ss\r
- asm mov ds,ax\r
- asm pop bp\r
- asm pop di\r
- asm pop si\r
-\r
- asm pop bx\r
- asm mov al,BYTE PTR [bitmasks2+bx]\r
- asm or al,al\r
- asm jz nosecond\r
-\r
- //\r
- // draw a second byte for vertical strips that cross two bytes\r
- //\r
- asm inc di\r
- asm mov dx,GC_INDEX+1\r
- asm out dx,al // set bit mask register\r
- asm push si\r
- asm push di\r
- asm push bp\r
- asm xor bp,bp\r
- asm mov dx,[WORD PTR longtemp+2]\r
- asm mov ds,[2]\r
- asm call ss:[DWORD PTR longtemp] // scale the line of pixels\r
- asm mov ax,ss\r
- asm mov ds,ax\r
- asm pop bp\r
- asm pop di\r
- asm pop si\r
-\r
-\r
- //\r
- // advance to the next drawn line\r
- //\r
-nosecond:;\r
- if ( (pixel+=pixwidth) == rightclip )\r
- {\r
- asm mov WORD PTR [0],0\r
- asm mov WORD PTR [2],0\r
- return; // all done!\r
- }\r
-\r
- do\r
- {\r
- pixwidth = *++widthptr;\r
- codehandle++;\r
- } while (!pixwidth);\r
-\r
- if (pixel+pixwidth > rightclip)\r
- pixwidth = rightclip-pixel;\r
-\r
- } while (1);\r
-\r
-}\r
-\r
-//\r
-// bit mask tables for drawing scaled strips up to eight pixels wide\r
-//\r
-\r
-byte bitmasks1[8][8] = {\r
-{0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff},\r
-{0x40,0x60,0x70,0x78,0x7c,0x7e,0x7f,0x7f},\r
-{0x20,0x30,0x38,0x3c,0x3e,0x3f,0x3f,0x3f},\r
-{0x10,0x18,0x1c,0x1e,0x1f,0x1f,0x1f,0x1f},\r
-{0x8,0xc,0xe,0xf,0xf,0xf,0xf,0xf},\r
-{0x4,0x6,0x7,0x7,0x7,0x7,0x7,0x7},\r
-{0x2,0x3,0x3,0x3,0x3,0x3,0x3,0x3},\r
-{0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1} };\r
-\r
-byte bitmasks2[8][8] = {\r
-{0,0,0,0,0,0,0,0},\r
-{0,0,0,0,0,0,0,0x80},\r
-{0,0,0,0,0,0,0x80,0xc0},\r
-{0,0,0,0,0,0x80,0xc0,0xe0},\r
-{0,0,0,0,0x80,0xc0,0xe0,0xf0},\r
-{0,0,0,0x80,0xc0,0xe0,0xf0,0xf8},\r
-{0,0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc},\r
-{0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe} };\r
-\r
-\r
-\r
-\r
-\r
-\r