From f4c33a2b6a3a851239934c8ecfff1ca876257096 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Tue, 7 Sep 2021 21:55:12 +0200 Subject: [PATCH] Enable wipe effect with no additional heap --- cgdoom/doomdef.h | 4 +-- cgdoom/f_wipe.c | 62 +++++++++++++++++++++++++++++------------------ cgdoom/i_system.c | 8 ++++++ cgdoom/i_video.c | 9 +++++++ cgdoom/r_data.c | 4 +-- cgdoom/v_video.c | 7 ++++-- 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/cgdoom/doomdef.h b/cgdoom/doomdef.h index d3c2744..1967f0f 100644 --- a/cgdoom/doomdef.h +++ b/cgdoom/doomdef.h @@ -48,8 +48,8 @@ typedef enum indetermined // Well, no IWAD found. } GameMode_t; -//CGGOOM -//#define ENABLE_F_WIPE + +#define ENABLE_F_WIPE // Mission packs - might be useful for TC stuff? diff --git a/cgdoom/f_wipe.c b/cgdoom/f_wipe.c index 6538e30..773d7e2 100644 --- a/cgdoom/f_wipe.c +++ b/cgdoom/f_wipe.c @@ -46,24 +46,6 @@ 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 not ready to scroll yet) @@ -154,8 +140,29 @@ int wipe_initMelt( int width, int height, int ticks ) return 0; } +/* See wipe_doMelt(). */ +short SPU2_read16(short *x) +{ + if ((int)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; @@ -179,21 +186,23 @@ int wipe_doMelt( int width, int height, int ticks ) { 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]]; + 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] = *(s++); + d[idx] = SPU2_read16(s); + s += width; /* Row-major order */ idx += width; } y[i] += dy; - s = &((short *)wipe_scr_start)[i*height]; + 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] = *(s++); + d[idx] = SPU2_read16(s); + s += width; /* Row-major order */ idx += width; } done = false; @@ -226,7 +235,12 @@ 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; } diff --git a/cgdoom/i_system.c b/cgdoom/i_system.c index 28363a7..33821c0 100644 --- a/cgdoom/i_system.c +++ b/cgdoom/i_system.c @@ -24,6 +24,7 @@ #include "platform.h" #include "cgdoom.h" +#include "cgdoom-alloc.h" #include #include "doomdef.h" @@ -131,6 +132,13 @@ byte *I_ScreenBase(int screen) if (screen == 4) return CGDOOM_SCREENS_BASE + 320*200*2; + /* For the wipe buffers, use PRAM. This can be done with rather little + changes because the wipe buffers are used only in f_wipe.c. */ + if (screen == 2) + return CGD_PRAM_Malloc(320*200); + if (screen == 3) + return CGD_PRAM_Malloc(320*200); + return NULL; } diff --git a/cgdoom/i_video.c b/cgdoom/i_video.c index 872254c..42b0b15 100644 --- a/cgdoom/i_video.c +++ b/cgdoom/i_video.c @@ -248,3 +248,12 @@ void I_SetWindowAfterError(void) } #endif + + +// +// I_ReadScreen +// +void I_ReadScreen (byte* scr) +{ + memcpy(scr, screens[0], SCREENWIDTH*SCREENHEIGHT); +} diff --git a/cgdoom/r_data.c b/cgdoom/r_data.c index bfb6d0b..b183f22 100644 --- a/cgdoom/r_data.c +++ b/cgdoom/r_data.c @@ -374,8 +374,8 @@ const byte* R_GetColumn ( int tex, int col ) lump = texturecolumnlump[tex][col]; ofs = texturecolumnofs[tex][col]; - /* CGDOOM: To save RAM in WADs bound by limited memory, composite textures - can be allowed only up to a certain size. Original CGDOOM limits to 8192 + /* CGDoom: To save RAM in WADs bound by limited memory, composite textures + can be allowed only up to a certain size. Original CGDoom limits to 8192 bytes so that switches can appear, but some other textures fail. */ #if 0 if(lump <= 0 && texturecompositesize[tex] > 8192) diff --git a/cgdoom/v_video.c b/cgdoom/v_video.c index 9cc3d1e..ceeb914 100644 --- a/cgdoom/v_video.c +++ b/cgdoom/v_video.c @@ -355,11 +355,14 @@ void V_Init (void) screens[0] = I_ScreenBase(0); /* screens[1] is used for the level end sequence (intermission) */ screens[1] = I_ScreenBase(1); - /* screens[2] and screens[3] are used for wipe effects (disabled here) */ + /* screens[2] and screens[3] are used for wipe effects */ + screens[2] = I_ScreenBase(2); + screens[3] = I_ScreenBase(3); /* screens[4] is used for the status bar (allocated by st_stuff.c) */ + screens[4] = NULL; } -/* CGDOOM-specific function to clear screen when changing window size */ +/* CGDoom-specific function to clear screen when changing window size */ void V_Clear (void) { memset(screens[0], 0, 320*(200-32));