shithub: choc

Download patch

ref: 5bddaa7c571d0abf1543fbc9c735bc5054f568ef
parent: 512f850d914cc753359b702d085677715cd94d39
author: Simon Howard <fraggle@soulsphere.org>
date: Tue May 31 15:47:48 EDT 2016

diskicon: Draw disk icon with black background.

Vanilla {Doom,Strife} show a black background to the disk icons if the
icons are transparent, a side effect of how the disk icon code works
(the commented-out version can be found in Heretic's i_ibm.c). To be
consistent with how the vanilla code works, don't use V_DrawPatch to
draw the loading icon every time, but rather draw it to a buffer on
startup and blit the whole disk region to the screen.

--- a/src/v_diskicon.c
+++ b/src/v_diskicon.c
@@ -27,14 +27,18 @@
 
 #include "v_diskicon.h"
 
+#define DISK_ICON_W 16
+#define DISK_ICON_H 16
+
 // 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;
+// Two buffers: disk_data contains the data representing the disk icon
+// (raw, not a patch_t) while saved_background is an equivalently-sized
+// buffer where we save the background data while the disk is on screen.
+static byte *disk_data;
 static byte *saved_background;
 
 static int loading_disk_xoffs = 0;
@@ -44,6 +48,47 @@
 static size_t recent_bytes_read = 0;
 static boolean disk_drawn;
 
+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 void SaveDiskData(char *disk_lump, int xoffs, int yoffs)
+{
+    byte *tmpscreen;
+    patch_t *disk;
+
+    // Allocate a complete temporary screen where we'll draw the patch.
+    tmpscreen = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
+    memset(tmpscreen, 0, SCREENWIDTH * SCREENHEIGHT);
+    V_UseBuffer(tmpscreen);
+
+    // Buffer where we'll save the disk data.
+    disk_data = Z_Malloc(DISK_ICON_W * DISK_ICON_H, PU_STATIC, NULL);
+
+    // Draw the patch and save the result to disk_data.
+    disk = W_CacheLumpName(disk_lump, PU_STATIC);
+    V_DrawPatch(loading_disk_xoffs, loading_disk_yoffs, disk);
+    CopyRegion(disk_data, DISK_ICON_W,
+               tmpscreen + yoffs * SCREENWIDTH + xoffs, SCREENWIDTH,
+               DISK_ICON_W, DISK_ICON_H);
+    W_ReleaseLumpName(disk_lump);
+
+    V_RestoreBuffer();
+    Z_Free(tmpscreen);
+}
+
 void V_EnableLoadingDisk(int xoffs, int yoffs)
 {
     char *disk_name;
@@ -56,9 +101,8 @@
     else
         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);
+    saved_background = Z_Malloc(DISK_ICON_W * DISK_ICON_H, PU_STATIC, NULL);
+    SaveDiskData(disk_name, xoffs, yoffs);
 }
 
 void V_BeginRead(size_t nbytes)
@@ -66,42 +110,26 @@
     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;
+    return I_VideoBuffer
+         + loading_disk_yoffs * SCREENWIDTH
+         + loading_disk_xoffs;
 }
 
 void V_DrawDiskIcon(void)
 {
-    if (disk != NULL && recent_bytes_read > diskicon_threshold)
+    if (disk_data != NULL && recent_bytes_read > diskicon_threshold)
     {
         // Save the background behind the disk before we draw it.
-        CopyRegion(saved_background, SHORT(disk->width),
+        CopyRegion(saved_background, DISK_ICON_W,
                    DiskRegionPointer(), SCREENWIDTH,
-                   SHORT(disk->width), SHORT(disk->height));
+                   DISK_ICON_W, DISK_ICON_H);
 
-        // Draw the disk to the screen
-        V_DrawPatch(loading_disk_xoffs, loading_disk_yoffs, disk);
+        // Write the disk to the screen buffer.
+        CopyRegion(DiskRegionPointer(), SCREENWIDTH,
+                   disk_data, DISK_ICON_W,
+                   DISK_ICON_W, DISK_ICON_H);
         disk_drawn = true;
     }
 
@@ -114,8 +142,8 @@
     {
         // Restore the background.
         CopyRegion(DiskRegionPointer(), SCREENWIDTH,
-                   saved_background, SHORT(disk->width),
-                   SHORT(disk->width), SHORT(disk->height));
+                   saved_background, DISK_ICON_W,
+                   DISK_ICON_W, DISK_ICON_H);
 
         disk_drawn = false;
     }