shithub: choc

Download patch

ref: b9be9f99ef4b050650018a9eee4478077255c9e8
parent: f12587122d8e22cac6a02cd9788a792a02301f28
author: Simon Howard <fraggle@gmail.com>
date: Sun Oct 23 16:22:35 EDT 2005

Drastically refactor the WAD merging code. Allow multiple replacements
of the same sprite in a PWAD (fixes Scientist 2)

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 222

--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
 
     Silence sounds at odd sample rates (rather than bombing out); this
         is the way Vanilla Doom behaves.
+    Handle multiple replacements of the same sprite in a PWAD.
 
 0.1.1 (2005-10-18):
     Display startup "banners" if they have been modified through 
--- a/src/w_merge.c
+++ b/src/w_merge.c
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*- 
 //-----------------------------------------------------------------------------
 //
-// $Id: w_merge.c 179 2005-10-09 00:25:49Z fraggle $
+// $Id: w_merge.c 222 2005-10-23 20:22:35Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -21,6 +21,10 @@
 // 02111-1307, USA.
 //
 // $Log$
+// Revision 1.3  2005/10/23 20:22:35  fraggle
+// Drastically refactor the WAD merging code.  Allow multiple replacements
+// of the same sprite in a PWAD (fixes Scientist 2)
+//
 // Revision 1.2  2005/10/09 00:25:49  fraggle
 // Improved sprite merging
 //
@@ -60,10 +64,11 @@
 {
     char sprname[4];
     char frame;
-    int angles;
-} replace_frame_t;
+    lumpinfo_t *angle_lumps[8];
+} sprite_frame_t;
 
 static searchlist_t iwad;
+static searchlist_t iwad_sprites;
 static searchlist_t pwad;
 
 static searchlist_t iwad_flats;
@@ -71,9 +76,9 @@
 static searchlist_t pwad_flats;
 
 // lumps with these sprites must be replaced in the IWAD
-static replace_frame_t *replace_frames;
-static int num_replace_frames;
-static int replace_frames_alloced;
+static sprite_frame_t *sprite_frames;
+static int num_sprite_frames;
+static int sprite_frames_alloced;
 
 // Search in a list to find a lump with a particular name
 // Linear search (slow!)
@@ -93,206 +98,251 @@
     return -1;
 }
 
-// Sets up the sprite/flat search lists
-
-static void SetupLists(void)
+static boolean SetupList(searchlist_t *list, searchlist_t *src_list,
+                         char *startname, char *endname,
+                         char *startname2, char *endname2)
 {
     int startlump, endlump;
-    
-    // IWAD
-    // look for the flats section
 
-    startlump = FindInList(&iwad, "F_START");
-    endlump = FindInList(&iwad, "F_END");
+    list->numlumps = 0;
+    startlump = FindInList(src_list, startname);
 
-    if (startlump < 0 || endlump < 0)
+    if (startname2 != NULL && startlump < 0)
     {
-        I_Error("Flats section not found in IWAD");
+        startlump = FindInList(src_list, startname2);
     }
 
-    iwad_flats.lumps = iwad.lumps + startlump + 1;
-    iwad_flats.numlumps = endlump - startlump - 1;
-
-    // PWAD
-    // look for a flats section
-
-    pwad_flats.numlumps = 0;
-    startlump = FindInList(&pwad, "FF_START");
-
-    if (startlump < 0)
-    {
-        startlump = FindInList(&pwad, "F_START");
-    }
-
     if (startlump >= 0)
     {
-        endlump = FindInList(&pwad, "FF_END");
+        endlump = FindInList(src_list, endname);
 
-        if (endlump < 0)
+        if (endname2 != NULL && endlump < 0)
         {
-            endlump = FindInList(&pwad, "F_END");
+            endlump = FindInList(src_list, endname2);
         }
 
         if (endlump > startlump)
         {
-            pwad_flats.lumps = pwad.lumps + startlump + 1;
-            pwad_flats.numlumps = endlump - startlump - 1;
+            list->lumps = src_list->lumps + startlump + 1;
+            list->numlumps = endlump - startlump - 1;
+            return true;
         }
     }
 
-    // look for a sprites section
+    return false;
+}
 
-    pwad_sprites.numlumps = 0;
-    startlump = FindInList(&pwad, "SS_START");
+// Sets up the sprite/flat search lists
 
-    if (startlump < 0)
+static void SetupLists(void)
+{
+    // IWAD
+
+    if (!SetupList(&iwad_flats, &iwad, "F_START", "F_END", NULL, NULL))
     {
-        startlump = FindInList(&pwad, "S_START");
+        I_Error("Flats section not found in IWAD");
     }
 
-    if (startlump >= 0)
-    {
-        endlump = FindInList(&pwad, "SS_END");
+    if (!SetupList(&iwad_sprites, &iwad, "S_START", "S_END", NULL, NULL))
 
-        if (endlump < startlump)
-        {
-            endlump = FindInList(&pwad, "S_END");
-        }
-
-        if (endlump > startlump)
-        {
-            pwad_sprites.lumps = pwad.lumps + startlump + 1;
-            pwad_sprites.numlumps = endlump - startlump - 1;
-        }
+    {
+        I_Error("Sprites section not found in IWAD");
     }
+    
+    // PWAD
+
+    SetupList(&pwad_flats, &pwad, "F_START", "F_END", "FF_START", "FF_END");
+    SetupList(&pwad_sprites, &pwad, "S_START", "S_END", "SS_START", "SS_END");
 }
 
 // Initialise the replace list
 
-static void InitReplaceList(void)
+static void InitSpriteList(void)
 {
-    if (replace_frames == NULL)
+    if (sprite_frames == NULL)
     {
-        replace_frames_alloced = 128;
-        replace_frames = Z_Malloc(sizeof(*replace_frames) * replace_frames_alloced,
+        sprite_frames_alloced = 128;
+        sprite_frames = Z_Malloc(sizeof(*sprite_frames) * sprite_frames_alloced,
                                  PU_STATIC, NULL);
     }
 
-    num_replace_frames = 0;
+    num_sprite_frames = 0;
 }
 
-// Add new sprite to the replace list
+// Find a sprite frame
 
-static void AddReplaceFrame(replace_frame_t *frame)
+static sprite_frame_t *FindSpriteFrame(char *name, int frame)
 {
+    sprite_frame_t *result;
     int i;
 
-    // Find if this is already in the list
+    // Search the list and try to find the frame
 
-    for (i=0; i<num_replace_frames; ++i)
+    for (i=0; i<num_sprite_frames; ++i)
     {
-        if (!strncasecmp(replace_frames[i].sprname, frame->sprname, 4)
-         && replace_frames[i].frame == frame->frame)
+        sprite_frame_t *cur = &sprite_frames[i];
+
+        if (!strncasecmp(cur->sprname, name, 4) && cur->frame == frame)
         {
-            replace_frames[i].angles |= frame->angles;
-            return;
+            return cur;
         }
     }
-    
-    // Need to add to the list
 
-    if (num_replace_frames >= replace_frames_alloced)
+    // Not found in list; Need to add to the list
+
+    // Grow list?
+
+    if (num_sprite_frames >= sprite_frames_alloced)
     {
-        replace_frame_t *newframes;
+        sprite_frame_t *newframes;
 
-        newframes = Z_Malloc(replace_frames_alloced * 2 * sizeof(*replace_frames),
+        newframes = Z_Malloc(sprite_frames_alloced * 2 * sizeof(*sprite_frames),
                              PU_STATIC, NULL);
-        memcpy(newframes, replace_frames,
-               replace_frames_alloced * sizeof(*replace_frames));
-        Z_Free(replace_frames);
-        replace_frames_alloced *= 2;
-        replace_frames = newframes;
+        memcpy(newframes, sprite_frames,
+               sprite_frames_alloced * sizeof(*sprite_frames));
+        Z_Free(sprite_frames);
+        sprite_frames_alloced *= 2;
+        sprite_frames = newframes;
     }
 
     // Add to end of list
     
-    replace_frames[num_replace_frames++] = *frame;
+    result = &sprite_frames[num_sprite_frames];
+    strncpy(result->sprname, name, 4);
+    result->frame = frame;
+
+    for (i=0; i<8; ++i)
+        result->angle_lumps[i] = NULL;
+
+    ++num_sprite_frames;
+
+    return result;
 }
 
-// Converts a sprite name into an replace_frame_t
+// Check if sprite lump is needed in the new wad
 
-static void ParseSpriteName(char *name, replace_frame_t *result)
+static boolean SpriteLumpNeeded(lumpinfo_t *lump)
 {
+    sprite_frame_t *sprite;
     int angle_num;
+    int i;
 
-    strncpy(result->sprname, name, 4);
-    result->frame = name[4];
+    // check the first frame
 
-    angle_num = name[5] - '0';
-    
+    sprite = FindSpriteFrame(lump->name, lump->name[4]);
+    angle_num = lump->name[5] - '0';
+
     if (angle_num == 0)
     {
-        // '0' sprites are used for all angles
+        // must check all frames
 
-        result->angles = 0xffff;
+        for (i=0; i<8; ++i)
+        {
+            if (sprite->angle_lumps[i] == lump)
+                return true;
+        }
     }
-    else
+    else 
     {
-       result->angles = 1 << angle_num;
+        // check if this lump is being used for this frame
+
+        if (sprite->angle_lumps[angle_num - 1] == lump)
+            return true;
     }
+            
+    // second frame if any
+    
+    // no second frame?
+    if (lump->name[6] == '\0')
+        return false;
 
-    if (name[6] != '\0')
+    sprite = FindSpriteFrame(lump->name, lump->name[6]);
+    angle_num = lump->name[7] - '0';
+
+    if (angle_num == 0)
     {
-        // second angle
+        // must check all frames
 
-        angle_num = name[7] - '0';
-
-        if (angle_num == 0)
+        for (i=0; i<8; ++i)
         {
-            result->angles = 0xffff;
+            if (sprite->angle_lumps[i] == lump)
+                return true;
         }
-        else
-        {
-            result->angles |= 1 << angle_num;
-        }
     }
-}
+    else 
+    {
+        // check if this lump is being used for this frame
 
-// Check if a sprite is in the replace list
+        if (sprite->angle_lumps[angle_num - 1] == lump)
+            return true;
+    }
 
-static boolean InReplaceList(char *name)
+    return false;
+}
+
+static void AddSpriteLump(lumpinfo_t *lump)
 {
-    replace_frame_t igsprite;
+    sprite_frame_t *sprite;
+    int angle_num;
     int i;
     
-    ParseSpriteName(name, &igsprite);
+    // first angle
 
-    for (i=0; i<num_replace_frames; ++i)
+    sprite = FindSpriteFrame(lump->name, lump->name[4]);
+    angle_num = lump->name[5] - '0';
+    
+    if (angle_num == 0) 
     {
-        if (!strncasecmp(replace_frames[i].sprname, igsprite.sprname, 4)
-         && replace_frames[i].frame == igsprite.frame
-         && (replace_frames[i].angles & igsprite.angles) != 0)
-        {
-            return true;
-        }
+        for (i=0; i<8; ++i)
+            sprite->angle_lumps[i] = lump;
     }
+    else
+    {
+        sprite->angle_lumps[angle_num - 1] = lump;
+    }
     
-    return false;
+    // second angle
+
+    // no second angle?
+  
+    if (lump->name[6] == '\0')
+        return;
+    
+    sprite = FindSpriteFrame(lump->name, lump->name[6]);
+    angle_num = lump->name[7] - '0';
+    
+    if (angle_num == 0) 
+    {
+        for (i=0; i<8; ++i)
+            sprite->angle_lumps[i] = lump;
+    }
+    else
+    {
+        sprite->angle_lumps[angle_num - 1] = lump;
+    }
 }
 
 // Generate the list.  Run at the start, before merging
 
-static void GenerateReplaceList(void)
+static void GenerateSpriteList(void)
 {
-    replace_frame_t igsprite;
     int i;
 
-    InitReplaceList();
+    InitSpriteList();
+    
+    // Add all sprites from the IWAD
+    
+    for (i=0; i<iwad_sprites.numlumps; ++i)
+    {
+        AddSpriteLump(&iwad_sprites.lumps[i]);
+    }
+    
+    // Add all sprites from the PWAD
+    // (replaces IWAD sprites)
 
     for (i=0; i<pwad_sprites.numlumps; ++i)
     {
-        ParseSpriteName(pwad_sprites.lumps[i].name, &igsprite);
-        AddReplaceFrame(&igsprite);
+        AddSpriteLump(&pwad_sprites.lumps[i]);
     }
 }
 
@@ -396,7 +446,10 @@
 
                     for (n=0; n<pwad_sprites.numlumps; ++n)
                     {
-                        newlumps[num_newlumps++] = pwad_sprites.lumps[n];
+                        if (SpriteLumpNeeded(&pwad_sprites.lumps[n]))
+                        {
+                            newlumps[num_newlumps++] = pwad_sprites.lumps[n];
+                        }
                     }
 
                     // copy the ending
@@ -410,7 +463,7 @@
                     // Is this lump holding a sprite to be replaced in the
                     // PWAD? If so, wait until the end to add it.
 
-                    if (!InReplaceList(lump->name))
+                    if (SpriteLumpNeeded(lump))
                     {
                         newlumps[num_newlumps++] = *lump;
                     }
@@ -479,6 +532,16 @@
     free(lumpinfo);
     lumpinfo = newlumps;
     numlumps = num_newlumps;
+
+#if 0
+    // debug
+    for (i=0; i<numlumps; ++i)
+    {
+        for (n=0; n<8 && lumpinfo[i].name[n] != '\0'; ++n)
+            putchar(lumpinfo[i].name[n]);
+        putchar('\n');
+    }
+#endif
 }
 
 // Merge in a file by name
@@ -512,7 +575,7 @@
 
     // Generate list of sprites to be replaced by the PWAD
 
-    GenerateReplaceList();
+    GenerateSpriteList();
 
     // Perform the merge