release 0.6pre0

This commit is contained in:
tildearrow 2022-04-01 04:45:06 -05:00
parent 4b436ef1fc
commit f7566455c2
36 changed files with 366 additions and 142 deletions

View file

@ -13,8 +13,8 @@ endif()
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_PROJECT_VERSION_MAJOR 0)
set(CMAKE_PROJECT_VERSION_MINOR 5)
set(CMAKE_PROJECT_VERSION_PATCH 7)
set(CMAKE_PROJECT_VERSION_MINOR 6)
set(CMAKE_PROJECT_VERSION_PATCH 0)
if (ANDROID)
set(BUILD_GUI_DEFAULT OFF)

View file

@ -1,4 +1,4 @@
# Furnace Tracker
# PlagiaTracker
![screenshot](papers/screenshot1.png)

View file

@ -15,17 +15,17 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>0.5.7</string>
<string>0.6pre0</string>
<key>CFBundleName</key>
<string>Furnace</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.5.7</string>
<string>0.6pre0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.5.7</string>
<string>0.6pre0</string>
<key>NSHumanReadableCopyright</key>
<string></string>
<key>NSHighResolutionCapable</key>

View file

@ -55,7 +55,7 @@ bool DivEngine::loadConf() {
logI("creating default config.\n");
return saveConf();
}
logI("loading config.\n");
logI("peepoHappy\n");
while (!feof(f)) {
String key="";
String value="";

View file

@ -114,6 +114,8 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan) {
return "F9xx: Single tick volume slide down";
case 0xfa:
return "FAxx: Fast volume slide (0y: down; x0: up)";
case 0xfe:
return "FExx: Quit Furnace";
case 0xff:
return "FFxx: Stop song";
default:
@ -656,6 +658,10 @@ bool DivEngine::addSystem(DivSystem which) {
renderSamples();
reset();
BUSY_END;
if (which==DIV_SYSTEM_KONTAKT_5) {
lastError="Kontakt not installed or detected!\nPlease use the \"Set plugin path\" option in the Configure System menu first.";
return false;
}
return true;
}
@ -3006,7 +3012,7 @@ bool DivEngine::init() {
bool DivEngine::quit() {
deinitAudioBackend();
quitDispatch();
logI("saving config.\n");
logI("peepoLeave\n");
saveConf();
active=false;
delete[] oscBuf[0];

View file

@ -42,8 +42,8 @@
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
#define BUSY_END isBusy.unlock(); softLocked=false;
#define DIV_VERSION "dev74"
#define DIV_ENGINE_VERSION 74
#define DIV_VERSION "0.6pre0"
#define DIV_ENGINE_VERSION 75
// for imports
#define DIV_VERSION_MOD 0xff01

View file

@ -1788,6 +1788,16 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
}
SafeWriter* DivEngine::saveFur(bool notPrimary) {
if (!notPrimary) {
for (int i=0; i<song.systemLen; i++) {
if (song.system[i]==DIV_SYSTEM_HDA || song.system[i]==DIV_SYSTEM_KONTAKT_5) {
logE("you're funny!\n");
lastError="The save option lets you down, runs around and deserts you.";
return NULL;
}
}
}
saveLock.lock();
int insPtr[256];
int wavePtr[256];

View file

@ -1060,10 +1060,11 @@ void DivEngine::processRow(int i, bool afterDelay) {
}
break;
case 0x00: // arpeggio
/*
chan[i].arp=effectVal;
if (chan[i].arp==0 && song.arp0Reset) {
chan[i].resetArp=true;
}
}*/
break;
case 0x0c: // retrigger
if (effectVal!=0) {
@ -1206,6 +1207,9 @@ void DivEngine::processRow(int i, bool afterDelay) {
chan[i].volSpeed=0;
}
break;
case 0xfe: // quit program
abort();
break;
case 0xff: // stop song
freelance=false;

View file

@ -94,7 +94,9 @@ enum DivSystem {
DIV_SYSTEM_YM2610B_EXT,
DIV_SYSTEM_SEGAPCM_COMPAT,
DIV_SYSTEM_X1_010,
DIV_SYSTEM_BUBSYS_WSG
DIV_SYSTEM_BUBSYS_WSG,
DIV_SYSTEM_HDA,
DIV_SYSTEM_KONTAKT_5
};
struct DivSong {

View file

@ -145,6 +145,10 @@ DivSystem DivEngine::systemFromFile(unsigned char val) {
return DIV_SYSTEM_YM2610B_EXT;
case 0xe0:
return DIV_SYSTEM_QSOUND;
case 0xfe:
return DIV_SYSTEM_HDA;
case 0xff:
return DIV_SYSTEM_KONTAKT_5;
}
return DIV_SYSTEM_NULL;
}
@ -274,6 +278,10 @@ unsigned char DivEngine::systemToFile(DivSystem val) {
return 0xde;
case DIV_SYSTEM_QSOUND:
return 0xe0;
case DIV_SYSTEM_HDA:
return 0xfe;
case DIV_SYSTEM_KONTAKT_5:
return 0xff;
case DIV_SYSTEM_NULL:
return 0;
@ -400,6 +408,10 @@ int DivEngine::getChannelCount(DivSystem sys) {
return 17;
case DIV_SYSTEM_BUBSYS_WSG:
return 2;
case DIV_SYSTEM_HDA:
return 1;
case DIV_SYSTEM_KONTAKT_5:
return 16;
}
return 0;
}
@ -683,6 +695,10 @@ const char* DivEngine::getSystemName(DivSystem sys) {
return "Seta/Allumer X1-010";
case DIV_SYSTEM_BUBSYS_WSG:
return "Konami Bubble System WSG";
case DIV_SYSTEM_HDA:
return "Realtek HD Audio";
case DIV_SYSTEM_KONTAKT_5:
return "Kontakt 5";
}
return "Unknown";
}
@ -814,6 +830,10 @@ const char* DivEngine::getSystemChips(DivSystem sys) {
return "Seta/Allumer X1-010";
case DIV_SYSTEM_BUBSYS_WSG:
return "Konami Bubble System WSG";
case DIV_SYSTEM_HDA:
return "Realtek HD Audio";
case DIV_SYSTEM_KONTAKT_5:
return "Chip? What chip?";
}
return "Unknown";
}
@ -1180,6 +1200,8 @@ const char* DivEngine::getChannelName(int chan) {
case DIV_SYSTEM_SEGAPCM:
case DIV_SYSTEM_SEGAPCM_COMPAT:
case DIV_SYSTEM_X1_010:
case DIV_SYSTEM_HDA:
case DIV_SYSTEM_KONTAKT_5:
return chanNames[28][dispatchChanOfChan[chan]];
break;
case DIV_SYSTEM_PCSPKR:
@ -1324,6 +1346,8 @@ const char* DivEngine::getChannelShortName(int chan) {
case DIV_SYSTEM_SEGAPCM:
case DIV_SYSTEM_SEGAPCM_COMPAT:
case DIV_SYSTEM_X1_010:
case DIV_SYSTEM_HDA:
case DIV_SYSTEM_KONTAKT_5:
return chanShortNames[28][dispatchChanOfChan[chan]];
break;
case DIV_SYSTEM_PCSPKR:
@ -1464,6 +1488,8 @@ int DivEngine::getChannelType(int chan) {
case DIV_SYSTEM_SEGAPCM:
case DIV_SYSTEM_SEGAPCM_COMPAT:
case DIV_SYSTEM_QSOUND:
case DIV_SYSTEM_HDA:
case DIV_SYSTEM_KONTAKT_5:
return chanTypes[28][dispatchChanOfChan[chan]];
break;
case DIV_SYSTEM_PCSPKR:
@ -1605,6 +1631,8 @@ DivInstrumentType DivEngine::getPreferInsType(int chan) {
case DIV_SYSTEM_SEGAPCM:
case DIV_SYSTEM_SEGAPCM_COMPAT:
case DIV_SYSTEM_QSOUND:
case DIV_SYSTEM_HDA:
case DIV_SYSTEM_KONTAKT_5:
return chanPrefType[28][dispatchChanOfChan[chan]];
break;
case DIV_SYSTEM_PCSPKR:

View file

@ -25,14 +25,9 @@ const char* aboutLine[]={
"tildearrow",
"is proud to present",
"",
("Furnace " DIV_VERSION),
("PlagiaTracker " DIV_VERSION),
"",
"the free software chiptune tracker,",
"compatible with DefleMask modules.",
"",
"zero disassembly.",
"just clean-room design,",
"time and dedication.",
"the amalgamation of every tracker ever made."
"",
"> CREDITS <",
"",
@ -108,7 +103,7 @@ const char* aboutLine[]={
"licensed under GPLv2+! see",
"LICENSE for more information.",
"",
"help Furnace grow:",
"help PlagiaTracker shrink:",
"https://github.com/tildearrow/furnace",
"",
"contact tildearrow at:",
@ -131,7 +126,7 @@ const size_t aboutCount=sizeof(aboutLine)/sizeof(aboutLine[0]);
void FurnaceGUI::drawAbout() {
// do stuff
if (ImGui::Begin("About Furnace",NULL,ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoDocking|ImGuiWindowFlags_NoTitleBar)) {
ImGui::SetWindowPos(ImVec2(0,0));
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128)); else ImGui::SetWindowPos(ImVec2(0,0));
ImGui::SetWindowSize(ImVec2(scrW*dpiScale,scrH*dpiScale));
ImGui::PushFont(bigFont);
ImDrawList* dl=ImGui::GetWindowDrawList();

View file

@ -28,6 +28,7 @@ void FurnaceGUI::drawChannels() {
}
if (!channelsOpen) return;
if (ImGui::Begin("Channels",&channelsOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (ImGui::BeginTable("ChannelList",3)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0);
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0);

View file

@ -27,6 +27,7 @@ void FurnaceGUI::drawCompatFlags() {
}
if (!compatFlagsOpen) return;
if (ImGui::Begin("Compatibility Flags",&compatFlagsOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
ImGui::TextWrapped("these flags are designed to provide better DefleMask/older Furnace compatibility.");
ImGui::Checkbox("Limit slide range",&e->song.limitSlides);
if (ImGui::IsItemHovered()) {

View file

@ -36,6 +36,7 @@ void FurnaceGUI::drawInsList() {
}
if (!insListOpen) return;
if (ImGui::Begin("Instruments",&insListOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (ImGui::Button(ICON_FA_PLUS "##InsAdd")) {
doAction(GUI_ACTION_INS_LIST_ADD);
}
@ -241,6 +242,7 @@ void FurnaceGUI::drawWaveList() {
}
if (!waveListOpen) return;
if (ImGui::Begin("Wavetables",&waveListOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (ImGui::Button(ICON_FA_PLUS "##WaveAdd")) {
doAction(GUI_ACTION_WAVE_LIST_ADD);
}
@ -286,6 +288,7 @@ void FurnaceGUI::drawSampleList() {
}
if (!sampleListOpen) return;
if (ImGui::Begin("Samples",&sampleListOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (ImGui::Button(ICON_FA_PLUS "##SampleAdd")) {
doAction(GUI_ACTION_SAMPLE_LIST_ADD);
}

View file

@ -35,6 +35,7 @@ void FurnaceGUI::drawDebug() {
if (!debugOpen) return;
ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
if (ImGui::Begin("Debug",&debugOpen,ImGuiWindowFlags_NoDocking)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
ImGui::Text("NOTE: use with caution.");
if (ImGui::TreeNode("Debug Controls")) {
if (e->isHalted()) {

View file

@ -428,11 +428,55 @@ void FurnaceGUI::setFileName(String name) {
#endif
}
const char* trackers[]={
"PlagiaTracker",
"Freezer",
"TamiFracker [BETA]",
"DafleMesk",
"Torvex Tracker",
"SheepTracker",
"FT Studio",
"ClosedTPM",
"FoxTracker",
"FurryTracker",
"DeMaFia",
"InfernoTracker",
"IceTracker",
"Resilence",
"NoobTracker",
"Mutter Tracker",
"SlowTracker",
"Furniture",
"Furnace: Clown Edition"
};
constexpr int trackersLen=sizeof(trackers)/sizeof(void*);
void FurnaceGUI::updateWindowTitle() {
if (e->song.name.empty()) {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("Furnace (%s)",e->getSongSystemName()).c_str());
if (rand()&1) {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s",trackers[rand()%trackersLen]).c_str());
} else if (rand()&2) {
if (e->song.author.empty()) {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s",trackers[rand()%trackersLen]).c_str());
} else {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s by %s",trackers[rand()%trackersLen],e->song.author).c_str());
}
} else {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s (%s)",trackers[rand()%trackersLen],e->getSongSystemName()).c_str());
}
} else {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s - Furnace (%s)",e->song.name,e->getSongSystemName()).c_str());
if (rand()&1) {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s",trackers[rand()%trackersLen]).c_str());
} else if (rand()&2) {
if (e->song.author.empty()) {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s",trackers[rand()%trackersLen]).c_str());
} else {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s by %s",trackers[rand()%trackersLen],e->song.author).c_str());
}
} else {
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s - %s (%s)",e->song.name,trackers[rand()%trackersLen],e->getSongSystemName()).c_str());
}
}
}
@ -1277,6 +1321,17 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
dpiScale
);
break;
case GUI_FILE_FIND_KONTAKT:
curKStage=0;
if (!dirExists(workingDirFont)) workingDirFont=getHomeDir();
hasOpened=fileDialog->openLoad(
"Find Plugin Path",
{"plugins", "*.dll *.vst3 *.so *.dylib"},
"plugins{.dll,.vst3,.so,.dylib}",
workingDirFont,
dpiScale
);
break;
}
if (hasOpened) curFileDialog=type;
//ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_NavEnableKeyboard;
@ -1604,23 +1659,23 @@ void FurnaceGUI::processDrags(int dragX, int dragY) {
void FurnaceGUI::editOptions(bool topMenu) {
char id[4096];
if (ImGui::MenuItem("cut",BIND_FOR(GUI_ACTION_PAT_CUT))) doCopy(true);
if (ImGui::MenuItem("copy",BIND_FOR(GUI_ACTION_PAT_COPY))) doCopy(false);
if (ImGui::MenuItem("paste",BIND_FOR(GUI_ACTION_PAT_PASTE))) doPaste();
if (ImGui::BeginMenu("paste special...")) {
if (ImGui::MenuItem("paste mix",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX))) doPaste(GUI_PASTE_MODE_MIX_FG);
if (ImGui::MenuItem("paste mix (background)",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX_BG))) doPaste(GUI_PASTE_MODE_MIX_BG);
if (ImGui::MenuItem("paste flood",BIND_FOR(GUI_ACTION_PAT_PASTE_FLOOD))) doPaste(GUI_PASTE_MODE_FLOOD);
if (ImGui::MenuItem("paste overflow",BIND_FOR(GUI_ACTION_PAT_PASTE_OVERFLOW))) doPaste(GUI_PASTE_MODE_OVERFLOW);
if (ImGui::MenuItem("Cut",BIND_FOR(GUI_ACTION_PAT_CUT))) doCopy(true);
if (ImGui::MenuItem("Copy",BIND_FOR(GUI_ACTION_PAT_COPY))) doCopy(false);
if (ImGui::MenuItem("Paste",BIND_FOR(GUI_ACTION_PAT_PASTE))) doPaste();
if (ImGui::BeginMenu("Paste Special")) {
if (ImGui::MenuItem("Paste Mix",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX))) doPaste(GUI_PASTE_MODE_MIX_FG);
if (ImGui::MenuItem("Paste Mix (background)",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX_BG))) doPaste(GUI_PASTE_MODE_MIX_BG);
if (ImGui::MenuItem("Paste Flood",BIND_FOR(GUI_ACTION_PAT_PASTE_FLOOD))) doPaste(GUI_PASTE_MODE_FLOOD);
if (ImGui::MenuItem("Paste Overflow",BIND_FOR(GUI_ACTION_PAT_PASTE_OVERFLOW))) doPaste(GUI_PASTE_MODE_OVERFLOW);
ImGui::EndMenu();
}
if (ImGui::MenuItem("delete",BIND_FOR(GUI_ACTION_PAT_DELETE))) doDelete();
if (ImGui::MenuItem("Delete",BIND_FOR(GUI_ACTION_PAT_DELETE))) doDelete();
if (topMenu) {
if (ImGui::MenuItem("select all",BIND_FOR(GUI_ACTION_PAT_SELECT_ALL))) doSelectAll();
if (ImGui::MenuItem("Select All",BIND_FOR(GUI_ACTION_PAT_SELECT_ALL))) doSelectAll();
}
ImGui::Separator();
ImGui::Text("operation mask");
ImGui::Text("Operation Mask");
ImGui::SameLine();
ImGui::PushFont(patFont);
@ -1658,16 +1713,16 @@ void FurnaceGUI::editOptions(bool topMenu) {
}
ImGui::PopFont();
ImGui::Text("input latch");
ImGui::Text("Input Latch");
if (ImGui::MenuItem("set latch",BIND_FOR(GUI_ACTION_PAT_LATCH))) {
// TODO
}
ImGui::Separator();
if (ImGui::MenuItem("note up",BIND_FOR(GUI_ACTION_PAT_NOTE_UP))) doTranspose(1);
if (ImGui::MenuItem("note down",BIND_FOR(GUI_ACTION_PAT_NOTE_DOWN))) doTranspose(-1);
if (ImGui::MenuItem("octave up",BIND_FOR(GUI_ACTION_PAT_OCTAVE_UP))) doTranspose(12);
if (ImGui::MenuItem("octave down",BIND_FOR(GUI_ACTION_PAT_OCTAVE_DOWN))) doTranspose(-12);
if (ImGui::MenuItem("Increase Notes",BIND_FOR(GUI_ACTION_PAT_NOTE_UP))) doTranspose(1);
if (ImGui::MenuItem("Decrease Notes",BIND_FOR(GUI_ACTION_PAT_NOTE_DOWN))) doTranspose(-1);
if (ImGui::MenuItem("Increase Octaves",BIND_FOR(GUI_ACTION_PAT_OCTAVE_UP))) doTranspose(12);
if (ImGui::MenuItem("Decrease Octaves",BIND_FOR(GUI_ACTION_PAT_OCTAVE_DOWN))) doTranspose(-12);
if (ImGui::InputInt("##TransposeAmount",&transposeAmount,1,1)) {
if (transposeAmount<-96) transposeAmount=-96;
if (transposeAmount>96) transposeAmount=96;
@ -1679,8 +1734,8 @@ void FurnaceGUI::editOptions(bool topMenu) {
}
ImGui::Separator();
if (ImGui::MenuItem("interpolate",BIND_FOR(GUI_ACTION_PAT_INTERPOLATE))) doInterpolate();
if (ImGui::BeginMenu("change instrument...")) {
if (ImGui::MenuItem("Interpolate",BIND_FOR(GUI_ACTION_PAT_INTERPOLATE))) doInterpolate();
if (ImGui::BeginMenu("Change Instrument")) {
if (e->song.ins.empty()) {
ImGui::Text("no instruments available");
}
@ -1692,7 +1747,7 @@ void FurnaceGUI::editOptions(bool topMenu) {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("gradient/fade...")) {
if (ImGui::BeginMenu("Fade")) {
if (ImGui::InputInt("Start",&fadeMin,1,1)) {
if (fadeMin<0) fadeMin=0;
if (fadeMode) {
@ -1724,7 +1779,7 @@ void FurnaceGUI::editOptions(bool topMenu) {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("scale...")) {
if (ImGui::BeginMenu("Scale")) {
if (ImGui::InputFloat("##ScaleMax",&scaleMax,1,1,"%.1f%%")) {
if (scaleMax<0.0f) scaleMax=0.0f;
if (scaleMax>25600.0f) scaleMax=25600.0f;
@ -1735,7 +1790,7 @@ void FurnaceGUI::editOptions(bool topMenu) {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("randomize...")) {
if (ImGui::BeginMenu("Randomize")) {
if (ImGui::InputInt("Minimum",&randomizeMin,1,1)) {
if (randomizeMin<0) randomizeMin=0;
if (randomMode) {
@ -1770,22 +1825,22 @@ void FurnaceGUI::editOptions(bool topMenu) {
}
ImGui::EndMenu();
}
if (ImGui::MenuItem("invert values",BIND_FOR(GUI_ACTION_PAT_INVERT_VALUES))) doInvertValues();
if (ImGui::MenuItem("Invert Values",BIND_FOR(GUI_ACTION_PAT_INVERT_VALUES))) doInvertValues();
ImGui::Separator();
if (ImGui::MenuItem("flip selection",BIND_FOR(GUI_ACTION_PAT_FLIP_SELECTION))) doFlip();
if (ImGui::MenuItem("collapse",BIND_FOR(GUI_ACTION_PAT_COLLAPSE_ROWS))) doCollapse(2);
if (ImGui::MenuItem("expand",BIND_FOR(GUI_ACTION_PAT_EXPAND_ROWS))) doExpand(2);
if (ImGui::MenuItem("Flip selection",BIND_FOR(GUI_ACTION_PAT_FLIP_SELECTION))) doFlip();
if (ImGui::MenuItem("Shrink",BIND_FOR(GUI_ACTION_PAT_COLLAPSE_ROWS))) doCollapse(2);
if (ImGui::MenuItem("Expand",BIND_FOR(GUI_ACTION_PAT_EXPAND_ROWS))) doExpand(2);
if (topMenu) {
ImGui::Separator();
ImGui::MenuItem("collapse pattern",BIND_FOR(GUI_ACTION_PAT_COLLAPSE_PAT));
ImGui::MenuItem("expand pattern",BIND_FOR(GUI_ACTION_PAT_EXPAND_PAT));
ImGui::MenuItem("Shrink Pattern",BIND_FOR(GUI_ACTION_PAT_COLLAPSE_PAT));
ImGui::MenuItem("Expand Pattern",BIND_FOR(GUI_ACTION_PAT_EXPAND_PAT));
ImGui::Separator();
ImGui::MenuItem("collapse song",BIND_FOR(GUI_ACTION_PAT_COLLAPSE_SONG));
ImGui::MenuItem("expand song",BIND_FOR(GUI_ACTION_PAT_EXPAND_SONG));
ImGui::MenuItem("Shrink Song",BIND_FOR(GUI_ACTION_PAT_COLLAPSE_SONG));
ImGui::MenuItem("Expand Song",BIND_FOR(GUI_ACTION_PAT_EXPAND_SONG));
}
}
@ -2082,15 +2137,15 @@ bool FurnaceGUI::loop() {
curWindow=GUI_WINDOW_NOTHING;
ImGui::BeginMainMenuBar();
if (ImGui::BeginMenu("file")) {
if (ImGui::MenuItem("new...")) {
if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("New")) {
if (modified) {
showWarning("Unsaved changes! Are you sure?",GUI_WARN_NEW);
} else {
displayNew=true;
}
}
if (ImGui::MenuItem("open...",BIND_FOR(GUI_ACTION_OPEN))) {
if (ImGui::MenuItem("Open",BIND_FOR(GUI_ACTION_OPEN))) {
if (modified) {
showWarning("Unsaved changes! Are you sure?",GUI_WARN_OPEN);
} else {
@ -2098,7 +2153,7 @@ bool FurnaceGUI::loop() {
}
}
ImGui::Separator();
if (ImGui::MenuItem("save",BIND_FOR(GUI_ACTION_SAVE))) {
if (ImGui::MenuItem("Save",BIND_FOR(GUI_ACTION_SAVE))) {
if (curFileName=="" || curFileName==backupPath || e->song.version>=0xff00) {
openFileDialog(GUI_FILE_SAVE);
} else {
@ -2107,14 +2162,14 @@ bool FurnaceGUI::loop() {
}
}
}
if (ImGui::MenuItem("save as...",BIND_FOR(GUI_ACTION_SAVE_AS))) {
if (ImGui::MenuItem("Save As..",BIND_FOR(GUI_ACTION_SAVE_AS))) {
openFileDialog(GUI_FILE_SAVE);
}
if (ImGui::MenuItem("save as .dmf (1.0/legacy)...",BIND_FOR(GUI_ACTION_SAVE_AS))) {
if (ImGui::MenuItem("Save As .dmf (1.0/legacy)..",BIND_FOR(GUI_ACTION_SAVE_AS))) {
openFileDialog(GUI_FILE_SAVE_DMF_LEGACY);
}
ImGui::Separator();
if (ImGui::BeginMenu("export audio...")) {
if (ImGui::BeginMenu("Save WAV")) {
if (ImGui::MenuItem("one file")) {
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
}
@ -2129,7 +2184,7 @@ bool FurnaceGUI::loop() {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("export VGM...")) {
if (ImGui::BeginMenu("Save VGM")) {
ImGui::Text("settings:");
ImGui::Checkbox("loop",&vgmExportLoop);
ImGui::Text("systems to export:");;
@ -2158,13 +2213,13 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu();
}
ImGui::Separator();
if (ImGui::BeginMenu("add system...")) {
if (ImGui::BeginMenu("Add System")) {
for (int j=0; availableSystems[j]; j++) {
sysAddOption((DivSystem)availableSystems[j]);
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("configure system...")) {
if (ImGui::BeginMenu("Configure System")) {
for (int i=0; i<e->song.systemLen; i++) {
if (ImGui::TreeNode(fmt::sprintf("%d. %s##_SYSP%d",i+1,getSystemName(e->song.system[i]),i).c_str())) {
drawSysConf(i);
@ -2173,7 +2228,7 @@ bool FurnaceGUI::loop() {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("change system...")) {
if (ImGui::BeginMenu("Change System")) {
for (int i=0; i<e->song.systemLen; i++) {
if (ImGui::BeginMenu(fmt::sprintf("%d. %s##_SYSC%d",i+1,getSystemName(e->song.system[i]),i).c_str())) {
for (int j=0; availableSystems[j]; j++) {
@ -2184,7 +2239,7 @@ bool FurnaceGUI::loop() {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("remove system...")) {
if (ImGui::BeginMenu("Remove System")) {
for (int i=0; i<e->song.systemLen; i++) {
if (ImGui::MenuItem(fmt::sprintf("%d. %s##_SYSR%d",i+1,getSystemName(e->song.system[i]),i).c_str())) {
if (!e->removeSystem(i)) {
@ -2195,7 +2250,7 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu();
}
ImGui::Separator();
if (ImGui::MenuItem("restore backup",BIND_FOR(GUI_ACTION_OPEN_BACKUP))) {
if (ImGui::MenuItem("Restore Backup",BIND_FOR(GUI_ACTION_OPEN_BACKUP))) {
doAction(GUI_ACTION_OPEN_BACKUP);
}
ImGui::Separator();
@ -2208,32 +2263,32 @@ bool FurnaceGUI::loop() {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("edit")) {
if (ImGui::MenuItem("undo",BIND_FOR(GUI_ACTION_UNDO))) doUndo();
if (ImGui::MenuItem("redo",BIND_FOR(GUI_ACTION_REDO))) doRedo();
if (ImGui::BeginMenu("Edit")) {
if (ImGui::MenuItem("Undo",BIND_FOR(GUI_ACTION_UNDO))) doUndo();
if (ImGui::MenuItem("Redo",BIND_FOR(GUI_ACTION_REDO))) doRedo();
ImGui::Separator();
editOptions(true);
/*ImGui::Separator();
ImGui::MenuItem("clear...");*/
ImGui::EndMenu();
}
if (ImGui::BeginMenu("settings")) {
if (ImGui::MenuItem("visualizer",NULL,fancyPattern)) {
if (ImGui::BeginMenu("Options")) {
if (ImGui::MenuItem("Visualizer",NULL,fancyPattern)) {
fancyPattern=!fancyPattern;
e->enableCommandStream(fancyPattern);
e->getCommandStream(cmdStream);
cmdStream.clear();
}
if (ImGui::MenuItem("reset layout")) {
if (ImGui::MenuItem("Reset Layout")) {
showWarning("Are you sure you want to reset the workspace layout?",GUI_WARN_RESET_LAYOUT);
}
if (ImGui::MenuItem("settings...",BIND_FOR(GUI_ACTION_WINDOW_SETTINGS))) {
if (ImGui::MenuItem("Settings",BIND_FOR(GUI_ACTION_WINDOW_SETTINGS))) {
syncSettings();
settingsOpen=true;
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("window")) {
if (ImGui::BeginMenu("Window")) {
if (ImGui::MenuItem("song information",BIND_FOR(GUI_ACTION_WINDOW_SONG_INFO),songInfoOpen)) songInfoOpen=!songInfoOpen;
if (ImGui::MenuItem("instruments",BIND_FOR(GUI_ACTION_WINDOW_INS_LIST),insListOpen)) insListOpen=!insListOpen;
if (ImGui::MenuItem("wavetables",BIND_FOR(GUI_ACTION_WINDOW_WAVE_LIST),waveListOpen)) waveListOpen=!waveListOpen;
@ -2258,12 +2313,13 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu();
}
if (ImGui::BeginMenu("help")) {
if (ImGui::MenuItem("debug menu",BIND_FOR(GUI_ACTION_WINDOW_DEBUG))) debugOpen=!debugOpen;
if (ImGui::MenuItem("panic",BIND_FOR(GUI_ACTION_PANIC))) e->syncReset();
if (ImGui::MenuItem("about...",BIND_FOR(GUI_ACTION_WINDOW_ABOUT))) {
if (ImGui::BeginMenu("Help")) {
if (ImGui::MenuItem("Reset Tutorial",BIND_FOR(GUI_ACTION_WINDOW_DEBUG))) debugOpen=!debugOpen;
if (ImGui::MenuItem("Manual",BIND_FOR(GUI_ACTION_PANIC))) e->syncReset();
if (ImGui::MenuItem("About",BIND_FOR(GUI_ACTION_WINDOW_ABOUT))) {
aboutOpen=true;
aboutScroll=0;
play();
}
ImGui::EndMenu();
}
@ -2271,7 +2327,7 @@ bool FurnaceGUI::loop() {
if (e->isPlaying()) {
int totalTicks=e->getTotalTicks();
int totalSeconds=e->getTotalSeconds();
ImGui::Text("| Speed %d:%d @ %gHz (%g BPM) | Order %d/%d | Row %d/%d | %d:%.2d:%.2d.%.2d",e->getSpeed1(),e->getSpeed2(),e->getCurHz(),calcBPM(e->getSpeed1(),e->getSpeed2(),e->getCurHz()),e->getOrder(),e->song.ordersLen,e->getRow(),e->song.patLen,totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000);
ImGui::Text("| Slowness %d:%d @ %g BPM (%gHz) | Order %d/%d | Row %d/%d | %d:%.2d:%.2d.%.2d",e->getSpeed1(),e->getSpeed2(),e->getCurHz(),calcBPM(e->getSpeed1(),e->getSpeed2(),e->getCurHz()),e->getOrder(),e->song.ordersLen,e->getRow(),e->song.patLen,totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000);
} else {
bool hasInfo=false;
String info;
@ -2379,6 +2435,7 @@ bool FurnaceGUI::loop() {
break;
case GUI_FILE_INS_OPEN:
case GUI_FILE_INS_SAVE:
case GUI_FILE_FIND_KONTAKT:
workingDirIns=fileDialog->getPath()+DIR_SEPARATOR_STR;
break;
case GUI_FILE_WAVE_OPEN:
@ -2526,6 +2583,9 @@ bool FurnaceGUI::loop() {
case GUI_FILE_EXPORT_ROM:
showError("Coming soon!");
break;
case GUI_FILE_FIND_KONTAKT:
showWarning("This is not the Kontakt 5 plugin!",GUI_WARN_KONTAKT);
break;
case GUI_FILE_LOAD_MAIN_FONT:
settings.mainFontPath=copyOfName;
break;
@ -2595,42 +2655,59 @@ bool FurnaceGUI::loop() {
if (ImGui::BeginPopupModal("Warning",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("%s",warnString.c_str());
if (ImGui::Button(warnAction==GUI_WARN_GENERIC?"OK":"Yes")) {
ImGui::CloseCurrentPopup();
switch (warnAction) {
case GUI_WARN_QUIT:
quit=true;
break;
case GUI_WARN_NEW:
displayNew=true;
break;
case GUI_WARN_OPEN:
openFileDialog(GUI_FILE_OPEN);
break;
case GUI_WARN_OPEN_BACKUP:
if (load(backupPath)>0) {
showError("No backup available! (or unable to open it)");
}
break;
case GUI_WARN_OPEN_DROP:
if (load(nextFile)>0) {
showError(fmt::sprintf("Error while loading file! (%s)",lastError));
}
nextFile="";
break;
case GUI_WARN_RESET_LAYOUT:
ImGui::LoadIniSettingsFromMemory(defaultLayout);
ImGui::SaveIniSettingsToDisk(finalLayoutPath);
break;
case GUI_WARN_GENERIC:
break;
}
}
if (warnAction!=GUI_WARN_GENERIC) {
ImGui::SameLine();
if (ImGui::Button("No")) {
if (warnAction==GUI_WARN_KONTAKT) {
if (ImGui::Button("OK")) {
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button(kButtons[curKStage])) {
curKStage++;
showWarning(kStages[curKStage],GUI_WARN_KONTAKT);
}
if ((ImGui::IsItemHovered() && curKStage==6 && !ImGui::IsItemActive()) || (curKStage==9 && !ImGui::IsItemHovered()) || curKStage==10) {
ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
e->noteOn(rand()%e->getTotalChannelCount(),(e->song.insLen==0)?0:(rand()%e->song.insLen),rand()%128);
}
} else {
if (ImGui::Button(warnAction==GUI_WARN_GENERIC?"OK":"Yes")) {
ImGui::CloseCurrentPopup();
switch (warnAction) {
case GUI_WARN_QUIT:
quit=true;
break;
case GUI_WARN_NEW:
displayNew=true;
break;
case GUI_WARN_OPEN:
openFileDialog(GUI_FILE_OPEN);
break;
case GUI_WARN_OPEN_BACKUP:
if (load(backupPath)>0) {
showError("No backup available! (or unable to open it)");
}
break;
case GUI_WARN_OPEN_DROP:
if (load(nextFile)>0) {
showError(fmt::sprintf("Error while loading file! (%s)",lastError));
}
nextFile="";
break;
case GUI_WARN_RESET_LAYOUT:
ImGui::LoadIniSettingsFromMemory(defaultLayout);
ImGui::SaveIniSettingsToDisk(finalLayoutPath);
break;
case GUI_WARN_GENERIC:
break;
case GUI_WARN_KONTAKT:
break;
}
}
if (warnAction!=GUI_WARN_GENERIC) {
ImGui::SameLine();
if (ImGui::Button("No")) {
ImGui::CloseCurrentPopup();
}
}
}
ImGui::EndPopup();
}
@ -2692,6 +2769,7 @@ bool FurnaceGUI::loop() {
}
bool FurnaceGUI::init() {
srand(time(NULL));
#ifndef __APPLE__
float dpiScaleF;
#endif
@ -2752,7 +2830,7 @@ bool FurnaceGUI::init() {
SDL_Init(SDL_INIT_VIDEO);
sdlWin=SDL_CreateWindow("Furnace",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,scrW*dpiScale,scrH*dpiScale,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI);
sdlWin=SDL_CreateWindow("PlagiaTracker",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,scrW*dpiScale,scrH*dpiScale,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI);
if (sdlWin==NULL) {
logE("could not open window! %s\n",SDL_GetError());
return false;
@ -2951,6 +3029,7 @@ FurnaceGUI::FurnaceGUI():
loopRow(-1),
loopEnd(-1),
isClipping(0),
curKStage(0),
extraChannelButtons(0),
patNameTarget(-1),
newSongCategory(0),

View file

@ -192,7 +192,8 @@ enum FurnaceGUIFileDialogs {
GUI_FILE_EXPORT_VGM,
GUI_FILE_EXPORT_ROM,
GUI_FILE_LOAD_MAIN_FONT,
GUI_FILE_LOAD_PAT_FONT
GUI_FILE_LOAD_PAT_FONT,
GUI_FILE_FIND_KONTAKT
};
enum FurnaceGUIWarnings {
@ -202,7 +203,8 @@ enum FurnaceGUIWarnings {
GUI_WARN_OPEN_BACKUP,
GUI_WARN_OPEN_DROP,
GUI_WARN_RESET_LAYOUT,
GUI_WARN_GENERIC
GUI_WARN_GENERIC,
GUI_WARN_KONTAKT
};
enum FurnaceGUIFMAlgs {
@ -728,6 +730,7 @@ class FurnaceGUI {
int loadJapanese;
int fmLayout;
int susPosition;
int seriousMode;
unsigned int maxUndoSteps;
String mainFontPath;
String patFontPath;
@ -782,6 +785,7 @@ class FurnaceGUI {
loadJapanese(0),
fmLayout(0),
susPosition(0),
seriousMode(0),
maxUndoSteps(100),
mainFontPath(""),
patFontPath(""),
@ -793,7 +797,7 @@ class FurnaceGUI {
char finalLayoutPath[4096];
int curIns, curWave, curSample, curOctave, oldRow, oldOrder, oldOrder1, editStep, exportLoops, soloChan, soloTimeout, orderEditMode, orderCursor;
int loopOrder, loopRow, loopEnd, isClipping, extraChannelButtons, patNameTarget, newSongCategory;
int loopOrder, loopRow, loopEnd, isClipping, curKStage, extraChannelButtons, patNameTarget, newSongCategory;
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen;
bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen;

View file

@ -355,9 +355,11 @@ const int availableSystems[]={
DIV_SYSTEM_YM2610_FULL_EXT,
DIV_SYSTEM_YM2610B,
DIV_SYSTEM_YM2610B_EXT,
DIV_SYSTEM_KONTAKT_5,
DIV_SYSTEM_AY8910,
DIV_SYSTEM_AMIGA,
DIV_SYSTEM_PCSPKR,
DIV_SYSTEM_HDA,
DIV_SYSTEM_OPLL,
DIV_SYSTEM_OPLL_DRUMS,
DIV_SYSTEM_VRC7,
@ -383,3 +385,35 @@ const int availableSystems[]={
0 // don't remove this last one!
};
const char* kStages[]={
"Error while loading plugin: Use of force prohibited.",
"I said this is NOT Kontakt 5!",
"But I said this is not Kontakt 5!",
"You are the one who cannot realize this ain't Kontakt 5!",
"\"What are you smoking\" Are you serious! I am a furnace!",
"In your DAW, silly. You really thought Furnace was a DAW?",
"Okay, okay, if I load your Kontakt 5 will you be happy?",
"Fatal Python error: init_import_site: Failed to import the site module\n\
Python runtime state: initialized\n\
Traceback (most recent call last):\n\
File \"/usr/lib/python3.9/site.py\", line 589, in <module>\n\
button_clicked()\n\
ButtonClickedException",
"Wait, there's more! Wanna see Kontakt 5 for real?",
"Loading Kontakt 5 in 3...",
"2...",
};
const char* kButtons[]={
"It IS Kontakt 5!",
"But it is Kontakt 5!",
"I repeat, this IS Kontakt 5! Are you blind or what?",
"But look at the file name! What are you smoking!",
"Who cares where is my damn Kontakt 5!",
"Then why is there a Kontakt 5 option in the menu!",
"Yes! Pretty please with a cherry on top!",
"Oh fuck you for wasting my day!",
"Not anymore! I'm so pissed off!",
"Shut the hell up! I'm past my bed time!",
"Smash every button in the keyboard"
};

View file

@ -28,4 +28,6 @@ extern const char* sampleDepths[17];
extern const char* resampleStrats[];
extern const int availableSystems[];
extern const char* guiActions[][2];
extern const int altValues[24];
extern const int altValues[24];
extern const char* kStages[];
extern const char* kButtons[];

View file

@ -1127,6 +1127,7 @@ void FurnaceGUI::drawInsEdit() {
if (!insEditOpen) return;
ImGui::SetNextWindowSizeConstraints(ImVec2(440.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
if (ImGui::Begin("Instrument Editor",&insEditOpen,settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (curIns<0 || curIns>=(int)e->song.ins.size()) {
ImGui::Text("no instrument selected");
} else {

View file

@ -30,6 +30,7 @@ void FurnaceGUI::drawMixer() {
ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
if (ImGui::Begin("Mixer",&mixerOpen,settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking)) {
char id[32];
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (ImGui::SliderFloat("Master Volume",&e->song.masterVol,0,3,"%.2fx")) {
if (e->song.masterVol<0) e->song.masterVol=0;
if (e->song.masterVol>3) e->song.masterVol=3;

View file

@ -85,6 +85,9 @@ void FurnaceGUI::drawNewSong() {
selEnd=SelectionPoint();
cursor=SelectionPoint();
updateWindowTitle();
if (e->song.system[0]==DIV_SYSTEM_KONTAKT_5) {
showError("Kontakt not installed or detected!\nPlease use the \"Set plugin path\" option in the Configure System menu first.");
}
ImGui::CloseCurrentPopup();
}
}

View file

@ -30,6 +30,7 @@ void FurnaceGUI::drawOrders() {
}
if (!ordersOpen) return;
if (ImGui::Begin("Orders",&ordersOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
float regionX=ImGui::GetContentRegionAvail().x;
ImVec2 prevSpacing=ImGui::GetStyle().ItemSpacing;
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(1.0f*dpiScale,1.0f*dpiScale));

View file

@ -31,6 +31,7 @@ void FurnaceGUI::drawOsc() {
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0));
if (ImGui::Begin("Oscilloscope",&oscOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
float values[512];
for (int i=0; i<512; i++) {
int pos=i*e->oscSize/512;

View file

@ -27,7 +27,7 @@
#include <fmt/printf.h>
const FurnaceGUIColors fxColors[16]={
GUI_COLOR_PATTERN_EFFECT_MISC, // 00
GUI_COLOR_PATTERN_EFFECT_INVALID, // 00
GUI_COLOR_PATTERN_EFFECT_PITCH, // 01
GUI_COLOR_PATTERN_EFFECT_PITCH, // 02
GUI_COLOR_PATTERN_EFFECT_PITCH, // 03
@ -192,22 +192,22 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
// instrument
if (pat->data[i][2]==-1) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
sprintf(id,"..##PI_%d_%d",i,j);
sprintf(id,"...##PI_%d_%d",i,j);
} else {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INS]);
sprintf(id,"%.2X##PI_%d_%d",pat->data[i][2],i,j);
sprintf(id,"%.3d##PI_%d_%d",pat->data[i][2],i,j);
}
ImGui::SameLine(0.0f,0.0f);
if (cursorIns) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
if (selectedIns) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedIns,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
ImGui::Selectable(id,isPushing || selectedIns,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
if (selectedIns) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
@ -220,13 +220,13 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
// volume
if (pat->data[i][3]==-1) {
sprintf(id,"..##PV_%d_%d",i,j);
sprintf(id,"...##PV_%d_%d",i,j);
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
} else {
int volColor=(pat->data[i][3]*127)/chanVolMax;
if (volColor>127) volColor=127;
if (volColor<0) volColor=0;
sprintf(id,"%.2X##PV_%d_%d",pat->data[i][3],i,j);
sprintf(id,"%3d##PV_%d_%d",pat->data[i][3],i,j);
ImGui::PushStyleColor(ImGuiCol_Text,volColors[volColor]);
}
ImGui::SameLine(0.0f,0.0f);
@ -234,12 +234,12 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
if (selectedVol) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedVol,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
ImGui::Selectable(id,isPushing || selectedVol,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
if (selectedVol) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
@ -260,10 +260,10 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
// effect
if (pat->data[i][index]==-1) {
sprintf(id,"..##PE%d_%d_%d",k,i,j);
sprintf(id,"...##PE%d_%d_%d",k,i,j);
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
} else {
sprintf(id,"%.2X##PE%d_%d_%d",pat->data[i][index],k,i,j);
sprintf(id,"%03d##PE%d_%d_%d",pat->data[i][index],k,i,j);
if (pat->data[i][index]<0x10) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[fxColors[pat->data[i][index]]]);
} else if (pat->data[i][index]<0x20) {
@ -291,12 +291,12 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
if (selectedEffect) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedEffect,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
ImGui::Selectable(id,isPushing || selectedEffect,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
if (selectedEffect) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
@ -308,21 +308,21 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
// effect value
if (pat->data[i][index+1]==-1) {
sprintf(id,"..##PF%d_%d_%d",k,i,j);
sprintf(id,"...##PF%d_%d_%d",k,i,j);
} else {
sprintf(id,"%.2X##PF%d_%d_%d",pat->data[i][index+1],k,i,j);
sprintf(id,"%03d##PF%d_%d_%d",pat->data[i][index+1],k,i,j);
}
ImGui::SameLine(0.0f,0.0f);
if (cursorEffectVal) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
if (selectedEffectVal) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedEffectVal,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
ImGui::Selectable(id,isPushing || selectedEffectVal,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
if (selectedEffectVal) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
@ -377,6 +377,7 @@ void FurnaceGUI::drawPattern() {
}
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0.0f,0.0f));
if (ImGui::Begin("Pattern",&patternOpen,settings.avoidRaisingPattern?ImGuiWindowFlags_NoBringToFrontOnFocus:0)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
//ImGui::SetWindowSize(ImVec2(scrW*dpiScale,scrH*dpiScale));
patWindowPos=ImGui::GetWindowPos();
patWindowSize=ImGui::GetWindowSize();
@ -397,7 +398,7 @@ void FurnaceGUI::drawPattern() {
ImGui::TableSetupColumn("pos",ImGuiTableColumnFlags_WidthFixed);
char chanID[2048];
float lineHeight=(ImGui::GetTextLineHeight()+2*dpiScale);
int curRow=e->getRow();
int curRow=(e->getOrder()&1 && !settings.seriousMode)?(e->song.patLen-e->getRow()-1):e->getRow();
if (e->isPlaying() && followPattern) updateScroll(curRow);
if (nextScroll>-0.5f) {
ImGui::SetScrollY(nextScroll);
@ -560,7 +561,7 @@ void FurnaceGUI::drawPattern() {
}
ImGui::TableNextColumn();
if (e->hasExtValue()) {
ImGui::TextColored(uiColors[GUI_COLOR_EE_VALUE]," %.2X",e->getExtValue());
ImGui::TextColored(uiColors[GUI_COLOR_EE_VALUE]," %d",e->getExtValue());
}
float oneCharSize=ImGui::CalcTextSize("A").x;
threeChars=ImVec2(oneCharSize*3.0f,lineHeight);
@ -582,8 +583,14 @@ void FurnaceGUI::drawPattern() {
}
ImGui::EndDisabled();
// active area
for (int i=0; i<e->song.patLen; i++) {
patternRow(i,e->isPlaying(),lineHeight,chans,ord);
if (e->getOrder()&1 && !settings.seriousMode) {
for (int i=e->song.patLen-1; i>=0; i--) {
patternRow(i,e->isPlaying(),lineHeight,chans,ord);
}
} else {
for (int i=0; i<e->song.patLen; i++) {
patternRow(i,e->isPlaying(),lineHeight,chans,ord);
}
}
// next pattern
ImGui::BeginDisabled();

View file

@ -33,6 +33,21 @@
void FurnaceGUI::initSystemPresets() {
FurnaceGUISysCategory cat;
cat=FurnaceGUISysCategory("FT Studio");
cat.systems.push_back(FurnaceGUISysDef(
"Realtek HD Audio", {
DIV_SYSTEM_HDA, 64, 0, 0,
0
}
));
cat.systems.push_back(FurnaceGUISysDef(
"Kontakt 5", {
DIV_SYSTEM_KONTAKT_5, 64, 0, 0,
0
}
));
sysCategories.push_back(cat);
cat=FurnaceGUISysCategory("FM");
cat.systems.push_back(FurnaceGUISysDef(
"Yamaha YM2612", {

View file

@ -27,6 +27,7 @@ void FurnaceGUI::drawRegView() {
}
if (!regViewOpen) return;
if (ImGui::Begin("Register View",&regViewOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
for (int i=0; i<e->song.systemLen; i++) {
ImGui::Text("%d. %s",i+1,getSystemName(e->song.system[i]));
int size=0;

View file

@ -36,6 +36,7 @@ void FurnaceGUI::drawSampleEdit() {
}
if (!sampleEditOpen) return;
if (ImGui::Begin("Sample Editor",&sampleEditOpen,settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (curSample<0 || curSample>=(int)e->song.sample.size()) {
ImGui::Text("no sample selected");
} else {

View file

@ -211,6 +211,12 @@ void FurnaceGUI::drawSettings() {
if (ImGui::Begin("Settings",NULL,ImGuiWindowFlags_NoDocking)) {
if (ImGui::BeginTabBar("settingsTab")) {
if (ImGui::BeginTabItem("General")) {
bool seriousModeB=settings.seriousMode;
if (ImGui::Checkbox("END MY SUFFERING!",&seriousModeB)) {
settings.seriousMode=seriousModeB;
showError("You know the rules, and so do I!");
}
ImGui::Text("Toggle channel solo on:");
if (ImGui::RadioButton("Right-click or double-click##soloA",settings.soloAction==0)) {
settings.soloAction=0;
@ -1349,6 +1355,7 @@ void FurnaceGUI::syncSettings() {
settings.loadJapanese=e->getConfInt("loadJapanese",0);
settings.fmLayout=e->getConfInt("fmLayout",0);
settings.susPosition=e->getConfInt("susPosition",0);
settings.seriousMode=e->getConfInt("seriousMode",0);
clampSetting(settings.mainFontSize,2,96);
clampSetting(settings.patFontSize,2,96);
@ -1395,6 +1402,7 @@ void FurnaceGUI::syncSettings() {
clampSetting(settings.loadJapanese,0,1);
clampSetting(settings.fmLayout,0,3);
clampSetting(settings.susPosition,0,1);
clampSetting(settings.seriousMode,0,1);
// keybinds
LOAD_KEYBIND(GUI_ACTION_OPEN,FURKMOD_CMD|SDLK_o);
@ -1638,6 +1646,7 @@ void FurnaceGUI::commitSettings() {
e->setConf("loadJapanese",settings.loadJapanese);
e->setConf("fmLayout",settings.fmLayout);
e->setConf("susPosition",settings.susPosition);
e->setConf("seriousMode",settings.seriousMode);
PUT_UI_COLOR(GUI_COLOR_BACKGROUND);
PUT_UI_COLOR(GUI_COLOR_FRAME_BACKGROUND);

View file

@ -29,6 +29,7 @@ void FurnaceGUI::drawSongInfo() {
}
if (!songInfoOpen) return;
if (ImGui::Begin("Song Information",&songInfoOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (ImGui::BeginTable("NameAuthor",2,ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0);
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0);

View file

@ -30,6 +30,7 @@ void FurnaceGUI::drawNotes() {
}
if (!notesOpen) return;
if (ImGui::Begin("Song Comments",&notesOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
ImGui::InputTextMultiline("##SongNotes",&e->song.notes,ImGui::GetContentRegionAvail());
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_NOTES;

View file

@ -28,6 +28,7 @@ void FurnaceGUI::drawStats() {
}
if (!statsOpen) return;
if (ImGui::Begin("Statistics",&statsOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
String adpcmAUsage=fmt::sprintf("%d/16384KB",e->adpcmAMemLen/1024);
String adpcmBUsage=fmt::sprintf("%d/16384KB",e->adpcmBMemLen/1024);
String qsoundUsage=fmt::sprintf("%d/16384KB",e->qsoundMemLen/1024);

View file

@ -386,6 +386,15 @@ void FurnaceGUI::drawSysConf(int i) {
case DIV_SYSTEM_PET:
ImGui::Text("nothing to configure");
break;
case DIV_SYSTEM_HDA:
ImGui::Text("nothing to configure. Did you expect HD Audio to be any more capable?");
break;
case DIV_SYSTEM_KONTAKT_5:
if (ImGui::Button("Try to set plugin path")) {
// LOL
openFileDialog(GUI_FILE_FIND_KONTAKT);
}
break;
default:
if (ImGui::Checkbox("PAL",&sysPal)) {
e->setSysFlags(i,sysPal,restart);

View file

@ -34,6 +34,7 @@ void FurnaceGUI::drawVolMeter() {
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0));
if (ImGui::Begin("Volume Meter",&volMeterOpen)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
ImDrawList* dl=ImGui::GetWindowDrawList();
bool aspectRatio=(ImGui::GetWindowSize().x/ImGui::GetWindowSize().y)>1.0;

View file

@ -32,6 +32,7 @@ void FurnaceGUI::drawWaveEdit() {
float wavePreview[256];
ImGui::SetNextWindowSizeConstraints(ImVec2(450.0f*dpiScale,300.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
if (ImGui::Begin("Wavetable Editor",&waveEditOpen,settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking)) {
if (curKStage==10) ImGui::SetWindowPos(ImVec2(ImGui::GetWindowPos().x+(rand()%256)-128,ImGui::GetWindowPos().y+(rand()%256)-128));
if (curWave<0 || curWave>=(int)e->song.wave.size()) {
ImGui::Text("no wavetable selected");
} else {

View file

@ -127,7 +127,7 @@ bool pLogLevel(String val) {
}
bool pVersion(String) {
printf("Furnace version " DIV_VERSION ".\n\n");
printf("Furniture version " DIV_VERSION ".\n\n");
printf("copyright (C) 2021-2022 tildearrow and contributors.\n");
printf("licensed under the GNU General Public License version 2 or later\n");
printf("<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>.\n\n");
@ -135,7 +135,7 @@ bool pVersion(String) {
printf("pass the -warranty parameter for more information.\n\n");
printf("DISCLAIMER: this program is not affiliated with Delek in any form.\n");
printf("\n");
printf("furnace is powered by:\n");
printf("furniture is powered by:\n");
printf("- libsndfile by Erik de Castro Lopo and rest of libsndfile team (LGPLv2.1)\n");
printf("- SDL2 by Sam Lantinga (zlib license)\n");
printf("- zlib by Jean-loup Gailly and Mark Adler (zlib license)\n");
@ -235,7 +235,7 @@ void initParams() {
params.push_back(TAParam("l","loops",true,pLoops,"<count>","set number of loops (-1 means loop forever)"));
params.push_back(TAParam("o","outmode",true,pOutMode,"one|persys|perchan","set file output mode"));
params.push_back(TAParam("V","version",false,pVersion,"","view information about Furnace."));
params.push_back(TAParam("V","version",false,pVersion,"","view information about Furniture."));
params.push_back(TAParam("W","warranty",false,pWarranty,"","view warranty disclaimer."));
}
@ -310,7 +310,7 @@ int main(int argc, char** argv) {
logI("usage: %s file\n",argv[0]);
return 1;
}
logI("Furnace version " DIV_VERSION ".\n");
logI("Furniture version " DIV_VERSION ".\n");
if (!fileName.empty()) {
logI("loading module...\n");
FILE* f=ps_fopen(fileName.c_str(),"rb");