📄 f_wipe.c
字号:
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// Mission begin melt/wipe screen special effect.
//
//-----------------------------------------------------------------------------
static const char rcsid[] = "$Id: f_wipe.c,v 1.2 1997/02/03 22:45:09 b1 Exp $";
#include "z_zone.h"
#include "i_video.h"
#include "v_video.h"
#include "m_random.h"
#include "doomdef.h"
#include "f_wipe.h"
void WriteDebug(char *);
//
// SCREEN WIPE PACKAGE
//
// when zero, stop the wipe
static boolean go = 0;
//static byte* wipe_scr_start;
//static byte* wipe_scr_end;
//static byte* wipe_scr;
void
wipe_shittyColMajorXform
( short* array,
int width,
int height )
{
int x;
int y;
short* dest;
dest = (short*) Z_Malloc(width*height*2, PU_STATIC, 0);
for(y=0;y<height;y++)
for(x=0;x<width;x++)
dest[x*height+y] = array[y*width+x];
memcpy(array, dest, width*height*2);
Z_Free(dest);
}
int
wipe_initColorXForm
( int width,
int height,
int ticks,
/*DQ*/
BOOL bAdvance,
PBUFFER RenderBuffer,
PBUFFER WipeStartBuffer,
PBUFFER WipeEndBuffer)
{
// DQ start
// buffer width may not equal buffer pitch
int y;
BYTE * RBuffer;
long * RYLookup;
BYTE * StartBuffer;
long * StartYLookup;
RBuffer = RenderBuffer->Buffer;
RYLookup = RenderBuffer->YLookup;
StartBuffer = WipeStartBuffer->Buffer;
StartYLookup = WipeStartBuffer->YLookup;
for (y=0; y < height; y++)
{
memcpy(RBuffer + RYLookup[y], StartBuffer + StartYLookup[y], width);
}
// DQ end
// memcpy(wipe_scr, wipe_scr_start, width*height); // original
return 0;
}
int
wipe_doColorXForm
( int width,
int height,
int ticks,
/*DQ*/
BOOL bAdvance,
PBUFFER RenderBuffer,
PBUFFER WipeStartBuffer,
PBUFFER WipeEndBuffer)
{
boolean changed;
byte* w;
byte* e;
int newval;
// DQ start
int x, y;
BYTE * RBuffer;
long * RYLookup;
BYTE * EndBuffer;
long * EndYLookup;
RBuffer = RenderBuffer->Buffer;
RYLookup = RenderBuffer->YLookup;
EndBuffer = WipeEndBuffer->Buffer;
EndYLookup = WipeEndBuffer->YLookup;
// DQ end
changed = false;
//w = wipe_scr;
//e = wipe_scr_end;
for (y = 0; y < height; y++) // DQ
{
w = RBuffer + RYLookup[y];
e = EndBuffer + EndYLookup[y];
for (x = 0; x < width; x++)
//while (w!=wipe_scr+width*height)
{
if (*w != *e)
{
if (*w > *e)
{
newval = *w - ticks;
if (newval < *e)
*w = *e;
else
*w = newval;
changed = true;
}
else if (*w < *e)
{
newval = *w + ticks;
if (newval > *e)
*w = *e;
else
*w = newval;
changed = true;
}
}
w++;
e++;
}
}
return !changed;
}
int
wipe_exitColorXForm
( int width,
int height,
int ticks,
/*DQ*/
BOOL bAdvance,
PBUFFER RenderBuffer,
PBUFFER WipeStartBuffer,
PBUFFER WipeEndBuffer)
{
return 0;
}
static int* yArray; // renamed by DQ
//static int* y;
// DQ changed the init melt to support stereoscopic views
//int
//wipe_initMelt
//( int width,
// int height,
// int ticks )
//{
// int i, r;
//
// // copy start screen to main screen
// memcpy(wipe_scr, wipe_scr_start, width*height);
//
// // makes this wipe faster (in theory)
// // to have stuff in column-major format
// wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height);
// wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height);
//
// // setup initial column positions
// // (y<0 => not ready to scroll yet)
// y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0);
// y[0] = -(M_Random()%16);
// for (i=1;i<width;i++)
// {
// r = (M_Random()%3) - 1;
// y[i] = y[i-1] + r;
// if (y[i] > 0) y[i] = 0;
// else if (y[i] == -16) y[i] = -15;
// }
//
// return 0;
//}
// DQ start addition
int
wipe_initMelt
( int width,
int height,
int ticks,
BOOL bAdvance,
PBUFFER RenderBuffer,
PBUFFER WipeStartBuffer,
PBUFFER WipeEndBuffer)
{
int i, r;
// makes this wipe faster (in theory)
// to have stuff in column-major format
// DQ - I removed this step. The images change between frames (left vs. right)
// and I don't want to assume that they have changed orientation
//wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height);
//wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height);
// setup initial column positions
// (y<0 => not ready to scroll yet)
yArray = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0);
yArray[0] = -(M_Random()%16);
for (i=1;i<width;i++)
{
r = (M_Random()%3) - 1;
yArray[i] = yArray[i-1] + r;
if (yArray[i] > 0) yArray[i] = 0;
else if (yArray[i] == -16) yArray[i] = -15;
}
return 0;
}
// DQ end addition
//int
//wipe_doMelt
//( int width,
// int height,
// int ticks )
//{
// int i;
// int j;
// int dy;
// int idx;
//
// short* s;
// short* d;
// boolean done = true;
//
// width/=2;
//
// while (ticks--)
// {
// for (i=0;i<width;i++)
// {
// if (y[i]<0)
// {
// y[i]++; done = false;
// }
// else if (y[i] < height)
// {
// dy = (y[i] < 16) ? y[i]+1 : 8;
// if (y[i]+dy >= height) dy = height - y[i];
// s = &((short *)wipe_scr_end)[i*height+y[i]];
// d = &((short *)wipe_scr)[y[i]*width+i];
// idx = 0;
// for (j=dy;j;j--)
// {
// d[idx] = *(s++);
// idx += width;
// }
// y[i] += dy;
// s = &((short *)wipe_scr_start)[i*height];
// d = &((short *)wipe_scr)[y[i]*width+i];
// idx = 0;
// for (j=height-y[i];j;j--)
// {
// d[idx] = *(s++);
// idx += width;
// }
// done = false;
// }
// }
// }
//
// return done;
//
//}
// DQ start addition
int
wipe_doMelt
( int width,
int height,
int ticks,
BOOL bAdvance,
PBUFFER RenderBuffer,
PBUFFER WipeStartBuffer,
PBUFFER WipeEndBuffer)
{
int x;
int y;
DWORD *s;
DWORD *d;
boolean done = true;
int speedupfactor = 1;
BYTE * RBuffer;
long * RYLookup;
BYTE * StartBuffer;
long * StartYLookup;
BYTE * EndBuffer;
long * EndYLookup;
RBuffer = RenderBuffer->Buffer;
RYLookup = RenderBuffer->YLookup;
StartBuffer = WipeStartBuffer->Buffer;
StartYLookup = WipeStartBuffer->YLookup;
EndBuffer = WipeEndBuffer->Buffer;
EndYLookup = WipeEndBuffer->YLookup;
// DQFIXME - rearrange the loops, doing Y on outer, X on inside
// we want the wipe rate to be about the same as it would be at 320x200. increase
// the amount that we wipe downward to compensate.
speedupfactor = (width * height) / (320L * 200L);
if (speedupfactor < 1)
{
speedupfactor = 1;
}
width /= sizeof(*s);
for (x=0;x<width;x++)
{
if (yArray[x] > 0 && yArray[x] <= height)
{
// copy the end screen - the screen that appears behind the wipe
for (y=0;y< yArray[x];y++)
{
s = (DWORD *)EndBuffer + (EndYLookup[y])/sizeof(*s) + x;
d = (DWORD *)RBuffer + (RYLookup[y])/sizeof(*s) + x;
*d = *s;
}
// copy the start image - the part that wipes down
for (y=yArray[x]; y < height;y++)
{
s = (DWORD *)StartBuffer + (StartYLookup[y - yArray[x]])/sizeof(*s) + x; // DQ
d = (DWORD *)RBuffer + (RYLookup[y])/sizeof(*s) + x; // DQ
*d = *s;
}
if (yArray[x] < height)
done = false;
}
// move down the screen
if (bAdvance)
{
// speed up to approximate the wipe rate of 320 x 200
yArray[x] += (yArray[x] < 8 ? 1 : 8) * speedupfactor;
if (yArray[x] > height)
{
yArray[x] = height;
}
if (yArray[x] < height)
{
done = false;
}
}
}
return done;
}
// DQ end addition
int
wipe_exitMelt
( int width,
int height,
int ticks,
/*DQ*/
BOOL bAdvance,
PBUFFER RenderBuffer,
PBUFFER WipeStartBuffer,
PBUFFER WipeEndBuffer)
{
Z_Free(yArray);
return 0;
}
int
wipe_StartScreen
( int x,
int y,
int width,
int height,
PBUFFER WipeStartBuffer, // DQ
PBUFFER DisplayBuffer // DQ
)
{
//wipe_scr_start = screens[2]; // DQ removed
//I_ReadScreen(wipe_scr_start); // DQ removed
I_ReadScreen(WipeStartBuffer, DisplayBuffer);
return 0;
}
// DQ start addition
void ScreensSwap(byte * ScreenA, byte * ScreenB)
{
// swap DWORD at a time, to speed up the operation. All screen sizes are multiples of 4
// so this will not miss any data
DWORD dwBucket;
DWORD * lpdwSource;
DWORD * lpdwDest;
long lCounter;
lpdwSource = (DWORD *)ScreenA;
lpdwDest = (DWORD *)ScreenB;
for (lCounter = 0; lCounter < SCREENWIDTH * SCREENHEIGHT; lCounter += sizeof(DWORD))
{
dwBucket = *lpdwDest;
*lpdwDest = *lpdwSource;
*lpdwSource = dwBucket;
lpdwDest++;
lpdwSource++;
}
}
int
wipe_RightEndScreen
(PBUFFER RightEndScreen/*DQ*/,
PBUFFER DisplayBuffer/*DQ*/)
{
I_ReadScreen(RightEndScreen/*DQ*/, DisplayBuffer/*DQ*/);
return 0;
}
// DQ end addition
int
wipe_EndScreen
( int x,
int y,
int width,
int height,
PBUFFER WipeEndBuffer/*DQ*/,
PBUFFER DisplayBuffer/*DQ*/)
{
//wipe_scr_end = screens[3];
//I_ReadScreen(wipe_scr_end);
//V_DrawBlock(x, y, RenderBuffer/*DQ 0*/, DestYLookup/*DQ*/, width, height, wipe_scr_start); // restore start scr.
// DQ start
I_ReadScreen(WipeEndBuffer/*DQ*/, DisplayBuffer/*DQ*/);
// DQFIXME - why is this needed?
// V_DrawBlock(x, y, RenderBuffer/*DQ 0*/, width, height, WipeStartBuffer); // restore start scr.
// DQ end
return 0;
}
int
wipe_ScreenWipe
( int wipeno,
int x,
int y,
int width,
int height,
int ticks
// DQ start addition
, BOOL bAdvance, // first of the two eyes
PBUFFER RenderBuffer,
PBUFFER WipeStartBuffer,
PBUFFER WipeEndBuffer
// DQ end addition
)
{
int rc;
static int (*wipes[])(int, int, int, BOOL/*DQ*/, PBUFFER/*DQ*/, PBUFFER/*DQ*/, PBUFFER/*DQ*/) =
{
wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm,
wipe_initMelt, wipe_doMelt, wipe_exitMelt
};
void V_MarkRect(int, int, int, int);
// initial stuff
if (!go)
{
go = 1; // original line
// wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG
//wipe_scr = screens[0]; // DQ removed
(*wipes[wipeno*3])(width, height, ticks, bAdvance,
RenderBuffer,
WipeStartBuffer,
WipeEndBuffer);//DQ
//(*wipes[wipeno*3])(width, height, ticks, bAdvance,);
}
// do a piece of wipe-in
V_MarkRect(0, 0, width, height);
rc = (*wipes[wipeno*3+1])(width, height, ticks, bAdvance,
RenderBuffer,
WipeStartBuffer,
WipeEndBuffer);//DQ
//rc = (*wipes[wipeno*3+1])(width, height, ticks, bAdvance);
// V_DrawBlock(x, y, 0, width, height, wipe_scr); // DEBUG
// final stuff
if (rc && bAdvance /* DQ */)
{
go = 0;
(*wipes[wipeno*3+2])(width, height, ticks, bAdvance,
RenderBuffer,
WipeStartBuffer,
WipeEndBuffer);//DQ
//(*wipes[wipeno*3+2])(width, height, ticks, bAdvance);
}
return !go;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -