- Search for the MUS header within the first 32 bytes of the song so that the music in

diescum.wad works.

SVN r2273 (trunk)
This commit is contained in:
Randy Heit 2010-04-06 03:12:32 +00:00
parent d875a0c674
commit 114412d5a2
4 changed files with 103 additions and 56 deletions

View file

@ -1671,10 +1671,10 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *
chan->setReverbProperties(&reverb); chan->setReverbProperties(&reverb);
} }
} }
chan->setPaused(false);
chan->getPriority(&def_priority); chan->getPriority(&def_priority);
FISoundChannel *schan = CommonChannelSetup(chan, reuse_chan); FISoundChannel *schan = CommonChannelSetup(chan, reuse_chan);
schan->Rolloff = *rolloff; schan->Rolloff = *rolloff;
chan->setPaused(false);
return schan; return schan;
} }

View file

@ -84,6 +84,8 @@ extern void ChildSigHandler (int signum);
#define GZIP_FNAME 8 #define GZIP_FNAME 8
#define GZIP_FCOMMENT 16 #define GZIP_FCOMMENT 16
extern int MUSHeaderSearch(const BYTE *head, int len);
EXTERN_CVAR (Int, snd_samplerate) EXTERN_CVAR (Int, snd_samplerate)
EXTERN_CVAR (Int, snd_mididevice) EXTERN_CVAR (Int, snd_mididevice)
@ -295,9 +297,14 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
{ {
FILE *file; FILE *file;
MusInfo *info = NULL; MusInfo *info = NULL;
DWORD id; union
{
DWORD id[32/4];
BYTE idstr[32];
};
const char *fmt; const char *fmt;
BYTE *ungzipped; BYTE *ungzipped;
int i;
if (nomusic) if (nomusic)
{ {
@ -322,22 +329,32 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
{ {
fseek (file, offset, SEEK_SET); fseek (file, offset, SEEK_SET);
} }
if (len < 32)
if (fread (&id, 4, 1, file) != 1) {
return 0;
}
if (fread (id, 4, 32/4, file) != 32/4)
{ {
fclose (file); fclose (file);
return 0; return 0;
} }
fseek (file, -4, SEEK_CUR); fseek (file, -32, SEEK_CUR);
} }
else else
{ {
file = NULL; file = NULL;
id = *(DWORD *)musiccache; if (len < 32)
{
return 0;
}
for (i = 0; i < 32/4; ++i)
{
id[i] = ((DWORD *)musiccache)[i];
}
} }
#ifndef _WIN32 #ifndef _WIN32
// non-windows platforms don't support MDEV_MIDI so map to MDEV_FMOD // non-Windows platforms don't support MDEV_MMAPI so map to MDEV_FMOD
if (device == MDEV_MMAPI) if (device == MDEV_MMAPI)
device = MDEV_FMOD; device = MDEV_FMOD;
#endif #endif
@ -346,7 +363,7 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
// that can handle it, so it simplifies things if we make all songs // that can handle it, so it simplifies things if we make all songs
// gzippable. // gzippable.
ungzipped = NULL; ungzipped = NULL;
if ((id & MAKE_ID(255,255,255,0)) == GZIP_ID) if ((id[0] & MAKE_ID(255,255,255,0)) == GZIP_ID)
{ {
if (offset != -1) if (offset != -1)
{ {
@ -370,11 +387,15 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
return NULL; return NULL;
} }
musiccache = ungzipped; musiccache = ungzipped;
id = *(DWORD *)ungzipped; for (i = 0; i < 32/4; ++i)
{
id[i] = ((DWORD *)musiccache)[i];
}
} }
// Check for MUS format // Check for MUS format
if (id == MAKE_ID('M','U','S',0x1a)) // Tolerate sloppy wads by searching up to 32 bytes for the header
if (MUSHeaderSearch(idstr, sizeof(idstr)) >= 0)
{ {
/* MUS are played as: /* MUS are played as:
- OPL: - OPL:
@ -453,7 +474,7 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
// Check for MIDI format // Check for MIDI format
else else
{ {
if (id == MAKE_ID('M','T','h','d')) if (id[0] == MAKE_ID('M','T','h','d'))
{ {
// This is a midi file // This is a midi file
@ -502,36 +523,15 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
#endif // _WIN32 #endif // _WIN32
} }
// Check for various raw OPL formats // Check for various raw OPL formats
else if (len >= 12 && else if (
(id == MAKE_ID('R','A','W','A') || // Rdos Raw OPL (id[0] == MAKE_ID('R','A','W','A') && id[1] == MAKE_ID('D','A','T','A')) || // Rdos Raw OPL
id == MAKE_ID('D','B','R','A') || // DosBox Raw OPL (id[0] == MAKE_ID('D','B','R','A') && id[1] == MAKE_ID('W','O','P','L')) || // DosBox Raw OPL
id == MAKE_ID('A','D','L','I'))) // Martin Fernandez's modified IMF (id[0] == MAKE_ID('A','D','L','I') && *((BYTE *)id + 4) == 'B')) // Martin Fernandez's modified IMF
{
DWORD fullsig[2];
if (file != NULL)
{
if (fread (fullsig, 4, 2, file) != 2)
{
fclose (file);
return 0;
}
fseek (file, -8, SEEK_CUR);
}
else
{
memcpy(fullsig, musiccache, 8);
}
if ((fullsig[0] == MAKE_ID('R','A','W','A') && fullsig[1] == MAKE_ID('D','A','T','A')) ||
(fullsig[0] == MAKE_ID('D','B','R','A') && fullsig[1] == MAKE_ID('W','O','P','L')) ||
(fullsig[0] == MAKE_ID('A','D','L','I') && (fullsig[1] & MAKE_ID(255,255,0,0)) == MAKE_ID('B',1,0,0)))
{ {
info = new OPLMUSSong (file, musiccache, len); info = new OPLMUSSong (file, musiccache, len);
} }
}
// Check for game music // Check for game music
else if ((fmt = GME_CheckFormat(id)) != NULL && fmt[0] != '\0') else if ((fmt = GME_CheckFormat(id[0])) != NULL && fmt[0] != '\0')
{ {
info = GME_OpenSong(file, musiccache, len, fmt); info = GME_OpenSong(file, musiccache, len, fmt);
} }
@ -545,7 +545,7 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
if (info == NULL) if (info == NULL)
{ {
// Check for CDDA "format" // Check for CDDA "format"
if (id == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24))) if (id[0] == (('R')|(('I')<<8)|(('F')<<16)|(('F')<<24)))
{ {
if (file != NULL) if (file != NULL)
{ {
@ -572,7 +572,7 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
// smaller than this can't possibly be a valid music file if it hasn't // smaller than this can't possibly be a valid music file if it hasn't
// been identified already, so don't even bother trying to load it. // been identified already, so don't even bother trying to load it.
// Of course MIDIs shorter than 1024 bytes should pass. // Of course MIDIs shorter than 1024 bytes should pass.
if (info == NULL && (len >= 1024 || id == MAKE_ID('M','T','h','d'))) if (info == NULL && (len >= 1024 || id[0] == MAKE_ID('M','T','h','d')))
{ {
// Let FMOD figure out what it is. // Let FMOD figure out what it is.
if (file != NULL) if (file != NULL)

View file

@ -51,6 +51,8 @@
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
int MUSHeaderSearch(const BYTE *head, int len);
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
@ -99,32 +101,55 @@ MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
} }
#endif #endif
MusHeader = (MUSHeader *)new BYTE[len]; BYTE front[32];
if (file != NULL) int start;
if (file == NULL)
{ {
if (fread(MusHeader, 1, len, file) != (size_t)len) memcpy(front, musiccache, len);
}
else if (fread(front, 1, 32, file) != 32)
{ {
return; return;
} }
// To tolerate sloppy wads (diescum.wad, I'm looking at you), we search
// the first 32 bytes of the file for a signature. My guess is that DMX
// does no validation whatsoever and just assumes it was passed a valid
// MUS file, since where the header is offset affects how it plays.
start = MUSHeaderSearch(front, sizeof(front));
if (start < 0)
{
return;
}
// Read the remainder of the song.
len = int(len - start);
if (len < sizeof(MusHeader))
{ // It's too short.
return;
}
MusHeader = (MUSHeader *)new BYTE[len];
if (file == NULL)
{
memcpy(MusHeader, musiccache + start, len);
} }
else else
{ {
memcpy(MusHeader, musiccache, len); memcpy(MusHeader, front + start, 32 - start);
} if (fread((BYTE *)MusHeader + 32 - start, 1, len - (32 - start), file) != (size_t)(len - (32 - start)))
// Do some validation of the MUS file
if (MusHeader->Magic != MAKE_ID('M','U','S','\x1a'))
{ {
return; return;
} }
}
// Do some validation of the MUS file.
if (LittleShort(MusHeader->NumChans) > 15) if (LittleShort(MusHeader->NumChans) > 15)
{ {
return; return;
} }
MusBuffer = (BYTE *)MusHeader + LittleShort(MusHeader->SongStart); MusBuffer = (BYTE *)MusHeader + LittleShort(MusHeader->SongStart);
MaxMusP = MIN<int> (LittleShort(MusHeader->SongLen), len - LittleShort(MusHeader->SongStart)); MaxMusP = MIN<int>(LittleShort(MusHeader->SongLen), len - LittleShort(MusHeader->SongStart));
Division = 140; Division = 140;
InitialTempo = 1000000; InitialTempo = 1000000;
} }
@ -376,3 +401,25 @@ MUSSong2::MUSSong2(const MUSSong2 *original, const char *filename, EMIDIDevice t
Division = 140; Division = 140;
InitialTempo = 1000000; InitialTempo = 1000000;
} }
//==========================================================================
//
// MUSHeaderSearch
//
// Searches for the MUS header within the given memory block, returning
// the offset it was found at, or -1 if not present.
//
//==========================================================================
int MUSHeaderSearch(const BYTE *head, int len)
{
len -= 4;
for (int i = 0; i <= len; ++i)
{
if (head[i+0] == 'M' && head[i+1] == 'U' && head[i+2] == 'S' && head[i+3] == 0x1A)
{
return i;
}
}
return -1;
}

View file

@ -318,7 +318,7 @@
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386" AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="gdi32.lib user32.lib comctl32.lib shell32.lib advapi32.lib comdlg32.lib ole32.lib dxguid.lib dsound.lib dinput8.lib strmiids.lib wsock32.lib winmm.lib fmodex_vc.lib setupapi.lib ws2_32.lib oleaut32.lib" AdditionalDependencies="gdi32.lib user32.lib comctl32.lib shell32.lib advapi32.lib comdlg32.lib ole32.lib dxguid.lib dsound.lib dinput8.lib strmiids.lib wsock32.lib winmm.lib setupapi.lib ws2_32.lib oleaut32.lib fmodex_vc.lib"
OutputFile="../zdoomd.exe" OutputFile="../zdoomd.exe"
LinkIncremental="2" LinkIncremental="2"
SuppressStartupBanner="true" SuppressStartupBanner="true"