bool module_renderer::ReadMO3(const uint8_t * lpStream, const uint32_t dwMemLength) //----------------------------------------------------------- { // no valid MO3 file (magic bytes: "MO3") if(dwMemLength < 4 || lpStream[0] != 'M' || lpStream[1] != 'O' || lpStream[2] != '3') return false; #ifdef NO_MO3_SUPPORT /* As of August 2010, the format revision is 5; Versions > 31 are unlikely to exist in the next few years, so we will just ignore those if there's no UNMO3 library to tell us if the file is valid or not (avoid log entry with .MOD files that have a song name starting with "MO3" */ if(lpStream[3] > 31) return false; #ifdef MODPLUG_TRACKER if(m_pModDoc != nullptr) m_pModDoc->AddToLog(GetStrI18N(_TEXT("The file appears to be a MO3 file, but this OpenMPT build does not support loading MO3 files."))); #endif // MODPLUG_TRACKER return false; #else bool bResult = false; // result of trying to load the module, false == fail. int iLen = static_cast<int>(dwMemLength); void **mo3Stream = (void **)&lpStream; // try to load unmo3.dll dynamically. #ifdef MODPLUG_TRACKER CHAR szPath[MAX_PATH]; strcpy(szPath, theApp.GetAppDirPath()); _tcsncat(szPath, _TEXT("unmo3.dll"), MAX_PATH - (_tcslen(szPath) + 1)); HMODULE unmo3 = LoadLibrary(szPath); #else HMODULE unmo3 = LoadLibrary(_TEXT("unmo3.dll")); #endif // MODPLUG_TRACKER if(unmo3 == NULL) // Didn't succeed. { #ifdef MODPLUG_TRACKER if(m_pModDoc != nullptr) m_pModDoc->AddToLog(GetStrI18N(_TEXT("Loading MO3 file failed because unmo3.dll could not be loaded."))); #endif // MODPLUG_TRACKER } else //case: dll loaded succesfully. { UNMO3_DECODE UNMO3_Decode = (UNMO3_DECODE)GetProcAddress(unmo3, "UNMO3_Decode"); UNMO3_FREE UNMO3_Free = (UNMO3_FREE)GetProcAddress(unmo3, "UNMO3_Free"); if(UNMO3_Decode != NULL && UNMO3_Free != NULL) { if(UNMO3_Decode(mo3Stream, &iLen) == 0) { /* if decoding was successful, mo3Stream and iLen will keep the new pointers now. */ if(iLen > 0) { bResult = true; if ((!ReadXM((const uint8_t *)*mo3Stream, (uint32_t)iLen)) && (!ReadIT((const uint8_t *)*mo3Stream, (uint32_t)iLen)) && (!ReadS3M((const uint8_t *)*mo3Stream, (uint32_t)iLen)) #ifndef FASTSOUNDLIB && (!ReadMTM((const uint8_t *)*mo3Stream, (uint32_t)iLen)) #endif // FASTSOUNDLIB && (!ReadMod((const uint8_t *)*mo3Stream, (uint32_t)iLen))) bResult = false; } UNMO3_Free(*mo3Stream); } } FreeLibrary(unmo3); } return bResult; #endif // NO_MO3_SUPPORT }
BOOL CSoundFile::Create(LPCBYTE lpStream, DWORD dwMemLength) //---------------------------------------------------------- { int i; m_nType = MOD_TYPE_NONE; m_dwSongFlags = 0; m_nChannels = 0; m_nMixChannels = 0; m_nSamples = 0; m_nInstruments = 0; m_nFreqFactor = m_nTempoFactor = 128; m_nMasterVolume = 128; m_nDefaultGlobalVolume = 256; m_nGlobalVolume = 256; m_nOldGlbVolSlide = 0; m_nDefaultSpeed = 6; m_nDefaultTempo = 125; m_nPatternDelay = 0; m_nFrameDelay = 0; m_nNextRow = 0; m_nRow = 0; m_nPattern = 0; m_nCurrentPattern = 0; m_nNextPattern = 0; m_nRestartPos = 0; m_nMinPeriod = 16; m_nMaxPeriod = 32767; m_nSongPreAmp = 0x30; m_nPatternNames = 0; m_nMaxOrderPosition = 0; m_lpszPatternNames = NULL; m_lpszSongComments = NULL; memset(Ins, 0, sizeof(Ins)); memset(ChnMix, 0, sizeof(ChnMix)); memset(Chn, 0, sizeof(Chn)); memset(Headers, 0, sizeof(Headers)); memset(Order, 0xFF, sizeof(Order)); memset(Patterns, 0, sizeof(Patterns)); memset(m_szNames, 0, sizeof(m_szNames)); memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); ResetMidiCfg(); for (UINT npt=0; npt<MAX_PATTERNS; npt++) PatternSize[npt] = 64; for (UINT nch=0; nch<MAX_BASECHANNELS; nch++) { ChnSettings[nch].nPan = 128; ChnSettings[nch].nVolume = 64; ChnSettings[nch].dwFlags = 0; ChnSettings[nch].szName[0] = 0; } if (lpStream) { #ifdef MMCMP_SUPPORT BOOL bMMCmp = MMCMP_Unpack(&lpStream, &dwMemLength); #endif if ((!ReadXM(lpStream, dwMemLength)) && (!ReadS3M(lpStream, dwMemLength)) && (!ReadIT(lpStream, dwMemLength)) && (!ReadWav(lpStream, dwMemLength)) #ifndef MODPLUG_BASIC_SUPPORT /* Sequencer File Format Support */ && (!ReadABC(lpStream, dwMemLength)) && (!ReadMID(lpStream, dwMemLength)) && (!ReadPAT(lpStream, dwMemLength)) && (!ReadSTM(lpStream, dwMemLength)) && (!ReadMed(lpStream, dwMemLength)) && (!ReadMTM(lpStream, dwMemLength)) && (!ReadMDL(lpStream, dwMemLength)) && (!ReadDBM(lpStream, dwMemLength)) && (!Read669(lpStream, dwMemLength)) && (!ReadFAR(lpStream, dwMemLength)) && (!ReadAMS(lpStream, dwMemLength)) && (!ReadOKT(lpStream, dwMemLength)) && (!ReadPTM(lpStream, dwMemLength)) && (!ReadUlt(lpStream, dwMemLength)) && (!ReadDMF(lpStream, dwMemLength)) && (!ReadDSM(lpStream, dwMemLength)) && (!ReadUMX(lpStream, dwMemLength)) && (!ReadAMF(lpStream, dwMemLength)) && (!ReadPSM(lpStream, dwMemLength)) && (!ReadMT2(lpStream, dwMemLength)) #endif // MODPLUG_BASIC_SUPPORT && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE; #ifdef MMCMP_SUPPORT if (bMMCmp) { GlobalFreePtr(lpStream); lpStream = NULL; } #endif } // Adjust song names for (i=0; i<MAX_SAMPLES; i++) { LPSTR p = m_szNames[i]; int j = 31; p[j] = 0; while ((j>=0) && (p[j]<=' ')) p[j--] = 0; while (j>=0) { if (((BYTE)p[j]) < ' ') p[j] = ' '; j--; } } // Adjust channels for (i=0; i<MAX_BASECHANNELS; i++) { if (ChnSettings[i].nVolume > 64) ChnSettings[i].nVolume = 64; if (ChnSettings[i].nPan > 256) ChnSettings[i].nPan = 128; Chn[i].nPan = ChnSettings[i].nPan; Chn[i].nGlobalVol = ChnSettings[i].nVolume; Chn[i].dwFlags = ChnSettings[i].dwFlags; Chn[i].nVolume = 256; Chn[i].nCutOff = 0x7F; } // Checking instruments MODINSTRUMENT *pins = Ins; for (i=0; i<MAX_INSTRUMENTS; i++, pins++) { if (pins->pSample) { if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; if (pins->nLoopStart + 3 >= pins->nLoopEnd) { pins->nLoopStart = 0; pins->nLoopEnd = 0; } if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength; if (pins->nSustainStart + 3 >= pins->nSustainEnd) { pins->nSustainStart = 0; pins->nSustainEnd = 0; } } else { pins->nLength = 0; pins->nLoopStart = 0; pins->nLoopEnd = 0; pins->nSustainStart = 0; pins->nSustainEnd = 0; } if (!pins->nLoopEnd) pins->uFlags &= ~CHN_LOOP; if (!pins->nSustainEnd) pins->uFlags &= ~CHN_SUSTAINLOOP; if (pins->nGlobalVol > 64) pins->nGlobalVol = 64; } // Check invalid instruments while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--; // Set default values if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20; if (m_nDefaultTempo < 32) m_nDefaultTempo = 125; if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; m_nMusicSpeed = m_nDefaultSpeed; m_nMusicTempo = m_nDefaultTempo; m_nGlobalVolume = m_nDefaultGlobalVolume; m_nNextPattern = 0; m_nCurrentPattern = 0; m_nPattern = 0; m_nBufferCount = 0; m_nTickCount = m_nMusicSpeed; m_nNextRow = 0; m_nRow = 0; if ((m_nRestartPos >= MAX_ORDERS) || (Order[m_nRestartPos] >= MAX_PATTERNS)) m_nRestartPos = 0; // Load plugins if (gpMixPluginCreateProc) { for (UINT iPlug=0; iPlug<MAX_MIXPLUGINS; iPlug++) { if ((m_MixPlugins[iPlug].Info.dwPluginId1) || (m_MixPlugins[iPlug].Info.dwPluginId2)) { gpMixPluginCreateProc(&m_MixPlugins[iPlug]); if (m_MixPlugins[iPlug].pMixPlugin) { m_MixPlugins[iPlug].pMixPlugin->RestoreAllParameters(); } } } } if (m_nType) { UINT maxpreamp = 0x10+(m_nChannels*8); if (maxpreamp > 100) maxpreamp = 100; if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp; return TRUE; } return FALSE; }
OPENMPT_NAMESPACE_BEGIN bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) //------------------------------------------------------------------- { file.Rewind(); // No valid MO3 file (magic bytes: "MO3") if(!file.CanRead(8) || !file.ReadMagic("MO3")) { return false; } else if(loadFlags == onlyVerifyHeader) { return true; } #ifdef NO_MO3 // As of November 2013, the format revision is 5; Versions > 31 are unlikely to exist in the next few years, // so we will just ignore those if there's no UNMO3 library to tell us if the file is valid or not // (avoid log entry with .MOD files that have a song name starting with "MO3". if(file.ReadUint8() > 31) { return false; } AddToLog(GetStrI18N("The file appears to be a MO3 file, but this OpenMPT build does not support loading MO3 files.")); return false; #else bool result = false; // Result of trying to load the module, false == fail. // Try to load unmo3 dynamically. mpt::Library unmo3 = mpt::Library(mpt::LibraryPath::App(MPT_PATHSTRING("unmo3"))); if(!unmo3.IsValid()) { // Didn't succeed. AddToLog(GetStrI18N("Loading MO3 file failed because unmo3.dll could not be loaded.")); } else { // Library loaded successfully. #if MPT_OS_WINDOWS #define UNMO3_API __stdcall #else #define UNMO3_API #endif typedef uint32 (UNMO3_API * UNMO3_GETVERSION)(); // Decode a MO3 file (returns the same "exit codes" as UNMO3.EXE, eg. 0=success) // IN: data/len = MO3 data/len // OUT: data/len = decoded data/len (if successful) // flags & 1: Don't load samples typedef int32 (UNMO3_API * UNMO3_DECODE_OLD)(const void **data, uint32 *len); typedef int32 (UNMO3_API * UNMO3_DECODE)(const void **data, uint32 *len, uint32 flags); // Free the data returned by UNMO3_Decode typedef void (UNMO3_API * UNMO3_FREE)(const void *data); #undef UNMO3_API UNMO3_GETVERSION UNMO3_GetVersion = nullptr; UNMO3_DECODE_OLD UNMO3_Decode_Old = nullptr; UNMO3_DECODE UNMO3_Decode = nullptr; UNMO3_FREE UNMO3_Free = nullptr; unmo3.Bind(UNMO3_GetVersion, "UNMO3_GetVersion"); if(UNMO3_GetVersion == nullptr) { // Old API version: No "flags" parameter. unmo3.Bind(UNMO3_Decode_Old, "UNMO3_Decode"); } else { unmo3.Bind(UNMO3_Decode, "UNMO3_Decode"); } unmo3.Bind(UNMO3_Free, "UNMO3_Free"); if((UNMO3_Decode != nullptr || UNMO3_Decode_Old != nullptr) && UNMO3_Free != nullptr) { file.Rewind(); const void *stream = file.GetRawData(); uint32 length = mpt::saturate_cast<uint32>(file.GetLength()); int32 unmo3result; if(UNMO3_Decode != nullptr) { unmo3result = UNMO3_Decode(&stream, &length, (loadFlags & loadSampleData) ? 0 : 1); } else { // Old API version: No "flags" parameter. unmo3result = UNMO3_Decode_Old(&stream, &length); } if(unmo3result == 0) { // If decoding was successful, stream and length will keep the new pointers now. FileReader unpackedFile(stream, length); result = ReadXM(unpackedFile, loadFlags) || ReadIT(unpackedFile, loadFlags) || ReadS3M(unpackedFile, loadFlags) || ReadMTM(unpackedFile, loadFlags) || ReadMod(unpackedFile, loadFlags) || ReadM15(unpackedFile, loadFlags); if(result) { m_ContainerType = MOD_CONTAINERTYPE_MO3; } UNMO3_Free(stream); } } } return result; #endif // NO_MO3 }