From 26ff5e112626399e388a93bdb80f731d1cd7fe7f Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Wed, 13 Mar 2024 17:14:36 +0100 Subject: [PATCH] additional screen wipe: fizzle fade from Wolf 3D (#1586) * alternative screen wipe: fizzle fade from Wolf 3D * comment out static functions to let CI pass * copy one "pixel" at a time * add as a third alternative --- src/f_wipe.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ src/f_wipe.h | 1 + src/m_config.c | 4 +- src/mn_setup.c | 2 +- 4 files changed, 128 insertions(+), 3 deletions(-) diff --git a/src/f_wipe.c b/src/f_wipe.c index dfbaca22..0f4d2115 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -214,6 +214,127 @@ static int wipe_NOP(int x, int y, int t) return 0; } +/* +// Copyright(C) 1992 Id Software, Inc. +// Copyright(C) 2007-2011 Moritz "Ripper" Kroll + +=================== += += FizzleFade += += It uses maximum-length Linear Feedback Shift Registers (LFSR) counters. += You can find a list of them with lengths from 3 to 168 at: += http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf += Many thanks to Xilinx for this list!!! += +=================== +*/ + +// XOR masks for the pseudo-random number sequence starting with n=17 bits +static const uint32_t rndmasks[] = { + // n XNOR from (starting at 1, not 0 as usual) + 0x00012000, // 17 17,14 + 0x00020400, // 18 18,11 + 0x00040023, // 19 19,6,2,1 + 0x00090000, // 20 20,17 + 0x00140000, // 21 21,19 + 0x00300000, // 22 22,21 + 0x00420000, // 23 23,18 + 0x00e10000, // 24 24,23,22,17 + 0x01200000, // 25 25,22 (this is enough for 8191x4095) +}; + +// Returns the number of bits needed to represent the given value +static int log2_ceil(uint32_t x) +{ + int n = 0; + uint32_t v = 1; + + while (v < x) + { + n++; + v <<= 1; + } + + return n; +} + +static unsigned int rndbits_y; +static unsigned int rndmask; +static unsigned int lastrndval; + +static int wipe_initFizzle(int width, int height, int ticks) +{ + int rndbits_x = log2_ceil(video.unscaledw); + rndbits_y = log2_ceil(COLUMN_MAX_Y); + + int rndbits = rndbits_x + rndbits_y; + if (rndbits < 17) + rndbits = 17; // no problem, just a bit slower + else if (rndbits > 25) + rndbits = 25; // fizzle fade will not fill whole screen + + rndmask = rndmasks[rndbits - 17]; + + V_PutBlock(0, 0, width, height, wipe_scr_start); + + lastrndval = 0; + + return 0; +} + +static int wipe_doFizzle(int width, int height, int ticks) +{ + const int pixperframe = (video.unscaledw * COLUMN_MAX_Y) >> 5; + unsigned int rndval = lastrndval; + + for (unsigned p = 0; p < pixperframe; p++) + { + // seperate random value into x/y pair + + unsigned int x = rndval >> rndbits_y; + unsigned int y = rndval & ((1 << rndbits_y) - 1); + + // advance to next random element + + rndval = (rndval >> 1) ^ (rndval & 1 ? 0 : rndmask); + + if (x >= video.unscaledw || y >= COLUMN_MAX_Y) + { + if (rndval == 0) // entire sequence has been completed + { + return true; + } + + p--; + continue; + } + + // copy one pixel + vrect_t rect = {x, y, 1, 1}; + V_ScaleRect(&rect); + + byte *src = wipe_scr_end + rect.sy * width + rect.sx; + byte *dest = wipe_scr + rect.sy * video.pitch + rect.sx; + + while (rect.sh--) + { + memcpy(dest, src, rect.sw); + src += width; + dest += video.pitch; + } + + if (rndval == 0) // entire sequence has been completed + { + return true; + } + } + + lastrndval = rndval; + + return false; +} + static int (*const wipes[])(int, int, int) = { wipe_NOP, wipe_NOP, @@ -224,6 +345,9 @@ static int (*const wipes[])(int, int, int) = { wipe_initColorXForm, wipe_doColorXForm, wipe_exit, + wipe_initFizzle, + wipe_doFizzle, + wipe_exit, }; // killough 3/5/98: reformatted and cleaned up diff --git a/src/f_wipe.h b/src/f_wipe.h index 1121bf9f..28e760c3 100644 --- a/src/f_wipe.h +++ b/src/f_wipe.h @@ -28,6 +28,7 @@ enum { wipe_None, wipe_Melt, // weird screen melt wipe_ColorXForm, + wipe_Fizzle, wipe_NUMWIPES }; diff --git a/src/m_config.c b/src/m_config.c index 5b6410bd..84d9592d 100644 --- a/src/m_config.c +++ b/src/m_config.c @@ -606,8 +606,8 @@ default_t defaults[] = { { "screen_melt", (config_t *) &screen_melt, NULL, - {wipe_Melt}, {wipe_None, wipe_ColorXForm}, number, ss_gen, wad_no, - "screen wipe effect (0 = none, 1 = melt, 2 = crossfade)" + {wipe_Melt}, {wipe_None, wipe_Fizzle}, number, ss_gen, wad_no, + "screen wipe effect (0 = none, 1 = melt, 2 = crossfade, 3 = fizzlefade)" }, { diff --git a/src/mn_setup.c b/src/mn_setup.c index dbe8c12d..6dac8b1a 100644 --- a/src/mn_setup.c +++ b/src/mn_setup.c @@ -2253,7 +2253,7 @@ const char *default_skill_strings[] = { static const char *death_use_action_strings[] = {"default", "last save", "nothing"}; -static const char *screen_melt_strings[] = {"Off", "Melt", "Crossfade"}; +static const char *screen_melt_strings[] = {"Off", "Melt", "Crossfade", "Fizzle"}; static const char *invul_mode_strings[] = {"Vanilla", "MBF", "Gray"};