- 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->setPaused(false);
chan->getPriority(&def_priority);
FISoundChannel *schan = CommonChannelSetup(chan, reuse_chan);
schan->Rolloff = *rolloff;
chan->setPaused(false);
return schan;
}

View file

@ -84,6 +84,8 @@ extern void ChildSigHandler (int signum);
#define GZIP_FNAME 8
#define GZIP_FCOMMENT 16
extern int MUSHeaderSearch(const BYTE *head, int len);
EXTERN_CVAR (Int, snd_samplerate)
EXTERN_CVAR (Int, snd_mididevice)
@ -295,9 +297,14 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
{
FILE *file;
MusInfo *info = NULL;
DWORD id;
union
{
DWORD id[32/4];
BYTE idstr[32];
};
const char *fmt;
BYTE *ungzipped;
int i;
if (nomusic)
{
@ -322,22 +329,32 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
{
fseek (file, offset, SEEK_SET);
}
if (fread (&id, 4, 1, file) != 1)
if (len < 32)
{
return 0;
}
if (fread (id, 4, 32/4, file) != 32/4)
{
fclose (file);
return 0;
}
fseek (file, -4, SEEK_CUR);
fseek (file, -32, SEEK_CUR);
}
else
{
file = NULL;
id = *(DWORD *)musiccache;
if (len < 32)
{
return 0;
}
for (i = 0; i < 32/4; ++i)
{
id[i] = ((DWORD *)musiccache)[i];
}
}
#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)
device = MDEV_FMOD;
#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
// gzippable.
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)
{
@ -370,11 +387,15 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
return NULL;
}
musiccache = ungzipped;
id = *(DWORD *)ungzipped;
for (i = 0; i < 32/4; ++i)
{
id[i] = ((DWORD *)musiccache)[i];
}
}
// 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:
- OPL:
@ -453,7 +474,7 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
// Check for MIDI format
else
{
if (id == MAKE_ID('M','T','h','d'))
if (id[0] == MAKE_ID('M','T','h','d'))
{
// This is a midi file
@ -502,36 +523,15 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
#endif // _WIN32
}
// Check for various raw OPL formats
else if (len >= 12 &&
(id == MAKE_ID('R','A','W','A') || // Rdos Raw OPL
id == MAKE_ID('D','B','R','A') || // DosBox Raw OPL
id == MAKE_ID('A','D','L','I'))) // Martin Fernandez's modified IMF
else if (
(id[0] == MAKE_ID('R','A','W','A') && id[1] == MAKE_ID('D','A','T','A')) || // Rdos Raw OPL
(id[0] == MAKE_ID('D','B','R','A') && id[1] == MAKE_ID('W','O','P','L')) || // DosBox Raw OPL
(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
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);
}
@ -545,7 +545,7 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
if (info == NULL)
{
// 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)
{
@ -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
// been identified already, so don't even bother trying to load it.
// 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.
if (file != NULL)

View file

@ -51,6 +51,8 @@
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
int MUSHeaderSearch(const BYTE *head, int len);
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
@ -99,32 +101,55 @@ MUSSong2::MUSSong2 (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
}
#endif
MusHeader = (MUSHeader *)new BYTE[len];
if (file != NULL)
BYTE front[32];
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;
}
// 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
{
memcpy(MusHeader, front + start, 32 - start);
if (fread((BYTE *)MusHeader + 32 - start, 1, len - (32 - start), file) != (size_t)(len - (32 - start)))
{
return;
}
}
else
{
memcpy(MusHeader, musiccache, len);
}
// Do some validation of the MUS file
if (MusHeader->Magic != MAKE_ID('M','U','S','\x1a'))
{
return;
}
// Do some validation of the MUS file.
if (LittleShort(MusHeader->NumChans) > 15)
{
return;
}
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;
InitialTempo = 1000000;
}
@ -376,3 +401,25 @@ MUSSong2::MUSSong2(const MUSSong2 *original, const char *filename, EMIDIDevice t
Division = 140;
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
Name="VCLinkerTool"
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"
LinkIncremental="2"
SuppressStartupBanner="true"