Refactor loading disk icon code.

Only draw the disk icon just before doing the SDL blit to the screen,
and restore the background to I_VideoBuffer immediately after doing
so. This avoids the possibility of the disk remaining in the video
buffer and fixes #668.

Also centralize most loading disk code inside v_diskicon.c.
This commit is contained in:
Simon Howard 2016-05-22 17:34:17 +02:00
parent ebeccb0ff2
commit ced40ce2c4
6 changed files with 83 additions and 43 deletions

View file

@ -214,7 +214,7 @@ void D_Display (void)
break;
if (automapactive)
AM_Drawer ();
if (wipe || (viewheight != SCREENHEIGHT && fullscreen) || disk_indicator == disk_dirty)
if (wipe || (viewheight != SCREENHEIGHT && fullscreen))
redrawsbar = true;
if (inhelpscreensstate && !inhelpscreens)
redrawsbar = true; // just put away the help screen

View file

@ -175,12 +175,6 @@ int png_screenshots = 0;
int show_diskicon = 1;
// Only display the disk icon if more then this much bytes have been read
// during the previous tic.
static const int diskicon_threshold = 20*1024;
int diskicon_readbytes = 0;
// if true, I_VideoBuffer is screen->pixels
static boolean native_surface;
@ -965,18 +959,8 @@ void I_FinishUpdate (void)
I_VideoBuffer[ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
}
if (show_diskicon && disk_indicator == disk_on)
{
if (diskicon_readbytes >= diskicon_threshold)
{
V_BeginRead();
}
}
else if (disk_indicator == disk_dirty)
{
disk_indicator = disk_off;
}
diskicon_readbytes = 0;
// Draw disk icon before blit, if necessary.
V_DrawDiskIcon();
// draw to screen
@ -1012,6 +996,9 @@ void I_FinishUpdate (void)
}
SDL_Flip(screen);
// Restore background and undo the disk indicator, if it was drawn.
V_RestoreDiskBackground();
}

View file

@ -301,7 +301,7 @@ void D_Display (void)
// see if the border needs to be updated to the screen
if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320)
{
if (menuactive || menuactivestate || !viewactivestate || disk_indicator == disk_dirty)
if (menuactive || menuactivestate || !viewactivestate)
{
borderdrawcount = 3;
popupactivestate = false;

View file

@ -18,6 +18,8 @@
#include "doomtype.h"
#include "deh_str.h"
#include "i_swap.h"
#include "i_video.h"
#include "m_argv.h"
#include "v_video.h"
#include "w_wad.h"
@ -25,14 +27,22 @@
#include "v_diskicon.h"
// Only display the disk icon if more then this much bytes have been read
// during the previous tic.
static const int diskicon_threshold = 20*1024;
// disk image patch (either STDISK or STCDROM)
static patch_t *disk;
static byte *saved_background;
static int loading_disk_xoffs = 0;
static int loading_disk_yoffs = 0;
disk_indicator_e disk_indicator = disk_off;
// Number of bytes read since the last call to V_DrawDiskIcon().
static size_t recent_bytes_read = 0;
static boolean disk_drawn;
void V_EnableLoadingDisk(int xoffs, int yoffs)
{
@ -47,15 +57,67 @@ void V_EnableLoadingDisk(int xoffs, int yoffs)
disk_name = DEH_String("STDISK");
disk = W_CacheLumpName(disk_name, PU_STATIC);
saved_background = Z_Malloc(SHORT(disk->width) * SHORT(disk->height),
PU_STATIC, NULL);
}
void V_BeginRead(void)
void V_BeginRead(size_t nbytes)
{
if (disk == NULL)
return;
// Draw the disk to the screen
V_DrawPatch(loading_disk_xoffs, loading_disk_yoffs, disk);
disk_indicator = disk_dirty;
recent_bytes_read += nbytes;
}
static void CopyRegion(byte *dest, int dest_pitch,
byte *src, int src_pitch,
int w, int h)
{
byte *s, *d;
int y;
s = src; d = dest;
for (y = 0; y < h; ++y)
{
memcpy(d, s, w);
s += src_pitch;
d += dest_pitch;
}
}
static byte *DiskRegionPointer(void)
{
int x, y;
x = loading_disk_xoffs + SHORT(disk->leftoffset);
y = loading_disk_yoffs + SHORT(disk->topoffset);
return I_VideoBuffer + y * SCREENWIDTH + x;
}
void V_DrawDiskIcon(void)
{
if (disk != NULL && recent_bytes_read > diskicon_threshold)
{
// Save the background behind the disk before we draw it.
CopyRegion(saved_background, SHORT(disk->width),
DiskRegionPointer(), SCREENWIDTH,
SHORT(disk->width), SHORT(disk->height));
// Draw the disk to the screen
V_DrawPatch(loading_disk_xoffs, loading_disk_yoffs, disk);
disk_drawn = true;
}
recent_bytes_read = 0;
}
void V_RestoreDiskBackground(void)
{
if (disk_drawn)
{
// Restore the background.
CopyRegion(DiskRegionPointer(), SCREENWIDTH,
saved_background, SHORT(disk->width),
SHORT(disk->width), SHORT(disk->height));
disk_drawn = false;
}
}

View file

@ -24,16 +24,9 @@
#define LOADING_DISK_W 16
#define LOADING_DISK_H 16
typedef enum
{
disk_off,
disk_on,
disk_dirty
} disk_indicator_e;
extern disk_indicator_e disk_indicator;
extern void V_EnableLoadingDisk (int xoffs, int yoffs);
extern void V_BeginRead (void);
extern void V_EnableLoadingDisk(int xoffs, int yoffs);
extern void V_BeginRead(size_t nbytes);
extern void V_DrawDiskIcon(void);
extern void V_RestoreDiskBackground(void);
#endif

View file

@ -348,9 +348,7 @@ void W_ReadLump(lumpindex_t lump, void *dest)
l = lumpinfo[lump];
diskicon_readbytes += l->size;
disk_indicator = disk_on;
V_BeginRead(l->size);
c = W_Read(l->wad_file, l->position, dest, l->size);