Mercurial > audlegacy-plugins
diff src/modplug/load_s3m.cxx @ 2337:107c1fed3d92
Port Schism modplug core.
author | "Tony Vroon <chainsaw@gentoo.org>" |
---|---|
date | Thu, 24 Jan 2008 12:05:59 +0000 |
parents | 6907fc39b53f |
children | 0b0609eff29b |
line wrap: on
line diff
--- a/src/modplug/load_s3m.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_s3m.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -289,14 +289,14 @@ { UINT j = bswapLE32(*((LPDWORD)(s+0x10))); if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH; - if (j < 4) j = 0; + if (j < 2) j = 0; Ins[iSmp].nLength = j; j = bswapLE32(*((LPDWORD)(s+0x14))); if (j >= Ins[iSmp].nLength) j = Ins[iSmp].nLength - 1; Ins[iSmp].nLoopStart = j; j = bswapLE32(*((LPDWORD)(s+0x18))); if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH; - if (j < 4) j = 0; + if (j < 2) j = 0; if (j > Ins[iSmp].nLength) j = Ins[iSmp].nLength; Ins[iSmp].nLoopEnd = j; j = s[0x1C]; @@ -319,11 +319,15 @@ // Reading patterns for (UINT iPat=0; iPat<patnum; iPat++) { - UINT nInd = ((DWORD)ptr[nins+iPat]) << 4; - if (nInd + 0x40 > dwMemLength) continue; + UINT nInd = ((DWORD)ptr[nins+iPat]) << 4; + // if the parapointer is zero, the pattern is blank (so ignore it) + if (nInd == 0) + continue; + if (nInd + 0x40 > dwMemLength) continue; WORD len = bswapLE16(*((WORD *)(lpStream+nInd))); nInd += 2; PatternSize[iPat] = 64; + PatternAllocSize[iPat] = 64; if ((!len) || (nInd + len > dwMemLength - 6) || ((Patterns[iPat] = AllocatePattern(64, m_nChannels)) == NULL)) continue; LPBYTE src = (LPBYTE)(lpStream+nInd); @@ -383,8 +387,11 @@ // Reading samples for (UINT iRaw=1; iRaw<=insnum; iRaw++) if ((Ins[iRaw].nLength) && (insfile[iRaw])) { - UINT flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U; - if (insflags[iRaw-1] & 4) flags += 5; + UINT flags; + if (insflags[iRaw-1] & 4) + flags = (psfh.version == 1) ? RS_PCM16S : RS_PCM16U; + else + flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U; if (insflags[iRaw-1] & 2) flags |= RSF_STEREO; if (inspack[iRaw-1] == 4) flags = RS_ADPCM4; dwMemPos = insfile[iRaw]; @@ -397,254 +404,3 @@ } -#ifndef MODPLUG_NO_FILESAVE -#pragma warning(disable:4100) - -static BYTE S3MFiller[16] = -{ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 -}; - - -BOOL CSoundFile::SaveS3M(LPCSTR lpszFileName, UINT nPacking) -//---------------------------------------------------------- -{ - FILE *f; - BYTE header[0x60]; - UINT nbo,nbi,nbp,i; - WORD patptr[128]; - WORD insptr[128]; - BYTE buffer[5*1024]; - S3MSAMPLESTRUCT insex[128]; - - if ((!m_nChannels) || (!lpszFileName)) return FALSE; - if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; - // Writing S3M header - memset(header, 0, sizeof(header)); - memset(insex, 0, sizeof(insex)); - memcpy(header, m_szNames[0], 0x1C); - header[0x1B] = 0; - header[0x1C] = 0x1A; - header[0x1D] = 0x10; - nbo = (GetNumPatterns() + 15) & 0xF0; - if (!nbo) nbo = 16; - header[0x20] = nbo & 0xFF; - header[0x21] = nbo >> 8; - nbi = m_nInstruments; - if (!nbi) nbi = m_nSamples; - if (nbi > 99) nbi = 99; - header[0x22] = nbi & 0xFF; - header[0x23] = nbi >> 8; - nbp = 0; - for (i=0; Patterns[i]; i++) { nbp = i+1; if (nbp >= MAX_PATTERNS) break; } - for (i=0; i<MAX_ORDERS; i++) if ((Order[i] < MAX_PATTERNS) && (Order[i] >= nbp)) nbp = Order[i] + 1; - header[0x24] = nbp & 0xFF; - header[0x25] = nbp >> 8; - if (m_dwSongFlags & SONG_FASTVOLSLIDES) header[0x26] |= 0x40; - if ((m_nMaxPeriod < 20000) || (m_dwSongFlags & SONG_AMIGALIMITS)) header[0x26] |= 0x10; - header[0x28] = 0x20; - header[0x29] = 0x13; - header[0x2A] = 0x02; // Version = 1 => Signed samples - header[0x2B] = 0x00; - header[0x2C] = 'S'; - header[0x2D] = 'C'; - header[0x2E] = 'R'; - header[0x2F] = 'M'; - header[0x30] = m_nDefaultGlobalVolume >> 2; - header[0x31] = m_nDefaultSpeed; - header[0x32] = m_nDefaultTempo; - header[0x33] = ((m_nSongPreAmp < 0x20) ? 0x20 : m_nSongPreAmp) | 0x80; // Stereo - header[0x35] = 0xFC; - for (i=0; i<32; i++) - { - if (i < m_nChannels) - { - UINT tmp = (i & 0x0F) >> 1; - header[0x40+i] = (i & 0x10) | ((i & 1) ? 8+tmp : tmp); - } else header[0x40+i] = 0xFF; - } - fwrite(header, 0x60, 1, f); - fwrite(Order, nbo, 1, f); - memset(patptr, 0, sizeof(patptr)); - memset(insptr, 0, sizeof(insptr)); - UINT ofs0 = 0x60 + nbo; - UINT ofs1 = ((0x60 + nbo + nbi*2 + nbp*2 + 15) & 0xFFF0) + 0x20; - UINT ofs = ofs1; - - for (i=0; i<nbi; i++) insptr[i] = (WORD)((ofs + i*0x50) / 16); - for (i=0; i<nbp; i++) patptr[i] = (WORD)((ofs + nbi*0x50) / 16); - fwrite(insptr, nbi, 2, f); - fwrite(patptr, nbp, 2, f); - if (header[0x35] == 0xFC) - { - BYTE chnpan[32]; - for (i=0; i<32; i++) - { - chnpan[i] = 0x20 | (ChnSettings[i].nPan >> 4); - } - fwrite(chnpan, 0x20, 1, f); - } - if ((nbi*2+nbp*2) & 0x0F) - { - fwrite(S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F), 1, f); - } - ofs1 = ftell(f); - fwrite(insex, nbi, 0x50, f); - // Packing patterns - ofs += nbi*0x50; - for (i=0; i<nbp; i++) - { - WORD len = 64; - memset(buffer, 0, sizeof(buffer)); - patptr[i] = ofs / 16; - if (Patterns[i]) - { - len = 2; - MODCOMMAND *p = Patterns[i]; - for (int row=0; row<64; row++) if (row < PatternSize[i]) - { - for (UINT j=0; j<m_nChannels; j++) - { - UINT b = j; - MODCOMMAND *m = &p[row*m_nChannels+j]; - UINT note = m->note; - UINT volcmd = m->volcmd; - UINT vol = m->vol; - UINT command = m->command; - UINT param = m->param; - - if ((note) || (m->instr)) b |= 0x20; - if (!note) note = 0xFF; else - if (note >= 0xFE) note = 0xFE; else - if (note < 13) note = 0; else note -= 13; - if (note < 0xFE) note = (note % 12) + ((note / 12) << 4); - if (command == CMD_VOLUME) - { - command = 0; - if (param > 64) param = 64; - volcmd = VOLCMD_VOLUME; - vol = param; - } - if (volcmd == VOLCMD_VOLUME) b |= 0x40; else - if (volcmd == VOLCMD_PANNING) { vol |= 0x80; b |= 0x40; } - if (command) - { - S3MSaveConvert(&command, ¶m, FALSE); - if (command) b |= 0x80; - } - if (b & 0xE0) - { - buffer[len++] = b; - if (b & 0x20) - { - buffer[len++] = note; - buffer[len++] = m->instr; - } - if (b & 0x40) - { - buffer[len++] = vol; - } - if (b & 0x80) - { - buffer[len++] = command; - buffer[len++] = param; - } - if (len > sizeof(buffer) - 20) break; - } - } - buffer[len++] = 0; - if (len > sizeof(buffer) - 20) break; - } - } - buffer[0] = (len - 2) & 0xFF; - buffer[1] = (len - 2) >> 8; - len = (len+15) & (~0x0F); - fwrite(buffer, len, 1, f); - ofs += len; - } - // Writing samples - for (i=1; i<=nbi; i++) - { - MODINSTRUMENT *pins = &Ins[i]; - if (m_nInstruments) - { - pins = Ins; - if (Headers[i]) - { - for (UINT j=0; j<128; j++) - { - UINT n = Headers[i]->Keyboard[j]; - if ((n) && (n < MAX_INSTRUMENTS)) - { - pins = &Ins[n]; - break; - } - } - } - } - memcpy(insex[i-1].dosname, pins->name, 12); - memcpy(insex[i-1].name, m_szNames[i], 28); - memcpy(insex[i-1].scrs, "SCRS", 4); - insex[i-1].hmem = (BYTE)((DWORD)ofs >> 20); - insex[i-1].memseg = (WORD)((DWORD)ofs >> 4); - if (pins->pSample) - { - insex[i-1].type = 1; - insex[i-1].length = pins->nLength; - insex[i-1].loopbegin = pins->nLoopStart; - insex[i-1].loopend = pins->nLoopEnd; - insex[i-1].vol = pins->nVolume / 4; - insex[i-1].flags = (pins->uFlags & CHN_LOOP) ? 1 : 0; - if (pins->nC4Speed) - insex[i-1].finetune = pins->nC4Speed; - else - insex[i-1].finetune = TransposeToFrequency(pins->RelativeTone, pins->nFineTune); - UINT flags = RS_PCM8U; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking))) - { - insex[i-1].pack = 4; - flags = RS_ADPCM4; - } - } else -#endif // NO_PACKING - { - if (pins->uFlags & CHN_16BIT) - { - insex[i-1].flags |= 4; - flags = RS_PCM16U; - } - if (pins->uFlags & CHN_STEREO) - { - insex[i-1].flags |= 2; - flags = (pins->uFlags & CHN_16BIT) ? RS_STPCM16U : RS_STPCM8U; - } - } - DWORD len = WriteSample(f, pins, flags); - if (len & 0x0F) - { - fwrite(S3MFiller, 0x10 - (len & 0x0F), 1, f); - } - ofs += (len + 15) & (~0x0F); - } else - { - insex[i-1].length = 0; - } - } - // Updating parapointers - fseek(f, ofs0, SEEK_SET); - fwrite(insptr, nbi, 2, f); - fwrite(patptr, nbp, 2, f); - fseek(f, ofs1, SEEK_SET); - fwrite(insex, 0x50, nbi, f); - fclose(f); - return TRUE; -} - -#pragma warning(default:4100) -#endif // MODPLUG_NO_FILESAVE -