dependencies/SDL_sound/libmodplug/load_mdl.c in gosu-1.3.0 vs dependencies/SDL_sound/libmodplug/load_mdl.c in gosu-1.4.0

- old
+ new

@@ -37,11 +37,11 @@ CHAR name[16]; WORD data[1]; } MDLPATTERNDATA; -void ConvertMDLCommand(MODCOMMAND *m, UINT eff, UINT data) +static void ConvertMDLCommand(MODCOMMAND *m, UINT eff, UINT data) //-------------------------------------------------------- { UINT command = 0, param = data; switch(eff) { @@ -86,23 +86,16 @@ m->param = param; } } -void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTrack, const BYTE *lpTracks) +static void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTrack, const BYTE *lpTracks, UINT len) //------------------------------------------------------------------------------------------------- { MODCOMMAND cmd, *m = pat; - UINT len = *((WORD *)lpTracks); UINT pos = 0, row = 0, i; - lpTracks += 2; - for (UINT ntrk=1; ntrk<nTrack; ntrk++) - { - lpTracks += len; - len = *((WORD *)lpTracks); - lpTracks += 2; - } + cmd.note = cmd.instr = 0; cmd.volcmd = cmd.vol = 0; cmd.command = cmd.param = 0; while ((row < nRows) && (pos < len)) { @@ -170,18 +163,16 @@ } } } - BOOL CSoundFile_ReadMDL(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLength) //--------------------------------------------------------------- { DWORD dwMemPos, dwPos, blocklen, dwTrackPos; const MDLSONGHEADER *pmsh = (const MDLSONGHEADER *)lpStream; const MDLINFOBLOCK *pmib; - const MDLPATTERNDATA *pmpd; UINT i,j, norders = 0, npatterns = 0, ntracks = 0; UINT ninstruments = 0, nsamples = 0; WORD block; WORD patterntracks[MAX_PATTERNS*32]; BYTE smpinfo[MAX_SAMPLES]; @@ -190,10 +181,11 @@ LPCBYTE pvolenv, ppanenv, ppitchenv; UINT nvolenv, npanenv, npitchenv; if ((!lpStream) || (dwMemLength < 1024)) return FALSE; if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE; + const UINT hdrLen = (pmsh->version>0)? 59 : 57; SDL_memset(patterntracks, 0, sizeof(patterntracks)); SDL_memset(smpinfo, 0, sizeof(smpinfo)); SDL_memset(insvolenv, 0, sizeof(insvolenv)); SDL_memset(inspanenv, 0, sizeof(inspanenv)); dwMemPos = 5; @@ -201,25 +193,27 @@ pvolenv = ppanenv = ppitchenv = NULL; nvolenv = npanenv = npitchenv = 0; _this->m_nSamples = _this->m_nInstruments = 0; while (dwMemPos+6 < dwMemLength) { - block = *((WORD *)(lpStream+dwMemPos)); - blocklen = *((DWORD *)(lpStream+dwMemPos+2)); + const BYTE *pp = lpStream + dwMemPos; + block = pp[0] | (pp[1] << 8); + blocklen = pp[2] | (pp[3] << 8) | (pp[4] << 16) | (pp[5] << 24); dwMemPos += 6; - if (dwMemPos + blocklen > dwMemLength) + if (blocklen > dwMemLength - dwMemPos) { if (dwMemPos == 11) return FALSE; break; } switch(block) { // IN: infoblock case 0x4E49: - pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos); + pmib = (const MDLINFOBLOCK *)(lpStream+dwMemPos); norders = pmib->norders; if (norders > MAX_ORDERS) norders = MAX_ORDERS; + if (blocklen < sizeof(MDLINFOBLOCK) + norders - sizeof(pmib->seq)) return FALSE; _this->m_nRestartPos = pmib->repeatpos; _this->m_nDefaultGlobalVolume = pmib->globalvol; _this->m_nDefaultTempo = pmib->tempo; _this->m_nDefaultSpeed = pmib->speed; _this->m_nChannels = 4; @@ -242,45 +236,57 @@ npatterns = lpStream[dwMemPos]; if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS; dwPos = dwMemPos + 1; for (i=0; i<npatterns; i++) { - if (dwPos+18 >= dwMemLength) break; - pmpd = (MDLPATTERNDATA *)(lpStream + dwPos); - if (pmpd->channels > 32) break; - _this->PatternSize[i] = pmpd->lastrow+1; - if (_this->m_nChannels < pmpd->channels) _this->m_nChannels = pmpd->channels; - dwPos += 18 + 2*pmpd->channels; - for (j=0; j<pmpd->channels; j++) + const BYTE *data; + UINT ch; + if (pmsh->version == 0) { + if (_this->m_nChannels < 32) _this->m_nChannels = 32; + ch = 32; + } else { + if (dwPos+18 >= dwMemLength) break; + const MDLPATTERNDATA *pmpd = (const MDLPATTERNDATA *)(lpStream + dwPos); + if (pmpd->channels > 32) break; + _this->PatternSize[i] = pmpd->lastrow+1; + if (_this->m_nChannels < pmpd->channels) _this->m_nChannels = pmpd->channels; + ch = pmpd->channels; + } + + if (2 * ch >= dwMemLength - dwPos) break; + data = lpStream + dwPos; + dwPos += 2 * ch; + for (j=0; j<ch && j<_this->m_nChannels; j++, data+=2) { - patterntracks[i*32+j] = pmpd->data[j]; + patterntracks[i*32+j] = data[0] | (data[1] << 8); } } break; // TR: Track Data case 0x5254: if (dwTrackPos) break; - ntracks = *((WORD *)(lpStream+dwMemPos)); + pp = lpStream + dwMemPos; + ntracks = pp[0] | (pp[1] << 8); dwTrackPos = dwMemPos+2; break; // II: Instruments case 0x4949: ninstruments = lpStream[dwMemPos]; dwPos = dwMemPos+1; - for (i=0; i<ninstruments; i++) + for (i=0; dwPos+34<dwMemLength && i<ninstruments; i++) { UINT nins = lpStream[dwPos]; if ((nins >= MAX_INSTRUMENTS) || (!nins)) break; if (_this->m_nInstruments < nins) _this->m_nInstruments = nins; if (!_this->Headers[nins]) { UINT note = 12; - if ((_this->Headers[nins] = (INSTRUMENTHEADER *) SDL_malloc(sizeof (INSTRUMENTHEADER))) == NULL) break; + if ((_this->Headers[nins] = (INSTRUMENTHEADER *) SDL_calloc(1, sizeof (INSTRUMENTHEADER))) == NULL) break; INSTRUMENTHEADER *penv = _this->Headers[nins]; - SDL_memset(penv, 0, sizeof(INSTRUMENTHEADER)); penv->nGlobalVol = 64; penv->nPPC = 5*12; + if (34 + 14u*lpStream[dwPos+1] > dwMemLength - dwPos) break; for (j=0; j<lpStream[dwPos+1]; j++) { const BYTE *ps = lpStream+dwPos+34+14*j; while ((note < (UINT)(ps[1]+12)) && (note < NOTE_MAX)) { @@ -316,74 +322,81 @@ } dwPos += 34 + 14*lpStream[dwPos+1]; } for (j=1; j<=_this->m_nInstruments; j++) if (!_this->Headers[j]) { - _this->Headers[j] = (INSTRUMENTHEADER *) SDL_malloc(sizeof (INSTRUMENTHEADER)); - if (_this->Headers[j]) SDL_memset(_this->Headers[j], 0, sizeof(INSTRUMENTHEADER)); + _this->Headers[j] = (INSTRUMENTHEADER *) SDL_calloc(1, sizeof (INSTRUMENTHEADER)); } break; // VE: Volume Envelope case 0x4556: - if ((nvolenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + nvolenv*32 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1; + if (nvolenv || (nvolenv = lpStream[dwMemPos]) == 0) break; + if (dwMemPos + nvolenv*33 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1; break; // PE: Panning Envelope case 0x4550: - if ((npanenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + npanenv*32 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1; + if (npanenv || (npanenv = lpStream[dwMemPos]) == 0) break; + if (dwMemPos + npanenv*33 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1; break; // FE: Pitch Envelope case 0x4546: - if ((npitchenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + npitchenv*32 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1; + if (npitchenv || (npitchenv = lpStream[dwMemPos]) == 0) break; + if (dwMemPos + npitchenv*33 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1; break; // IS: Sample Infoblock case 0x5349: nsamples = lpStream[dwMemPos]; + i = blocklen / hdrLen; + if (i< nsamples) nsamples = i; dwPos = dwMemPos+1; - for (i=0; i<nsamples; i++, dwPos += 59) + for (i=0; i<nsamples; i++, dwPos += hdrLen) { UINT nins = lpStream[dwPos]; if ((nins >= MAX_SAMPLES) || (!nins)) continue; if (_this->m_nSamples < nins) _this->m_nSamples = nins; MODINSTRUMENT *pins = &_this->Ins[nins]; - pins->nC4Speed = *((DWORD *)(lpStream+dwPos+41)); - pins->nLength = *((DWORD *)(lpStream+dwPos+45)); - pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49)); - pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53)); + pp = lpStream + dwPos + 41; + pins->nC4Speed = pp[0] | (pp[1] << 8); pp += 2; + if (pmsh->version > 0) { + pins->nC4Speed |= (pp[0] << 16) | (pp[1] << 24); pp += 2; + } + pins->nLength = pp[0] | (pp[1] << 8) | (pp[2] << 16) | (pp[3] << 24); pp += 4; + pins->nLoopStart = pp[0] | (pp[1] << 8) | (pp[2] << 16) | (pp[3] << 24); pp += 4; + pins->nLoopEnd = pins->nLoopStart + (pp[0] | (pp[1] << 8) | (pp[2] << 16) | (pp[3] << 24)); if (pins->nLoopEnd > pins->nLoopStart) pins->uFlags |= CHN_LOOP; pins->nGlobalVol = 64; - if (lpStream[dwPos+58] & 0x01) + if (pmsh->version == 0) pins->nVolume = pp[4]; + if (lpStream[dwPos+hdrLen-1] & 0x01) { pins->uFlags |= CHN_16BIT; pins->nLength >>= 1; pins->nLoopStart >>= 1; pins->nLoopEnd >>= 1; } - if (lpStream[dwPos+58] & 0x02) pins->uFlags |= CHN_PINGPONGLOOP; - smpinfo[nins] = (lpStream[dwPos+58] >> 2) & 3; + if (lpStream[dwPos+hdrLen-1] & 0x02) pins->uFlags |= CHN_PINGPONGLOOP; + smpinfo[nins] = (lpStream[dwPos+hdrLen-1] >> 2) & 3; } break; // SA: Sample Data case 0x4153: dwPos = dwMemPos; for (i=1; i<=_this->m_nSamples; i++) if ((_this->Ins[i].nLength) && (!_this->Ins[i].pSample) && (smpinfo[i] != 3) && (dwPos < dwMemLength)) { MODINSTRUMENT *pins = &_this->Ins[i]; UINT flags = (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; + pp = lpStream + dwPos; if (!smpinfo[i]) { - dwPos += CSoundFile_ReadSample(_this, pins, flags, (LPSTR)(lpStream+dwPos), dwMemLength - dwPos); + dwPos += CSoundFile_ReadSample(_this, pins, flags, (LPCSTR)pp, dwMemLength - dwPos); } else { - DWORD dwLen = *((DWORD *)(lpStream+dwPos)); + DWORD dwLen = pp[0] | (pp[1] << 8) | (pp[2] << 16) | (pp[3] << 24); pp += 4; dwPos += 4; - if ((dwLen < dwMemLength) && (dwLen <= dwMemLength - dwPos) && (dwLen > 4)) + if ((dwLen <= dwMemLength) && (dwPos <= dwMemLength - dwLen) && (dwLen > 4)) { flags = (pins->uFlags & CHN_16BIT) ? RS_MDL16 : RS_MDL8; - CSoundFile_ReadSample(_this, pins, flags, (LPSTR)(lpStream+dwPos), dwLen); + CSoundFile_ReadSample(_this, pins, flags, (LPCSTR)pp, dwLen); } dwPos += dwLen; } } break; @@ -396,12 +409,28 @@ for (UINT ipat=0; ipat<npatterns; ipat++) { if ((_this->Patterns[ipat] = CSoundFile_AllocatePattern(_this->PatternSize[ipat], _this->m_nChannels)) == NULL) break; for (UINT chn=0; chn<_this->m_nChannels; chn++) if ((patterntracks[ipat*32+chn]) && (patterntracks[ipat*32+chn] <= ntracks)) { + const BYTE *lpTracks = lpStream + dwTrackPos; + UINT len = lpTracks[0] | (lpTracks[1] << 8); + if (len < dwMemLength-dwTrackPos) { MODCOMMAND *m = _this->Patterns[ipat] + chn; - UnpackMDLTrack(m, _this->m_nChannels, _this->PatternSize[ipat], patterntracks[ipat*32+chn], lpStream+dwTrackPos); + UINT nTrack = patterntracks[ipat*32+chn]; + + lpTracks += 2; + for (UINT ntrk=1; ntrk<nTrack && lpTracks + 1 < (dwMemLength + lpStream - len); ntrk++) + { + lpTracks += len; + len = lpTracks[0] | (lpTracks[1] << 8); + lpTracks += 2; + } + + if ( len > dwMemLength - (lpTracks - lpStream) ) len = 0; + + UnpackMDLTrack(m, _this->m_nChannels, _this->PatternSize[ipat], nTrack, lpTracks, len); + } } } } // Set up envelopes for (UINT iIns=1; iIns<=_this->m_nInstruments; iIns++) if (_this->Headers[iIns]) @@ -470,19 +499,17 @@ // MDL Huffman ReadBits compression WORD MDLReadBits(DWORD *bitbuf, UINT *bitnum, LPBYTE *_ibuf, CHAR n) //----------------------------------------------------------------- { - LPBYTE ibuf = *_ibuf; + LPBYTE ibuf = *_ibuf; const WORD v = (WORD)(*bitbuf & ((1 << n) - 1) ); *bitbuf >>= n; *bitnum -= n; if (*bitnum <= 24) { *bitbuf |= (((DWORD)(*ibuf++)) << *bitnum); *bitnum += 8; } - *_ibuf = ibuf; + *_ibuf = ibuf; return v; } - -