Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt

* 'master' of https://github.com/tildearrow/furnace:
  GUI: improve unified data view
  GUI: sample editor preview in selection
  finally
  Revert "fudge and bread"
  Revert "fire!"
  Revert "temporarily kill MSVC"
  Revert "MSVC: ughh, f**k you, you d**khead."
  MSVC: ughh, f**k you, you d**khead.
  temporarily kill MSVC
  fire!

# Conflicts:
#	src/engine/engine.h
#	src/engine/playback.cpp
This commit is contained in:
cam900 2022-05-30 08:13:27 +09:00
commit 4f6f13e938
11 changed files with 217 additions and 74 deletions

View File

@ -517,7 +517,7 @@ endif()
set(USED_SOURCES ${ENGINE_SOURCES} ${AUDIO_SOURCES} src/main.cpp)
if (USE_BACKWARD)
list(APPEND DEPENDENCIES_DEFINES HAVE_BACKWARD)
list(APPEND USED_SOURCES src/backtrace.cpp)
if (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
list(APPEND DEPENDENCIES_LIBRARIES dbghelp psapi)
endif()

View File

@ -12,12 +12,9 @@
- the last three compat flags
- add OPL drum instrument type
- Game Boy envelope macro/sequence
- sample editor preview in selection
- rewrite the system name detection function anyway
- unified data view
- volume commands should work on Game Boy
- add another FM editor layout
- try to find out why does VSlider not accept keyboard input
- if macros have release, note off should release them
- add ability to select a column by double clicking
- add ability to move selection by dragging

View File

@ -4490,6 +4490,38 @@ private:
printer.address = true;
printer.print(st, std::cerr);
#ifdef _WIN32
MessageBox(NULL,"Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.","Error",MB_OK|MB_ICONERROR);
std::string crashLocation;
char* userProfile=getenv("USERPROFILE");
if (userProfile==NULL) {
crashLocation="furnace_crash.txt";
} else {
crashLocation=userProfile;
crashLocation+="\\furnace_crash.txt";
}
FILE* crashDump=fopen(crashLocation.c_str(),"w");
#else
FILE* crashDump=fopen("/tmp/furnace_crash.txt","w");
#endif
if (crashDump!=NULL) {
Printer printer;
printer.address = true;
printer.print(st, crashDump);
fclose(crashDump);
} else {
#ifdef _WIN32
std::string str;
//Printer failedPrinter;
//failedPrinter.address = true;
//failedPrinter.print(st, str);
str+="\r\ncould not open furnace_crash.txt!\r\nplease take a screenshot of this error message box!";
fprintf(stderr,"NOTICE: could not open furnace_crash.txt!\n");
MessageBox(NULL,str.c_str(),"Error",MB_OK|MB_ICONERROR);
#endif
}
}
};

View File

@ -39,12 +39,4 @@ namespace backward {
backward::SignalHandling sh;
void checkInitialized() {
if (!sh.loaded()) {
#ifdef _WIN32
MessageBox(NULL,"Warning","crash backtrace not available!",MB_OK|MB_ICONWARNING);
#endif
}
}
} // namespace backward

View File

