123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698 |
- /* Catacomb Armageddon Source Code
- * Copyright (C) 1993-2014 Flat Rock Software
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- // C3_SCALE.C
- #include "DEF.H"
- #pragma hdrstop
- //const unsigned viewheight = 144;
- const unsigned screenbwide = 40;
- const byte BACKGROUNDPIX = 5;
- unsigned shapesize[NUMSCALEPICS];
- t_compscale _seg *scaledirectory[NUMSCALEPICS];
- t_compshape _seg *shapedirectory[NUMSCALEPICS];
- memptr walldirectory[NUMSCALEWALLS];
- /*
- ===========================
- =
- = DeplanePic
- =
- = Takes a raw bit map of width bytes by height and creates a scaleable shape
- =
- = Returns the length of the shape in bytes
- =
- = Fills in spotvis (a convenient 64*64 array) with the color values
- =
- ===========================
- */
- void DeplanePic (int picnum)
- {
- byte far *plane0,far *plane1,far *plane2,far *plane3;
- byte by0,by1,by2,by3;
- unsigned x,y,b,color,shift,width,height;
- byte *dest;
- //
- // convert ega pixels to byte color values in a temp buffer
- //
- width = pictable[picnum-STARTPICS].width;
- height = pictable[picnum-STARTPICS].height;
- if (width>8 || height!=64)
- Quit ("DePlanePic: Bad size shape");
- memset (spotvis,BACKGROUNDPIX,sizeof(spotvis));
- plane0 = (byte _seg *)grsegs[picnum];
- plane1 = plane0 + width*height;
- plane2 = plane1 + width*height;
- plane3 = plane2 + width*height;
- for (y=0;y<height;y++)
- {
- dest = &spotvis[y][0];
- for (x=0;x<width;x++)
- {
- by0 = *plane0++;
- by1 = *plane1++;
- by2 = *plane2++;
- by3 = *plane3++;
- for (b=0;b<8;b++)
- {
- shift=8-b;
- color = 0;
- asm mov cl,[BYTE PTR shift]
- asm mov al,[BYTE PTR by3]
- asm rcr al,cl;
- asm rcl [BYTE PTR color],1;
- asm mov cl,[BYTE PTR shift]
- asm mov al,[BYTE PTR by2]
- asm rcr al,cl;
- asm rcl [BYTE PTR color],1;
- asm mov cl,[BYTE PTR shift]
- asm mov al,[BYTE PTR by1]
- asm rcr al,cl;
- asm rcl [BYTE PTR color],1;
- asm mov cl,[BYTE PTR shift]
- asm mov al,[BYTE PTR by0]
- asm rcr al,cl;
- asm rcl [BYTE PTR color],1;
- *dest++ = color;
- } // B
- } // X
- } // Y
- }
- /*
- ========================
- =
- = BuildCompScale
- =
- = Builds a compiled scaler object that will scale a 64 tall object to
- = the given height (centered vertically on the screen)
- =
- = height should be even
- =
- = Call with
- = ---------
- = DS:SI Source for scale
- = ES:DI Dest for scale
- =
- = Calling the compiled scaler only destroys AL
- =
- ========================
- */
- unsigned BuildCompScale (int height, memptr *finalspot)
- {
- t_compscale _seg *work;
- byte far *code;
- int i;
- long fix,step;
- unsigned src,totalscaled,totalsize;
- int startpix,endpix,toppix;
- MM_GetPtr (&(memptr)work,20000);
- step = ((long)height<<16) / 64;
- code = &work->code[0];
- toppix = (viewheight-height)/2;
- fix = 0;
- for (src=0;src<=64;src++)
- {
- startpix = fix>>16;
- fix += step;
- endpix = fix>>16;
- work->start[src] = startpix;
- if (endpix>startpix)
- work->width[src] = endpix-startpix;
- else
- work->width[src] = 0;
- //
- // mark the start of the code
- //
- work->codeofs[src] = FP_OFF(code);
- //
- // compile some code if the source pixel generates any screen pixels
- //
- startpix+=toppix;
- endpix+=toppix;
- if (startpix == endpix || endpix < 0 || startpix >= VIEWHEIGHT || src == 64)
- continue;
- //
- // mov al,[si+src]
- //
- *code++ = 0x8a;
- *code++ = 0x44;
- *code++ = src;
- for (;startpix<endpix;startpix++)
- {
- if (startpix >= VIEWHEIGHT)
- break; // off the bottom of the view area
- if (startpix < 0)
- continue; // not into the view area
- //
- // and [es:di+heightofs],al
- //
- *code++ = 0x26;
- *code++ = 0x20;
- *code++ = 0x85;
- *((unsigned far *)code)++ = startpix*screenbwide;
- }
- }
- //
- // retf
- //
- *code++ = 0xcb;
- totalsize = FP_OFF(code);
- MM_GetPtr (finalspot,totalsize);
- _fmemcpy ((byte _seg *)(*finalspot),(byte _seg *)work,totalsize);
- MM_FreePtr (&(memptr)work);
- return totalsize;
- }
- /*
- ========================
- =
- = BuildCompShape
- =
- = typedef struct
- = {
- = unsigned width;
- = unsigned codeofs[64];
- = } t_compshape;
- =
- = Width is the number of compiled line draws in the shape. The shape
- = drawing code will assume that the midpoint of the shape is in the
- = middle of the width.
- =
- = The non background pixel data will start at codeofs[width], so codeofs
- = greater than width will be invalid.
- =
- = Each code offset will draw one vertical line of the shape, consisting
- = of 0 or more segments of scaled pixels.
- =
- = The scaled shapes use ss:0-4 as a scratch variable for the far call to
- = the compiled scaler, so zero it back out after the shape is scaled, or
- = a "null pointer assignment" will result upon termination.
- =
- = Setup for a call to a compiled shape
- = -----------------------------------
- = ax toast
- = bx toast
- = cx toast
- = dx segment of compiled shape
- = si toast
- = di byte at top of view area to draw the line in
- = bp 0
- = ss:2 and ds the segment of the compiled scaler to use
- = es screenseg
- =
- = Upon return, ds IS NOT SET to the data segment. Do:
- = mov ax,ss
- = mov ds,ax
- =
- =
- = GC_BITMASK set to the pixels to be drawn in the row of bytes under DI
- = GC_MODE read mode 1, write mode 2
- = GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff
- =
- =
- = Code generated for each segment
- = -------------------------------
- = mov bx,[(segend+1)*2]
- = mov cx,[bx]
- = mov [BYTE PTR bx],0xc8 // far return
- = mov ax,[segstart*2]
- = mov [ss:0],ax // entry point into the compiled scaler
- = mov ds,dx // (mov ds,cs) the data is after the compiled code
- = mov si,ofs data
- = call [bp] // scale some pixels
- = mov ds,[bp+2]
- = mov [bx],cx // un patch return
- =
- = Code generated after all segments on a line
- = -------------------------------------------
- = retf
- =
- ========================
- */
- unsigned BuildCompShape (t_compshape _seg **finalspot)
- {
- t_compshape _seg *work;
- byte far *code;
- int firstline,lastline,x,y;
- unsigned firstpix,lastpix,width;
- unsigned totalsize,pixelofs;
- unsigned buff;
- // MM_GetPtr (&(memptr)work,20000);
- EGAWRITEMODE(0);
- EGAREADMAP(0); // use ega screen memory for temp buffer
- EGAMAPMASK(1);
- buff = screenloc[1];
- work = (t_compshape _seg *)(0xa000+(buff+15)/16);
- //
- // find the width of the shape
- //
- firstline = -1;
- x=0;
- do
- {
- for (y=0;y<64;y++)
- if (spotvis[y][x] != BACKGROUNDPIX)
- {
- firstline = x;
- break;
- }
- if (++x == 64)
- Quit ("BuildCompShape: No shape data!");
- } while (firstline == -1);
- lastline = -1;
- x=63;
- do
- {
- for (y=0;y<64;y++)
- if (spotvis[y][x] != BACKGROUNDPIX)
- {
- lastline = x;
- break;
- }
- x--;
- } while (lastline == -1);
- width = lastline-firstline+1;
- work->width = width;
- code = (byte far *)&work->codeofs[width];
- //
- // copy all non background pixels to the work space
- //
- pixelofs = FP_OFF(code);
- for (x=firstline;x<=lastline;x++)
- for (y=0;y<64;y++)
- if (spotvis[y][x] != BACKGROUNDPIX)
- *code++ = spotvis[y][x];
- //
- // start compiling the vertical lines
- //
- for (x=firstline;x<=lastline;x++)
- {
- work->codeofs[x-firstline] = FP_OFF(code);
- y=0;
- do
- {
- //
- // scan past black background pixels
- //
- while (spotvis[y][x] == BACKGROUNDPIX && y<64)
- y++;
- if (y>63) // no more segments
- break;
- firstpix = y+1; // +1 because width is before codeofs
- //
- // scan past scalable pixels
- //
- while (spotvis[y][x] != BACKGROUNDPIX && y<64)
- y++;
- if (y>63)
- lastpix = 65;
- else
- lastpix = y+1; // actually one pixel past the last displayed
- //
- // compile the scale call
- //
- *code++ = 0x8b; // mov bx,[lastpix*2]
- *code++ = 0x1e;
- *((unsigned far *)code)++ = lastpix*2;
- *code++ = 0x8b; // mov cx,[bx]
- *code++ = 0x0f;
- *code++ = 0xc6; // move [BYTE bx],0xcb
- *code++ = 0x07;
- *code++ = 0xcb;
- *code++ = 0xa1; // mov ax,[firstpix*2] /*************
- *((unsigned far *)code)++ = firstpix*2;
- *code++ = 0x36; // mov [ss:0],ax
- *code++ = 0xa3;
- *code++ = 0x00;
- *code++ = 0x00;
- *code++ = 0x8e; // mov ds,dx (mov ds,cs)
- *code++ = 0xda;
- *code++ = 0xbe; // mov si,OFFSET pixelofs-firstpixel
- *((unsigned far *)code)++ = pixelofs-firstpix;
- *code++ = 0xff; // call [DWORD bp]
- *code++ = 0x5e;
- *code++ = 0x00;
- *code++ = 0x8e; // mov ds,[bp+2]
- *code++ = 0x5e;
- *code++ = 0x02;
- *code++ = 0x89; // mov [bx],cx
- *code++ = 0x0f;
- pixelofs += (lastpix-firstpix);
- } while (y<63);
- //
- // retf
- //
- *code++ = 0xcb;
- }
- //
- // copy the final shape to a properly sized buffer
- //
- totalsize = FP_OFF(code);
- if (totalsize >= (PAGELEN*2))
- Quit("BuildCompShape(): Shape is too complex!");
- MM_GetPtr ((memptr *)finalspot,totalsize);
- _fmemcpy ((byte _seg *)(*finalspot),(byte _seg *)work,totalsize);
- // MM_FreePtr (&(memptr)work);
- return totalsize;
- }
- /*
- =======================
- =
- = ScaleShape
- =
- = Draws a compiled shape at [scale] pixels high
- =
- = Setup for call
- = --------------
- = GC_MODE read mode 1, write mode 2
- = GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff
- = GC_INDEX pointing at GC_BITMASK
- =
- =======================
- */
- static long longtemp;
- void ScaleShape (int xcenter, t_compshape _seg *compshape, unsigned scale)
- {
- #define MAX_OBJ_SCALE (MAXSCALE)
- t_compscale _seg *comptable;
- unsigned width,scalewidth;
- int x,pixel,lastpixel,pixwidth,min;
- unsigned far *codehandle, far *widthptr;
- unsigned badcodeptr;
- int rightclip;
- if (!compshape)
- Quit ("ScaleShape: NULL compshape ptr!");
- scale = (scale+1)/2;
- if (!scale)
- return; // too far away
- if (scale>MAX_OBJ_SCALE)
- scale = MAX_OBJ_SCALE;
- comptable = scaledirectory[scale];
- width = compshape->width;
- scalewidth = comptable->start[width];
- pixel = xcenter - scalewidth/2;
- lastpixel = pixel+scalewidth-1;
- if (pixel >= VIEWWIDTH || lastpixel < 0)
- return; // totally off screen
- //
- // scan backwards from the right edge until pixels are visable
- // rightclip is the first NON VISABLE pixel
- //
- if (lastpixel>=VIEWWIDTH-1)
- rightclip = VIEWWIDTH-1;
- else
- rightclip = lastpixel;
- if (zbuffer[rightclip]>scale)
- {
- if (pixel>0)
- min = pixel;
- else
- min = 0;
- do
- {
- if (--rightclip < min)
- return; // totally covered or before 0
- if (zbuffer[rightclip]<=scale)
- break;
- } while (1);
- }
- rightclip++;
- //
- // scan from the left until it is on screen, leaving
- // [pixel],[pixwidth],[codehandle],and [widthptr] set correctly
- //
- *(((unsigned *)&longtemp)+1) = (unsigned)compshape; // seg of shape
- codehandle = &compshape->codeofs[0];
- badcodeptr = compshape->codeofs[width];
- widthptr = &comptable->width[0];
- asm mov ax,[comptable]
- asm mov WORD PTR [2],ax // ds:0-4 is used as a far call pointer
- // by the compiled shapes
- pixwidth = *widthptr; // scaled width of this pixel
- while (!pixwidth)
- {
- pixwidth = *++widthptr; // find the first visable pixel
- codehandle++;
- }
- if (pixel<0)
- {
- do
- {
- if (pixel+pixwidth>0)
- {
- pixwidth += pixel;
- pixel = 0;
- break;
- }
- do
- {
- pixwidth = *++widthptr;
- codehandle++;
- } while (!pixwidth);
- pixel+=pixwidth;
- } while (1);
- }
- //
- // scan until it is visable, leaving
- // [pixel],[pixwidth],[codehandle],and [widthptr] set correctly
- //
- do
- {
- if (zbuffer[pixel] <= scale)
- break; // start drawing here
- pixel++;
- if (!--pixwidth)
- {
- do
- {
- pixwidth = *++widthptr;
- codehandle++;
- } while (!pixwidth);
- }
- } while (1);
- if (pixel+pixwidth>rightclip)
- pixwidth = rightclip-pixel;
- //
- // draw lines
- //
- do // while (1)
- {
- //
- // scale a vertical segment [pixwidth] pixels wide at [pixel]
- //
- (unsigned)longtemp = *codehandle; // offset of compiled code
- if ((unsigned)longtemp == badcodeptr)
- Quit ("ScaleShape: codehandle past end!");
- asm mov bx,[pixel]
- asm mov di,bx
- asm shr di,1
- asm shr di,1
- asm shr di,1 // X in bytes
- asm add di,[bufferofs]
- asm and bx,7
- asm shl bx,1
- asm shl bx,1
- asm shl bx,1
- asm add bx,[pixwidth] // bx = pixel*8+pixwidth-1
- asm dec bx
- asm push bx
- asm mov al,BYTE PTR [bitmasks1+bx]
- asm mov dx,GC_INDEX+1
- asm out dx,al // set bit mask register
- asm mov es,[screenseg]
- asm push si
- asm push di
- asm push bp
- asm xor bp,bp
- asm mov dx,[WORD PTR longtemp+2]
- asm mov ds,[2]
- asm call ss:[DWORD PTR longtemp] // scale the line of pixels
- asm mov ax,ss
- asm mov ds,ax
- asm pop bp
- asm pop di
- asm pop si
- asm pop bx
- asm mov al,BYTE PTR [bitmasks2+bx]
- asm or al,al
- asm jz nosecond
- //
- // draw a second byte for vertical strips that cross two bytes
- //
- asm inc di
- asm mov dx,GC_INDEX+1
- asm out dx,al // set bit mask register
- asm push si
- asm push di
- asm push bp
- asm xor bp,bp
- asm mov dx,[WORD PTR longtemp+2]
- asm mov ds,[2]
- asm call ss:[DWORD PTR longtemp] // scale the line of pixels
- asm mov ax,ss
- asm mov ds,ax
- asm pop bp
- asm pop di
- asm pop si
- //
- // advance to the next drawn line
- //
- nosecond:;
- if ( (pixel+=pixwidth) == rightclip )
- {
- asm mov WORD PTR [0],0
- asm mov WORD PTR [2],0
- return; // all done!
- }
- do
- {
- pixwidth = *++widthptr;
- codehandle++;
- } while (!pixwidth);
- if (pixel+pixwidth > rightclip)
- pixwidth = rightclip-pixel;
- } while (1);
- }
- //
- // bit mask tables for drawing scaled strips up to eight pixels wide
- //
- byte bitmasks1[8][8] = {
- {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff},
- {0x40,0x60,0x70,0x78,0x7c,0x7e,0x7f,0x7f},
- {0x20,0x30,0x38,0x3c,0x3e,0x3f,0x3f,0x3f},
- {0x10,0x18,0x1c,0x1e,0x1f,0x1f,0x1f,0x1f},
- {0x8,0xc,0xe,0xf,0xf,0xf,0xf,0xf},
- {0x4,0x6,0x7,0x7,0x7,0x7,0x7,0x7},
- {0x2,0x3,0x3,0x3,0x3,0x3,0x3,0x3},
- {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1} };
- byte bitmasks2[8][8] = {
- {0,0,0,0,0,0,0,0},
- {0,0,0,0,0,0,0,0x80},
- {0,0,0,0,0,0,0x80,0xc0},
- {0,0,0,0,0,0x80,0xc0,0xe0},
- {0,0,0,0,0x80,0xc0,0xe0,0xf0},
- {0,0,0,0x80,0xc0,0xe0,0xf0,0xf8},
- {0,0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc},
- {0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe} };
|