diff --git a/demos/genesis/mm5_boss.fur b/demos/genesis/mm5_boss.fur new file mode 100644 index 000000000..d3eb6caf5 Binary files /dev/null and b/demos/genesis/mm5_boss.fur differ diff --git a/doc/2-interface/asset-list.md b/doc/2-interface/asset-list.md index 936c4a32f..836d9b694 100644 --- a/doc/2-interface/asset-list.md +++ b/doc/2-interface/asset-list.md @@ -33,6 +33,6 @@ Everything from the instrument list applies here also, with one major difference ![samples window](samples.png) -Everything from the wavetables list applies here also, with the addition of two buttons: +Everything from the wavetables list applies here also, with the addition of two buttons before the Delete button: - **Preview**: Plays the selected sample at its default note. - **Stop preview**: Stops the sample playback. diff --git a/doc/2-interface/instruments-folder.png b/doc/2-interface/instruments-folder.png index a2fbb5ab2..0afe5e0e9 100644 Binary files a/doc/2-interface/instruments-folder.png and b/doc/2-interface/instruments-folder.png differ diff --git a/doc/2-interface/instruments.png b/doc/2-interface/instruments.png index 00102e543..56f994957 100644 Binary files a/doc/2-interface/instruments.png and b/doc/2-interface/instruments.png differ diff --git a/doc/2-interface/samples.png b/doc/2-interface/samples.png index 2be62a9ba..654ff8787 100644 Binary files a/doc/2-interface/samples.png and b/doc/2-interface/samples.png differ diff --git a/doc/2-interface/wavetables.png b/doc/2-interface/wavetables.png index 4ac45f2c8..3de7413c3 100644 Binary files a/doc/2-interface/wavetables.png and b/doc/2-interface/wavetables.png differ diff --git a/doc/4-instrument/README.md b/doc/4-instrument/README.md index bd00b6b85..7ab7898ec 100644 --- a/doc/4-instrument/README.md +++ b/doc/4-instrument/README.md @@ -1,11 +1,3 @@ -# instrument list - -![instrument list](list.png) - -click on an instrument to select it. - -double-click to open the instrument editor. - # instrument editor every instrument can be renamed and have its type changed. @@ -66,14 +58,16 @@ Some macros are "bitmap" style. They represent a number of "bits" that can be to The number between the macro type label and the macro type button is the macro length in steps. The `-` and `+` buttons change the length of the macro. Start out by adding at least a few steps. -The values of the macro can be drawn in the "bar graph box". Just beneath the box is shorter bar graph. -- Click to set the start point of a loop; the end point is the last value or release point. Right-click to remove the loop. -- Shift-click to set the release point. When played, the macro will hold here until the note is released. Right-click to remove the release point. +The values of the macro can be drawn in the "bar graph" box. + +Just beneath the box is a shorter bar that controls looping. +- Click to set the start point of a loop; the end point is the last value or release point. It appears as half-height bars. Right-click to remove the loop. +- Shift-click to set the release point. When played, the macro will hold here until the note is released. It appears as a full-height bar. Right-click to remove the release point. Finally, the sequence of values can be directly edited in the text box at the bottom. - The loop start is entered as a `|`. - The release point is entered as a `/`. -- In arpeggio macros, a value starting with a `@` is an absolute note (instead of a relative shift). No matter the note played, `@` values will be played at that exact note. This is especially useful for noise instruments with preset periods. +- In arpeggio macros, a value starting with a `@` is an absolute note (instead of a relative shift). No matter the note entered in the pattern, `@` values will be played at that exact note. This is especially useful for noise instruments with preset periods. ### ADSR @@ -100,15 +94,29 @@ Finally, the sequence of values can be directly edited in the text box at the bo - **Phase** is which part of the waveform the macro will start at, measured in 1/1024 increments. - **Shape** is the waveform used. Triangle is the default, and Saw and Square are exactly as they say. -# samples + + +# wavetable + +This tab appears for PC Engine, FDS, Namco WSG, and other wavetable-based instruments. + +![wavetable tab](wavetable.png) + +When **Enable synthesizer** is off, the only option is to select a wavetable entry with the text entry box beneath the **Wave 1** preview. + +To use the wavetable synthesizer, refer to the bottom part of [the wavetable documentation](../5-wave/README.md). + + +# sample This tab appears for Generic PCM, SNES, Amiga, and other sample-based instruments. -![](sample-map.png) +![sample tab](sample-map.png) - **Initial Sample**: the sample that the instrument will use. - **Use wavetable**: instead of samples, use wavetables. this causes the [Wavetables](../5-wave/README.md) tab to appear next to Sample. - depending on the system and use of the wavetable synthesizer, this may or may not be reproducible on hardware. - **Use sample map**: assigns a sample to each note. - - samples will be played at their default pitch. - - to set a note's sample, click the list entry in the `#` column then type the number of the sample. + - to set a note's sample, click the list entry in the "#" column then type the number of the sample. + - to set the pitch at which a sample is played, click the list entry in the "note" column and press the key for the new note. + diff --git a/doc/4-instrument/list.png b/doc/4-instrument/list.png deleted file mode 100644 index e8af84a83..000000000 Binary files a/doc/4-instrument/list.png and /dev/null differ diff --git a/doc/4-instrument/macro-seq.png b/doc/4-instrument/macro-seq.png index 6ea2050b4..e4bd6ee9e 100644 Binary files a/doc/4-instrument/macro-seq.png and b/doc/4-instrument/macro-seq.png differ diff --git a/doc/4-instrument/macro.png b/doc/4-instrument/macro.png deleted file mode 100644 index 4e03bad92..000000000 Binary files a/doc/4-instrument/macro.png and /dev/null differ diff --git a/doc/4-instrument/sample-map.png b/doc/4-instrument/sample-map.png index 1d2787122..fb1f9b51e 100644 Binary files a/doc/4-instrument/sample-map.png and b/doc/4-instrument/sample-map.png differ diff --git a/doc/4-instrument/wavetable.png b/doc/4-instrument/wavetable.png new file mode 100644 index 000000000..7c862d953 Binary files /dev/null and b/doc/4-instrument/wavetable.png differ diff --git a/extern/igfd/ImGuiFileDialog.cpp b/extern/igfd/ImGuiFileDialog.cpp index 2ccc3e9c0..d66dadf74 100644 --- a/extern/igfd/ImGuiFileDialog.cpp +++ b/extern/igfd/ImGuiFileDialog.cpp @@ -800,138 +800,138 @@ namespace IGFD // will be called internally // will not been exposed to IGFD API - bool IGFD::FilterManager::prFillFileStyle(std::shared_ptr vFileInfos) const + bool IGFD::FilterManager::prFillFileStyle(FileInfos& vFileInfos) const { - if (vFileInfos.use_count() && !prFilesStyle.empty()) + if (!prFilesStyle.empty()) { for (const auto& _flag : prFilesStyle) { for (const auto& _file : _flag.second) { - if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos->fileType == 'd') + if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos.fileType == 'd') { if (_file.first.empty()) // for all dirs { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } - else if (_file.first == vFileInfos->fileNameExt) // for dirs who are equal to style criteria + else if (_file.first == vFileInfos.fileNameExt) // for dirs who are equal to style criteria { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } - else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos->fileType == 'f') + else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos.fileType == 'f') { if (_file.first.empty()) // for all files { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } - else if (_file.first == vFileInfos->fileNameExt) // for files who are equal to style criteria + else if (_file.first == vFileInfos.fileNameExt) // for files who are equal to style criteria { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } - else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos->fileType == 'l') + else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos.fileType == 'l') { if (_file.first.empty()) // for all links { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } - else if (_file.first == vFileInfos->fileNameExt) // for links who are equal to style criteria + else if (_file.first == vFileInfos.fileNameExt) // for links who are equal to style criteria { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } if (_flag.first & IGFD_FileStyleByExtention) { - if (_file.first == vFileInfos->fileExt) + if (_file.first == vFileInfos.fileExt) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } // can make sense for some dirs like the hidden by ex ".git" - if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos->fileType == 'd') + if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos.fileType == 'd') { - if (_file.first == vFileInfos->fileExt) + if (_file.first == vFileInfos.fileExt) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } - else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos->fileType == 'f') + else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos.fileType == 'f') { - if (_file.first == vFileInfos->fileExt) + if (_file.first == vFileInfos.fileExt) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } - else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos->fileType == 'l') + else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos.fileType == 'l') { - if (_file.first == vFileInfos->fileExt) + if (_file.first == vFileInfos.fileExt) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } } if (_flag.first & IGFD_FileStyleByFullName) { - if (_file.first == vFileInfos->fileNameExt) + if (_file.first == vFileInfos.fileNameExt) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } - if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos->fileType == 'd') + if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos.fileType == 'd') { - if (_file.first == vFileInfos->fileNameExt) + if (_file.first == vFileInfos.fileNameExt) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } - else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos->fileType == 'f') + else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos.fileType == 'f') { - if (_file.first == vFileInfos->fileNameExt) + if (_file.first == vFileInfos.fileNameExt) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } - else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos->fileType == 'l') + else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos.fileType == 'l') { - if (_file.first == vFileInfos->fileNameExt) + if (_file.first == vFileInfos.fileNameExt) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } } if (_flag.first & IGFD_FileStyleByContainedInFullName) { - if (vFileInfos->fileNameExt.find(_file.first) != std::string::npos) + if (vFileInfos.fileNameExt.find(_file.first) != std::string::npos) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } - if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos->fileType == 'd') + if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos.fileType == 'd') { - if (vFileInfos->fileNameExt.find(_file.first) != std::string::npos) + if (vFileInfos.fileNameExt.find(_file.first) != std::string::npos) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } - else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos->fileType == 'f') + else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos.fileType == 'f') { - if (vFileInfos->fileNameExt.find(_file.first) != std::string::npos) + if (vFileInfos.fileNameExt.find(_file.first) != std::string::npos) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } - else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos->fileType == 'l') + else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos.fileType == 'l') { - if (vFileInfos->fileNameExt.find(_file.first) != std::string::npos) + if (vFileInfos.fileNameExt.find(_file.first) != std::string::npos) { - vFileInfos->fileStyle = _file.second; + vFileInfos.fileStyle = _file.second; } } } - if (vFileInfos->fileStyle.use_count()) + if (vFileInfos.fileStyle.use_count()) return true; } } @@ -1142,6 +1142,7 @@ namespace IGFD for (int i=1; i<4; i++) { puSortingDirection[i]=false; } + invalidFile.isValid=false; } void IGFD::FileManager::OpenCurrentPath(const FileDialogInternal& vFileDialogInternal) @@ -1191,29 +1192,24 @@ namespace IGFD puHeaderFileName = tableHeaderDescendingIcon + puHeaderFileName; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (a==NULL || b==NULL) - return false; - if (!a.use_count() || !b.use_count()) - return false; - // this code fail in c:\\Users with the link "All users". got a invalid comparator /* // use code from https://github.com/jackm97/ImGuiFileDialog/commit/bf40515f5a1de3043e60562dc1a494ee7ecd3571 // strict ordering for file/directory types beginning in '.' // common on Linux platforms - if (a->fileNameExt[0] == '.' && b->fileNameExt[0] != '.') + if (a.fileNameExt[0] == '.' && b.fileNameExt[0] != '.') return false; - if (a->fileNameExt[0] != '.' && b->fileNameExt[0] == '.') + if (a.fileNameExt[0] != '.' && b.fileNameExt[0] == '.') return true; - if (a->fileNameExt[0] == '.' && b->fileNameExt[0] == '.') + if (a.fileNameExt[0] == '.' && b.fileNameExt[0] == '.') { - return (stricmp(a->fileNameExt.c_str(), b->fileNameExt.c_str()) < 0); // sort in insensitive case + return (stricmp(a.fileNameExt.c_str(), b.fileNameExt.c_str()) < 0); // sort in insensitive case } */ - if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first - return (stricmp(a->fileNameExt.c_str(), b->fileNameExt.c_str()) < 0); // sort in insensitive case + if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first + return (stricmp(a.fileNameExt.c_str(), b.fileNameExt.c_str()) < 0); // sort in insensitive case }); } else @@ -1222,28 +1218,23 @@ namespace IGFD puHeaderFileName = tableHeaderAscendingIcon + puHeaderFileName; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (a==NULL || b==NULL) - return false; - if (!a.use_count() || !b.use_count()) - return false; - // this code fail in c:\\Users with the link "All users". got a invalid comparator /* // use code from https://github.com/jackm97/ImGuiFileDialog/commit/bf40515f5a1de3043e60562dc1a494ee7ecd3571 // strict ordering for file/directory types beginning in '.' // common on Linux platforms - if (a->fileNameExt[0] == '.' && b->fileNameExt[0] != '.') + if (a.fileNameExt[0] == '.' && b.fileNameExt[0] != '.') return false; - if (a->fileNameExt[0] != '.' && b->fileNameExt[0] == '.') + if (a.fileNameExt[0] != '.' && b.fileNameExt[0] == '.') return true; - if (a->fileNameExt[0] == '.' && b->fileNameExt[0] == '.') + if (a.fileNameExt[0] == '.' && b.fileNameExt[0] == '.') { - return (stricmp(a->fileNameExt.c_str(), b->fileNameExt.c_str()) > 0); // sort in insensitive case + return (stricmp(a.fileNameExt.c_str(), b.fileNameExt.c_str()) > 0); // sort in insensitive case } */ - return (stricmp(a->fileNameExt.c_str(), b->fileNameExt.c_str()) > 0); // sort in insensitive case + return (stricmp(a.fileNameExt.c_str(), b.fileNameExt.c_str()) > 0); // sort in insensitive case }); } } @@ -1259,13 +1250,10 @@ namespace IGFD puHeaderFileType = tableHeaderDescendingIcon + puHeaderFileType; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (!a.use_count() || !b.use_count()) - return false; - - if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first - return (a->fileExt < b->fileExt); // else + if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first + return (a.fileExt < b.fileExt); // else }); } else @@ -1274,15 +1262,10 @@ namespace IGFD puHeaderFileType = tableHeaderAscendingIcon + puHeaderFileType; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (a==NULL || b==NULL) - return false; - if (!a.use_count() || !b.use_count()) - return false; - - if (a->fileType != b->fileType) return (a->fileType != 'd'); // directory in last - return (a->fileExt > b->fileExt); // else + if (a.fileType != b.fileType) return (a.fileType != 'd'); // directory in last + return (a.fileExt > b.fileExt); // else }); } } @@ -1298,15 +1281,10 @@ namespace IGFD puHeaderFileSize = tableHeaderDescendingIcon + puHeaderFileSize; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (a==NULL || b==NULL) - return false; - if (!a.use_count() || !b.use_count()) - return false; - - if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first - return (a->fileSize < b->fileSize); // else + if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first + return (a.fileSize < b.fileSize); // else }); } else @@ -1315,15 +1293,10 @@ namespace IGFD puHeaderFileSize = tableHeaderAscendingIcon + puHeaderFileSize; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (a==NULL || b==NULL) - return false; - if (!a.use_count() || !b.use_count()) - return false; - - if (a->fileType != b->fileType) return (a->fileType != 'd'); // directory in last - return (a->fileSize > b->fileSize); // else + if (a.fileType != b.fileType) return (a.fileType != 'd'); // directory in last + return (a.fileSize > b.fileSize); // else }); } } @@ -1339,15 +1312,10 @@ namespace IGFD puHeaderFileDate = tableHeaderDescendingIcon + puHeaderFileDate; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (a==NULL || b==NULL) - return false; - if (!a.use_count() || !b.use_count()) - return false; - - if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first - return (a->fileModifDate < b->fileModifDate); // else + if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first + return (a.fileModifDate < b.fileModifDate); // else }); } else @@ -1356,15 +1324,10 @@ namespace IGFD puHeaderFileDate = tableHeaderAscendingIcon + puHeaderFileDate; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (a==NULL || b==NULL) - return false; - if (!a.use_count() || !b.use_count()) - return false; - - if (a->fileType != b->fileType) return (a->fileType != 'd'); // directory in last - return (a->fileModifDate > b->fileModifDate); // else + if (a.fileType != b.fileType) return (a.fileType != 'd'); // directory in last + return (a.fileModifDate > b.fileModifDate); // else }); } } @@ -1384,15 +1347,12 @@ namespace IGFD puHeaderFileThumbnails = tableHeaderDescendingIcon + puHeaderFileThumbnails; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (!a.use_count() || !b.use_count()) - return false; - - if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first - if (a->thumbnailInfo.textureWidth == b->thumbnailInfo.textureWidth) - return (a->thumbnailInfo.textureHeight < b->thumbnailInfo.textureHeight); - return (a->thumbnailInfo.textureWidth < b->thumbnailInfo.textureWidth); + if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first + if (a.thumbnailInfo.textureWidth == b.thumbnailInfo.textureWidth) + return (a.thumbnailInfo.textureHeight < b.thumbnailInfo.textureHeight); + return (a.thumbnailInfo.textureWidth < b.thumbnailInfo.textureWidth); }); } @@ -1402,15 +1362,12 @@ namespace IGFD puHeaderFileThumbnails = tableHeaderAscendingIcon + puHeaderFileThumbnails; #endif // USE_CUSTOM_SORTING_ICON std::sort(prFileList.begin(), prFileList.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool + [](const FileInfos& a, const FileInfos& b) -> bool { - if (!a.use_count() || !b.use_count()) - return false; - - if (a->fileType != b->fileType) return (a->fileType != 'd'); // directory in last - if (a->thumbnailInfo.textureWidth == b->thumbnailInfo.textureWidth) - return (a->thumbnailInfo.textureHeight > b->thumbnailInfo.textureHeight); - return (a->thumbnailInfo.textureWidth > b->thumbnailInfo.textureWidth); + if (a.fileType != b.fileType) return (a.fileType != 'd'); // directory in last + if (a.thumbnailInfo.textureWidth == b.thumbnailInfo.textureWidth) + return (a.thumbnailInfo.textureHeight > b.thumbnailInfo.textureHeight); + return (a.thumbnailInfo.textureWidth > b.thumbnailInfo.textureWidth); }); } } @@ -1441,38 +1398,38 @@ namespace IGFD return fileNameExt; } - void IGFD::FileManager::AddFile(const FileDialogInternal& vFileDialogInternal, const std::string& vPath, const std::string& vFileName, const char& vFileType, void* ent) + void IGFD::FileManager::AddFile(const FileDialogInternal& vFileDialogInternal, const std::string& vPath, const std::string& vFileName, char vFileType, void* ent) { - auto infos = std::make_shared(); + FileInfos infos; #ifdef _WIN32 struct dirent* dent=(struct dirent*)ent; #endif - infos->filePath = vPath; - infos->fileNameExt = vFileName; - infos->fileNameExt_optimized = prOptimizeFilenameForSearchOperations(infos->fileNameExt); - infos->fileType = vFileType; + infos.filePath = vPath; + infos.fileNameExt = vFileName; + infos.fileNameExt_optimized = prOptimizeFilenameForSearchOperations(infos.fileNameExt); + infos.fileType = vFileType; - if (infos->fileNameExt.empty() || ((infos->fileNameExt == "." || infos->fileNameExt == "..") && !vFileDialogInternal.puFilterManager.puDLGFilters.empty())) return; // filename empty or filename is the current dir '.' //-V807 - if (infos->fileNameExt != ".." && (vFileDialogInternal.puDLGflags & ImGuiFileDialogFlags_DontShowHiddenFiles) && infos->fileNameExt[0] == '.') // dont show hidden files - if (!vFileDialogInternal.puFilterManager.puDLGFilters.empty() || (vFileDialogInternal.puFilterManager.puDLGFilters.empty() && infos->fileNameExt != ".")) // except "." if in directory mode //-V728 + if (infos.fileNameExt.empty() || ((infos.fileNameExt == "." || infos.fileNameExt == "..") && !vFileDialogInternal.puFilterManager.puDLGFilters.empty())) return; // filename empty or filename is the current dir '.' //-V807 + if (infos.fileNameExt != ".." && (vFileDialogInternal.puDLGflags & ImGuiFileDialogFlags_DontShowHiddenFiles) && infos.fileNameExt[0] == '.') // dont show hidden files + if (!vFileDialogInternal.puFilterManager.puDLGFilters.empty() || (vFileDialogInternal.puFilterManager.puDLGFilters.empty() && infos.fileNameExt != ".")) // except "." if in directory mode //-V728 return; - if (infos->fileType == 'f' || - infos->fileType == 'l') // link can have the same extention of a file + if (infos.fileType == 'f' || + infos.fileType == 'l') // link can have the same extention of a file { - size_t lpt = infos->fileNameExt.find_last_of('.'); + size_t lpt = infos.fileNameExt.find_last_of('.'); if (lpt != std::string::npos) { - infos->fileExt = infos->fileNameExt.substr(lpt); + infos.fileExt = infos.fileNameExt.substr(lpt); } - for (char& i: infos->fileExt) { + for (char& i: infos.fileExt) { if (i>='A' && i<='Z') i+='a'-'A'; } - if (!vFileDialogInternal.puFilterManager.IsCoveredByFilters(infos->fileExt)) + if (!vFileDialogInternal.puFilterManager.IsCoveredByFilters(infos.fileExt)) { return; } @@ -1483,16 +1440,16 @@ namespace IGFD SYSTEMTIME localTime; char timebuf[100]; - infos->fileSize=dent->dwin_size; + infos.fileSize=dent->dwin_size; if (FileTimeToSystemTime(&dent->dwin_mtime,&systemTime)==TRUE) { if (SystemTimeToTzSpecificLocalTime(NULL,&systemTime,&localTime)==TRUE) { snprintf(timebuf,99,"%d/%.2d/%.2d %.2d:%.2d",localTime.wYear,localTime.wMonth,localTime.wDay,localTime.wHour,localTime.wMinute); } else { snprintf(timebuf,99,"%d/%.2d/%.2d %.2d:%.2d",systemTime.wYear,systemTime.wMonth,systemTime.wDay,systemTime.wHour,systemTime.wMinute); } - infos->fileModifDate=timebuf; + infos.fileModifDate=timebuf; } else { - infos->fileModifDate="???"; + infos.fileModifDate="???"; } #endif @@ -1534,7 +1491,7 @@ namespace IGFD { struct dirent* ent = files[i]; std::string where = path + std::string(PATH_SEP_STR) + std::string(ent->d_name); - char fileType = 0; + char fileType = 'f'; #if defined(HAVE_DIRENT_TYPE) || defined(_WIN32) if (ent->d_type != DT_UNKNOWN) { @@ -1544,7 +1501,7 @@ namespace IGFD fileType = 'f'; break; case DT_DIR: fileType = 'd'; break; - case DT_LNK: + case DT_LNK: { #ifdef _WIN32 fileType = 'f'; #else @@ -1557,7 +1514,8 @@ namespace IGFD } else { - fileType = 'l'; + // why does 'l' make it crash? + fileType = 'f'; } } else @@ -1568,6 +1526,9 @@ namespace IGFD #endif break; } + default: + fileType = 'f'; break; + } } else #endif // HAVE_DIRENT_TYPE @@ -1622,12 +1583,12 @@ namespace IGFD ClearFileLists(); for (auto& drive : drives) { - auto info = std::make_shared(); - info->fileNameExt = drive; - info->fileNameExt_optimized = prOptimizeFilenameForSearchOperations(drive); - info->fileType = 'd'; + FileInfos info; + info.fileNameExt = drive; + info.fileNameExt_optimized = prOptimizeFilenameForSearchOperations(drive); + info.fileType = 'd'; - if (!info->fileNameExt.empty()) + if (!info.fileNameExt.empty()) { prFileList.push_back(info); } @@ -1658,11 +1619,11 @@ namespace IGFD return prFileList.size(); } - std::shared_ptr IGFD::FileManager::GetFullFileAt(size_t vIdx) + const FileInfos& IGFD::FileManager::GetFullFileAt(size_t vIdx) { if (vIdx < prFileList.size()) return prFileList[vIdx]; - return nullptr; + return invalidFile; } bool IGFD::FileManager::IsFilteredListEmpty() @@ -1675,11 +1636,11 @@ namespace IGFD return prFilteredFileList.size(); } - std::shared_ptr IGFD::FileManager::GetFilteredFileAt(size_t vIdx) + const FileInfos& IGFD::FileManager::GetFilteredFileAt(size_t vIdx) { if (vIdx < prFilteredFileList.size()) return prFilteredFileList[vIdx]; - return nullptr; + return invalidFile; } bool IGFD::FileManager::IsFileNameSelected(const std::string& vFileName) @@ -1706,14 +1667,12 @@ namespace IGFD void IGFD::FileManager::ApplyFilteringOnFileList(const FileDialogInternal& vFileDialogInternal) { prFilteredFileList.clear(); - for (const auto& file : prFileList) + for (const FileInfos& file : prFileList) { - if (!file.use_count()) - continue; bool show = true; - if (!file->IsTagFound(vFileDialogInternal.puSearchManager.puSearchTag)) // if search tag + if (!file.IsTagFound(vFileDialogInternal.puSearchManager.puSearchTag)) // if search tag show = false; - if (puDLGDirectoryMode && file->fileType != 'd') // directory mode + if (puDLGDirectoryMode && file.fileType != 'd') // directory mode show = false; if (show) prFilteredFileList.push_back(file); @@ -1750,13 +1709,10 @@ namespace IGFD return ""; } - void IGFD::FileManager::prCompleteFileInfos(const std::shared_ptr& vInfos) + void IGFD::FileManager::prCompleteFileInfos(FileInfos& vInfos) { - if (!vInfos.use_count()) - return; - - if (vInfos->fileNameExt != "." && - vInfos->fileNameExt != "..") + if (vInfos.fileNameExt != "." && + vInfos.fileNameExt != "..") { // _stat struct : //dev_t st_dev; /* ID of device containing file */ @@ -1774,25 +1730,25 @@ namespace IGFD //time_t st_ctime; /* time of last status change - not sure out of ntfs */ #ifdef _WIN32 - if (vInfos->fileType != 'd') + if (vInfos.fileType != 'd') { - vInfos->formatedFileSize = prFormatFileSize(vInfos->fileSize); + vInfos.formatedFileSize = prFormatFileSize(vInfos.fileSize); } #else std::string fpn; - if (vInfos->fileType == 'f' || vInfos->fileType == 'l' || vInfos->fileType == 'd') // file - fpn = vInfos->filePath + std::string(1u, PATH_SEP) + vInfos->fileNameExt; + if (vInfos.fileType == 'f' || vInfos.fileType == 'l' || vInfos.fileType == 'd') // file + fpn = vInfos.filePath + std::string(1u, PATH_SEP) + vInfos.fileNameExt; struct stat statInfos = {}; char timebuf[100]; int result = stat(fpn.c_str(), &statInfos); if (result!=-1) { - if (vInfos->fileType != 'd') + if (vInfos.fileType != 'd') { - vInfos->fileSize = (size_t)statInfos.st_size; - vInfos->formatedFileSize = prFormatFileSize(vInfos->fileSize); + vInfos.fileSize = (size_t)statInfos.st_size; + vInfos.formatedFileSize = prFormatFileSize(vInfos.fileSize); } size_t len = 0; @@ -1806,12 +1762,12 @@ namespace IGFD #endif // MSVC if (len) { - vInfos->fileModifDate = std::string(timebuf, len); + vInfos.fileModifDate = std::string(timebuf, len); } } else { - vInfos->fileSize=0; - vInfos->formatedFileSize = prFormatFileSize(vInfos->fileSize); - vInfos->fileModifDate="???"; + vInfos.fileSize=0; + vInfos.formatedFileSize = prFormatFileSize(vInfos.fileSize); + vInfos.fileModifDate="???"; } #endif } @@ -1994,14 +1950,11 @@ namespace IGFD IGFD::Utils::SetBuffer(puFileNameBuffer, MAX_FILE_DIALOG_NAME_BUFFER, vFileName); } - bool IGFD::FileManager::SelectDirectory(const std::shared_ptr& vInfos) + bool IGFD::FileManager::SelectDirectory(const FileInfos& vInfos) { - if (!vInfos.use_count()) - return false; - bool pathClick = false; - if (vInfos->fileNameExt == "..") + if (vInfos.fileNameExt == "..") { pathClick = SetPathOnParentDirectoryIfAny(); } @@ -2011,23 +1964,23 @@ namespace IGFD if (puShowDrives) { - newPath = vInfos->fileNameExt + std::string(1u, PATH_SEP); + newPath = vInfos.fileNameExt + std::string(1u, PATH_SEP); } else { #ifdef __linux__ if (puFsRoot == prCurrentPath) - newPath = prCurrentPath + vInfos->fileNameExt; + newPath = prCurrentPath + vInfos.fileNameExt; else #endif // __linux__ - newPath = prCurrentPath + std::string(1u, PATH_SEP) + vInfos->fileNameExt; + newPath = prCurrentPath + std::string(1u, PATH_SEP) + vInfos.fileNameExt; } if (IGFD::Utils::IsDirectoryExist(newPath)) { if (puShowDrives) { - prCurrentPath = vInfos->fileNameExt; + prCurrentPath = vInfos.fileNameExt; puFsRoot = prCurrentPath; } else @@ -2041,35 +1994,32 @@ namespace IGFD return pathClick; } - void IGFD::FileManager::SelectFileName(const FileDialogInternal& vFileDialogInternal, const std::shared_ptr& vInfos) + void IGFD::FileManager::SelectFileName(const FileDialogInternal& vFileDialogInternal, const FileInfos& vInfos) { - if (!vInfos.use_count()) - return; - if (ImGui::GetIO().KeyCtrl) { if (puDLGcountSelectionMax == 0) // infinite selection { - if (prSelectedFileNames.find(vInfos->fileNameExt) == prSelectedFileNames.end()) // not found +> add + if (prSelectedFileNames.find(vInfos.fileNameExt) == prSelectedFileNames.end()) // not found +> add { - prAddFileNameInSelection(vInfos->fileNameExt, true); + prAddFileNameInSelection(vInfos.fileNameExt, true); } else // found +> remove { - prRemoveFileNameInSelection(vInfos->fileNameExt); + prRemoveFileNameInSelection(vInfos.fileNameExt); } } else // selection limited by size { if (prSelectedFileNames.size() < puDLGcountSelectionMax) { - if (prSelectedFileNames.find(vInfos->fileNameExt) == prSelectedFileNames.end()) // not found +> add + if (prSelectedFileNames.find(vInfos.fileNameExt) == prSelectedFileNames.end()) // not found +> add { - prAddFileNameInSelection(vInfos->fileNameExt, true); + prAddFileNameInSelection(vInfos.fileNameExt, true); } else // found +> remove { - prRemoveFileNameInSelection(vInfos->fileNameExt); + prRemoveFileNameInSelection(vInfos.fileNameExt); } } } @@ -2081,18 +2031,15 @@ namespace IGFD prSelectedFileNames.clear(); // we will iterate filelist and get the last selection after the start selection bool startMultiSelection = false; - std::string fileNameToSelect = vInfos->fileNameExt; + std::string fileNameToSelect = vInfos.fileNameExt; std::string savedLastSelectedFileName; // for invert selection mode - for (const auto& file : prFileList) + for (const FileInfos& file : prFileList) { - if (!file.use_count()) - continue; - bool canTake = true; - if (!file->IsTagFound(vFileDialogInternal.puSearchManager.puSearchTag)) canTake = false; + if (!file.IsTagFound(vFileDialogInternal.puSearchManager.puSearchTag)) canTake = false; if (canTake) // if not filtered, we will take files who are filtered by the dialog { - if (file->fileNameExt == prLastSelectedFileName) + if (file.fileNameExt == prLastSelectedFileName) { startMultiSelection = true; prAddFileNameInSelection(prLastSelectedFileName, false); @@ -2101,13 +2048,13 @@ namespace IGFD { if (puDLGcountSelectionMax == 0) // infinite selection { - prAddFileNameInSelection(file->fileNameExt, false); + prAddFileNameInSelection(file.fileNameExt, false); } else // selection limited by size { if (prSelectedFileNames.size() < puDLGcountSelectionMax) { - prAddFileNameInSelection(file->fileNameExt, false); + prAddFileNameInSelection(file.fileNameExt, false); } else { @@ -2119,7 +2066,7 @@ namespace IGFD } } - if (file->fileNameExt == fileNameToSelect) + if (file.fileNameExt == fileNameToSelect) { if (!startMultiSelection) // we are before the last Selected FileName, so we must inverse { @@ -2145,7 +2092,7 @@ namespace IGFD { prSelectedFileNames.clear(); IGFD::Utils::ResetBuffer(puFileNameBuffer); - prAddFileNameInSelection(vInfos->fileNameExt, true); + prAddFileNameInSelection(vInfos.fileNameExt, true); } } @@ -3922,11 +3869,8 @@ namespace IGFD } // returns 0 if not break loop, 1 if break loop, 2 if exit dialog - int IGFD::FileDialog::prSelectableItem(int vidx, std::shared_ptr vInfos, bool vSelected, const char* vFmt, ...) + int IGFD::FileDialog::prSelectableItem(int vidx, const FileInfos& vInfos, bool vSelected, const char* vFmt, ...) { - if (!vInfos.use_count()) - return 0; - auto& fdi = prFileDialogInternal.puFileManager; static ImGuiSelectableFlags selectableFlags = ImGuiSelectableFlags_AllowDoubleClick | @@ -3957,7 +3901,7 @@ namespace IGFD #endif // USE_EXPLORATION_BY_KEYS if (res) { - if (vInfos->fileType == 'd') + if (vInfos.fileType == 'd') { bool isSelectingDir=false; // nav system, selectebale cause open directory or select directory @@ -4012,27 +3956,27 @@ namespace IGFD return 0; } - void IGFD::FileDialog::prBeginFileColorIconStyle(std::shared_ptr vFileInfos, bool& vOutShowColor, std::string& vOutStr, ImFont** vOutFont) + void IGFD::FileDialog::prBeginFileColorIconStyle(const FileInfos& vFileInfos, bool& vOutShowColor, std::string& vOutStr, ImFont** vOutFont) { vOutStr.clear(); vOutShowColor = false; - if (vFileInfos->fileStyle.use_count()) //-V807 //-V522 + if (vFileInfos.fileStyle.use_count()) //-V807 //-V522 { vOutShowColor = true; - *vOutFont = vFileInfos->fileStyle->font; + *vOutFont = vFileInfos.fileStyle->font; } - if (vOutShowColor && !vFileInfos->fileStyle->icon.empty()) vOutStr = vFileInfos->fileStyle->icon; - else if (vFileInfos->fileType == 'd') vOutStr = dirEntryString; - else if (vFileInfos->fileType == 'l') vOutStr = linkEntryString; - else if (vFileInfos->fileType == 'f') vOutStr = fileEntryString; + if (vOutShowColor && !vFileInfos.fileStyle->icon.empty()) vOutStr = vFileInfos.fileStyle->icon; + else if (vFileInfos.fileType == 'd') vOutStr = dirEntryString; + else if (vFileInfos.fileType == 'l') vOutStr = linkEntryString; + else if (vFileInfos.fileType == 'f') vOutStr = fileEntryString; - vOutStr += " " + vFileInfos->fileNameExt; + vOutStr += " " + vFileInfos.fileNameExt; if (vOutShowColor) - ImGui::PushStyleColor(ImGuiCol_Text, vFileInfos->fileStyle->color); + ImGui::PushStyleColor(ImGuiCol_Text, vFileInfos.fileStyle->color); if (*vOutFont) ImGui::PushFont(*vOutFont); } @@ -4126,13 +4070,13 @@ namespace IGFD { if (i < 0) continue; - auto infos = fdi.GetFilteredFileAt((size_t)i); - if (!infos.use_count()) + const FileInfos& infos = fdi.GetFilteredFileAt((size_t)i); + if (!infos.isValid) continue; prBeginFileColorIconStyle(infos, _showColor, _str, &_font); - bool selected = fdi.IsFileNameSelected(infos->fileNameExt); // found + bool selected = fdi.IsFileNameSelected(infos.fileNameExt); // found ImGui::TableNextRow(); @@ -4147,13 +4091,13 @@ namespace IGFD } if (ImGui::TableNextColumn()) // file type { - ImGui::Text("%s", infos->fileExt.c_str()); + ImGui::Text("%s", infos.fileExt.c_str()); } if (ImGui::TableNextColumn()) // file size { - if (infos->fileType != 'd') + if (infos.fileType != 'd') { - ImGui::Text("%s ", infos->formatedFileSize.c_str()); + ImGui::Text("%s ", infos.formatedFileSize.c_str()); } else { @@ -4162,7 +4106,7 @@ namespace IGFD } if (ImGui::TableNextColumn()) // file date + time { - ImGui::Text("%s", infos->fileModifDate.c_str()); + ImGui::Text("%s", infos.fileModifDate.c_str()); } prEndFileColorIconStyle(_showColor, _font); diff --git a/extern/igfd/ImGuiFileDialog.h b/extern/igfd/ImGuiFileDialog.h index 93db26e9d..0850cd680 100644 --- a/extern/igfd/ImGuiFileDialog.h +++ b/extern/igfd/ImGuiFileDialog.h @@ -766,7 +766,7 @@ namespace IGFD void ParseFilters(const char* vFilters); // Parse filter syntax, detect and parse filter collection void SetSelectedFilterWithExt(const std::string& vFilter); // Select filter - bool prFillFileStyle(std::shared_ptr vFileInfos) const; // fill with the good style + bool prFillFileStyle(FileInfos& vFileInfos) const; // fill with the good style void SetFileStyle( const IGFD_FileStyleFlags& vFlags, @@ -812,6 +812,7 @@ namespace IGFD #ifdef USE_THUMBNAILS IGFD_Thumbnail_Info thumbnailInfo; // structre for the display for image file tetxure #endif // USE_THUMBNAILS + bool isValid = true; public: bool IsTagFound(const std::string& vTag) const; @@ -824,6 +825,7 @@ namespace IGFD class FileManager { public: // types + FileInfos invalidFile; enum class SortingFieldEnum // sorting for filetering of the file lsit { FIELD_NONE = 0, // no sorting preference, result indetermined haha.. @@ -839,8 +841,8 @@ namespace IGFD private: std::string prCurrentPath; // current path (to be decomposed in prCurrentPathDecomposition std::vector prCurrentPathDecomposition; // part words - std::vector> prFileList; // base container - std::vector> prFilteredFileList; // filtered container (search, sorting, etc..) + std::vector prFileList; // base container + std::vector prFilteredFileList; // filtered container (search, sorting, etc..) std::string prLastSelectedFileName; // for shift multi selection std::set prSelectedFileNames; // the user selection of FilePathNames bool prCreateDirectoryMode = false; // for create directory widget @@ -879,11 +881,11 @@ namespace IGFD static std::string prRoundNumber(double vvalue, int n); // custom rounding number static std::string prFormatFileSize(size_t vByteSize); // format file size field static std::string prOptimizeFilenameForSearchOperations(const std::string& vFileNameExt); // turn all text in lower case for search facilitie - static void prCompleteFileInfos(const std::shared_ptr& FileInfos); // set time and date infos of a file (detail view mode) + static void prCompleteFileInfos(FileInfos& FileInfos); // set time and date infos of a file (detail view mode) void prRemoveFileNameInSelection(const std::string& vFileName); // selection : remove a file name void prAddFileNameInSelection(const std::string& vFileName, bool vSetLastSelectionFileName); // selection : add a file name void AddFile(const FileDialogInternal& vFileDialogInternal, - const std::string& vPath, const std::string& vFileName, const char& vFileType, void* ent); // add file called by scandir + const std::string& vPath, const std::string& vFileName, char vFileType, void* ent); // add file called by scandir public: FileManager(); @@ -892,9 +894,9 @@ namespace IGFD bool IsFileListEmpty(); bool IsFilteredListEmpty(); size_t GetFullFileListSize(); - std::shared_ptr GetFullFileAt(size_t vIdx); + const FileInfos& GetFullFileAt(size_t vIdx); size_t GetFilteredListSize(); - std::shared_ptr GetFilteredFileAt(size_t vIdx); + const FileInfos& GetFilteredFileAt(size_t vIdx); bool IsFileNameSelected(const std::string& vFileName); std::string GetBack(); void ClearComposer(); @@ -912,9 +914,9 @@ namespace IGFD void SetCurrentPath(const std::string& vCurrentPath); // set the current path static bool IsFileExist(const std::string& vFile); void SetDefaultFileName(const std::string& vFileName); - bool SelectDirectory(const std::shared_ptr& vInfos); // enter directory + bool SelectDirectory(const FileInfos& vInfos); // enter directory void SelectFileName(const FileDialogInternal& vFileDialogInternal, - const std::shared_ptr& vInfos); // select filename + const FileInfos& vInfos); // select filename //depend of dirent.h void SetCurrentDir(const std::string& vPath); // define current directory for scan @@ -1311,7 +1313,7 @@ namespace IGFD // widgets components virtual void prDrawSidePane(float vHeight); // draw side pane virtual int prSelectableItem(int vidx, - std::shared_ptr vInfos, + const FileInfos& vInfos, bool vSelected, const char* vFmt, ...); // draw a custom selectable behavior item virtual bool prDrawFileListView(ImVec2 vSize); // draw file list view (default mode) @@ -1325,7 +1327,7 @@ namespace IGFD // - prDrawThumbnailsListView // - prDrawThumbnailsGridView void prBeginFileColorIconStyle( - std::shared_ptr vFileInfos, + const FileInfos& vFileInfos, bool& vOutShowColor, std::string& vOutStr, ImFont** vOutFont); // begin style apply of filter with color an icon if any diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 1b9f427c8..d27b6a57e 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -3851,6 +3851,23 @@ void DivEngine::delSample(int index) { song.sampleLen=song.sample.size(); removeAsset(song.sampleDir,index); checkAssetDir(song.sampleDir,song.sample.size()); + + // compensate + for (DivInstrument* i: song.ins) { + if (i->amiga.initSample==index) { + i->amiga.initSample=-1; + } else if (i->amiga.initSample>index) { + i->amiga.initSample--; + } + for (int j=0; j<120; j++) { + if (i->amiga.noteMap[j].map==index) { + i->amiga.noteMap[j].map=-1; + } else if (i->amiga.noteMap[j].map>index) { + i->amiga.noteMap[j].map--; + } + } + } + renderSamples(); } saveLock.unlock(); @@ -4042,6 +4059,27 @@ void DivEngine::exchangeIns(int one, int two) { } } +void DivEngine::exchangeWave(int one, int two) { + // TODO +} + +void DivEngine::exchangeSample(int one, int two) { + for (DivInstrument* i: song.ins) { + if (i->amiga.initSample==one) { + i->amiga.initSample=two; + } else if (i->amiga.initSample==two) { + i->amiga.initSample=one; + } + for (int j=0; j<120; j++) { + if (i->amiga.noteMap[j].map==one) { + i->amiga.noteMap[j].map=two; + } else if (i->amiga.noteMap[j].map==two) { + i->amiga.noteMap[j].map=one; + } + } + } +} + bool DivEngine::moveInsUp(int which) { if (which<1 || which>=(int)song.ins.size()) return false; BUSY_BEGIN; @@ -4064,6 +4102,7 @@ bool DivEngine::moveWaveUp(int which) { song.wave[which]=song.wave[which-1]; song.wave[which-1]=prev; moveAsset(song.waveDir,which,which-1); + exchangeWave(which,which-1); saveLock.unlock(); BUSY_END; return true; @@ -4080,6 +4119,7 @@ bool DivEngine::moveSampleUp(int which) { song.sample[which]=song.sample[which-1]; song.sample[which-1]=prev; moveAsset(song.sampleDir,which,which-1); + exchangeSample(which,which-1); saveLock.unlock(); renderSamples(); BUSY_END; @@ -4107,6 +4147,7 @@ bool DivEngine::moveWaveDown(int which) { saveLock.lock(); song.wave[which]=song.wave[which+1]; song.wave[which+1]=prev; + exchangeWave(which,which+1); moveAsset(song.waveDir,which,which+1); saveLock.unlock(); BUSY_END; @@ -4123,6 +4164,7 @@ bool DivEngine::moveSampleDown(int which) { saveLock.lock(); song.sample[which]=song.sample[which+1]; song.sample[which+1]=prev; + exchangeSample(which,which+1); moveAsset(song.sampleDir,which,which+1); saveLock.unlock(); renderSamples(); diff --git a/src/engine/engine.h b/src/engine/engine.h index 87ff7116e..0f13659b8 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -531,6 +531,9 @@ class DivEngine { void initSongWithDesc(const char* description, bool inBase64=true, bool oldVol=false); void exchangeIns(int one, int two); + void exchangeWave(int one, int two); + void exchangeSample(int one, int two); + void swapChannels(int src, int dest); void stompChannel(int ch); diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 6e87a4431..de1074d6d 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -1937,8 +1937,8 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { ds.system[i]=systemFromFileFur(sysID); logD("- %d: %.2x (%s)",i,sysID,getSystemName(ds.system[i])); if (sysID!=0 && systemToFileFur(ds.system[i])==0) { - logE("unrecognized system ID %.2x",ds.system[i]); - lastError=fmt::sprintf("unrecognized system ID %.2x!",ds.system[i]); + logE("unrecognized system ID %.2x",sysID); + lastError=fmt::sprintf("unrecognized system ID %.2x!",sysID); delete[] file; return false; } diff --git a/src/engine/platform/es5506.cpp b/src/engine/platform/es5506.cpp index c44cdb0cf..4f8745bda 100644 --- a/src/engine/platform/es5506.cpp +++ b/src/engine/platform/es5506.cpp @@ -360,26 +360,6 @@ void DivPlatformES5506::tick(bool sysTick) { } } } - if (chan[i].pcm.isNoteMap) { - // note map macros - if (chan[i].std.wave.had) { - if (chan[i].std.wave.val>=0 && chan[i].std.wave.val<120) { - if (chan[i].pcm.next!=chan[i].std.wave.val) { - chan[i].pcm.next=chan[i].std.wave.val; - chan[i].pcmChanged.index=1; - } - } - } - } else if (!chan[i].pcm.isNoteMap) { - if (chan[i].std.wave.had) { - if (chan[i].std.wave.val>=0 && chan[i].std.wave.valsong.sampleLen) { - if (chan[i].pcm.next!=chan[i].std.wave.val) { - chan[i].pcm.next=chan[i].std.wave.val; - chan[i].pcmChanged.index=1; - } - } - } - } // update registers if (chan[i].volChanged.changed) { // calculate volume (16 bit) @@ -432,7 +412,7 @@ void DivPlatformES5506::tick(bool sysTick) { off=(double)center/8363.0; } if (ins->amiga.useNoteMap) { - chan[i].pcm.note=next; + //chan[i].pcm.note=next; } // get loop mode DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX; @@ -748,13 +728,13 @@ int DivPlatformES5506::dispatch(DivCommand c) { if (((ins->amiga.useNoteMap) && (c.value>=0 && c.value<120)) || ((!ins->amiga.useNoteMap) && (ins->amiga.initSample>=0 && ins->amiga.initSamplesong.sampleLen))) { int sample=ins->amiga.getSample(c.value); - c.value=ins->amiga.getFreq(c.value); if (sample>=0 && samplesong.sampleLen) { sampleValid=true; chan[c.chan].volMacroMax=ins->type==DIV_INS_AMIGA?64:0xfff; chan[c.chan].panMacroMax=ins->type==DIV_INS_AMIGA?127:0xfff; - chan[c.chan].pcm.note=c.value; chan[c.chan].pcm.next=ins->amiga.useNoteMap?c.value:sample; + c.value=ins->amiga.getFreq(c.value); + chan[c.chan].pcm.note=c.value; chan[c.chan].filter=ins->es5506.filter; chan[c.chan].envelope=ins->es5506.envelope; } @@ -870,20 +850,6 @@ int DivPlatformES5506::dispatch(DivCommand c) { chan[c.chan].pitch=c.value; chan[c.chan].freqChanged=true; break; - // sample commands - case DIV_CMD_WAVE: - if (!chan[c.chan].useWave) { - if (chan[c.chan].active) { - DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_ES5506); - if (((ins->amiga.useNoteMap) && (c.value>=0 && c.value<120)) || - ((!ins->amiga.useNoteMap) && (c.value>=0 && c.valuesong.sampleLen))) { - chan[c.chan].pcm.next=c.value; - chan[c.chan].pcmChanged.index=1; - } - } - } - // reserved for useWave - break; // Filter commands case DIV_CMD_ES5506_FILTER_MODE: if (!chan[c.chan].active) { diff --git a/src/engine/platform/msm6258.cpp b/src/engine/platform/msm6258.cpp index fbede0b59..e5de16456 100644 --- a/src/engine/platform/msm6258.cpp +++ b/src/engine/platform/msm6258.cpp @@ -386,6 +386,9 @@ int DivPlatformMSM6258::init(DivEngine* p, int channels, int sugRate, const DivC oscBuf[i]=new DivDispatchOscBuffer; } msm=new okim6258_device(4000000); + msm->set_start_div(okim6258_device::FOSC_DIV_BY_1024); + msm->set_type(okim6258_device::TYPE_4BITS); + msm->set_outbits(okim6258_device::OUTPUT_12BITS); msm->device_start(); setFlags(flags); reset(); diff --git a/src/engine/platform/msm6258.h b/src/engine/platform/msm6258.h index 2c18d90c4..6be120c2b 100644 --- a/src/engine/platform/msm6258.h +++ b/src/engine/platform/msm6258.h @@ -47,7 +47,6 @@ class DivPlatformMSM6258: public DivDispatch { }; FixedQueue writes; okim6258_device* msm; - unsigned char lastBusy; unsigned char sampleBank, msmPan, msmDivider, rateSel, msmClock, clockSel; signed char msmDividerCount, msmClockCount; diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index 8fac52356..2ea68f756 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -130,9 +130,9 @@ void DivPlatformNES::acquire_NSFPlay(short** buf, size_t len) { for (size_t i=0; iTick(1); - nes2_NP->TickFrameSequence(1); - nes2_NP->Tick(1); + nes1_NP->Tick(8); + nes2_NP->TickFrameSequence(8); + nes2_NP->Tick(8); nes1_NP->Render(out1); nes2_NP->Render(out2); @@ -140,7 +140,7 @@ void DivPlatformNES::acquire_NSFPlay(short** buf, size_t len) { if (sample>32767) sample=32767; if (sample<-32768) sample=-32768; buf[0][i]=sample; - if (++writeOscBuf>=32) { + if (++writeOscBuf>=4) { writeOscBuf=0; oscBuf[0]->data[oscBuf[0]->needle++]=nes1_NP->out[0]<<11; oscBuf[1]->data[oscBuf[1]->needle++]=nes1_NP->out[1]<<11; @@ -749,8 +749,11 @@ void DivPlatformNES::setFlags(const DivConfig& flags) { } CHECK_CUSTOM_CLOCK; rate=chipClock; + if (useNP) { + rate/=8; + } for (int i=0; i<5; i++) { - oscBuf[i]->rate=rate/32; + oscBuf[i]->rate=rate/(useNP?4:32); } dpcmModeDefault=flags.getBool("dpcmMode",true); diff --git a/src/engine/platform/tia.cpp b/src/engine/platform/tia.cpp index 1836bee10..86038216a 100644 --- a/src/engine/platform/tia.cpp +++ b/src/engine/platform/tia.cpp @@ -356,12 +356,12 @@ void DivPlatformTIA::poke(std::vector& wlist) { void DivPlatformTIA::setFlags(const DivConfig& flags) { if (flags.getInt("clockSel",0)) { - rate=COLOR_PAL*4.0/5.0; + chipClock=COLOR_PAL*4.0/5.0; } else { - rate=COLOR_NTSC; + chipClock=COLOR_NTSC; } CHECK_CUSTOM_CLOCK; - chipClock=rate; + rate=chipClock; mixingType=flags.getInt("mixingType",0)&3; for (int i=0; i<2; i++) { oscBuf[i]->rate=rate/114; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index e242f0a39..f999a2d6f 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1542,7 +1542,6 @@ void DivEngine::registerSystems() { ); EffectHandlerMap es5506PreEffectHandlerMap={ - {0x10, {DIV_CMD_WAVE, "10xx: Change waveform (00 to FF)",effectVal}}, {0x11, {DIV_CMD_ES5506_FILTER_MODE, "11xx: Set filter mode (00 to 03)",effectValAnd<3>}}, {0x14, {DIV_CMD_ES5506_FILTER_K1, "14xx: Set filter coefficient K1 low byte (00 to FF)",effectValShift<0>,constVal<0x00ff>}}, {0x15, {DIV_CMD_ES5506_FILTER_K1, "15xx: Set filter coefficient K1 high byte (00 to FF)",effectValShift<8>,constVal<0xff00>}}, diff --git a/src/gui/about.cpp b/src/gui/about.cpp index 37a40c527..a79ce6e34 100644 --- a/src/gui/about.cpp +++ b/src/gui/about.cpp @@ -121,6 +121,7 @@ const char* aboutLine[]={ "SwapXFO", "TakuikaNinja", "TCORPStudios", + "Teuthida", "The Blender Fiddler", "TheDuccinator", "theloredev", diff --git a/src/gui/dataList.cpp b/src/gui/dataList.cpp index 289584492..f9e2ab749 100644 --- a/src/gui/dataList.cpp +++ b/src/gui/dataList.cpp @@ -330,9 +330,6 @@ void FurnaceGUI::insListItem(int i, int dir, int asset) { if (ImGui::MenuItem("save")) { doAction(GUI_ACTION_INS_LIST_SAVE); } - if (ImGui::MenuItem("save (legacy .fui)")) { - doAction(GUI_ACTION_INS_LIST_SAVE_OLD); - } if (ImGui::MenuItem("save (.dmp)")) { doAction(GUI_ACTION_INS_LIST_SAVE_DMP); } diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index 60d713d32..56f1e32f9 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -642,9 +642,6 @@ void FurnaceGUI::doAction(int what) { case GUI_ACTION_INS_LIST_SAVE: if (curIns>=0 && curIns<(int)e->song.ins.size()) openFileDialog(GUI_FILE_INS_SAVE); break; - case GUI_ACTION_INS_LIST_SAVE_OLD: - if (curIns>=0 && curIns<(int)e->song.ins.size()) openFileDialog(GUI_FILE_INS_SAVE_OLD); - break; case GUI_ACTION_INS_LIST_SAVE_DMP: if (curIns>=0 && curIns<(int)e->song.ins.size()) openFileDialog(GUI_FILE_INS_SAVE_DMP); break; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 4c73d7f1c..0883dce3f 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1653,16 +1653,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { dpiScale ); break; - case GUI_FILE_INS_SAVE_OLD: - if (!dirExists(workingDirIns)) workingDirIns=getHomeDir(); - hasOpened=fileDialog->openSave( - "Save Instrument", - {"Furnace instrument", "*.fui"}, - "Furnace instrument{.fui}", - workingDirIns, - dpiScale - ); - break; case GUI_FILE_INS_SAVE_DMP: if (!dirExists(workingDirIns)) workingDirIns=getHomeDir(); hasOpened=fileDialog->openSave( @@ -4592,7 +4582,6 @@ bool FurnaceGUI::loop() { case GUI_FILE_INS_OPEN: case GUI_FILE_INS_OPEN_REPLACE: case GUI_FILE_INS_SAVE: - case GUI_FILE_INS_SAVE_OLD: case GUI_FILE_INS_SAVE_DMP: workingDirIns=fileDialog->getPath()+DIR_SEPARATOR_STR; break; @@ -4695,9 +4684,6 @@ bool FurnaceGUI::loop() { if (curFileDialog==GUI_FILE_INS_SAVE) { checkExtension(".fui"); } - if (curFileDialog==GUI_FILE_INS_SAVE_OLD) { - checkExtension(".fui"); - } if (curFileDialog==GUI_FILE_INS_SAVE_DMP) { checkExtension(".dmp"); } @@ -4791,11 +4777,6 @@ bool FurnaceGUI::loop() { e->song.ins[curIns]->save(copyOfName.c_str(),false,&e->song); } break; - case GUI_FILE_INS_SAVE_OLD: - if (curIns>=0 && curIns<(int)e->song.ins.size()) { - e->song.ins[curIns]->save(copyOfName.c_str(),true); - } - break; case GUI_FILE_INS_SAVE_DMP: if (curIns>=0 && curIns<(int)e->song.ins.size()) { if (!e->song.ins[curIns]->saveDMP(copyOfName.c_str())) { diff --git a/src/gui/gui.h b/src/gui/gui.h index c14bea088..65b1cc293 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -402,7 +402,6 @@ enum FurnaceGUIFileDialogs { GUI_FILE_INS_OPEN, GUI_FILE_INS_OPEN_REPLACE, GUI_FILE_INS_SAVE, - GUI_FILE_INS_SAVE_OLD, GUI_FILE_INS_SAVE_DMP, GUI_FILE_WAVE_OPEN, GUI_FILE_WAVE_OPEN_REPLACE, @@ -607,7 +606,6 @@ enum FurnaceGUIActions { GUI_ACTION_INS_LIST_OPEN, GUI_ACTION_INS_LIST_OPEN_REPLACE, GUI_ACTION_INS_LIST_SAVE, - GUI_ACTION_INS_LIST_SAVE_OLD, GUI_ACTION_INS_LIST_SAVE_DMP, GUI_ACTION_INS_LIST_MOVE_UP, GUI_ACTION_INS_LIST_MOVE_DOWN, diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index 7e7aecc18..09fe601d4 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -641,7 +641,6 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("INS_LIST_OPEN", "Open", 0), D("INS_LIST_OPEN_REPLACE", "Open (replace current)", 0), D("INS_LIST_SAVE", "Save", 0), - D("INS_LIST_SAVE_OLD", "Save (legacy .fui)", 0), D("INS_LIST_SAVE_DMP", "Save (.dmp)", 0), D("INS_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP), D("INS_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN), diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index e3997bf46..a490b0a6e 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2288,9 +2288,6 @@ void FurnaceGUI::drawInsEdit() { ImGui::SetTooltip("Save"); } if (ImGui::BeginPopupContextItem("InsSaveFormats",ImGuiMouseButton_Right)) { - if (ImGui::MenuItem("save in legacy format...")) { - doAction(GUI_ACTION_INS_LIST_SAVE_OLD); - } if (ImGui::MenuItem("save as .dmp...")) { doAction(GUI_ACTION_INS_LIST_SAVE_DMP); } @@ -5563,6 +5560,7 @@ void FurnaceGUI::drawInsEdit() { if (ins->type==DIV_INS_MSM6295) waveMax=0; if (ins->type==DIV_INS_SEGAPCM) waveMax=0; if (ins->type==DIV_INS_K007232) waveMax=0; + if (ins->type==DIV_INS_ES5506) waveMax=0; if (ins->type==DIV_INS_GA20) waveMax=0; if (ins->type==DIV_INS_K053260) waveMax=0; if (ins->type==DIV_INS_POKEMINI) waveMax=0; diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index 05f5af87a..356ac6f6a 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -991,7 +991,7 @@ void FurnaceGUI::initSystemPresets() { } ); ENTRY( - "PC + AdLib/Sound Blaster (drums mode)", { + "PC + Sound Blaster (drums mode)", { CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, ""), CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, ""), CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0,