From: <sag...@us...> - 2009-08-22 22:48:10
|
Revision: 338 http://modplug.svn.sourceforge.net/modplug/?rev=338&view=rev Author: saga-games Date: 2009-08-22 22:47:59 +0000 (Sat, 22 Aug 2009) Log Message: ----------- [Fix] Macro config: "Show All" FX display starts at 1 instead of 0, like all other FX enumerations [Imp] PSM Loader: Several improvements; Near-perfect effect conversion. [Imp] XM Loader: Detecting MPT-Made XM files more reliably [Imp] Playback: If restart position is 0 and a subtune is played (i.e. a tune separated with a "---" pattern), OpenMPT will now try to jump back to the first order of this subtune instead. Modified Paths: -------------- trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/soundlib/Load_psm.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Sndmix.cpp Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-08-22 10:21:22 UTC (rev 337) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-08-22 22:47:59 UTC (rev 338) @@ -2096,7 +2096,7 @@ { pVstPlugin->GetParamName(param, s, 256); paramName = s; - line.Format("FX%d: %s\t Param %d (%x): %s\n", plug, plugName, param, param+80, paramName); + line.Format("FX%d: %s\t Param %d (%x): %s\n", plug + 1, plugName, param, param+80, paramName); message += line; } } Modified: trunk/OpenMPT/soundlib/Load_psm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_psm.cpp 2009-08-22 10:21:22 UTC (rev 337) +++ trunk/OpenMPT/soundlib/Load_psm.cpp 2009-08-22 22:47:59 UTC (rev 338) @@ -6,12 +6,14 @@ * and partly reverse-engineered. * * What's playing? - * - Epic Pinball - Seems to be working perfectly, apart from some portas? (esp. Deep Sea, Shareware Info - Linear freq slides needed!?) + * - Epic Pinball - Seems to be working perfectly with linear freq slides enabled * - Extreme Pinball - Default tempo / speed / restart position of subtunes is missing. * I'm using the last default values, restart position is still completely missing - * - Jazz Jackrabbit - Hmm, I don't like some of the portas, but apart from that it's great. (same problem as Epic Pinball) + * - Jazz Jackrabbit - Hmm, I don't like some of the portas (BONUS.PSM - the guitar portamento is too "deep"), but apart from that it's great. * - One Must Fall! - Perfect! (I modelled the volume slide and portamento conversion after this, as I got the original MTM files) * - Silverball - Currently not supported (old PSM16 format) + * + * Effect conversion should be about right, however I have my doubts wheter linear freq slides are used or not. */ #include "stdafx.h" @@ -55,7 +57,7 @@ struct PSMSAMPLEHEADER // Use this instead { BYTE flags; - CHAR sampleFormat[8]; + CHAR fileName[8]; DWORD sampleID; // INS0...INS9 (only last digit of sample ID, i.e. sample 1 and sample 11 are equal) CHAR sampleName[33]; CHAR unknown1[6]; // 00 00 00 00 00 FF @@ -72,13 +74,6 @@ #pragma pack() -BYTE convert_psm_param(BYTE param) -{ - // special conversion of some PSM parameters. is this done correctly? - return param >> 1; - //return (param + 1) >> 1; -} - bool CSoundFile::ReadPSM(const LPCBYTE lpStream, const DWORD dwMemLength) //----------------------------------------------------------------------- { @@ -97,7 +92,7 @@ // Yep, this seems to be a valid file. m_nType = MOD_TYPE_PSM; - //m_dwSongFlags |= SONG_LINEARSLIDES; // TODO + m_dwSongFlags |= SONG_LINEARSLIDES; // Seems to be correct for Epic Pinball and Jazz Jackrabbit? m_nChannels = 0; dwMemPos += 12; @@ -142,8 +137,11 @@ // Pattern ID (something like "P0 " or "P13 ") follows if(memcmp(lpStream + dwMemPos + 4, "P", 1)) return false; + char patternID[4]; + memcpy(patternID, lpStream + dwMemPos + 5, 3); + patternID[3] = 0; patternOffsets.push_back(dwMemPos + 8); - patternIDs.push_back(*(DWORD *)(lpStream + dwMemPos + 4)); + patternIDs.push_back(atoi(patternID)); numPatterns++; // Convert later as we have to know how many channels there are. @@ -177,12 +175,12 @@ { case 0x45544144: // "DATE" - Song date (YYMMDD) if(subChunkSize < 6) break; + CHAR cDate[7]; memcpy(cDate, lpStream + dwChunkPos, 6); cDate[6] = 0; sComment += "\r\nDate: "; sComment += cDate; - // We don't care about the date. break; case 0x484C504F: // "OPLH" - Order list, channel + module settings @@ -199,12 +197,20 @@ { switch(lpStream[dwSettingsOffset]) { + case 0x00: // Seems to be the End item + dwSettingsOffset += 1; + break; + case 0x01: // Order list item if(dwSettingsOffset - dwChunkPos + 5 > subChunkSize) return false; // Pattern name follows - find pattern (this is the orderlist) for(PATTERNINDEX i = 0; i < patternIDs.size(); i++) { - if(patternIDs[i] == *(DWORD *)(lpStream + dwSettingsOffset + 1)) + char patternID[4]; + memcpy(patternID, lpStream + dwSettingsOffset + 2, 3); + patternID[3] = 0; + DWORD nPattern = atoi(patternID); + if(patternIDs[i] == nPattern) { Order.push_back(i); break; @@ -213,9 +219,17 @@ dwSettingsOffset += 5; break; - case 0x04: // "end?" "04 03 00 00" in most cases (not Extreme Pinball - maybe restart positions are dumped here?) - if(dwSettingsOffset - dwChunkPos + 4 > subChunkSize) return false; - dwSettingsOffset += 4; + case 0x04: + /* It looks like the 2nd number of this chunk could be the restart position, + where position = ((number < 15) ? 0 : (number - 15)) */ + #ifdef DEBUG + { + char s[32]; + wsprintf(s, " - restart %d", (lpStream[dwSettingsOffset + 1] < 15) ? 0 : lpStream[dwSettingsOffset + 1] - 15); + sComment += s; + dwSettingsOffset += 3; + } + #endif break; case 0x07: // Default Speed @@ -243,12 +257,8 @@ if(dwSettingsOffset - dwChunkPos + 3 > subChunkSize) break; dwSettingsOffset += 3; break; - - case 0x00: // "end?" - dwSettingsOffset += 1; - break; - default: // How the hell should this happen? I've listened through all existing PSM files. :) + default: // How the hell should this happen? I've listened through all existing (original) PSM files. :) CString s; s.Format("Please report to the OpenMPT team: Unknown chunk %d found at position %d (in the OPLH chunk of this PSM file)", lpStream[dwSettingsOffset], dwSettingsOffset); MessageBox(NULL, s, TEXT("OpenMPT PSM import"), MB_ICONERROR); @@ -288,7 +298,9 @@ SAMPLEINDEX smp = (SAMPLEINDEX)(LittleEndianW(pSample->sampleNumber) + 1); m_nSamples = max(m_nSamples, smp); memcpy(m_szNames[smp], pSample->sampleName, 31); - m_szNames[0][31] = 0; + m_szNames[smp][31] = 0; + memcpy(Samples[smp].filename, pSample->fileName, 8); + Samples[smp].filename[8] = 0; Samples[smp].nGlobalVol = 0x40; Samples[smp].nC5Speed = LittleEndianW(pSample->C5Freq); @@ -317,7 +329,6 @@ if(m_nChannels == 0) return false; - // Now that we know the number of channels, we can go through all the patterns. for(PATTERNINDEX i = 0; i < numPatterns; i++) { @@ -350,7 +361,7 @@ if(dwRowOffset + 1 > dwMemLength) return false; BYTE mask = lpStream[dwRowOffset]; // Point to the correct channel - MODCOMMAND *m = row_data + min(m_nChannels, lpStream[dwRowOffset + 1]); + MODCOMMAND *m = row_data + min(m_nChannels - 1, lpStream[dwRowOffset + 1]); dwRowOffset += 2; if(mask & 0x80) @@ -358,7 +369,10 @@ if(dwRowOffset + 1 > dwMemLength) return false; // Note present BYTE bNote = lpStream[dwRowOffset]; - bNote = (bNote & 0x0F) + 12 * (bNote >> 4) + 13; + if(bNote == 0xFF) + bNote = NOTE_NOTECUT; + else + bNote = (bNote & 0x0F) + 12 * (bNote >> 4) + 13; m->note = bNote; dwRowOffset++; } @@ -376,7 +390,7 @@ if(dwRowOffset + 1 > dwMemLength) return false; // Volume present m->volcmd = VOLCMD_VOLUME; - m->vol = (min(lpStream[dwRowOffset], 127)) >> 1; + m->vol = (min(lpStream[dwRowOffset], 127) + 1) >> 1; dwRowOffset++; } @@ -409,29 +423,29 @@ // Portamento case 0x0B: // fine portamento up command = CMD_PORTAMENTOUP; - param = 0xF0 | convert_psm_param(param); + param = 0xF0 | (param >> 1); break; case 0x0C: // portamento up command = CMD_PORTAMENTOUP; - param = convert_psm_param(param); + param >>= 1; break; case 0x0D: // fine portamento down command = CMD_PORTAMENTODOWN; - param = 0xF0 | convert_psm_param(param); + param = 0xF0 | (param >> 1); break; case 0x0E: // portamento down command = CMD_PORTAMENTODOWN; - param = convert_psm_param(param); + param >>= 1; break; case 0x0F: // tone portamento command = CMD_TONEPORTAMENTO; - param = convert_psm_param(param); + param >>= 2; break; - case 0x10: // glissando control + case 0x11: // glissando control command = CMD_S3MCMDEX; param = 0x10 | (param & 0x01); break; - case 0x11: // tone portamento + volslide up + case 0x10: // tone portamento + volslide up command = CMD_TONEPORTAVOL; param = param & 0xF0; break; @@ -472,9 +486,8 @@ param = lpStream[dwRowOffset + 2]; dwRowOffset += 2; break; - case 0x2A: // set finetune - command = CMD_S3MCMDEX; - param = 0x40 | (param & 0x0F); + case 0x2A: // retrigger + command = CMD_RETRIG; break; case 0x2B: // note cut command = CMD_S3MCMDEX; @@ -488,9 +501,11 @@ // Position change case 0x33: // position jump command = CMD_POSITIONJUMP; + param >>= 1; break; case 0x34: // pattern break command = CMD_PATTERNBREAK; + param >>= 1; break; case 0x35: // loop pattern command = CMD_S3MCMDEX; @@ -514,16 +529,22 @@ command = CMD_ARPEGGIO; break; case 0x48: // set finetune - command = CMD_MODCMDEX; - param = 0x50 | (param & 0x0F); + command = CMD_S3MCMDEX; + param = 0x20 | (param & 0x0F); break; case 0x49: // set balance command = CMD_S3MCMDEX; param = 0x80 | (param & 0x0F); break; + case CMD_MODCMDEX: + // for some strange home-made tunes + command = CMD_S3MCMDEX; + break; + default: - //ASSERT(false); + ASSERT(false); + //command = CMD_NONE; break; } Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2009-08-22 10:21:22 UTC (rev 337) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2009-08-22 22:47:59 UTC (rev 338) @@ -95,14 +95,22 @@ BYTE samples_used[(MAX_SAMPLES+7)/8]; UINT unused_samples; - bool bMadeWithModPlug = false; + bool bMadeWithModPlug = false, bProbablyMadeWithModPlug = false; // set this here already because XMs compressed with BoobieSqueezer will exit the function early SetModFlag(MSF_COMPATIBLE_PLAY, true); m_nChannels = 0; if ((!lpStream) || (dwMemLength < 0xAA)) return false; // the smallest XM I know is 174 Bytes if (_strnicmp((LPCSTR)lpStream, "Extended Module", 15)) return false; + memcpy(m_szNames[0], lpStream + 17, 20); + // look for null-terminated song name - that's most likely a tune made with modplug + for(int i = 0; i < 20; i++) + if(lpStream[17 + i] == 0) bProbablyMadeWithModPlug = true; + + if (!memcmp((LPCSTR)lpStream + 0x26, "FastTracker v2.00 ", 20) && bProbablyMadeWithModPlug) bMadeWithModPlug = true; + if (!memcmp((LPCSTR)lpStream + 0x26, "Open ModPlug Tracker", 20)) bMadeWithModPlug = true; + dwHdrSize = LittleEndian(*((DWORD *)(lpStream+60))); norders = LittleEndianW(*((WORD *)(lpStream+64))); if ((!norders) || (norders > MAX_ORDERS)) return false; @@ -328,6 +336,7 @@ min(ihsize - sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER))); xmsh.shsize = LittleEndian(xmsh.shsize); + if(xmsh.shsize == 0 && bProbablyMadeWithModPlug) bMadeWithModPlug = true; for (int i = 0; i < 24; ++i) { xmsh.venv[i] = LittleEndianW(xmsh.venv[i]); Modified: trunk/OpenMPT/soundlib/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2009-08-22 10:21:22 UTC (rev 337) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2009-08-22 22:47:59 UTC (rev 338) @@ -645,6 +645,21 @@ if (!m_nRepeatCount) return FALSE; + ORDERINDEX nRestartPosOverride = m_nRestartPos; + if(!m_nRestartPos && m_nCurrentPattern <= Order.size()) + { + // if we're in a subtune and there's no restart position, go to the first order of the subtune + for(ORDERINDEX iOrd = m_nCurrentPattern - 1; iOrd > 0; iOrd--) + { + if(Order[iOrd] == Order.GetInvalidPatIndex()) + { + // Jump back to first order of this subtune + nRestartPosOverride = iOrd + 1; + break; + } + } + } + if(CMainFrame::GetMainFrame()) { // If channel resetting is disabled, we will emulate a pattern break @@ -652,7 +667,7 @@ m_dwSongFlags |= SONG_BREAKTOROW; } - if (!m_nRestartPos && !(m_dwSongFlags & SONG_BREAKTOROW)) + if (!nRestartPosOverride && !(m_dwSongFlags & SONG_BREAKTOROW)) { //rewbs.instroVSTi: stop all VSTi at end of song, if looping. StopAllVsti(); @@ -690,7 +705,7 @@ //Handle Repeat position if (m_nRepeatCount > 0) m_nRepeatCount--; - m_nCurrentPattern = m_nRestartPos; + m_nCurrentPattern = nRestartPosOverride; //m_nRow = 0; m_dwSongFlags &= ~SONG_BREAKTOROW; //If restart pos points to +++, move along This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |