From: <sag...@us...> - 2010-07-13 20:00:06
|
Revision: 645 http://modplug.svn.sourceforge.net/modplug/?rev=645&view=rev Author: saga-games Date: 2010-07-13 19:59:59 +0000 (Tue, 13 Jul 2010) Log Message: ----------- [Ref] Unified code for song message allocation / freeing / reading. From now on, Message.cpp ahould contain all code used for song messages. Modified Paths: -------------- trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/soundlib/LOAD_DMF.CPP trunk/OpenMPT/soundlib/Load_669.cpp trunk/OpenMPT/soundlib/Load_ams.cpp trunk/OpenMPT/soundlib/Load_far.cpp trunk/OpenMPT/soundlib/Load_gdm.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_mdl.cpp trunk/OpenMPT/soundlib/Load_med.cpp trunk/OpenMPT/soundlib/Load_mid.cpp trunk/OpenMPT/soundlib/Load_mt2.cpp trunk/OpenMPT/soundlib/Load_mtm.cpp trunk/OpenMPT/soundlib/Load_ult.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Added Paths: ----------- trunk/OpenMPT/soundlib/Message.cpp Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2010-07-13 19:59:59 UTC (rev 645) @@ -346,6 +346,9 @@ RelativePath=".\MainFrm.cpp"> </File> <File + RelativePath="..\soundlib\Message.cpp"> + </File> + <File RelativePath=".\MIDIMappingDialog.cpp"> </File> <File @@ -394,6 +397,9 @@ RelativePath=".\mpt_midi.cpp"> </File> <File + RelativePath=".\MPTHacks.cpp"> + </File> + <File RelativePath=".\mptrack.cpp"> </File> <File Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-07-13 19:59:59 UTC (rev 645) @@ -465,6 +465,10 @@ > </File> <File + RelativePath="..\soundlib\Message.cpp" + > + </File> + <File RelativePath=".\MIDIMappingDialog.cpp" > </File> @@ -529,6 +533,10 @@ > </File> <File + RelativePath=".\MPTHacks.cpp" + > + </File> + <File RelativePath=".\mptrack.cpp" > </File> Modified: trunk/OpenMPT/soundlib/LOAD_DMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2010-07-13 19:59:59 UTC (rev 645) @@ -119,21 +119,9 @@ psi = (DMFINFO *)(lpStream+dwMemPos); if (id == 0x47534d43) dwMemPos++; if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit; - if ((psi->infosize >= 8) && (!m_lpszSongComments)) + if (psi->infosize >= 8) { - m_lpszSongComments = new char[psi->infosize]; - if (m_lpszSongComments) - { - for (UINT i=0; i<psi->infosize-1; i++) - { - CHAR c = lpStream[dwMemPos+8+i]; - if ((i % 40) == 39) - m_lpszSongComments[i] = 0x0d; - else - m_lpszSongComments[i] = (c < ' ') ? ' ' : c; - } - m_lpszSongComments[psi->infosize-1] = 0; - } + ReadFixedLineLengthMessage(lpStream + dwMemPos + 8, psi->infosize - 1, 40, 0); } dwMemPos += psi->infosize + 8 - 1; break; Modified: trunk/OpenMPT/soundlib/Load_669.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_669.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_669.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -92,10 +92,10 @@ Samples[nSmp].nGlobalVol = 64; Samples[nSmp].nPan = 128; } + // Song Message - m_lpszSongComments = new char[109]; - memcpy(m_lpszSongComments, pfh->songmessage, 108); - m_lpszSongComments[108] = 0; + ReadFixedLineLengthMessage((BYTE *)(&pfh->songmessage), 108, 36, 0); + // Reading Orders Order.ReadAsByte(pfh->orders, 128, 128); m_nRestartPos = pfh->restartpos; @@ -106,6 +106,7 @@ ChnSettings[npan].nPan = (npan & 1) ? 0x30 : 0xD0; ChnSettings[npan].nVolume = 64; } + // Reading Patterns dwMemPos = 0x1F1 + pfh->samples * 25; for (UINT npat=0; npat<pfh->patterns; npat++) @@ -179,6 +180,7 @@ } dwMemPos += 0x600; } + // Reading Samples for (UINT n=1; n<=m_nSamples; n++) { Modified: trunk/OpenMPT/soundlib/Load_ams.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ams.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_ams.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -8,7 +8,7 @@ */ ////////////////////////////////////////////// -// AMS module loader // +// AMS (Extreme's Tracker) module loader // ////////////////////////////////////////////// #include "stdafx.h" #include "sndfile.h" @@ -53,7 +53,7 @@ DWORD dwMemPos; UINT tmp, tmp2; - if ((!lpStream) || (dwMemLength < 1024)) return false; + if ((!lpStream) || (dwMemLength < 126)) return false; if ((pfh->verhi != 0x01) || (strncmp(pfh->szHeader, "Extreme", 7)) || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples > MAX_SAMPLES) || (pfh->patterns > MAX_PATTERNS) || (pfh->orders > MAX_ORDERS)) @@ -61,12 +61,12 @@ return ReadAMS2(lpStream, dwMemLength); } dwMemPos = sizeof(AMSFILEHEADER) + pfh->extra; - if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) + 256 >= dwMemLength) return false; + if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) >= dwMemLength) return false; m_nType = MOD_TYPE_AMS; m_nInstruments = 0; m_nChannels = (pfh->chncfg & 0x1F) + 1; m_nSamples = pfh->samples; - for (UINT nSmp=1; nSmp<=m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER)) + for (UINT nSmp=1; nSmp <= m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER)) { AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos); MODSAMPLE *pSmp = &Samples[nSmp]; @@ -83,14 +83,17 @@ if ((pSmp->nLoopEnd <= pSmp->nLength) && (pSmp->nLoopStart+4 <= pSmp->nLoopEnd)) pSmp->uFlags |= CHN_LOOP; pkinf[nSmp] = psh->infobyte; } + // Read Song Name + if (dwMemPos + 1 >= dwMemLength) return true; tmp = lpStream[dwMemPos++]; if (dwMemPos + tmp + 1 >= dwMemLength) return true; tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_szNames[0], lpStream+dwMemPos, tmp2); + if (tmp2) memcpy(m_szNames[0], lpStream + dwMemPos, tmp2); SpaceToNullStringFixed(m_szNames[0], tmp2); m_szNames[0][tmp2] = 0; dwMemPos += tmp; + // Read sample names for (UINT sNam=1; sNam<=m_nSamples; sNam++) { @@ -101,6 +104,7 @@ SpaceToNullStringFixed(m_szNames[sNam], tmp2); dwMemPos += tmp; } + // Read Channel names for (UINT cNam=0; cNam<m_nChannels; cNam++) { @@ -113,6 +117,7 @@ } dwMemPos += chnnamlen; } + // Read Pattern Names m_lpszPatternNames = new char[pfh->patterns * 32]; if (!m_lpszPatternNames) return true; @@ -126,24 +131,44 @@ if (tmp2) memcpy(m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2); dwMemPos += tmp; } + // Read Song Comments tmp = *((WORD *)(lpStream+dwMemPos)); dwMemPos += 2; if (dwMemPos + tmp >= dwMemLength) return true; - if (tmp) + if (tmp && AllocateMessage(tmp)) { - m_lpszSongComments = new char[tmp+1]; - if (!m_lpszSongComments) return true; - memset(m_lpszSongComments, 0, tmp+1); - memcpy(m_lpszSongComments, lpStream + dwMemPos, tmp); - dwMemPos += tmp; + // Translate that weird text format... + for(size_t i = 0; i < tmp; i++) + { + switch(lpStream[dwMemPos + i]) + { + case 0x00: + case 0x81: m_lpszSongComments[i] = ' '; break; + case 0x14: m_lpszSongComments[i] = '\xF6'; break; + case 0x19: m_lpszSongComments[i] = '\xD6'; break; + case 0x04: m_lpszSongComments[i] = '\xE4'; break; + case 0x0E: m_lpszSongComments[i] = '\xC4'; break; + case 0x06: m_lpszSongComments[i] = '\xE5'; break; + case 0x0F: m_lpszSongComments[i] = '\xC5'; break; + default: + if(lpStream[dwMemPos + i] > 0x81) + m_lpszSongComments[i] = '\r'; + else + m_lpszSongComments[i] = lpStream[dwMemPos + i]; + break; + } + } } + dwMemPos += tmp; + // Read Order List Order.resize(pfh->orders, Order.GetInvalidPatIndex()); for (UINT iOrd=0; iOrd < pfh->orders; iOrd++, dwMemPos += 2) { Order[iOrd] = (PATTERNINDEX)*((WORD *)(lpStream + dwMemPos)); } + // Read Patterns for (UINT iPat=0; iPat<pfh->patterns; iPat++) { @@ -244,6 +269,7 @@ } dwMemPos += len; } + // Read Samples for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Samples[iSmp].nLength) { @@ -256,7 +282,7 @@ ///////////////////////////////////////////////////////////////////// -// AMS 2.2 loader +// AMS (Velvet Studio) 2.2 loader #pragma pack(1) @@ -441,12 +467,7 @@ UINT composernamelen = lpStream[dwMemPos]; if (composernamelen) { - m_lpszSongComments = new char[composernamelen+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen); - m_lpszSongComments[composernamelen] = 0; - } + ReadMessage(lpStream + dwMemPos + 1, composernamelen, leCR); } dwMemPos += composernamelen + 1; // channel names Modified: trunk/OpenMPT/soundlib/Load_far.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_far.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_far.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -102,11 +102,7 @@ { UINT szLen = pmh1->stlen; if (szLen > dwMemLength - dwMemPos) szLen = dwMemLength - dwMemPos; - if ((m_lpszSongComments = new char[szLen + 1]) != NULL) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, szLen); - m_lpszSongComments[szLen] = 0; - } + ReadFixedLineLengthMessage(lpStream + dwMemPos, szLen, 132, 0); // 132 characters per line... wow. :) dwMemPos += pmh1->stlen; } // Reading orders Modified: trunk/OpenMPT/soundlib/Load_gdm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -272,7 +272,7 @@ for(UINT iRow = 0; iRow < 64; iRow++) { - do // zero byte = next row + while(true) // zero byte = next row { if(iPatternPos + 1 > dwMemLength) break; @@ -307,7 +307,7 @@ m->command = CMD_NONE; m->volcmd = CMD_NONE; - do + while(true) { if(iPatternPos + 2 > dwMemLength) break; BYTE bEffect = lpStream[iPatternPos++]; @@ -493,25 +493,20 @@ } if(!(bEffect & 0x20)) break; // no other effect follows - } while(1); + } } - } while(1); + } } iPatternsOffset += iPatternLength; } // read song comments - if(iMTLength) + if(iMTLength > 0) { - m_lpszSongComments = new char[iMTLength + 1]; - if (m_lpszSongComments) - { - memset(m_lpszSongComments, 0, iMTLength + 1); - memcpy(m_lpszSongComments, lpStream + iMTOffset, iMTLength); - } + ReadMessage(lpStream + iMTOffset, iMTLength, leAutodetect); } return true; Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -507,23 +507,14 @@ streamPos += sizeof(DWORD); if(id > uint16_max) return false; - // allocate comment string - if(m_lpszSongComments) delete[] m_lpszSongComments; - if (id < dwMemLength && id > 0) + // allocate and copy comment string + ASSERT_CAN_READ(id); + if(id > 0) { - m_lpszSongComments = new char[id]; + ReadMessage(lpStream + streamPos, id - 1, leCR); } - else - m_lpszSongComments = NULL; + streamPos += id; - // m_lpszSongComments - if (m_lpszSongComments && id) - { - ASSERT_CAN_READ(id); - memcpy(&m_lpszSongComments[0],lpStream+streamPos,id); - streamPos += id; - } - // Song global config ASSERT_CAN_READ(5*4); @@ -1032,21 +1023,10 @@ // Reading Song Message if ((pifh->special & 0x01) && (pifh->msglength) && (pifh->msglength <= dwMemLength) && (pifh->msgoffset < dwMemLength - pifh->msglength)) { - m_lpszSongComments = new char[pifh->msglength+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+pifh->msgoffset, pifh->msglength); - m_lpszSongComments[pifh->msglength] = 0; - // ChibiTracker uses \n instead of \r. - if(pifh->cwtv == 0x0214 && pifh->cmwt == 0x0214 && LittleEndian(pifh->reserved) == IT_CHBI) - { - for(size_t i = 0; i < pifh->msglength; i++) - { - if(m_lpszSongComments[i] == '\n') - m_lpszSongComments[i] = '\r'; - } - } - } + // Generally, IT files should use CR for line endings. However, ChibiTracker uses LF. One could do... + // if(pifh->cwtv == 0x0214 && pifh->cmwt == 0x0214 && LittleEndian(pifh->reserved) == IT_CHBI) --> Chibi detected. + // But we'll just use autodetection here: + ReadMessage(lpStream + pifh->msgoffset, pifh->msglength, leAutodetect); } // Reading orders UINT nordsize = pifh->ordnum; Modified: trunk/OpenMPT/soundlib/Load_mdl.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mdl.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_mdl.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -300,15 +300,9 @@ #ifdef MDL_LOG Log("song message: %d bytes\n", blocklen); #endif - if (blocklen) + if(blocklen) { - if (m_lpszSongComments) delete[] m_lpszSongComments; - m_lpszSongComments = new char[blocklen]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, blocklen); - m_lpszSongComments[blocklen-1] = 0; - } + ReadMessage(lpStream + dwMemPos, blocklen - 1, leCR); } break; // PA: Pattern Data Modified: trunk/OpenMPT/soundlib/Load_med.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_med.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_med.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -696,18 +696,13 @@ if (pmex->channelsplit[i8ch]) m_nChannels++; } } - // Song Comments + // Song Comments (null-terminated) UINT annotxt = BigEndian(pmex->annotxt); UINT annolen = BigEndian(pmex->annolen); annolen = min(annolen, MED_MAX_COMMENT_LENGTH); //Thanks to Luigi Auriemma for pointing out an overflow risk if ((annotxt) && (annolen) && (annolen <= dwMemLength) && (annotxt <= dwMemLength - annolen) ) { - m_lpszSongComments = new char[annolen+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+annotxt, annolen); - m_lpszSongComments[annolen] = 0; - } + ReadMessage(lpStream + annotxt, annolen - 1, leAutodetect); } // Song Name UINT songname = BigEndian(pmex->songname); Modified: trunk/OpenMPT/soundlib/Load_mid.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mid.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_mid.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -732,12 +732,7 @@ } else if ((!m_lpszSongComments) && (ptrk->ptracks[0]) && (ptrk->ptracks[0] < 0x7F)) { - m_lpszSongComments = new char [len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, ptrk->ptracks, len); - m_lpszSongComments[len] = 0; - } + ReadMessage(ptrk->ptracks, len, leAutodetect); } break; // FF.02 [text]: Song Copyright @@ -745,12 +740,7 @@ if (!len) break; if ((!m_lpszSongComments) && (ptrk->ptracks[0]) && (ptrk->ptracks[0] < 0x7F) && (len > 7)) { - m_lpszSongComments = new char [len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, ptrk->ptracks, len); - m_lpszSongComments[len] = 0; - } + ReadMessage(ptrk->ptracks, len, leAutodetect); } break; // FF.03: Sequence Name Modified: trunk/OpenMPT/soundlib/Load_mt2.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mt2.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_mt2.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -252,16 +252,11 @@ { // MSG case 0x0047534D: - if ((dwLen > 3) && (!m_lpszSongComments)) + if (dwLen > 3) { DWORD nTxtLen = dwLen; if (nTxtLen > 32000) nTxtLen = 32000; - m_lpszSongComments = new char[nTxtLen]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1); - m_lpszSongComments[nTxtLen-1] = 0; - } + ReadMessage(lpStream + dwMemPos + 1, nTxtLen - 1, leCRLF); } break; // SUM -> author name (or "Unregistered") Modified: trunk/OpenMPT/soundlib/Load_mtm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mtm.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_mtm.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -139,19 +139,7 @@ if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength)) { UINT n = pmh->commentsize; - m_lpszSongComments = new char[n+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, n); - m_lpszSongComments[n] = 0; - for (UINT i=0; i<n; i++) - { - if (!m_lpszSongComments[i]) - { - m_lpszSongComments[i] = ((i + 1) % 40) ? 0x20 : 0x0D; - } - } - } + ReadFixedLineLengthMessage(lpStream + dwMemPos, n, 39, 1); } dwMemPos += pmh->commentsize; // Reading Samples Modified: trunk/OpenMPT/soundlib/Load_ult.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ult.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_ult.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -332,18 +332,7 @@ uint8 nNumLines = (uint8)lpStream[dwMemPos++]; ASSERT_CAN_READ((DWORD)(nNumLines * 32)); // read "nNumLines" lines, each containing 32 characters. - if(m_lpszSongComments != nullptr) - delete(m_lpszSongComments); - m_lpszSongComments = new char[(nNumLines * 33) + 1]; - if(m_lpszSongComments) - { - for(size_t nLine = 0; nLine < nNumLines; nLine++) - { - memcpy(m_lpszSongComments + nLine * 33, lpStream + dwMemPos + nLine * 32, 32); - m_lpszSongComments[nLine * 33 + 32] = 0x0D; - } - m_lpszSongComments[nNumLines * 33] = 0; - } + ReadFixedLineLengthMessage(lpStream + dwMemPos, nNumLines * 32, 32, 0); dwMemPos += nNumLines * 32; ASSERT_CAN_READ(1); Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -607,12 +607,7 @@ dwMemPos += 8; if ((dwMemPos + len <= dwMemLength) && (len < 16384)) { - m_lpszSongComments = new char[len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, len); - m_lpszSongComments[len] = 0; - } + ReadMessage(lpStream + dwMemPos, len, leCR); dwMemPos += len; } bMadeWithModPlug = true; Added: trunk/OpenMPT/soundlib/Message.cpp =================================================================== --- trunk/OpenMPT/soundlib/Message.cpp (rev 0) +++ trunk/OpenMPT/soundlib/Message.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -0,0 +1,242 @@ +/* + * Message.cpp + * ----------- + * Purpose: Various functions concerning song messages (allocating, reading from file...) + * Notes : Those functions should offer a rather high level of abstraction compared to + * previous ways of reading the song messages. There are still many things to do, + * though. Future versions of ReadMessage() could f.e. offer charset conversion + * and the code is not yet ready for unicode. + * Some functions for preparing the message text to be written to a file would + * also be handy. + * Authors: OpenMPT Devs + * + */ + +#include "stdafx.h" +#include "Sndfile.h" + + +// Allocate memory for song message. +// [in] length: text length in characters, without possible trailing null terminator. +// [out] returns true on success. +bool CSoundFile::AllocateMessage(size_t length) +//--------------------------------------------- +{ + FreeMessage(); + m_lpszSongComments = new char[length + 1]; // + 1 for trailing null + if(m_lpszSongComments == nullptr) + { + return false; + } else + { + memset(m_lpszSongComments, 0, length + 1); + return true; + } +} + + +// Free previously allocated song message memory +void CSoundFile::FreeMessage() +//---------------------------- +{ + if(m_lpszSongComments) + { + delete[] m_lpszSongComments; + m_lpszSongComments = nullptr; + } +} + + +// Read song message from a mapped file. +// [in] data: pointer to the data in memory that is going to be read +// [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). +// [in] lineEnding: line ending formatting of the text in memory. +// [out] returns true on success. +bool CSoundFile::ReadMessage(const BYTE *data, const size_t length, enmLineEndings lineEnding) +//-------------------------------------------------------------------------------------------- +{ + // Simple line-ending detection algorithm. VERY simple. + if(lineEnding == leAutodetect) + { + size_t nCR = 0, nLF = 0, nCRLF = 0; + // find CRs, LFs and CRLFs + for(size_t i = 0; i < length; i++) + { + if(data[i] == '\r') nCR++; + else if(data[i] == '\n') nLF++; + + if(i && data[i - 1] == '\r' && data[i] == '\n') nCRLF++; + } + // evaluate findings + if(nCR == nLF && nCR == nCRLF) + lineEnding = leCRLF; + else if(nCR && !nLF) + lineEnding = leCR; + else if(!nCR && nLF) + lineEnding = leLF; + else + lineEnding = leMixed; + } + + size_t final_length = 0; + // calculate the final amount of characters to be allocated. + for(size_t i = 0; i < length; i++) + { + switch(data[i]) + { + case '\r': + if(lineEnding != leLF) final_length++; + break; + case '\n': + if(lineEnding != leCR && lineEnding != leCRLF) final_length++; + break; + default: + final_length++; + break; + } + } + + if(!AllocateMessage(final_length)) + return false; + + size_t cpos = 0; + for(size_t i = 0; i < length; i++, cpos++) + { + switch(data[i]) + { + case '\r': + if(lineEnding != leLF) + m_lpszSongComments[cpos] = '\r'; + else + m_lpszSongComments[cpos] = ' '; + if(lineEnding == leCRLF) i++; // skip the LF + break; + case '\n': + if(lineEnding != leCR && lineEnding != leCRLF) + m_lpszSongComments[cpos] = '\r'; + else + m_lpszSongComments[cpos] = ' '; + break; + case '\0': + m_lpszSongComments[cpos] = ' '; + break; + default: + m_lpszSongComments[cpos] = data[i]; + break; + } + } + + return true; +} + + +// Read comments with fixed line length from a mapped file. +// [in] data: pointer to the data in memory that is going to be read +// [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). +// [in] lineLength: The fixed length of a line. +// [in] lineEndingLength: The padding space between two fikxed lines. (there could for example be a null char after every line) +// [out] returns true on success. +bool CSoundFile::ReadFixedLineLengthMessage(const BYTE *data, const size_t length, const size_t lineLength, const size_t lineEndingLength) +//---------------------------------------------------------------------------------------------------------------------------------------- +{ + if(lineLength == 0) + return false; + + const size_t num_lines = (length / (lineLength + lineEndingLength)); + const size_t final_length = num_lines * (lineLength + 1); + if(!AllocateMessage(final_length)) + return false; + + for(size_t line = 0, fpos = 0, cpos = 0; line < num_lines; line++, fpos += (lineLength + lineEndingLength), cpos += (lineLength + 1)) + { + memcpy(m_lpszSongComments + cpos, data + fpos, min(lineLength, length - fpos)); + m_lpszSongComments[cpos + lineLength] = '\r'; + + // fix weird chars + for(size_t lpos = 0; lpos < lineLength; lpos++) + { + switch(m_lpszSongComments[cpos + lpos]) + { + case '\0': + case '\n': + case '\r': + m_lpszSongComments[cpos + lpos] = ' '; + break; + } + + } + } + return true; +} + + +// OLD and unused function. Do we still need it? +UINT CSoundFile::GetSongMessage(LPSTR s, UINT len, UINT linesize) +//--------------------------------------------------------------- +{ + LPCSTR p = m_lpszSongComments; + if (!p) return 0; + UINT i = 2, ln=0; + if ((len) && (s)) s[0] = '\x0D'; + if ((len > 1) && (s)) s[1] = '\x0A'; + while ((*p) && (i+2 < len)) + { + BYTE c = (BYTE)*p++; + if ((c == 0x0D) || ((c == ' ') && (ln >= linesize))) + { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; } + else + if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; } + } + if (s) s[i] = 0; + return i; +} + + +// OLD and unused function. Do we still need it? +UINT CSoundFile::GetRawSongMessage(LPSTR s, UINT len, UINT linesize) +//------------------------------------------------------------------ +{ + LPCSTR p = m_lpszSongComments; + if (!p) return 0; + UINT i = 0, ln=0; + while ((*p) && (i < len-1)) + { + BYTE c = (BYTE)*p++; + if ((c == 0x0D) || (c == 0x0A)) + { + if (ln) + { + while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; } + ln = 0; + } + } else + if ((c == ' ') && (!ln)) + { + UINT k=0; + while ((p[k]) && (p[k] >= ' ')) k++; + if (k <= linesize) + { + if (s) s[i] = ' '; + i++; + ln++; + } + } else + { + if (s) s[i] = c; + i++; + ln++; + if (ln == linesize) ln = 0; + } + } + if (ln) + { + while ((ln < linesize) && (i < len)) + { + if (s) s[i] = ' '; + i++; + ln++; + } + } + if (s) s[i] = 0; + return i; +} Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -859,8 +859,7 @@ delete[] m_lpszPatternNames; m_lpszPatternNames = NULL; - delete[] m_lpszSongComments; - m_lpszSongComments = NULL; + FreeMessage(); for (i=1; i<MAX_SAMPLES; i++) { @@ -955,76 +954,6 @@ } -UINT CSoundFile::GetSongComments(LPSTR s, UINT len, UINT linesize) -//---------------------------------------------------------------- -{ - LPCSTR p = m_lpszSongComments; - if (!p) return 0; - UINT i = 2, ln=0; - if ((len) && (s)) s[0] = '\x0D'; - if ((len > 1) && (s)) s[1] = '\x0A'; - while ((*p) && (i+2 < len)) - { - BYTE c = (BYTE)*p++; - if ((c == 0x0D) || ((c == ' ') && (ln >= linesize))) - { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; } - else - if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; } - } - if (s) s[i] = 0; - return i; -} - - -UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize) -//------------------------------------------------------------------- -{ - LPCSTR p = m_lpszSongComments; - if (!p) return 0; - UINT i = 0, ln=0; - while ((*p) && (i < len-1)) - { - BYTE c = (BYTE)*p++; - if ((c == 0x0D) || (c == 0x0A)) - { - if (ln) - { - while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; } - ln = 0; - } - } else - if ((c == ' ') && (!ln)) - { - UINT k=0; - while ((p[k]) && (p[k] >= ' ')) k++; - if (k <= linesize) - { - if (s) s[i] = ' '; - i++; - ln++; - } - } else - { - if (s) s[i] = c; - i++; - ln++; - if (ln == linesize) ln = 0; - } - } - if (ln) - { - while ((ln < linesize) && (i < len)) - { - if (s) s[i] = ' '; - i++; - ln++; - } - } - if (s) s[i] = 0; - return i; -} - - BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX) //---------------------------------------------------------------------------- { Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-07-13 19:59:59 UTC (rev 645) @@ -443,7 +443,17 @@ #include "PlaybackEventer.h" +// Line ending types (for reading song messages from module files) +enum enmLineEndings +{ + leCR, // Carriage Return (0x0D, \r) + leLF, // Line Feed (0x0A \n) + leCRLF, // Carriage Return, Line Feed (0x0D0A, \r\n) + leMixed, // It is not defined whether Carriage Return or Line Feed is the actual line ending. Both are accepted. + leAutodetect, // Detect suitable line ending +}; + class CSoundFile; @@ -627,8 +637,6 @@ UINT GetCurrentPos() const; UINT GetCurrentPattern() const { return m_nPattern; } ORDERINDEX GetCurrentOrder() const { return static_cast<ORDERINDEX>(m_nCurrentPattern); } - UINT GetSongComments(LPSTR s, UINT cbsize, UINT linesize=32); - UINT GetRawSongComments(LPSTR s, UINT cbsize, UINT linesize=32); UINT GetMaxPosition() const; CHANNELINDEX GetNumChannels() const { return m_nChannels; } @@ -851,8 +859,8 @@ void GlobalVolSlide(UINT param, UINT * nOldGlobalVolSlide); DWORD IsSongFinished(UINT nOrder, UINT nRow) const; BOOL IsValidBackwardJump(UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow) const; + public: - // Write pattern effect functions bool TryWriteEffect(PATTERNINDEX nPat, ROWINDEX nRow, BYTE nEffect, BYTE nParam, bool bIsVolumeEffect, CHANNELINDEX nChn = CHANNELINDEX_INVALID, bool bAllowMultipleEffects = true, bool bAllowNextRow = false, bool bRetry = true); @@ -937,12 +945,41 @@ static LPSTR AllocateSample(UINT nbytes); static void FreeSample(LPVOID p); static UINT Normalize24BitBuffer(LPBYTE pbuffer, UINT cbsizebytes, DWORD lmax24, DWORD dwByteInc); - UINT GetBestPlugin(UINT nChn, UINT priority, bool respectMutes); //private: static MODCOMMAND *AllocatePattern(UINT rows, UINT nchns); static void FreePattern(LPVOID pat); + // Song message helper functions public: + // Allocate memory for song message. + // [in] length: text length in characters, without possible trailing null terminator. + // [out] returns true on success. + bool AllocateMessage(size_t length); + + // Free previously allocated song message memory. + void FreeMessage(); + +protected: + // Read song message from a mapped file. + // [in] data: pointer to the data in memory that is going to be read + // [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). + // [in] lineEnding: line ending formatting of the text in memory. + // [out] returns true on success. + bool ReadMessage(const BYTE *data, const size_t length, enmLineEndings lineEnding); + + // Read comments with fixed line length from a mapped file. + // [in] data: pointer to the data in memory that is going to be read + // [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). + // [in] lineLength: The fixed length of a line. + // [in] lineEndingLength: The padding space between two fikxed lines. (there could for example be a null char after every line) + // [out] returns true on success. + bool ReadFixedLineLengthMessage(const BYTE *data, const size_t length, const size_t lineLength, const size_t lineEndingLength); + + // Currently unused (and the code doesn't look very nice :) + UINT GetSongMessage(LPSTR s, UINT cbsize, UINT linesize=32); + UINT GetRawSongMessage(LPSTR s, UINT cbsize, UINT linesize=32); + +public: int getVolEnvValueFromPosition(int position, MODINSTRUMENT* pIns); void resetEnvelopes(MODCHANNEL* pChn, enmResetEnv envToReset = ENV_RESET_ALL); void SetDefaultInstrumentValues(MODINSTRUMENT *pIns); @@ -955,6 +992,9 @@ void BuildDefaultInstrument(); long GetSampleOffset(); +public: + UINT GetBestPlugin(UINT nChn, UINT priority, bool respectMutes); + // A couple of functions for handling backwards jumps and stuff to prevent infinite loops when counting the mod length or rendering to wav. public: void InitializeVisitedRows(const bool bReset = true); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |