Mercurial > audlegacy-plugins
diff src/modplug/load_psm.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 |
line wrap: on
line diff
--- a/src/modplug/load_psm.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_psm.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -79,27 +79,24 @@ //----------------------------------------------------------- { PSMCHUNK *pfh = (PSMCHUNK *)lpStream; - PSMCHUNK pfh_swap; DWORD dwMemPos, dwSongPos; DWORD smpnames[MAX_SAMPLES]; DWORD patptrs[MAX_PATTERNS]; BYTE samplemap[MAX_SAMPLES]; UINT nPatterns; - pfh_swap.id = bswapLE32(pfh->id); - pfh_swap.len = bswapLE32(pfh->len); - pfh_swap.listid = bswapLE32(pfh->listid); - // Chunk0: "PSM ",filesize,"FILE" if (dwMemLength < 256) return FALSE; - if (pfh_swap.id == PSM_ID_OLD) + if (bswapLE32(pfh->id) == PSM_ID_OLD) { #ifdef PSM_LOG - Log("Old PSM format not supported\n"); + printf("Old PSM format not supported\n"); #endif return FALSE; } - if ((pfh_swap.id != PSM_ID_NEW) || (pfh_swap.len+12 > dwMemLength) || (pfh_swap.listid != IFFID_FILE)) return FALSE; + if ((bswapLE32(pfh->id) != PSM_ID_NEW) + || (bswapLE32(pfh->len)+12 > dwMemLength) + || (bswapLE32(pfh->listid) != IFFID_FILE)) return FALSE; m_nType = MOD_TYPE_PSM; m_nChannels = 16; m_nSamples = 0; @@ -111,19 +108,16 @@ UINT pan = (((iChPan & 3) == 1) || ((iChPan&3)==2)) ? 0xC0 : 0x40; ChnSettings[iChPan].nPan = pan; } + m_szNames[0][0]=0; while (dwMemPos+8 < dwMemLength) { PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos); - - pchunk->id = bswapLE32(pchunk->id); - pchunk->len = bswapLE32(pchunk->len); - pchunk->listid = bswapLE32(pchunk->listid); - - if ((pchunk->len >= dwMemLength - 8) || (dwMemPos + pchunk->len + 8 > dwMemLength)) break; + if ((bswapLE32(pchunk->len) >= dwMemLength - 8) + || (dwMemPos + bswapLE32(pchunk->len) + 8 > dwMemLength)) break; dwMemPos += 8; PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = pchunk->len; - if (len) switch(pchunk->id) + ULONG len = bswapLE32(pchunk->len); + if (len) switch(bswapLE32(pchunk->id)) { // "TITL": Song title case IFFID_TITL: @@ -152,23 +146,16 @@ m_nSamples++; MODINSTRUMENT *pins = &Ins[m_nSamples]; PSMSAMPLE *psmp = (PSMSAMPLE *)pdata; - - psmp->smpid = bswapLE32(psmp->smpid); - psmp->length = bswapLE32(psmp->length); - psmp->loopstart = bswapLE32(psmp->loopstart); - psmp->loopend = bswapLE32(psmp->loopend); - psmp->samplerate = bswapLE32(psmp->samplerate); - - smpnames[m_nSamples] = psmp->smpid; + smpnames[m_nSamples] = bswapLE32(psmp->smpid); memcpy(m_szNames[m_nSamples], psmp->samplename, 31); m_szNames[m_nSamples][31] = 0; samplemap[m_nSamples-1] = (BYTE)m_nSamples; // Init sample pins->nGlobalVol = 0x40; - pins->nC4Speed = psmp->samplerate; - pins->nLength = psmp->length; - pins->nLoopStart = psmp->loopstart; - pins->nLoopEnd = psmp->loopend; + pins->nC4Speed = bswapLE32(psmp->samplerate); + pins->nLength = bswapLE32(psmp->length); + pins->nLoopStart = bswapLE32(psmp->loopstart); + pins->nLoopEnd = bswapLE32(psmp->loopend); pins->nPan = 128; pins->nVolume = (psmp->defvol+1) * 2; pins->uFlags = (psmp->flags & 0x80) ? CHN_LOOP : 0; @@ -197,7 +184,7 @@ } #endif } - dwMemPos += pchunk->len; + dwMemPos += bswapLE32(pchunk->len); } // Step #1: convert song structure PSMSONGHDR *pSong = (PSMSONGHDR *)(lpStream+dwSongPos+8); @@ -210,16 +197,12 @@ while (dwMemPos + 8 < dwSongEnd) { PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos); - - pchunk->id = bswapLE32(pchunk->id); - pchunk->len = bswapLE32(pchunk->len); - pchunk->listid = bswapLE32(pchunk->listid); - dwMemPos += 8; - if ((pchunk->len > dwSongEnd) || (dwMemPos + pchunk->len > dwSongEnd)) break; + if ((bswapLE32(pchunk->len) > dwSongEnd) + || (dwMemPos + bswapLE32(pchunk->len) > dwSongEnd)) break; PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = pchunk->len; - switch(pchunk->id) + ULONG len = bswapLE32(pchunk->len); + switch(bswapLE32(pchunk->id)) { case IFFID_OPLH: if (len >= 0x20) @@ -265,7 +248,7 @@ } break; } - dwMemPos += pchunk->len; + dwMemPos += bswapLE32(pchunk->len); } } @@ -273,85 +256,66 @@ for (UINT nPat=0; nPat<nPatterns; nPat++) { PSMPATTERN *pPsmPat = (PSMPATTERN *)(lpStream+patptrs[nPat]+8); - - pPsmPat->size = bswapLE32(pPsmPat->size); - pPsmPat->name = bswapLE32(pPsmPat->name); - pPsmPat->rows = bswapLE16(pPsmPat->rows); - - ULONG len = *(DWORD *)(lpStream+patptrs[nPat]+4) - 12; - UINT nRows = pPsmPat->rows; - if (len > pPsmPat->size) len = pPsmPat->size; + ULONG len = bswapLE32(*(DWORD *)(lpStream+patptrs[nPat]+4)) - 12; + UINT nRows = bswapLE16(pPsmPat->rows); + if (len > bswapLE32(pPsmPat->size)) len = bswapLE32(pPsmPat->size); if ((nRows < 64) || (nRows > 256)) nRows = 64; PatternSize[nPat] = nRows; + PatternAllocSize[nPat] = nRows; if ((Patterns[nPat] = AllocatePattern(nRows, m_nChannels)) == NULL) break; MODCOMMAND *m = Patterns[nPat]; + MODCOMMAND *sp, dummy; BYTE *p = pPsmPat->data; UINT pos = 0; UINT row = 0; - UINT oldch = 0; - BOOL bNewRow = FALSE; + UINT rowlim; #ifdef PSM_LOG - Log("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream)); + //printf("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream)); #endif + rowlim = bswapLE16(pPsmPat->reserved1)-2; while ((row < nRows) && (pos+1 < len)) { - UINT flags = p[pos++]; - UINT ch = p[pos++]; - - #ifdef PSM_LOG - //Log("flags+ch: %02X.%02X\n", flags, ch); - #endif - if (((flags & 0xf0) == 0x10) && (ch <= oldch) /*&& (!bNewRow)*/) - { - if ((pos+1<len) && (!(p[pos] & 0x0f)) && (p[pos+1] < m_nChannels)) - { - #ifdef PSM_LOG - //if (!nPat) Log("Continuing on new row\n"); - #endif - row++; - m += m_nChannels; - oldch = ch; - continue; - } + UINT flags, ch; + if ((pos+1) >= rowlim) { + pos = rowlim; + rowlim = (((int)p[pos+1])<<8) + | ((int)p[pos+0]); + m += m_nChannels; + row++; + rowlim += pos; + pos += 2; } - if ((pos >= len) || (row >= nRows)) break; - if (!(flags & 0xf0)) - { + flags = p[pos++]; + ch = p[pos++]; + if (ch >= m_nChannels) { #ifdef PSM_LOG - //if (!nPat) Log("EOR(%d): %02X.%02X\n", row, p[pos], p[pos+1]); + printf("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch); #endif - row++; - m += m_nChannels; - bNewRow = TRUE; - oldch = ch; - continue; - } - bNewRow = FALSE; - if (ch >= m_nChannels) - { - #ifdef PSM_LOG - if (!nPat) Log("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch); - #endif - ch = 0; + sp = &dummy; + } else { + sp = &m[ch]; } // Note + Instr + if ((flags & 0x80) && (pos+1 < len)) + { + UINT note = p[pos++]; + note = (note>>4)*12+(note&0x0f)+12+1; + if (note > 0x80) note = 0; + sp->note = note; + } if ((flags & 0x40) && (pos+1 < len)) { - UINT note = p[pos++]; UINT nins = p[pos++]; #ifdef PSM_LOG - //if (!nPat) Log("note+ins: %02X.%02X\n", note, nins); - if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins); + if ((!nPat) && (nins >= m_nSamples)) printf("WARNING: invalid instrument number (%d)\n", nins); #endif - if ((note) && (note < 0x80)) note = (note>>4)*12+(note&0x0f)+12+1; - m[ch].instr = samplemap[nins]; - m[ch].note = note; + sp->instr = samplemap[nins]; } // Volume if ((flags & 0x20) && (pos < len)) { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = p[pos++] / 2; + sp->volcmd = VOLCMD_VOLUME; + sp->vol = p[pos++] / 2; } // Effect if ((flags & 0x10) && (pos+1 < len)) @@ -359,40 +323,94 @@ UINT command = p[pos++]; UINT param = p[pos++]; // Convert effects - switch(command) + switch(command & 0x3F) { // 01: fine volslide up - case 0x01: command = CMD_VOLUMESLIDE; param |= 0x0f; break; - // 04: fine volslide down - case 0x04: command = CMD_VOLUMESLIDE; param>>=4; param |= 0xf0; break; + case 0x01: +#if PSM_LOG + printf("fvup command pat=%d row=%d ch=%d %02x %02x\n", + nPat, + row,1+ch, + command, param); +#endif +#if 0 + if (!sp->volcmd) { + sp->volcmd = VOLCMD_FINEVOLUP; + sp->vol = (param >> 1) & 0xF; + command = CMD_PORTAMENTOUP; + param>>=4; param |= 0xf0; + if (param == 240) param=241; + } else { +#endif + command = CMD_VOLUMESLIDE; + param |= 0x0f; + if (param == 15) param=31; + break; + // 02: volslide up + case 0x02: command = CMD_VOLUMESLIDE; param>>=1; param<<=4; break; + // 03: fine volslide down + case 0x03: +#if PSM_LOG + printf("fvdown command pat=%d row=%d ch=%d %02x %02x\n", + nPat, + row,1+ch, + command, param); +#endif +#if 0 + if (!sp->volcmd) { + sp->volcmd = VOLCMD_FINEVOLDOWN; + sp->vol = (param >> 2) & 0xF; + if (!sp->vol) sp->vol = 1; + command = CMD_PORTAMENTODOWN; + } +#endif + command = CMD_VOLUMESLIDE; + param>>=4; param |= 0xf0; + if (param == 240) param=241; + break; + // 04: volslide down + case 0x04: command = CMD_VOLUMESLIDE; param>>=1; break; // 0C: portamento up case 0x0C: command = CMD_PORTAMENTOUP; param = (param+1)/2; break; // 0E: portamento down case 0x0E: command = CMD_PORTAMENTODOWN; param = (param+1)/2; break; + // 0F: tone portamento + case 0x0F: command = CMD_TONEPORTAMENTO; param = param/4; break; + // 15: vibrato + case 0x15: command = CMD_VIBRATO; break; + // 29: wtf + case 0x29: pos += 2; break; + // 2A: retrig + case 0x2A: command = CMD_RETRIG; break; // 33: Position Jump case 0x33: command = CMD_POSITIONJUMP; break; // 34: Pattern break case 0x34: command = CMD_PATTERNBREAK; break; // 3D: speed - case 0x3D: command = CMD_SPEED; break; + case 0x3D: command = CMD_SPEED; + if (!row && !nPat) + m_nDefaultSpeed = param; + break; // 3E: tempo - case 0x3E: command = CMD_TEMPO; break; + case 0x3E: command = CMD_TEMPO; + if (!row && !nPat) + m_nDefaultTempo = param; + break; // Unknown default: #ifdef PSM_LOG - Log("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param); + printf("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param); #endif command = param = 0; } - m[ch].command = (BYTE)command; - m[ch].param = (BYTE)param; + sp->command = (BYTE)command; + sp->param = (BYTE)param; } - oldch = ch; } #ifdef PSM_LOG if (pos < len) { - Log("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos); +// printf("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos); } #endif }