ref: ced40ce2c44caca11be2b33060f8283c12ef0d7b
parent: ebeccb0ff209b62ed4bf61dfd74f87565eb35a05
author: Simon Howard <fraggle@soulsphere.org>
date: Sun May 22 13:34:17 EDT 2016
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.
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -214,7 +214,7 @@
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
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -175,12 +175,6 @@
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 @@
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 @@
}
SDL_Flip(screen);
+
+ // Restore background and undo the disk indicator, if it was drawn.
+ V_RestoreDiskBackground();
}
--- a/src/strife/d_main.c
+++ b/src/strife/d_main.c
@@ -301,7 +301,7 @@
// 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;
--- a/src/v_diskicon.c
+++ b/src/v_diskicon.c
@@ -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 @@
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;
+ recent_bytes_read += nbytes;
+}
- // Draw the disk to the screen
- V_DrawPatch(loading_disk_xoffs, loading_disk_yoffs, disk);
+static void CopyRegion(byte *dest, int dest_pitch,
+ byte *src, int src_pitch,
+ int w, int h)
+{
+ byte *s, *d;
+ int y;
- disk_indicator = disk_dirty;
+ 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;
+ }
+}
+
--- a/src/v_diskicon.h
+++ b/src/v_diskicon.h
@@ -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
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -348,9 +348,7 @@
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);