📄 contigsc.c
字号:
// WL_SCALE.C
#include "WL_DEF.H"
#pragma hdrstop
#define OP_RETF 0xcb
/*
=============================================================================
GLOBALS
=============================================================================
*/
t_compscale far *scaledirectory[MAXSCALEHEIGHT+1];
long fullscalefarcall[MAXSCALEHEIGHT+1];
int maxscale,maxscaleshl2;
byte far *scalermemory;
byte _seg *endscalermemory;
long freescalermemory;
/*
=============================================================================
LOCALS
=============================================================================
*/
unsigned BuildCompScale (int height, byte far *code);
int stepbytwo;
//===========================================================================
/*
==============
=
= BadScale
=
==============
*/
void far BadScale (void)
{
Quit ("BadScale called!");
}
/*
==========================
=
= SetupScaling
=
==========================
*/
long SetupScaling (int maxscaleheight)
{
int i,x,y;
byte far *dest;
unsigned seg,ofs;
long size;
maxscaleheight/=2; // one scaler every two pixels
maxscale = maxscaleheight-1;
maxscaleshl2 = maxscale<<2;
dest = scalermemory;
//
// build the compiled scalers
//
stepbytwo = viewheight/2; // save space by double stepping
for (i=1;i<=maxscaleheight;i++)
{
seg = FP_SEG(dest);
ofs = (FP_OFF(dest)+15)&~15;
dest = MK_FP(seg+ofs/16,0);
scaledirectory[i] = (t_compscale far *)dest;
size = BuildCompScale (i*2,dest);
dest += size;
if ((byte huge *)dest-(byte huge *)scalermemory > MAXSCALERMEMORY)
Quit ("Compiled scalars exceeded allocated space!");
if (i>=stepbytwo)
i+= 2;
}
//
// get far call addresses
//
for (i=1;i<=maxscaleheight;i++)
{
fullscalefarcall[i] = (long)scaledirectory[i] + scaledirectory[i]->codeofs[0];
if (i>=stepbytwo)
{
scaledirectory[i+1] = scaledirectory[i];
fullscalefarcall[i+1] = (long)scaledirectory[i] + scaledirectory[i]->codeofs[0];
scaledirectory[i+2] = scaledirectory[i];
fullscalefarcall[i+2] = (long)scaledirectory[i] + scaledirectory[i]->codeofs[0];
i+=2;
}
}
scaledirectory[0] = scaledirectory[1];
fullscalefarcall[0] = fullscalefarcall[1];
//
// check for oversize wall drawing
//
for (i=maxscaleheight;i<MAXSCALEHEIGHT;i++)
fullscalefarcall[i] = (long)BadScale;
seg = FP_SEG(dest);
ofs = (FP_OFF(dest)+15)&~15;
endscalermemory = (void _seg *)(seg+ofs/16);
size = (byte huge *)dest-(byte huge *)scalermemory;
freescalermemory = MAXSCALERMEMORY-16-size;
return size;
}
//===========================================================================
/*
========================
=
= 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, byte far *code)
{
t_compscale far *work;
int i;
long fix,step;
unsigned src,totalscaled,totalsize;
int startpix,endpix,toppix;
work = (t_compscale far *)code;
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;
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
//
// mov [es:di+heightofs],al
//
*code++ = 0x26;
*code++ = 0x88;
*code++ = 0x85;
*((unsigned far *)code)++ = startpix*SCREENBWIDE;
}
}
//
// retf
//
*code++ = 0xcb;
totalsize = FP_OFF(code);
return totalsize;
}
/*
=======================
=
= ScaleLine
=
= linescale should have the high word set to the segment of the scaler
=
=======================
*/
extern int slinex,slinewidth;
extern unsigned far *linecmds;
extern long linescale;
extern unsigned maskword;
byte mask1,mask2,mask3;
void near ScaleLine (void)
{
asm mov cx,WORD PTR [linescale+2]
asm mov es,cx // segment of scaler
asm mov bp,WORD PTR [linecmds]
asm mov dx,SC_INDEX+1 // to set SC_MAPMASK
asm mov bx,[slinex]
asm mov di,bx
asm shr di,2 // X in bytes
asm add di,[bufferofs]
asm and bx,3
asm shl bx,3
asm add bx,[slinewidth] // bx = (pixel*8+pixwidth)
asm mov al,BYTE [mapmasks3-1+bx] // -1 because pixwidth of 1 is first
asm mov ds,WORD PTR [linecmds+2]
asm or al,al
asm jz notthreebyte // scale across three bytes
asm jmp threebyte
notthreebyte:
asm mov al,BYTE PTR ss:[mapmasks2-1+bx] // -1 because pixwidth of 1 is first
asm or al,al
asm jnz twobyte // scale across two bytes
//
// one byte scaling
//
asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first
asm out dx,al // set map mask register
scalesingle:
asm mov bx,[ds:bp] // table location of rtl to patch
asm or bx,bx
asm jz linedone // 0 signals end of segment list
asm mov bx,[es:bx]
asm mov dl,[es:bx] // save old value
asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in
asm mov si,[ds:bp+4] // table location of entry spot
asm mov ax,[es:si]
asm mov WORD PTR ss:[linescale],ax // call here to start scaling
asm mov si,[ds:bp+2] // corrected top of shape for this segment
asm add bp,6 // next segment list
asm mov ax,SCREENSEG
asm mov es,ax
asm call ss:[linescale] // scale the segment of pixels
asm mov es,cx // segment of scaler
asm mov BYTE PTR es:[bx],dl // unpatch the RETF
asm jmp scalesingle // do the next segment
//
// done
//
linedone:
asm mov ax,ss
asm mov ds,ax
return;
//
// two byte scaling
//
twobyte:
asm mov ss:[mask2],al
asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first
asm mov ss:[mask1],al
scaledouble:
asm mov bx,[ds:bp] // table location of rtl to patch
asm or bx,bx
asm jz linedone // 0 signals end of segment list
asm mov bx,[es:bx]
asm mov cl,[es:bx] // save old value
asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in
asm mov si,[ds:bp+4] // table location of entry spot
asm mov ax,[es:si]
asm mov WORD PTR ss:[linescale],ax // call here to start scaling
asm mov si,[ds:bp+2] // corrected top of shape for this segment
asm add bp,6 // next segment list
asm mov ax,SCREENSEG
asm mov es,ax
asm mov al,ss:[mask1]
asm out dx,al // set map mask register
asm call ss:[linescale] // scale the segment of pixels
asm inc di
asm mov al,ss:[mask2]
asm out dx,al // set map mask register
asm call ss:[linescale] // scale the segment of pixels
asm dec di
asm mov es,WORD PTR ss:[linescale+2] // segment of scaler
asm mov BYTE PTR es:[bx],cl // unpatch the RETF
asm jmp scaledouble // do the next segment
//
// three byte scaling
//
threebyte:
asm mov ss:[mask3],al
asm mov al,BYTE PTR ss:[mapmasks2-1+bx] // -1 because pixwidth of 1 is first
asm mov ss:[mask2],al
asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first
asm mov ss:[mask1],al
scaletriple:
asm mov bx,[ds:bp] // table location of rtl to patch
asm or bx,bx
asm jz linedone // 0 signals end of segment list
asm mov bx,[es:bx]
asm mov cl,[es:bx] // save old value
asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in
asm mov si,[ds:bp+4] // table location of entry spot
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -