Restore the last gameplay frame while on the intermission screen

This commit is contained in:
Jaime Passos 2019-11-05 17:04:57 -03:00
parent 96aa11c825
commit ed967f077c
3 changed files with 121 additions and 4 deletions

View file

@ -415,6 +415,7 @@ static void D_Display(void)
if (rendermode == render_soft)
{
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
Y_ConsiderScreenBuffer();
usebuffer = true;
}
lastdraw = false;

View file

@ -143,9 +143,21 @@ static patch_t *widebgpatch = NULL; // INTERSCW
static patch_t *bgtile = NULL; // SPECTILE/SRB2BACK
static patch_t *interpic = NULL; // custom picture defined in map header
static boolean usetile;
static INT32 timer;
typedef struct
{
INT32 source_width, source_height;
INT32 source_bpp, source_rowbytes;
UINT8 *source_picture;
INT32 target_width, target_height;
INT32 target_bpp, target_rowbytes;
UINT8 *target_picture;
} y_buffer_t;
boolean usebuffer = false;
static boolean useinterpic;
static INT32 timer;
static y_buffer_t *y_buffer;
static INT32 intertic;
static INT32 tallydonetic = -1;
@ -153,6 +165,8 @@ static INT32 endtic = -1;
intertype_t intertype = int_none;
static void Y_RescaleScreenBuffer(void);
static void Y_CleanupScreenBuffer(void);
static void Y_AwardCoopBonuses(void);
static void Y_AwardSpecialStageBonus(void);
static void Y_CalculateCompetitionWinners(void);
@ -207,6 +221,94 @@ static void Y_IntermissionTokenDrawer(void)
V_DrawCroppedPatch(32<<FRACBITS, y<<FRACBITS, FRACUNIT/2, 0, tokenicon, 0, 0, SHORT(tokenicon->width), calc);
}
//
// Y_ConsiderScreenBuffer
//
// Can we copy the current screen
// to a buffer?
//
void Y_ConsiderScreenBuffer(void)
{
if (gameaction != ga_completed)
return;
if (y_buffer == NULL)
y_buffer = Z_Calloc(sizeof(y_buffer_t), PU_STATIC, NULL);
else
return;
y_buffer->source_width = vid.width;
y_buffer->source_height = vid.height;
y_buffer->source_bpp = vid.bpp;
y_buffer->source_rowbytes = vid.rowbytes;
y_buffer->source_picture = ZZ_Alloc(y_buffer->source_width*vid.bpp * y_buffer->source_height);
VID_BlitLinearScreen(screens[1], y_buffer->source_picture, vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
// Make the rescaled screen buffer
Y_RescaleScreenBuffer();
}
//
// Y_RescaleScreenBuffer
//
// Write the rescaled source picture,
// to the destination picture that
// has the current screen's resolutions.
//
static void Y_RescaleScreenBuffer(void)
{
INT32 sx, sy; // source
INT32 dx, dy; // dest
fixed_t scalefac, yscalefac;
fixed_t rowfrac, colfrac;
UINT8 *dest;
// Who knows?
if (y_buffer == NULL)
return;
if (y_buffer->target_picture)
Z_Free(y_buffer->target_picture);
y_buffer->target_width = vid.width;
y_buffer->target_height = vid.height;
y_buffer->target_rowbytes = vid.rowbytes;
y_buffer->target_bpp = vid.bpp;
y_buffer->target_picture = ZZ_Alloc(y_buffer->target_width*vid.bpp * y_buffer->target_height);
dest = y_buffer->target_picture;
scalefac = FixedDiv(y_buffer->target_width*FRACUNIT, y_buffer->source_width*FRACUNIT);
yscalefac = FixedDiv(y_buffer->target_height*FRACUNIT, y_buffer->source_height*FRACUNIT);
rowfrac = FixedDiv(FRACUNIT, yscalefac);
colfrac = FixedDiv(FRACUNIT, scalefac);
for (sy = 0, dy = 0; sy < (y_buffer->source_height << FRACBITS) && dy < y_buffer->target_height; sy += rowfrac, dy++)
for (sx = 0, dx = 0; sx < (y_buffer->source_width << FRACBITS) && dx < y_buffer->target_width; sx += colfrac, dx += y_buffer->target_bpp)
dest[(dy * y_buffer->target_rowbytes) + dx] = y_buffer->source_picture[((sy>>FRACBITS) * y_buffer->source_width) + (sx>>FRACBITS)];
}
//
// Y_CleanupScreenBuffer
//
// Free all related memory.
//
static void Y_CleanupScreenBuffer(void)
{
// Who knows?
if (y_buffer == NULL)
return;
if (y_buffer->target_picture)
Z_Free(y_buffer->target_picture);
if (y_buffer->source_picture)
Z_Free(y_buffer->source_picture);
Z_Free(y_buffer);
y_buffer = NULL;
}
//
// Y_IntermissionDrawer
//
@ -229,12 +331,23 @@ void Y_IntermissionDrawer(void)
else if (!usetile)
{
if (rendermode == render_soft && usebuffer)
VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
{
// no y_buffer
if (y_buffer == NULL)
VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
else
{
// Maybe the resolution changed?
if ((y_buffer->target_width != vid.width) || (y_buffer->target_height != vid.height))
Y_RescaleScreenBuffer();
// Blit the already-scaled screen buffer to the current screen
VID_BlitLinearScreen(y_buffer->target_picture, screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
}
}
#ifdef HWRENDER
else if(rendermode != render_soft && usebuffer)
{
HWR_DrawIntermissionBG();
}
#endif
else
{
@ -2096,6 +2209,8 @@ static void Y_UnloadData(void)
if (rendermode != render_soft)
return;
Y_CleanupScreenBuffer();
// unload the background patches
UNLOAD(bgpatch);
UNLOAD(widebgpatch);

View file

@ -15,6 +15,7 @@ void Y_IntermissionDrawer(void);
void Y_Ticker(void);
void Y_StartIntermission(void);
void Y_EndIntermission(void);
void Y_ConsiderScreenBuffer(void);
typedef enum
{