mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-07 00:11:21 +00:00
- 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:
parent
d875a0c674
commit
114412d5a2
4 changed files with 103 additions and 56 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,30 +101,53 @@ 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;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in a new issue