284 lines
6.1 KiB
C
284 lines
6.1 KiB
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.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "z_zone.h"
|
|
#include "i_system.h"
|
|
#include "i_video.h"
|
|
#include "v_video.h"
|
|
#include "m_random.h"
|
|
|
|
#include "doomdef.h"
|
|
|
|
#ifdef ENABLE_F_WIPE
|
|
#include "f_wipe.h"
|
|
|
|
//
|
|
// 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;
|
|
|
|
|
|
int wipe_initColorXForm( int width, int height, int ticks )
|
|
{
|
|
ticks= 0; //Shuts up GCC
|
|
memcpy(wipe_scr, wipe_scr_start, width*height);
|
|
return 0;
|
|
}
|
|
|
|
int wipe_doColorXForm( int width, int height, int ticks )
|
|
{
|
|
boolean changed;
|
|
byte* w;
|
|
byte* e;
|
|
int newval;
|
|
|
|
changed = false;
|
|
w = wipe_scr;
|
|
e = wipe_scr_end;
|
|
|
|
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 )
|
|
{
|
|
ticks= 0; //Shuts up GCC
|
|
width= 0;
|
|
height= 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int* y;
|
|
|
|
int wipe_initMelt( int width, int height, int ticks )
|
|
{
|
|
int i, r;
|
|
|
|
ticks= 0; //Shuts up GCC
|
|
|
|
// copy start screen to main screen
|
|
memcpy(wipe_scr, wipe_scr_start, width*height);
|
|
|
|
/* CGDoom: Normally the wipe effect transposes the buffers in color-major
|
|
order to better use the cache, but uses a screen-sized temporary buffer in
|
|
the process. We don't need the added speed, but we sure need every bit of
|
|
memory we can scrape. So we keep the row-major order. */
|
|
// 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;
|
|
}
|
|
|
|
/* See wipe_doMelt(). */
|
|
short SPU2_read16(short *x)
|
|
{
|
|
if ((uintptr_t)x & 2) {
|
|
volatile int *z = (int *)(x - 1);
|
|
return *z & 0xffff;
|
|
}
|
|
else {
|
|
volatile int *z = (int *)x;
|
|
return *z >> 16;
|
|
}
|
|
}
|
|
|
|
int wipe_doMelt( int width, int height, int ticks )
|
|
{
|
|
/* CGDoom: To spare memory, we have left both wipe_scr_start and wipe_scr_end
|
|
in row-major order. This affects the computation of (short *s) as well as
|
|
its stride (now a full row instead of 2 pixels).
|
|
|
|
In addition, the screen wipe buffers are allocated in PRAM to reduce
|
|
pressure on the heap. Therefore, only 4-byte accesses are possible, so we
|
|
read with SPU2_read16() to keep everything working. */
|
|
|
|
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)[y[i]*width+i]; /* Row-major order */
|
|
d = &((short *)wipe_scr)[y[i]*width+i];
|
|
idx = 0;
|
|
for (j=dy;j;j--)
|
|
{
|
|
d[idx] = SPU2_read16(s);
|
|
s += width; /* Row-major order */
|
|
idx += width;
|
|
}
|
|
y[i] += dy;
|
|
s = &((short *)wipe_scr_start)[i]; /* Row-major order */
|
|
d = &((short *)wipe_scr)[y[i]*width+i];
|
|
idx = 0;
|
|
for (j=height-y[i];j;j--)
|
|
{
|
|
d[idx] = SPU2_read16(s);
|
|
s += width; /* Row-major order */
|
|
idx += width;
|
|
}
|
|
done = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
int wipe_exitMelt( int width, int height, int ticks )
|
|
{
|
|
ticks= 0; //Shuts up GCC
|
|
width= 0;
|
|
height= 0;
|
|
|
|
Z_Free(y);
|
|
return 0;
|
|
}
|
|
|
|
int wipe_StartScreen ()
|
|
{
|
|
wipe_scr_start = screens[2];
|
|
I_ReadScreen(wipe_scr_start);
|
|
return 0;
|
|
}
|
|
|
|
int wipe_EndScreen( int x, int y, int width, int height )
|
|
{
|
|
wipe_scr_end = screens[3];
|
|
I_ReadScreen(wipe_scr_end);
|
|
|
|
/* CGDoom: The wipe buffer is in PRAM, so the V_DrawBlock() below may not
|
|
at every position on screen. But we always wipe the whole screen, so
|
|
that's not going to be a problem. */
|
|
V_DrawBlock(x, y, 0, width, height, wipe_scr_start); // restore start scr.
|
|
|
|
return 0;
|
|
}
|
|
|
|
int wipe_ScreenWipe ( int wipeno, int width, int height, int ticks )
|
|
{
|
|
int rc;
|
|
static int (*wipes[])(int, int, int) =
|
|
{
|
|
wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm,
|
|
wipe_initMelt, wipe_doMelt, wipe_exitMelt
|
|
};
|
|
|
|
if (wipeno < 0 || wipeno >= wipe_NUMWIPES)
|
|
return 1;
|
|
|
|
// initial stuff
|
|
if (!go)
|
|
{
|
|
go = 1;
|
|
//wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // carmack debug, don't touch!
|
|
wipe_scr = screens[0];
|
|
(*wipes[wipeno*3])(width, height, ticks);
|
|
}
|
|
|
|
// do a piece of wipe-in
|
|
V_MarkRect(0, 0, width, height);
|
|
rc = (*wipes[wipeno*3+1])(width, height, ticks);
|
|
//V_DrawBlock(x, y, 0, width, height, wipe_scr); // carmack debug, don't touch!
|
|
|
|
// final stuff
|
|
if (rc)
|
|
{
|
|
go = 0;
|
|
(*wipes[wipeno*3+2])(width, height, ticks);
|
|
}
|
|
|
|
return !go;
|
|
|
|
}
|
|
#endif //#ifdef ENABLE_F_WIPE
|