mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 20:21:26 +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->setPaused(false);
|
||||
chan->getPriority(&def_priority);
|
||||
FISoundChannel *schan = CommonChannelSetup(chan, reuse_chan);
|
||||
schan->Rolloff = *rolloff;
|
||||
chan->setPaused(false);
|
||||
return schan;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
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)))
|
||||
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
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -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, musiccache, len);
|
||||
}
|
||||
|
||||
// Do some validation of the MUS file
|
||||
if (MusHeader->Magic != MAKE_ID('M','U','S','\x1a'))
|
||||
memcpy(MusHeader, front + start, 32 - start);
|
||||
if (fread((BYTE *)MusHeader + 32 - start, 1, len - (32 - start), file) != (size_t)(len - (32 - start)))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue