f_wipe fixes from Diet Boom

This commit is contained in:
Roman Fomin 2023-12-05 13:37:42 +07:00
parent 3d8c701a60
commit da0bd96a1d

View File

@ -17,12 +17,22 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "doomdef.h"
#include "i_video.h" #include "i_video.h"
#include "v_video.h" #include "v_video.h"
#include "m_random.h" #include "m_random.h"
#include "f_wipe.h" #include "f_wipe.h"
// Even in hires mode, we simulate what happens on a 320x200 screen; ie.
// the screen is vertically sliced into 160 columns that fall to the bottom
// of the screen. Other hires implementations of the melt effect look weird
// when they try to scale up the original logic to higher resolutions.
// Number of "falling columns" on the screen.
#define NUM_COLUMNS 160
// Distance a column falls before it reaches the bottom of the screen.
#define COLUMN_MAX_Y 200
// //
// SCREEN WIPE PACKAGE // SCREEN WIPE PACKAGE
// //
@ -31,15 +41,15 @@ static byte *wipe_scr_start;
static byte *wipe_scr_end; static byte *wipe_scr_end;
static byte *wipe_scr; static byte *wipe_scr;
static void wipe_shittyColMajorXform(short *array, int width, int height) static void wipe_shittyColMajorXform(byte *array, int width, int height)
{ {
short *dest = Z_Malloc(width*height*sizeof(short), PU_STATIC, 0); byte *dest = Z_Malloc(width*height, PU_STATIC, 0);
int x, y; int x, y;
for(y=0;y<height;y++) for(y=0;y<height;y++)
for(x=0;x<width;x++) for(x=0;x<width;x++)
dest[x*height+y] = array[y*width+x]; dest[x*height+y] = array[y*width+x];
memcpy(array, dest, width*height*sizeof(short)); memcpy(array, dest, width*height);
Z_Free(dest); Z_Free(dest);
} }
@ -73,33 +83,31 @@ static int wipe_exitColorXForm(int width, int height, int ticks)
return 0; return 0;
} }
static int *y; static int col_y[NUM_COLUMNS];
static int wipe_initMelt(int width, int height, int ticks) static int wipe_initMelt(int width, int height, int ticks)
{ {
int i; int i;
const int hires_size = (video.yscale >> FRACBITS);
// copy start screen to main screen // copy start screen to main screen
memcpy(wipe_scr, wipe_scr_start, width*height); memcpy(wipe_scr, wipe_scr_start, width*height);
// makes this wipe faster (in theory) // makes this wipe faster (in theory)
// to have stuff in column-major format // to have stuff in column-major format
wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height); wipe_shittyColMajorXform(wipe_scr_start, width, height);
wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height); wipe_shittyColMajorXform(wipe_scr_end, width, height);
// setup initial column positions (y<0 => not ready to scroll yet) // setup initial column positions (y<0 => not ready to scroll yet)
y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0); col_y[0] = -(M_Random()%16);
y[0] = -(M_Random()%16) * hires_size; for (i=1;i<NUM_COLUMNS;i++)
for (i=1;i<width;i++)
{ {
int r = ((M_Random()%3) - 1) * hires_size; int r = (M_Random()%3) - 1;
y[i] = y[i-1] + r; col_y[i] = col_y[i-1] + r;
if (y[i] > 0) if (col_y[i] > 0)
y[i] = 0; col_y[i] = 0;
else else
if (y[i] == -16 * hires_size) if (col_y[i] == -16)
y[i] = -15 * hires_size; col_y[i] = -15;
} }
return 0; return 0;
} }
@ -107,51 +115,55 @@ static int wipe_initMelt(int width, int height, int ticks)
static int wipe_doMelt(int width, int height, int ticks) static int wipe_doMelt(int width, int height, int ticks)
{ {
boolean done = true; boolean done = true;
int i; int x, y, xfactor, yfactor;
width /= 2;
while (ticks--) while (ticks--)
for (i=0;i<width;i++) for (x=0;x<NUM_COLUMNS;x++)
if (y[i]<0) if (col_y[x]<0)
{ {
y[i]++; col_y[x]++;
done = false; done = false;
} }
else else if (col_y[x] < COLUMN_MAX_Y)
if (y[i] < height)
{ {
short *s, *d; int dy = (col_y[x] < 16) ? col_y[x]+1 : 8;
int j, dy, idx; if (col_y[x]+dy >= COLUMN_MAX_Y)
dy = COLUMN_MAX_Y - col_y[x];
col_y[x] += dy;
done = false;
}
dy = (y[i] < 16) ? y[i]+1 : 8; xfactor = (width + NUM_COLUMNS - 1) / NUM_COLUMNS;
if (y[i]+dy >= height) yfactor = (height + COLUMN_MAX_Y - 1) / COLUMN_MAX_Y;
dy = height - y[i];
s = &((short *)wipe_scr_end)[i*height+y[i]]; for (x = 0; x < width; x++)
d = &((short *)wipe_scr)[y[i]*width+i];
idx = 0;
for (j=dy;j;j--)
{ {
d[idx] = *(s++); byte *s, *d;
idx += width; int scroff = col_y[x / xfactor] * yfactor;
} if (scroff > height)
y[i] += dy; scroff = height;
s = &((short *)wipe_scr_start)[i*height];
d = &((short *)wipe_scr)[y[i]*width+i]; d = wipe_scr + x;
idx = 0; s = wipe_scr_end + x * height;
for (j=height-y[i];j;j--) for (y = 0; y < scroff; ++y)
{ {
d[idx] = *(s++); *d = *s;
idx += width; d += width;
s++;
}
s = wipe_scr_start + x * height;
for (; y < height; ++y)
{
*d = *s;
d += width;
s++;
} }
done = false;
} }
return done; return done;
} }
static int wipe_exitMelt(int width, int height, int ticks) static int wipe_exitMelt(int width, int height, int ticks)
{ {
Z_Free(y);
Z_Free(wipe_scr_start); Z_Free(wipe_scr_start);
Z_Free(wipe_scr_end); Z_Free(wipe_scr_end);
return 0; return 0;
@ -190,7 +202,6 @@ int wipe_ScreenWipe(int wipeno, int x, int y, int width, int height, int ticks)
width = video.width; width = video.width;
height = video.height; height = video.height;
ticks = (ticks * video.yscale) >> FRACBITS;
if (!go) // initial stuff if (!go) // initial stuff
{ {