@ -1477,8 +1477,10 @@ int DivEngine::getEffectiveSampleRate(int rate) {
return rate;
}
void DivEngine::previewSample(int sample, int note) {
void DivEngine::previewSample(int sample, int note, int pStart, int pEnd) {
BUSY_BEGIN;
sPreview.pBegin=pStart;
sPreview.pEnd=pEnd;
if (sample<0 || sample>=(int)song.sample.size()) {
sPreview.sample=-1;
sPreview.pos=0;
@ -1495,7 +1497,7 @@ void DivEngine::previewSample(int sample, int note) {
if (rate<100) rate=100;
blip_set_rates(samp_bb,rate,got.rate);
samp_prevSample=0;
sPreview.pos=0;
sPreview.pos=(sPreview.pBegin>=0)?sPreview.pBegin:0;
sPreview.sample=sample;
sPreview.wave=-1;
sPreview.dir=false;

View File

@ -340,11 +340,14 @@ class DivEngine {
int wave;
unsigned int pos;
bool dir;
int pBegin, pEnd;
SamplePreview():
sample(-1),
wave(-1),
pos(0),
dir(false) {}
dir(false),
pBegin(-1),
pEnd(-1) {}
} sPreview;
short vibTable[64];
@ -527,7 +530,7 @@ class DivEngine {
void syncReset();
// trigger sample preview
void previewSample(int sample, int note=-1);
void previewSample(int sample, int note=-1, int pStart=-1, int pEnd=-1);
void stopSamplePreview();
// trigger wave preview

View File

@ -1173,8 +1173,12 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
if (sPreview.sample>=0 && sPreview.sample<(int)song.sample.size()) {
DivSample* s=song.sample[sPreview.sample];
const bool pBeginVaild=sPreview.pBegin>=0 && sPreview.pBegin<s->samples;
const bool pEndVaild=sPreview.pEnd>=0 && sPreview.pEnd<s->samples;
const int loopStart=pBeginVaild?sPreview.pBegin:s->loopStart;
const int loopEnd=pEndVaild?sPreview.pEnd:(int)s->loopEnd;
for (size_t i=0; i<prevtotal; i++) {
if (sPreview.pos>=s->samples) {
if (sPreview.pos>=s->samples || (sPreview.pEnd>=0 && (int)sPreview.pos>=sPreview.pEnd)) {
samp_temp=0;
} else {
samp_temp=s->data16[sPreview.pos];
@ -1188,19 +1192,19 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
samp_prevSample=samp_temp;
if (sPreview.dir) {
if (s->isLoopable() && ((int)sPreview.pos)<s->loopStart) {
if ((s->isLoopable() && sPreview.pos<s->loopEnd) && ((int)sPreview.pos)<loopStart) {
switch (s->loopMode) {
case DIV_SAMPLE_LOOPMODE_FORWARD:
sPreview.dir=false;
sPreview.pos=s->loopStart+1;
sPreview.pos=loopStart+1;
break;
case DIV_SAMPLE_LOOPMODE_BACKWARD:
sPreview.dir=true;
sPreview.pos=s->loopEnd-1;
sPreview.pos=loopEnd-1;
break;
case DIV_SAMPLE_LOOPMODE_PINGPONG:
sPreview.dir=false;
sPreview.pos=s->loopStart+1;
sPreview.pos=loopStart+1;
break;
case DIV_SAMPLE_LOOPMODE_ONESHOT:
default:
@ -1208,19 +1212,19 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
}
}
} else {
if (s->isLoopable() && sPreview.pos>=s->loopEnd) {
if ((s->isLoopable() && (int)sPreview.pos>=s->loopStart) && ((int)sPreview.pos)>=loopEnd) {
switch (s->loopMode) {
case DIV_SAMPLE_LOOPMODE_FORWARD:
sPreview.dir=false;
sPreview.pos=s->loopStart;
sPreview.pos=loopStart;
break;
case DIV_SAMPLE_LOOPMODE_BACKWARD:
sPreview.dir=true;
sPreview.pos=s->loopEnd-1;
sPreview.pos=loopEnd-1;
break;
case DIV_SAMPLE_LOOPMODE_PINGPONG:
sPreview.dir=true;
sPreview.pos=s->loopEnd-1;
sPreview.pos=loopEnd-1;
break;
case DIV_SAMPLE_LOOPMODE_ONESHOT:
default:
@ -1231,19 +1235,19 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
}
if (sPreview.dir) {
if (s->isLoopable() && ((int)sPreview.pos)<s->loopStart) {
if ((s->isLoopable() && sPreview.pos<s->loopEnd) && ((int)sPreview.pos)<loopStart) {
switch (s->loopMode) {
case DIV_SAMPLE_LOOPMODE_FORWARD:
sPreview.dir=false;
sPreview.pos=s->loopStart+1;
sPreview.pos=loopStart+1;
break;
case DIV_SAMPLE_LOOPMODE_BACKWARD:
sPreview.dir=true;
sPreview.pos=s->loopEnd-1;
sPreview.pos=loopEnd-1;
break;
case DIV_SAMPLE_LOOPMODE_PINGPONG:
sPreview.dir=false;
sPreview.pos=s->loopStart+1;
sPreview.pos=loopStart+1;
break;
case DIV_SAMPLE_LOOPMODE_ONESHOT:
default:
@ -1256,19 +1260,19 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
sPreview.sample=-1;
}
} else {
if (s->isLoopable() && sPreview.pos>=s->loopEnd) {
if ((s->isLoopable() && (int)sPreview.pos>=s->loopStart) && ((int)sPreview.pos)>=loopEnd) {
switch (s->loopMode) {
case DIV_SAMPLE_LOOPMODE_FORWARD:
sPreview.dir=false;
sPreview.pos=s->loopStart;
sPreview.pos=loopStart;
break;
case DIV_SAMPLE_LOOPMODE_BACKWARD:
sPreview.dir=true;
sPreview.pos=s->loopEnd-1;
sPreview.pos=loopEnd-1;
break;
case DIV_SAMPLE_LOOPMODE_PINGPONG:
sPreview.dir=true;
sPreview.pos=s->loopEnd-1;
sPreview.pos=loopEnd-1;
break;
case DIV_SAMPLE_LOOPMODE_ONESHOT:
default:

View File

@ -727,7 +727,7 @@ void DivSample::render() {
}
}
if (depth!=DIV_SAMPLE_DEPTH_YMZ_ADPCM) { // YMZ ADPCM
if (!initInternal(3,samples)) return;
if (!initInternal(DIV_SAMPLE_DEPTH_YMZ_ADPCM,samples)) return;
ymz_encode(data16,dataZ,(samples+7)&(~0x7));
}
if (depth!=DIV_SAMPLE_DEPTH_QSOUND_ADPCM) { // QSound ADPCM
@ -744,7 +744,7 @@ void DivSample::render() {
ymb_encode(data16,dataB,(samples+511)&(~0x1ff));
}
if (depth!=DIV_SAMPLE_DEPTH_8BIT) { // 8-bit PCM
if (!initInternal(8,samples)) return;
if (!initInternal(DIV_SAMPLE_DEPTH_8BIT,samples)) return;
for (unsigned int i=0; i<samples; i++) {
data8[i]=data16[i]>>8;
}

View File

@ -39,44 +39,124 @@ void FurnaceGUI::drawInsList() {
if (ImGui::Begin("Instruments",&insListOpen,globalWinFlags)) {
if (settings.unifiedDataView) settings.horizontalDataView=0;
if (ImGui::Button(ICON_FA_PLUS "##InsAdd")) {
doAction(GUI_ACTION_INS_LIST_ADD);
if (!settings.unifiedDataView) doAction(GUI_ACTION_INS_LIST_ADD);
}
if (settings.unifiedDataView) {
if (ImGui::BeginPopupContextItem("UnifiedAdd",ImGuiMouseButton_Left)) {
if (ImGui::MenuItem("instrument")) {
doAction(GUI_ACTION_INS_LIST_ADD);
}
if (ImGui::MenuItem("wavetable")) {
doAction(GUI_ACTION_WAVE_LIST_ADD);
}
if (ImGui::MenuItem("sample (create)")) {
doAction(GUI_ACTION_SAMPLE_LIST_ADD);
}
ImGui::EndPopup();
}
}
ImGui::SameLine();
if (ImGui::Button(ICON_FA_FILES_O "##InsClone")) {
doAction(GUI_ACTION_INS_LIST_DUPLICATE);
if (!settings.unifiedDataView) doAction(GUI_ACTION_INS_LIST_DUPLICATE);
}
if (settings.unifiedDataView) {
if (ImGui::BeginPopupContextItem("UnifiedClone",ImGuiMouseButton_Left)) {
if (ImGui::MenuItem("instrument")) {
doAction(GUI_ACTION_INS_LIST_DUPLICATE);
}
if (ImGui::MenuItem("wavetable")) {
doAction(GUI_ACTION_WAVE_LIST_DUPLICATE);
}
if (ImGui::MenuItem("sample")) {
doAction(GUI_ACTION_SAMPLE_LIST_DUPLICATE);
}
ImGui::EndPopup();
}
}
ImGui::SameLine();
if (ImGui::Button(ICON_FA_FOLDER_OPEN "##InsLoad")) {
doAction(GUI_ACTION_INS_LIST_OPEN);
if (!settings.unifiedDataView) doAction(GUI_ACTION_INS_LIST_OPEN);
}
if (ImGui::BeginPopupContextItem("InsOpenOpt")) {
if (ImGui::MenuItem("replace...")) {
doAction((curIns>=0 && curIns<(int)e->song.ins.size())?GUI_ACTION_INS_LIST_OPEN_REPLACE:GUI_ACTION_INS_LIST_OPEN);
if (settings.unifiedDataView) {
if (ImGui::BeginPopupContextItem("UnifiedLoad",ImGuiMouseButton_Left)) {
if (ImGui::MenuItem("instrument")) {
doAction(GUI_ACTION_INS_LIST_OPEN);
}
if (ImGui::MenuItem("instrument (replace...)")) {
doAction((curIns>=0 && curIns<(int)e->song.ins.size())?GUI_ACTION_INS_LIST_OPEN_REPLACE:GUI_ACTION_INS_LIST_OPEN);
}
if (ImGui::MenuItem("wavetable")) {
doAction(GUI_ACTION_WAVE_LIST_OPEN);
}
if (ImGui::MenuItem("sample")) {
doAction(GUI_ACTION_SAMPLE_LIST_OPEN);
}
ImGui::Separator();
if (ImGui::MenuItem("instrument from TX81Z")) {
doAction(GUI_ACTION_TX81Z_REQUEST);
}
ImGui::EndPopup();
}
ImGui::Separator();
if (ImGui::MenuItem("load from TX81Z")) {
doAction(GUI_ACTION_TX81Z_REQUEST);
} else {
if (ImGui::BeginPopupContextItem("InsOpenOpt")) {
if (ImGui::MenuItem("replace...")) {
doAction((curIns>=0 && curIns<(int)e->song.ins.size())?GUI_ACTION_INS_LIST_OPEN_REPLACE:GUI_ACTION_INS_LIST_OPEN);
}
ImGui::Separator();
if (ImGui::MenuItem("load from TX81Z")) {
doAction(GUI_ACTION_TX81Z_REQUEST);
}
ImGui::EndPopup();
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Open (insert; right-click to replace)");
}
ImGui::EndPopup();
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Open (insert; right-click to replace)");
}
ImGui::SameLine();
if (ImGui::Button(ICON_FA_FLOPPY_O "##InsSave")) {
doAction(GUI_ACTION_INS_LIST_SAVE);
if (!settings.unifiedDataView) doAction(GUI_ACTION_INS_LIST_SAVE);
}
ImGui::SameLine();
if (ImGui::ArrowButton("InsUp",ImGuiDir_Up)) {
doAction(GUI_ACTION_INS_LIST_MOVE_UP);
if (settings.unifiedDataView) {
if (ImGui::BeginPopupContextItem("UnifiedSave",ImGuiMouseButton_Left)) {
if (ImGui::MenuItem("instrument")) {
doAction(GUI_ACTION_INS_LIST_SAVE);
}
if (ImGui::MenuItem("wavetable")) {
doAction(GUI_ACTION_WAVE_LIST_SAVE);
}
if (ImGui::MenuItem("sample")) {
doAction(GUI_ACTION_SAMPLE_LIST_SAVE);
}
ImGui::EndPopup();
}
}
ImGui::SameLine();
if (ImGui::ArrowButton("InsDown",ImGuiDir_Down)) {
doAction(GUI_ACTION_INS_LIST_MOVE_DOWN);
if (!settings.unifiedDataView) {
ImGui::SameLine();
if (ImGui::ArrowButton("InsUp",ImGuiDir_Up)) {
doAction(GUI_ACTION_INS_LIST_MOVE_UP);
}
ImGui::SameLine();
if (ImGui::ArrowButton("InsDown",ImGuiDir_Down)) {
doAction(GUI_ACTION_INS_LIST_MOVE_DOWN);
}
}
ImGui::SameLine();
if (ImGui::Button(ICON_FA_TIMES "##InsDelete")) {
doAction(GUI_ACTION_INS_LIST_DELETE);
if (!settings.unifiedDataView) doAction(GUI_ACTION_INS_LIST_DELETE);
}
if (settings.unifiedDataView) {
if (ImGui::BeginPopupContextItem("UnifiedDelete",ImGuiMouseButton_Left)) {
if (ImGui::MenuItem("instrument")) {
doAction(GUI_ACTION_INS_LIST_DELETE);
}
if (ImGui::MenuItem("wavetable")) {
doAction(GUI_ACTION_WAVE_LIST_DELETE);
}
if (ImGui::MenuItem("sample")) {
doAction(GUI_ACTION_SAMPLE_LIST_DELETE);
}
ImGui::EndPopup();
}
}
ImGui::Separator();
int availableRows=ImGui::GetContentRegionAvail().y/ImGui::GetFrameHeight();
@ -98,6 +178,7 @@ void FurnaceGUI::drawInsList() {
int curRow=0;
for (int i=-1; i<(int)e->song.ins.size(); i++) {
ImGui::PushID(i);
String name=ICON_FA_CIRCLE_O " - None -";
const char* insType="Bug!";
if (i>=0) {
@ -250,13 +331,13 @@ void FurnaceGUI::drawInsList() {
curIns=i;
wavePreviewInit=true;
}
ImGui::PopStyleColor();
if (wantScrollList && curIns==i) ImGui::SetScrollHereY();
if (settings.insFocusesPattern && patternOpen && ImGui::IsItemActivated()) {
nextWindow=GUI_WINDOW_PATTERN;
curIns=i;
wavePreviewInit=true;
}
ImGui::PopStyleColor();
if (ImGui::IsItemHovered() && i>=0) {
ImGui::SetTooltip("%s",insType);
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
@ -264,9 +345,25 @@ void FurnaceGUI::drawInsList() {
nextWindow=GUI_WINDOW_INS_EDIT;
}
}
if (i>=0) {
if (ImGui::BeginPopupContextItem("InsRightMenu")) {
curIns=i;
if (ImGui::MenuItem("replace...")) {
doAction((curIns>=0 && curIns<(int)e->song.ins.size())?GUI_ACTION_INS_LIST_OPEN_REPLACE:GUI_ACTION_INS_LIST_OPEN);
}
if (ImGui::MenuItem("save")) {
doAction(GUI_ACTION_INS_LIST_SAVE);
}
if (ImGui::MenuItem("delete")) {
doAction(GUI_ACTION_INS_LIST_DELETE);
}
ImGui::EndPopup();
}
}
if (settings.horizontalDataView) {
if (++curRow>=availableRows) curRow=0;
}
ImGui::PopID();
}
if (settings.unifiedDataView) {
@ -297,9 +394,14 @@ void FurnaceGUI::drawInsList() {
void FurnaceGUI::drawWaveList() {
if (nextWindow==GUI_WINDOW_WAVE_LIST) {
waveListOpen=true;
ImGui::SetNextWindowFocus();
if (settings.unifiedDataView) {
ImGui::SetWindowFocus("Instruments");
} else {
ImGui::SetNextWindowFocus();
}
nextWindow=GUI_WINDOW_NOTHING;
}
if (settings.unifiedDataView) return;
if (!waveListOpen) return;
if (ImGui::Begin("Wavetables",&waveListOpen,globalWinFlags)) {
if (ImGui::Button(ICON_FA_PLUS "##WaveAdd")) {
@ -342,9 +444,14 @@ void FurnaceGUI::drawWaveList() {
void FurnaceGUI::drawSampleList() {
if (nextWindow==GUI_WINDOW_SAMPLE_LIST) {
sampleListOpen=true;
ImGui::SetNextWindowFocus();
if (settings.unifiedDataView) {
ImGui::SetWindowFocus("Instruments");
} else {
ImGui::SetNextWindowFocus();
}
nextWindow=GUI_WINDOW_NOTHING;
}
if (settings.unifiedDataView) return;
if (!sampleListOpen) return;
if (ImGui::Begin("Samples",&sampleListOpen,globalWinFlags)) {
if (ImGui::Button(ICON_FA_FILE "##SampleAdd")) {

View File

@ -2243,7 +2243,20 @@ int FurnaceGUI::processEvent(SDL_Event* ev) {
int key=noteKeys.at(ev->key.keysym.scancode);
int num=12*curOctave+key;
if (key!=100 && key!=101 && key!=102) {
e->previewSample(curSample,num);
int pStart=-1;
int pEnd=-1;
if (curWindow==GUI_WINDOW_SAMPLE_EDIT) {
if (sampleSelStart!=sampleSelEnd) {
pStart=sampleSelStart;
pEnd=sampleSelEnd;
if (pStart>pEnd) {
pStart^=pEnd;
pEnd^=pStart;
pStart^=pEnd;
}
}
}
e->previewSample(curSample,num,pStart,pEnd);
samplePreviewOn=true;
samplePreviewKey=ev->key.keysym.scancode;
samplePreviewNote=num;
@ -2947,9 +2960,13 @@ bool FurnaceGUI::loop() {
if (ImGui::BeginMenu("window")) {
if (ImGui::MenuItem("song information",BIND_FOR(GUI_ACTION_WINDOW_SONG_INFO),songInfoOpen)) songInfoOpen=!songInfoOpen;
if (ImGui::MenuItem("subsongs",BIND_FOR(GUI_ACTION_WINDOW_SUBSONGS),subSongsOpen)) subSongsOpen=!subSongsOpen;
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;
if (ImGui::MenuItem("samples",BIND_FOR(GUI_ACTION_WINDOW_SAMPLE_LIST),sampleListOpen)) sampleListOpen=!sampleListOpen;
if (settings.unifiedDataView) {
if (ImGui::MenuItem("assets",BIND_FOR(GUI_ACTION_WINDOW_INS_LIST),insListOpen)) insListOpen=!insListOpen;
} else {
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;
if (ImGui::MenuItem("samples",BIND_FOR(GUI_ACTION_WINDOW_SAMPLE_LIST),sampleListOpen)) sampleListOpen=!sampleListOpen;
}
if (ImGui::MenuItem("orders",BIND_FOR(GUI_ACTION_WINDOW_ORDERS),ordersOpen)) ordersOpen=!ordersOpen;
if (ImGui::MenuItem("pattern",BIND_FOR(GUI_ACTION_WINDOW_PATTERN),patternOpen)) patternOpen=!patternOpen;
if (ImGui::MenuItem("mixer",BIND_FOR(GUI_ACTION_WINDOW_MIXER),mixerOpen)) mixerOpen=!mixerOpen;

View File

@ -39,10 +39,6 @@
#include "gui/gui.h"
#endif
#ifdef HAVE_BACKWARD
#include "../extern/backward/backward.hpp"
#endif
DivEngine e;
#ifdef HAVE_GUI
@ -246,7 +242,6 @@ void initParams() {
// TODO: CoInitializeEx on Windows?
// TODO: add crash log
int main(int argc, char** argv) {
backward::SignalHandling sh;
initLog();
#if !(defined(__APPLE__) || defined(_WIN32) || defined(ANDROID))
// workaround for Wayland HiDPI issue
@ -306,12 +301,6 @@ int main(int argc, char** argv) {
}
}
if (!sh.loaded()) {
#ifdef _WIN32
MessageBox(NULL,"Warning","crash backtrace not available!",MB_OK|MB_ICONWARNING);
#endif
}
e.setConsoleMode(consoleMode);
#ifdef _WIN32