From: <sag...@us...> - 2010-09-26 22:16:14
|
Revision: 719 http://modplug.svn.sourceforge.net/modplug/?rev=719&view=rev Author: saga-games Date: 2010-09-26 22:16:07 +0000 (Sun, 26 Sep 2010) Log Message: ----------- [New] Edit history information can now be read from IT files and saved to IT / MPTM files. This is based on an undocumented feature in Impulse Tracker. Note: There's no way to access this data from the tracker yet. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/soundlib/IT_DEFS.H trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Sndfile.cpp Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2010-09-23 22:50:13 UTC (rev 718) +++ trunk/OpenMPT/mptrack/Moddoc.h 2010-09-26 22:16:07 UTC (rev 719) @@ -12,6 +12,7 @@ #include "sndfile.h" #include "misc_util.h" #include "Undo.h" +#include <time.h> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -115,6 +116,19 @@ ///////////////////////////////////////////////////////////////////////// +// File edit history +struct FileHistory +{ + // Date when the file was loaded in the the tracker or created. + tm load_date; + // Time the file was open in the editor (in seconds). + // For previous editing sessions, this stores the absolute time in seconds the editor was open. + // For the current editing session, this stores the time when editing was started (using the result of time()). + // To get the desired value in this case, use time(nullptr) - open_time. + time_t open_time; +}; + +///////////////////////////////////////////////////////////////////////// // Split Keyboard Settings (pattern editor) #define SPLIT_OCTAVE_RANGE 9 @@ -157,6 +171,7 @@ CPatternUndo m_PatternUndo; CSampleUndo m_SampleUndo; SplitKeyboardSettings m_SplitKeyboardSettings; // this is maybe not the best place to keep them, but it should do the job + vector<FileHistory> m_FileHistory; // File edit history protected: // create from serialization only CModDoc(); @@ -215,6 +230,7 @@ CPatternUndo *GetPatternUndo() { return &m_PatternUndo; } CSampleUndo *GetSampleUndo() { return &m_SampleUndo; } SplitKeyboardSettings *GetSplitKeyboardSettings() { return &m_SplitKeyboardSettings; } + vector<FileHistory> *GetFileHistory() { return &m_FileHistory; } // operations public: Modified: trunk/OpenMPT/soundlib/IT_DEFS.H =================================================================== --- trunk/OpenMPT/soundlib/IT_DEFS.H 2010-09-23 22:50:13 UTC (rev 718) +++ trunk/OpenMPT/soundlib/IT_DEFS.H 2010-09-26 22:16:07 UTC (rev 719) @@ -111,7 +111,7 @@ // IT Sample Format -typedef struct ITSAMPLESTRUCT +typedef struct tagITSAMPLESTRUCT { DWORD id; // 0x53504D49 CHAR filename[12]; @@ -135,6 +135,15 @@ BYTE vit; } ITSAMPLESTRUCT; + +// IT Header extension: Save history +typedef struct tagITHISTORYSTRUCT +{ + uint16 fatdate; // DOS/FAT date when the file was opened / created in the editor. For details, read http://msdn.microsoft.com/en-us/library/ms724247(VS.85).aspx + uint16 fattime; // DOS/FAT time when the file was opened / created in the editor. + uint32 runtime; // The time how long the file was open in the editor, in 1/18.2th seconds. (= ticks of the DOS timer) +} ITHISTORYSTRUCT; + #pragma pack() extern BYTE autovibit2xm[8]; Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2010-09-23 22:50:13 UTC (rev 718) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-09-26 22:16:07 UTC (rev 719) @@ -668,12 +668,44 @@ dwMemPos += pifh->patnum * 4; - // Reading IT Extra Info - if (dwMemPos + 2 < dwMemLength) + // Reading IT Edit History Info + if (dwMemPos + 2 < dwMemLength && (pifh->special & 0x02)) { - UINT nflt = *((WORD *)(lpStream + dwMemPos)); + size_t nflt = LittleEndianW(*((uint16*)(lpStream + dwMemPos))); dwMemPos += 2; - if (nflt * 8 < dwMemLength - dwMemPos) dwMemPos += nflt * 8; + + GetpModDoc()->GetFileHistory()->clear(); + if (nflt * 8 <= dwMemLength - dwMemPos) + { + for(size_t n = 0; n < nflt; n++) + { +#ifdef MODPLUG_TRACKER + ITHISTORYSTRUCT it_history = *((ITHISTORYSTRUCT *)(lpStream + dwMemPos)); + it_history.fatdate = LittleEndianW(it_history.fatdate); + it_history.fattime = LittleEndianW(it_history.fattime); + it_history.runtime = LittleEndian(it_history.runtime); + + FileHistory mpt_history; + mpt_history.load_date.tm_year = ((it_history.fatdate >> 9) & 0x7F) + 80; + mpt_history.load_date.tm_mon = ((it_history.fatdate >> 5) & 0x0F) - 1; + mpt_history.load_date.tm_mday = it_history.fatdate & 0x1F; + mpt_history.load_date.tm_hour = (it_history.fattime >> 11) & 0x1F; + mpt_history.load_date.tm_min = (it_history.fattime >> 5) & 0x3F; + mpt_history.load_date.tm_sec = (it_history.fattime & 0x1F) * 2; + mpt_history.open_time = (uint64)((float)(it_history.runtime) / 18.2f); + GetpModDoc()->GetFileHistory()->push_back(mpt_history); + +#ifdef DEBUG + const uint32 seconds = (uint32)(((float)it_history.runtime) / 18.2f); + CHAR stime[128]; + wsprintf(stime, "IT Edit History: Loaded %04u-%02u-%02u %02u:%02u:%02u, open in the editor for %u:%02u:%02u (%u ticks)\n", ((it_history.fatdate >> 9) & 0x7F) + 1980, (it_history.fatdate >> 5) & 0x0F, it_history.fatdate & 0x1F, (it_history.fattime >> 11) & 0x1F, (it_history.fattime >> 5) & 0x3F, (it_history.fattime & 0x1F) * 2, seconds / 3600, (seconds / 60) % 60, seconds % 60, it_history.runtime); + Log(stime); +#endif // DEBUG + +#endif // MODPLUG_TRACKER + dwMemPos += 8; + } + } } // Reading Midi Output & Macros if (m_dwSongFlags & SONG_EMBEDMIDICFG) @@ -1034,7 +1066,8 @@ // 193-202: Portamento To if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else // 203-212: Vibrato depth - if ((vol >= 203) && (vol <= 212)) { + if ((vol >= 203) && (vol <= 212)) + { m[ch].volcmd = VOLCMD_VIBRATODEPTH; m[ch].vol = vol - 203; // Old versions of ModPlug saved this as vibrato speed instead, so let's fix that if(m_dwLastSavedWithVersion <= MAKE_VERSION_NUMERIC(1, 17, 02, 54) && interpretModPlugMade) @@ -1133,12 +1166,45 @@ //end plastiq: code readability improvements #ifndef MODPLUG_NO_FILESAVE -//#define SAVEITTIMESTAMP + +// Save edit history +void SaveITEditHistory(const CSoundFile *pSndFile, FILE *f) +//--------------------------------------------------------- +{ + const size_t num = pSndFile->GetpModDoc()->GetFileHistory()->size(); + uint16 fnum = min(num, uint16_max); + fnum = LittleEndianW(fnum); + fwrite(&fnum, 2, 1, f); + + const size_t start = (num > uint16_max) ? num - uint16_max : 0; + for(size_t n = start; n < num; n++) + { + const FileHistory *mpt_history = &(pSndFile->GetpModDoc()->GetFileHistory()->at(n)); + ITHISTORYSTRUCT it_history; + // Create FAT file dates + it_history.fatdate = mpt_history->load_date.tm_mday | ((mpt_history->load_date.tm_mon + 1) << 5) | ((mpt_history->load_date.tm_year - 80) << 9); + it_history.fattime = (mpt_history->load_date.tm_sec / 2) | (mpt_history->load_date.tm_min << 5) | (mpt_history->load_date.tm_hour << 11); + if(n == num - 1) + { + // The current timestamp has to be converted first. + it_history.runtime = time(nullptr) - mpt_history->open_time; + } else + { + // Previous timestamps are left alone + it_history.runtime = mpt_history->open_time; + } + it_history.fatdate = LittleEndianW(it_history.fatdate); + it_history.fattime = LittleEndianW(it_history.fattime); + it_history.runtime = LittleEndian(it_history.runtime * 18); + fwrite(&it_history, 1, sizeof(it_history), f); + } +} + #pragma warning(disable:4100) bool CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking) -//------------------------------------------------------------- +//--------------------------------------------------------- { DWORD dwPatNamLen, dwChnNamLen; ITFILEHEADER header; @@ -1148,7 +1214,7 @@ DWORD inspos[MAX_INSTRUMENTS]; vector<DWORD> patpos; DWORD smppos[MAX_SAMPLES]; - DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2; + DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2 + min(GetpModDoc()->GetFileHistory()->size(), uint16_max) * 8; WORD patinfo[4]; // -> CODE#0006 // -> DESC="misc quantity changes" @@ -1224,7 +1290,7 @@ } header.flags = 0x0001; - header.special = 0x0006; + header.special = 0x02 | 0x04; // 0x02: embed file edit history if (m_nInstruments) header.flags |= 0x04; if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08; if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10; @@ -1255,9 +1321,7 @@ } } if (dwChnNamLen) dwExtra += dwChnNamLen + 8; -#ifdef SAVEITTIMESTAMP - dwExtra += 8; // Time Stamp -#endif + if (m_dwSongFlags & SONG_EMBEDMIDICFG) { header.flags |= 0x80; @@ -1288,23 +1352,7 @@ if (header.smpnum) fwrite(smppos, 4, header.smpnum, f); if (header.patnum) fwrite(&patpos[0], 4, header.patnum, f); // Writing editor history information - { -#ifdef SAVEITTIMESTAMP - SYSTEMTIME systime; - FILETIME filetime; - WORD timestamp[4]; - WORD nInfoEx = 1; - memset(timestamp, 0, sizeof(timestamp)); - fwrite(&nInfoEx, 1, 2, f); - GetSystemTime(&systime); - SystemTimeToFileTime(&systime, &filetime); - FileTimeToDosDateTime(&filetime, ×tamp[0], ×tamp[1]); - fwrite(timestamp, 1, 8, f); -#else - WORD nInfoEx = 0; - fwrite(&nInfoEx, 1, 2, f); -#endif - } + SaveITEditHistory(this, f); // Writing midi cfg if (header.flags & 0x80) { @@ -1805,7 +1853,7 @@ DWORD inspos[MAX_INSTRUMENTS]; DWORD patpos[MAX_PATTERNS]; DWORD smppos[MAX_SAMPLES]; - DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2; + DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2 + min(GetpModDoc()->GetFileHistory()->size(), uint16_max) * 8; WORD patinfo[4]; // -> CODE#0006 // -> DESC="misc quantity changes" @@ -1858,7 +1906,7 @@ } header.flags = 0x0001; - header.special = 0x0006; + header.special = 0x02 | 0x04; // 0x02: embed file edit history if (m_nInstruments) header.flags |= 0x04; if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08; if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10; @@ -1886,10 +1934,7 @@ */ } // if (dwChnNamLen) dwExtra += dwChnNamLen + 8; -/*#ifdef SAVEITTIMESTAMP - dwExtra += 8; // Time Stamp -#endif -*/ + if (m_dwSongFlags & SONG_EMBEDMIDICFG) { header.flags |= 0x80; @@ -1920,23 +1965,7 @@ if (header.smpnum) fwrite(smppos, 4, header.smpnum, f); if (header.patnum) fwrite(patpos, 4, header.patnum, f); // Writing editor history information - { -/*#ifdef SAVEITTIMESTAMP - SYSTEMTIME systime; - FILETIME filetime; - WORD timestamp[4]; - WORD nInfoEx = 1; - memset(timestamp, 0, sizeof(timestamp)); - fwrite(&nInfoEx, 1, 2, f); - GetSystemTime(&systime); - SystemTimeToFileTime(&systime, &filetime); - FileTimeToDosDateTime(&filetime, ×tamp[0], ×tamp[1]); - fwrite(timestamp, 1, 8, f); -#else -*/ WORD nInfoEx = 0; - fwrite(&nInfoEx, 1, 2, f); -//#endif - } + SaveITEditHistory(this, f); // Writing midi cfg if (header.flags & 0x80) { Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-09-23 22:50:13 UTC (rev 718) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-09-26 22:16:07 UTC (rev 719) @@ -562,6 +562,7 @@ memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); memset(&m_SongEQ, 0, sizeof(m_SongEQ)); ResetMidiCfg(); + //for (UINT npt=0; npt<Patterns.Size(); npt++) Patterns[npt].GetNumRows() = 64; for (CHANNELINDEX nChn = 0; nChn < MAX_BASECHANNELS; nChn++) { @@ -765,6 +766,18 @@ if ((m_nRestartPos >= Order.size()) || (Order[m_nRestartPos] >= Patterns.Size())) m_nRestartPos = 0; +#ifdef MODPLUG_TRACKER + // Set the creation date of this file (or the load time if we're loading an existing file) + { + FileHistory history; + time_t systime; + time(&systime); + localtime_s(&history.load_date, &systime); + history.open_time = systime; // Editing is starting right NOW! + pModDoc->GetFileHistory()->push_back(history); + } +#endif // MODPLUG_TRACKER + // plugin loader string sNotFound; std::list<PLUGINDEX> notFoundIDs; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |