ref: 90c196e4eb1d079fa946e764ed72a9ecd2c86dac
parent: b6938d1533d624a5815660c40aeda9125090f55e
author: James Haley <haleyjd@hotmail.com>
date: Sat Sep 11 17:12:06 EDT 2010
Added code (some possibly temporary?) to load voices.wad. Fixed several problems with playing of voice sounds - especially had to add a dynamic hashtable of voice sfxinfo_t's because Choco won't tolerate overwriting them once they've been used (see channel_playing array in i_sdlsound.c) - PROBLEM: Random Z_Malloc failures when trying to play sounds. Cannot catch in debugger so far. Subversion-branch: /branches/strife-branch Subversion-revision: 2065
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -50,6 +50,7 @@
{ "heretic.wad", heretic, retail, "Heretic" },
{ "heretic1.wad", heretic, shareware, "Heretic Shareware" },
{ "hexen.wad", hexen, commercial, "Hexen" },
+ //{ "strife0.wad", strife, commercial, "Strife" }, // haleyjd: STRIFE-FIXME
{ "strife1.wad", strife, commercial, "Strife" },
};
--- a/src/strife/d_main.c
+++ b/src/strife/d_main.c
@@ -127,6 +127,10 @@
boolean advancedemo;
+// haleyjd 09/11/10: [STRIFE] Game type variables
+boolean isregistered;
+boolean isdemoversion;
+
// Store demo, do not accept any inputs
// haleyjd [STRIFE] Unused.
//boolean storedemo;
@@ -696,7 +700,54 @@
return gamename;
}
+//
+// haleyjd: STRIFE-FIXME: Temporary?
+// Code borrowed from Eternity, and modified to return separator char
//
+char M_GetFilePath(const char *fn, char *dest, size_t len)
+{
+ boolean found_slash = false;
+ char *p;
+ char sepchar = '\0';
+
+ memset(dest, 0, len);
+
+ p = dest + len - 1;
+
+ strncpy(dest, fn, len);
+
+ while(p >= dest)
+ {
+ if(*p == '/' || *p == '\\')
+ {
+ sepchar = *p;
+ found_slash = true; // mark that the path ended with a slash
+ *p = '\0';
+ break;
+ }
+ *p = '\0';
+ p--;
+ }
+
+ // haleyjd: in the case that no slash was ever found, yet the
+ // path string is empty, we are dealing with a file local to the
+ // working directory. The proper path to return for such a string is
+ // not "", but ".", since the format strings add a slash now. When
+ // the string is empty but a slash WAS found, we really do want to
+ // return the empty string, since the path is relative to the root.
+ if(!found_slash && *dest == '\0')
+ *dest = '.';
+
+ // if a separator is not found, default to forward, because Windows
+ // supports that too.
+ if(sepchar == '\0')
+ sepchar = '/';
+
+ return sepchar;
+}
+
+
+//
// Find out what version of Doom is playing.
//
@@ -707,59 +758,59 @@
// IdentifyIWADByName. However, if the iwad does not match
// any known IWAD name, we may have a dilemma. Try to
// identify by its contents.
+
+ // STRIFE-TODO: some elaborate checks? for now we assume...
+ // The logic in strife1.exe is simple:
+ // * if strife1.wad is found, set isregistered = true
+ // * if strife0.wad is found, set isdemoversion = true
- if (gamemission == none)
+ // Make sure gamemode is set up correctly
+ gamemode = commercial;
+ gamemission = strife;
+ isregistered = true;
+
+ // Load voices.wad
+ if(isregistered)
{
- unsigned int i;
+ char *name = D_FindWADByName("voices.wad");
- for (i=0; i<numlumps; ++i)
+ if(!name) // not found?
{
- if (!strncasecmp(lumpinfo[i].name, "MAP01", 8))
+ int p;
+
+ // haleyjd STRIFE-FIXME: Temporary?
+ // If -iwad was used, check and see if voices.wad exists on the
+ // same filepath.
+ if((p = M_CheckParm("-iwad")) && p < myargc - 1)
{
- gamemission = doom2;
- break;
- }
- else if (!strncasecmp(lumpinfo[i].name, "E1M1", 8))
- {
- gamemission = doom;
- break;
- }
- }
+ char *iwad = myargv[p + 1];
+ size_t len = strlen(iwad) + 24;
+ char *filename = malloc(len);
+ char sepchar;
- if (gamemission == none)
- {
- // Still no idea. I don't think this is going to work.
+ // how the heck is Choco surviving without this routine?
+ sepchar = M_GetFilePath(iwad, filename, len);
+ filename[strlen(filename)] = sepchar;
+ strcat(filename, "voices.wad");
- I_Error("Unknown or invalid IWAD file.");
+ if(!M_FileExists(filename))
+ disable_voices = 1;
+ else
+ name = filename; // STRIFE-FIXME: memory leak!!
+ }
+ else
+ disable_voices = 1;
}
- }
- // Make sure gamemode is set up correctly
-
- if (gamemission == doom)
- {
- // Doom 1. But which version?
-
- if (W_CheckNumForName("E4M1") > 0)
+ if(disable_voices) // voices disabled?
{
- // Ultimate Doom
-
- gamemode = retail;
- }
- else if (W_CheckNumForName("E3M1") > 0)
- {
- gamemode = registered;
+ // STRIFE-FIXME:
+ // if(debugmode)
+ printf("Voices disabled\n");
+ return;
}
- else
- {
- gamemode = shareware;
- }
- }
- else
- {
- // Doom 2 of some kind.
- gamemode = commercial;
+ D_AddFile(name);
}
}
@@ -1625,7 +1676,7 @@
#endif
DEH_printf("S_Init: Setting up sound.\n");
- S_Init (sfxVolume * 8, musicVolume * 8);
+ S_Init (sfxVolume * 8, musicVolume * 8, voiceVolume * 8); // [STRIFE]: voice
DEH_printf("D_CheckNetGame: Checking network game status.\n");
D_CheckNetGame ();
--- a/src/strife/p_dialog.c
+++ b/src/strife/p_dialog.c
@@ -1151,7 +1151,8 @@
currentchoice = &(currentdialog->choices[choice]);
- // I_StartVoice(0); -- verify (should stop previous voice I believe)
+ I_StartVoice(NULL); // STRIFE-TODO: verify (should stop previous voice I believe)
+
// villsa 09/08/10: converted into for loop
for(i = 0; i < MDLG_MAXITEMS; i++)
{
@@ -1364,7 +1365,7 @@
V_DrawPatchDirect(0, 0, W_CacheLumpNum(pic, PU_CACHE));
// get voice
- //I_StartVoice(currentdialog->voice);
+ I_StartVoice(currentdialog->voice);
// get bye text
switch(rnd)
--- a/src/strife/s_sound.c
+++ b/src/strife/s_sound.c
@@ -137,8 +137,9 @@
// Sets channels, SFX and music volume,
// allocates channel buffer, sets S_sfx lookup.
//
-
-void S_Init(int sfxVolume, int musicVolume)
+// haleyjd 09/11/10: Added voice volume
+//
+void S_Init(int sfxVolume, int musicVolume, int voiceVolume)
{
int i;
@@ -149,6 +150,7 @@
S_SetSfxVolume(sfxVolume);
S_SetMusicVolume(musicVolume);
+ S_SetVoiceVolume(voiceVolume);
// Allocating the internal channels for mixing
// (the maximum numer of sounds rendered
@@ -257,6 +259,10 @@
for (cnum=0 ; cnum<snd_channels ; cnum++)
{
+ // haleyjd: do not stop voice here.
+ if(cnum == i_voicehandle)
+ continue;
+
if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
{
S_StopChannel(cnum);
@@ -280,7 +286,7 @@
channel_t* c;
// Find an open channel
- for (cnum=0 ; cnum<snd_channels ; cnum++)
+ for (cnum=0 ; cnum<snd_channels ; cnum++)
{
if (!channels[cnum].sfxinfo)
{
@@ -495,9 +501,83 @@
}
channels[cnum].handle = I_StartSound(sfx, cnum, volume, sep);
-}
+}
+
+// haleyjd 09/11/10: [STRIFE]
+// None of this was necessary in the vanilla EXE but Choco's low-level code
+// won't play nice with a temporary sfxinfo because it insists that the
+// "driver_data" member remain valid from the last time the sound was used,
+// even if it has already stopped playing. Thanks to this cuteness I get
+// to maintain a dynamic cache of sfxinfo objects!
+
+typedef struct voiceinfo_s
+{
+ sfxinfo_t sfx;
+ struct voiceinfo_s *next; // next on hash chain
+} voiceinfo_t;
+
+#define NUMVOICECHAINS 257
+
//
+// Ripped from Eternity.
+//
+static unsigned int S_voiceHash(const char *str)
+{
+ const char *c = str;
+ unsigned int h = 0;
+
+ if(!str)
+ I_Error("S_voiceHash: cannot hash NULL string!\n");
+
+ // note: this needs to be case insensitive for lump names
+ while(*c)
+ {
+ h = 5 * h + toupper(*c);
+ ++c;
+ }
+
+ return h;}
+
+static voiceinfo_t *voices[NUMVOICECHAINS];
+
+//
+// S_getVoice
+//
+// Gets an entry from the voice table, if it exists. If it does not, one will be
+// created.
+//
+static voiceinfo_t *S_getVoice(const char *name, int lumpnum)
+{
+ voiceinfo_t *voice;
+ int hashkey = S_voiceHash(name) % NUMVOICECHAINS;
+
+ voice = voices[hashkey];
+
+ while(voice && strcasecmp(voice->sfx.name, name))
+ voice = voice->next;
+
+ if(!voice)
+ {
+ voice = calloc(1, sizeof(voiceinfo_t));
+
+ strncpy(voice->sfx.name, name, 8);
+ voice->sfx.priority = INT_MIN; // make highest possible priority
+ voice->sfx.pitch = -1;
+ voice->sfx.volume = -1;
+ voice->sfx.numchannels = -1;
+ voice->sfx.usefulness = -1;
+ voice->sfx.lumpnum = lumpnum;
+
+ // throw it onto the table.
+ voice->next = voices[hashkey];
+ voices[hashkey] = voice;
+ }
+
+ return voice;
+}
+
+//
// I_StartVoice
//
// haleyjd 09/11/10: [STRIFE] New function
@@ -508,14 +588,14 @@
//
void I_StartVoice(const char *lumpname)
{
- static sfxinfo_t voicesfx; // a static "fake" sfxinfo for voices.
int lumpnum;
+ voiceinfo_t *voice; // choco-specific
// no voices in deathmatch mode.
if(netgame)
return;
- // TODO: checks if sfx_SndDevice == 83
+ // STRIFE-TODO: checks if snd_SfxDevice == 83
// This is probably turning off voice if using PC speaker...
// user has disabled voices?
@@ -523,25 +603,26 @@
return;
// have a voice playing already? stop it.
- if (i_voicehandle > 0)
+ if (i_voicehandle >= 0)
S_StopChannel(i_voicehandle);
- // haleyjd: Choco-specific: initialize the voicesfx structure
- memset(&voicesfx, 0, sizeof(sfxinfo_t));
- strncpy(voicesfx.name, lumpname, 8);
- voicesfx.priority = INT_MIN; // make highest possible priority
- voicesfx.pitch = -1;
- voicesfx.volume = -1;
- voicesfx.numchannels = -1;
- voicesfx.usefulness = -1;
+ // Vanilla STRIFE appears to have stopped any current voice without
+ // starting a new one if NULL was passed in here, though I cannot
+ // find an explicit check for NULL in the assembly. Either way, it
+ // didn't crash, so do a check now:
+ if(lumpname == NULL)
+ return;
if((lumpnum = W_CheckNumForName(lumpname)) != -1)
{
+ // haleyjd: Choco-specific: get a voice structure
+ voice = S_getVoice(lumpname, lumpnum);
+
// get a channel for the voice
- i_voicehandle = S_GetChannel(NULL, &voicesfx, true);
- voicesfx.lumpnum = lumpnum;
+ i_voicehandle = S_GetChannel(NULL, &voice->sfx, true);
+
channels[i_voicehandle].handle
- = I_StartSound(&voicesfx, i_voicehandle, snd_VoiceVolume, NORM_SEP);
+ = I_StartSound(&voice->sfx, i_voicehandle, snd_VoiceVolume, NORM_SEP);
}
}
--- a/src/strife/s_sound.h
+++ b/src/strife/s_sound.h
@@ -37,7 +37,7 @@
// allocates channel buffer, sets S_sfx lookup.
//
-void S_Init(int sfxVolume, int musicVolume);
+void S_Init(int sfxVolume, int musicVolume, int voiceVolume);
// Shut down sound
@@ -96,6 +96,8 @@
void S_SetVoiceVolume(int volume); // haleyjd 09/11/10: [STRIFE]
extern int snd_channels;
+
+extern int disable_voices;
#endif