aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl')
-rw-r--r--src/libui_sdl/DlgAudioSettings.cpp183
-rw-r--r--src/libui_sdl/DlgAudioSettings.h29
-rw-r--r--src/libui_sdl/DlgEmuSettings.cpp11
-rw-r--r--src/libui_sdl/DlgInputConfig.cpp252
-rw-r--r--src/libui_sdl/DlgInputConfig.h2
-rw-r--r--src/libui_sdl/Platform.cpp4
-rw-r--r--src/libui_sdl/libui/ui.h2
-rw-r--r--src/libui_sdl/libui/unix/area.c26
-rw-r--r--src/libui_sdl/libui/unix/stddialogs.c3
-rw-r--r--src/libui_sdl/libui/unix/window.c7
-rw-r--r--src/libui_sdl/libui/windows/button.cpp19
-rw-r--r--src/libui_sdl/main.cpp494
12 files changed, 838 insertions, 194 deletions
diff --git a/src/libui_sdl/DlgAudioSettings.cpp b/src/libui_sdl/DlgAudioSettings.cpp
new file mode 100644
index 0000000..b02b474
--- /dev/null
+++ b/src/libui_sdl/DlgAudioSettings.cpp
@@ -0,0 +1,183 @@
+/*
+ Copyright 2016-2019 StapleButter
+
+ This file is part of melonDS.
+
+ melonDS is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with melonDS. If not, see http://www.gnu.org/licenses/.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libui/ui.h"
+
+#include "../types.h"
+#include "../Config.h"
+
+#include "DlgAudioSettings.h"
+
+
+void MicLoadWav(char* path);
+
+
+namespace DlgAudioSettings
+{
+
+bool opened;
+uiWindow* win;
+
+uiSlider* slVolume;
+uiRadioButtons* rbMicInputType;
+uiEntry* txMicWavPath;
+
+int oldvolume;
+
+
+int OnCloseWindow(uiWindow* window, void* blarg)
+{
+ opened = false;
+ return 1;
+}
+
+void OnVolumeChanged(uiSlider* slider, void* blarg)
+{
+ Config::AudioVolume = uiSliderValue(slVolume);
+}
+
+void OnMicWavBrowse(uiButton* btn, void* blarg)
+{
+ char* file = uiOpenFile(win, "WAV file (*.wav)|*.wav|Any file|*.*", NULL);
+ if (!file)
+ {
+ return;
+ }
+
+ uiEntrySetText(txMicWavPath, file);
+ uiFreeText(file);
+}
+
+void OnCancel(uiButton* btn, void* blarg)
+{
+ Config::AudioVolume = oldvolume;
+
+ uiControlDestroy(uiControl(win));
+ opened = false;
+}
+
+void OnOk(uiButton* btn, void* blarg)
+{
+ Config::AudioVolume = uiSliderValue(slVolume);
+ Config::MicInputType = uiRadioButtonsSelected(rbMicInputType);
+
+ char* wavpath = uiEntryText(txMicWavPath);
+ strncpy(Config::MicWavPath, wavpath, 511);
+ uiFreeText(wavpath);
+
+ Config::Save();
+
+ if (Config::MicInputType == 3) MicLoadWav(Config::MicWavPath);
+
+ uiControlDestroy(uiControl(win));
+ opened = false;
+}
+
+void Open()
+{
+ if (opened)
+ {
+ uiControlSetFocus(uiControl(win));
+ return;
+ }
+
+ opened = true;
+ win = uiNewWindow("Audio settings - melonDS", 400, 100, 0, 0);
+ uiWindowSetMargined(win, 1);
+ uiWindowOnClosing(win, OnCloseWindow, NULL);
+
+ uiBox* top = uiNewVerticalBox();
+ uiWindowSetChild(win, uiControl(top));
+ uiBoxSetPadded(top, 1);
+
+ {
+ uiGroup* grp = uiNewGroup("Audio output");
+ uiBoxAppend(top, uiControl(grp), 0);
+ uiGroupSetMargined(grp, 1);
+
+ uiBox* in_ctrl = uiNewVerticalBox();
+ uiGroupSetChild(grp, uiControl(in_ctrl));
+
+ uiLabel* label_vol = uiNewLabel("Volume:");
+ uiBoxAppend(in_ctrl, uiControl(label_vol), 0);
+
+ slVolume = uiNewSlider(0, 256);
+ uiSliderOnChanged(slVolume, OnVolumeChanged, NULL);
+ uiBoxAppend(in_ctrl, uiControl(slVolume), 0);
+ }
+
+ {
+ uiGroup* grp = uiNewGroup("Microphone input");
+ uiBoxAppend(top, uiControl(grp), 0);
+ uiGroupSetMargined(grp, 1);
+
+ uiBox* in_ctrl = uiNewVerticalBox();
+ uiGroupSetChild(grp, uiControl(in_ctrl));
+
+ rbMicInputType = uiNewRadioButtons();
+ uiRadioButtonsAppend(rbMicInputType, "None");
+ uiRadioButtonsAppend(rbMicInputType, "Microphone");
+ uiRadioButtonsAppend(rbMicInputType, "White noise");
+ uiRadioButtonsAppend(rbMicInputType, "WAV file:");
+ uiBoxAppend(in_ctrl, uiControl(rbMicInputType), 0);
+
+ uiBox* path_box = uiNewHorizontalBox();
+ uiBoxAppend(in_ctrl, uiControl(path_box), 0);
+
+ txMicWavPath = uiNewEntry();
+ uiBoxAppend(path_box, uiControl(txMicWavPath), 1);
+
+ uiButton* path_browse = uiNewButton("...");
+ uiButtonOnClicked(path_browse, OnMicWavBrowse, NULL);
+ uiBoxAppend(path_box, uiControl(path_browse), 0);
+ }
+
+ {
+ uiBox* in_ctrl = uiNewHorizontalBox();
+ uiBoxSetPadded(in_ctrl, 1);
+ uiBoxAppend(top, uiControl(in_ctrl), 0);
+
+ uiLabel* dummy = uiNewLabel("");
+ uiBoxAppend(in_ctrl, uiControl(dummy), 1);
+
+ uiButton* btncancel = uiNewButton("Cancel");
+ uiButtonOnClicked(btncancel, OnCancel, NULL);
+ uiBoxAppend(in_ctrl, uiControl(btncancel), 0);
+
+ uiButton* btnok = uiNewButton("Ok");
+ uiButtonOnClicked(btnok, OnOk, NULL);
+ uiBoxAppend(in_ctrl, uiControl(btnok), 0);
+ }
+
+ if (Config::AudioVolume < 0) Config::AudioVolume = 0;
+ else if (Config::AudioVolume > 256) Config::AudioVolume = 256;
+
+ oldvolume = Config::AudioVolume;
+
+ uiSliderSetValue(slVolume, Config::AudioVolume);
+ uiRadioButtonsSetSelected(rbMicInputType, Config::MicInputType);
+ uiEntrySetText(txMicWavPath, Config::MicWavPath);
+
+ uiControlShow(uiControl(win));
+}
+
+}
diff --git a/src/libui_sdl/DlgAudioSettings.h b/src/libui_sdl/DlgAudioSettings.h
new file mode 100644
index 0000000..2333967
--- /dev/null
+++ b/src/libui_sdl/DlgAudioSettings.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-2019 StapleButter
+
+ This file is part of melonDS.
+
+ melonDS is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with melonDS. If not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef DLGAUDIOSETTINGS_H
+#define DLGAUDIOSETTINGS_H
+
+namespace DlgAudioSettings
+{
+
+void Open();
+
+}
+
+#endif // DLGAUDIOSETTINGS_H
diff --git a/src/libui_sdl/DlgEmuSettings.cpp b/src/libui_sdl/DlgEmuSettings.cpp
index 77bb18e..42c95b8 100644
--- a/src/libui_sdl/DlgEmuSettings.cpp
+++ b/src/libui_sdl/DlgEmuSettings.cpp
@@ -33,6 +33,7 @@ void ApplyNewSettings();
namespace DlgEmuSettings
{
+bool opened;
uiWindow* win;
uiCheckbox* cbDirectBoot;
@@ -42,12 +43,14 @@ uiCheckbox* cbBindAnyAddr;
int OnCloseWindow(uiWindow* window, void* blarg)
{
+ opened = false;
return 1;
}
void OnCancel(uiButton* btn, void* blarg)
{
uiControlDestroy(uiControl(win));
+ opened = false;
}
void OnOk(uiButton* btn, void* blarg)
@@ -59,12 +62,20 @@ void OnOk(uiButton* btn, void* blarg)
Config::Save();
uiControlDestroy(uiControl(win));
+ opened = false;
ApplyNewSettings();
}
void Open()
{
+ if (opened)
+ {
+ uiControlSetFocus(uiControl(win));
+ return;
+ }
+
+ opened = true;
win = uiNewWindow("Emu settings - melonDS", 300, 200, 0, 0);
uiWindowSetMargined(win, 1);
uiWindowOnClosing(win, OnCloseWindow, NULL);
diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp
index 6496307..287d7e3 100644
--- a/src/libui_sdl/DlgInputConfig.cpp
+++ b/src/libui_sdl/DlgInputConfig.cpp
@@ -35,19 +35,33 @@ extern SDL_Joystick* Joystick;
namespace DlgInputConfig
{
-uiWindow* win;
+typedef struct
+{
+ int type;
+ uiWindow* win;
+
+ uiAreaHandler areahandler;
+ uiArea* keypresscatcher;
+
+ int numkeys;
+ int keymap[32];
+ int joymap[32];
+
+ int pollid;
+ uiButton* pollbtn;
-uiAreaHandler areahandler;
-uiArea* keypresscatcher;
+} InputDlgData;
-int keyorder[12] = {0, 1, 10, 11, 5, 4, 6, 7, 9, 8, 3, 2};
-char keylabels[12][8] = {"A:", "B:", "Select:", "Start:", "Right:", "Left:", "Up:", "Down:", "R:", "L:", "X:", "Y:"};
-int keymap[12];
-int joymap[12];
+int dskeyorder[12] = {0, 1, 10, 11, 5, 4, 6, 7, 9, 8, 3, 2};
+char dskeylabels[12][8] = {"A:", "B:", "Select:", "Start:", "Right:", "Left:", "Up:", "Down:", "R:", "L:", "X:", "Y:"};
-int pollid;
-uiButton* pollbtn;
+int identity[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
+
+char hotkeylabels[HK_MAX][32] = {"Close/open lid:", "Microphone:"};
+
+int openedmask;
+InputDlgData inputdlg[2];
void JoyMappingName(int id, char* str)
@@ -97,7 +111,9 @@ void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height)
int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
{
- if (pollid < 0)
+ InputDlgData* dlg = (InputDlgData*)uiControl(area)->UserData;
+
+ if (dlg->pollid < 0)
return 0;
if (evt->Scancode == 0x38) // ALT
@@ -105,27 +121,27 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
if (evt->Modifiers == 0x2) // ALT+key
return 0;
- if (pollid > 12)
+ if (dlg->pollid > 12)
{
- if (pollid < 0x100) return 0;
- int id = pollid & 0xFF;
+ if (dlg->pollid < 0x100) return 0;
+ int id = dlg->pollid & 0xFF;
if (id > 12) return 0;
if (evt->Scancode != 0x1) // ESC
{
if (evt->Scancode == 0xE) // backspace
- joymap[id] = -1;
+ dlg->joymap[id] = -1;
else
return 1;
}
char keyname[16];
- JoyMappingName(joymap[id], keyname);
- uiButtonSetText(pollbtn, keyname);
- uiControlEnable(uiControl(pollbtn));
+ JoyMappingName(dlg->joymap[id], keyname);
+ uiButtonSetText(dlg->pollbtn, keyname);
+ uiControlEnable(uiControl(dlg->pollbtn));
- pollid = -1;
+ dlg->pollid = -1;
- uiControlSetFocus(uiControl(pollbtn));
+ uiControlSetFocus(uiControl(dlg->pollbtn));
return 1;
}
@@ -134,16 +150,16 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
{
// set key.
if (evt->Scancode != 0x1) // ESC
- keymap[pollid] = evt->Scancode;
+ dlg->keymap[dlg->pollid] = evt->Scancode;
- char* keyname = uiKeyName(keymap[pollid]);
- uiButtonSetText(pollbtn, keyname);
- uiControlEnable(uiControl(pollbtn));
+ char* keyname = uiKeyName(dlg->keymap[dlg->pollid]);
+ uiButtonSetText(dlg->pollbtn, keyname);
+ uiControlEnable(uiControl(dlg->pollbtn));
uiFreeText(keyname);
- pollid = -1;
+ dlg->pollid = -1;
- uiControlSetFocus(uiControl(pollbtn));
+ uiControlSetFocus(uiControl(dlg->pollbtn));
}
return 1;
@@ -151,8 +167,10 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
Uint32 JoyPoll(Uint32 interval, void* param)
{
- if (pollid < 0x100) return 0;
- int id = pollid & 0xFF;
+ InputDlgData* dlg = (InputDlgData*)param;
+
+ if (dlg->pollid < 0x100) return 0;
+ int id = dlg->pollid & 0xFF;
if (id > 12) return 0;
SDL_JoystickUpdate();
@@ -165,16 +183,16 @@ Uint32 JoyPoll(Uint32 interval, void* param)
{
if (SDL_JoystickGetButton(joy, i))
{
- joymap[id] = i;
+ dlg->joymap[id] = i;
char keyname[16];
- JoyMappingName(joymap[id], keyname);
- uiButtonSetText(pollbtn, keyname);
- uiControlEnable(uiControl(pollbtn));
+ JoyMappingName(dlg->joymap[id], keyname);
+ uiButtonSetText(dlg->pollbtn, keyname);
+ uiControlEnable(uiControl(dlg->pollbtn));
- pollid = -1;
+ dlg->pollid = -1;
- uiControlSetFocus(uiControl(pollbtn));
+ uiControlSetFocus(uiControl(dlg->pollbtn));
return 0;
}
}
@@ -187,16 +205,16 @@ Uint32 JoyPoll(Uint32 interval, void* param)
else if (blackhat & 0x4) blackhat = 0x4;
else blackhat = 0x8;
- joymap[id] = 0x100 | blackhat;
+ dlg->joymap[id] = 0x100 | blackhat;
char keyname[16];
- JoyMappingName(joymap[id], keyname);
- uiButtonSetText(pollbtn, keyname);
- uiControlEnable(uiControl(pollbtn));
+ JoyMappingName(dlg->joymap[id], keyname);
+ uiButtonSetText(dlg->pollbtn, keyname);
+ uiControlEnable(uiControl(dlg->pollbtn));
- pollid = -1;
+ dlg->pollid = -1;
- uiControlSetFocus(uiControl(pollbtn));
+ uiControlSetFocus(uiControl(dlg->pollbtn));
return 0;
}
@@ -206,98 +224,147 @@ Uint32 JoyPoll(Uint32 interval, void* param)
void OnKeyStartConfig(uiButton* btn, void* data)
{
- if (pollid != -1)
+ InputDlgData* dlg = (InputDlgData*)uiControl(btn)->UserData;
+
+ if (dlg->pollid != -1)
{
// TODO: handle this better?
- if (pollid <= 12)
- uiControlSetFocus(uiControl(keypresscatcher));
+ if (dlg->pollid <= 12)
+ uiControlSetFocus(uiControl(dlg->keypresscatcher));
return;
}
int id = *(int*)data;
- pollid = id;
- pollbtn = btn;
+ dlg->pollid = id;
+ dlg->pollbtn = btn;
uiButtonSetText(btn, "[press key]");
uiControlDisable(uiControl(btn));
- uiControlSetFocus(uiControl(keypresscatcher));
+ uiControlSetFocus(uiControl(dlg->keypresscatcher));
}
void OnJoyStartConfig(uiButton* btn, void* data)
{
- if (pollid != -1)
+ InputDlgData* dlg = (InputDlgData*)uiControl(btn)->UserData;
+
+ if (dlg->pollid != -1)
{
// TODO: handle this better?
- if (pollid <= 12)
- uiControlSetFocus(uiControl(keypresscatcher));
+ if (dlg->pollid <= 12)
+ uiControlSetFocus(uiControl(dlg->keypresscatcher));
return;
}
int id = *(int*)data;
- pollid = id | 0x100;
- pollbtn = btn;
+ dlg->pollid = id | 0x100;
+ dlg->pollbtn = btn;
uiButtonSetText(btn, "[press button]");
uiControlDisable(uiControl(btn));
- SDL_AddTimer(100, JoyPoll, NULL);
- uiControlSetFocus(uiControl(keypresscatcher));
+ SDL_AddTimer(100, JoyPoll, dlg);
+ uiControlSetFocus(uiControl(dlg->keypresscatcher));
}
int OnCloseWindow(uiWindow* window, void* blarg)
{
+ InputDlgData* dlg = (InputDlgData*)(uiControl(window)->UserData);
+ openedmask &= ~(1 << dlg->type);
return 1;
}
void OnGetFocus(uiWindow* window, void* blarg)
{
- if (pollid >= 0)
- uiControlSetFocus(uiControl(keypresscatcher));
+ InputDlgData* dlg = (InputDlgData*)(uiControl(window)->UserData);
+
+ if (dlg->pollid >= 0)
+ uiControlSetFocus(uiControl(dlg->keypresscatcher));
}
void OnLoseFocus(uiWindow* window, void* blarg)
{
}
-void OnCancel(uiButton* btn, void* blarg)
+void OnCancel(uiButton* btn, void* data)
{
- uiControlDestroy(uiControl(win));
+ InputDlgData* dlg = (InputDlgData*)data;
+
+ uiControlDestroy(uiControl(dlg->win));
+ openedmask &= ~(1 << dlg->type);
}
-void OnOk(uiButton* btn, void* blarg)
+void OnOk(uiButton* btn, void* data)
{
- memcpy(Config::KeyMapping, keymap, sizeof(int)*12);
- memcpy(Config::JoyMapping, joymap, sizeof(int)*12);
+ InputDlgData* dlg = (InputDlgData*)data;
+
+ if (dlg->type == 0)
+ {
+ memcpy(Config::KeyMapping, dlg->keymap, sizeof(int)*12);
+ memcpy(Config::JoyMapping, dlg->joymap, sizeof(int)*12);
+ }
+ else if (dlg->type == 1)
+ {
+ memcpy(Config::HKKeyMapping, dlg->keymap, sizeof(int)*HK_MAX);
+ memcpy(Config::HKJoyMapping, dlg->joymap, sizeof(int)*HK_MAX);
+ }
Config::Save();
- uiControlDestroy(uiControl(win));
+ uiControlDestroy(uiControl(dlg->win));
+ openedmask &= ~(1 << dlg->type);
}
-void Open()
+void Open(int type)
{
- pollid = -1;
+ InputDlgData* dlg = &inputdlg[type];
+
+ int mask = 1 << type;
+ if (openedmask & mask)
+ {
+ uiControlSetFocus(uiControl(dlg->win));
+ return;
+ }
+
+ openedmask |= mask;
+
+ dlg->type = type;
+ dlg->pollid = -1;
+
+ if (type == 0)
+ {
+ dlg->numkeys = 12;
+ memcpy(dlg->keymap, Config::KeyMapping, sizeof(int)*12);
+ memcpy(dlg->joymap, Config::JoyMapping, sizeof(int)*12);
+
+ dlg->win = uiNewWindow("Input config - melonDS", 600, 100, 0, 0);
+ }
+ else if (type == 1)
+ {
+ dlg->numkeys = HK_MAX;
+ memcpy(dlg->keymap, Config::HKKeyMapping, sizeof(int)*HK_MAX);
+ memcpy(dlg->joymap, Config::HKJoyMapping, sizeof(int)*HK_MAX);
+
+ dlg->win = uiNewWindow("Hotkey config - melonDS", 600, 100, 0, 0);
+ }
- memcpy(keymap, Config::KeyMapping, sizeof(int)*12);
- memcpy(joymap, Config::JoyMapping, sizeof(int)*12);
+ uiControl(dlg->win)->UserData = dlg;
- win = uiNewWindow("Input config - melonDS", 600, 400, 0, 0);
- uiWindowSetMargined(win, 1);
- uiWindowOnClosing(win, OnCloseWindow, NULL);
- uiWindowOnGetFocus(win, OnGetFocus, NULL);
- uiWindowOnLoseFocus(win, OnLoseFocus, NULL);
+ uiWindowSetMargined(dlg->win, 1);
+ uiWindowOnClosing(dlg->win, OnCloseWindow, NULL);
+ uiWindowOnGetFocus(dlg->win, OnGetFocus, NULL);
+ uiWindowOnLoseFocus(dlg->win, OnLoseFocus, NULL);
- areahandler.Draw = OnAreaDraw;
- areahandler.MouseEvent = OnAreaMouseEvent;
- areahandler.MouseCrossed = OnAreaMouseCrossed;
- areahandler.DragBroken = OnAreaDragBroken;
- areahandler.KeyEvent = OnAreaKeyEvent;
- areahandler.Resize = OnAreaResize;
+ dlg->areahandler.Draw = OnAreaDraw;
+ dlg->areahandler.MouseEvent = OnAreaMouseEvent;
+ dlg->areahandler.MouseCrossed = OnAreaMouseCrossed;
+ dlg->areahandler.DragBroken = OnAreaDragBroken;
+ dlg->areahandler.KeyEvent = OnAreaKeyEvent;
+ dlg->areahandler.Resize = OnAreaResize;
uiBox* top = uiNewVerticalBox();
- uiWindowSetChild(win, uiControl(top));
+ uiWindowSetChild(dlg->win, uiControl(top));
uiControlHide(uiControl(top));
{
@@ -312,19 +379,20 @@ void Open()
const int width = 120;
- for (int i = 0; i < 12; i++)
+ for (int i = 0; i < dlg->numkeys; i++)
{
- int j = keyorder[i];
+ int j = (type==0) ? dskeyorder[i] : i;
- uiLabel* label = uiNewLabel(keylabels[j]);
+ uiLabel* label = uiNewLabel((type==0) ? dskeylabels[j] : hotkeylabels[j]);
uiGridAppend(b_key, uiControl(label), 0, i, 1, 1, 1, uiAlignStart, 1, uiAlignCenter);
uiControlSetMinSize(uiControl(label), width, 1);
- char* keyname = uiKeyName(Config::KeyMapping[j]);
+ char* keyname = uiKeyName(dlg->keymap[j]);
uiButton* btn = uiNewButton(keyname);
+ uiControl(btn)->UserData = dlg;
uiGridAppend(b_key, uiControl(btn), 1, i, 1, 1, 1, uiAlignFill, 1, uiAlignCenter);
- uiButtonOnClicked(btn, OnKeyStartConfig, &keyorder[i]);
+ uiButtonOnClicked(btn, OnKeyStartConfig, (type==0) ? &dskeyorder[i] : &identity[i]);
uiControlSetMinSize(uiControl(btn), width, 1);
uiFreeText(keyname);
@@ -335,20 +403,21 @@ void Open()
uiGrid* b_joy = uiNewGrid();
uiGroupSetChild(g_joy, uiControl(b_joy));
- for (int i = 0; i < 12; i++)
+ for (int i = 0; i < dlg->numkeys; i++)
{
- int j = keyorder[i];
+ int j = (type==0) ? dskeyorder[i] : i;
- uiLabel* label = uiNewLabel(keylabels[j]);
+ uiLabel* label = uiNewLabel((type==0) ? dskeylabels[j] : hotkeylabels[j]);
uiGridAppend(b_joy, uiControl(label), 0, i, 1, 1, 1, uiAlignStart, 1, uiAlignCenter);
uiControlSetMinSize(uiControl(label), width, 1);
char keyname[16];
- JoyMappingName(Config::JoyMapping[j], keyname);
+ JoyMappingName(dlg->joymap[j], keyname);
uiButton* btn = uiNewButton(keyname);
+ uiControl(btn)->UserData = dlg;
uiGridAppend(b_joy, uiControl(btn), 1, i, 1, 1, 1, uiAlignFill, 1, uiAlignCenter);
- uiButtonOnClicked(btn, OnJoyStartConfig, &keyorder[i]);
+ uiButtonOnClicked(btn, OnJoyStartConfig, (type==0) ? &dskeyorder[i] : &identity[i]);
uiControlSetMinSize(uiControl(btn), width, 1);
}
}
@@ -364,21 +433,22 @@ void Open()
uiLabel* dummy = uiNewLabel("");
uiBoxAppend(in_ctrl, uiControl(dummy), 1);
- keypresscatcher = uiNewArea(&areahandler);
- uiBoxAppend(in_ctrl, uiControl(keypresscatcher), 0);
+ dlg->keypresscatcher = uiNewArea(&dlg->areahandler);
+ uiControl(dlg->keypresscatcher)->UserData = dlg;
+ uiBoxAppend(in_ctrl, uiControl(dlg->keypresscatcher), 0);
uiButton* btncancel = uiNewButton("Cancel");
- uiButtonOnClicked(btncancel, OnCancel, NULL);
+ uiButtonOnClicked(btncancel, OnCancel, dlg);
uiBoxAppend(in_ctrl, uiControl(btncancel), 0);
uiButton* btnok = uiNewButton("Ok");
- uiButtonOnClicked(btnok, OnOk, NULL);
+ uiButtonOnClicked(btnok, OnOk, dlg);
uiBoxAppend(in_ctrl, uiControl(btnok), 0);
}
uiControlShow(uiControl(top));
- uiControlShow(uiControl(win));
+ uiControlShow(uiControl(dlg->win));
}
}
diff --git a/src/libui_sdl/DlgInputConfig.h b/src/libui_sdl/DlgInputConfig.h
index c044016..2b0b6cb 100644
--- a/src/libui_sdl/DlgInputConfig.h
+++ b/src/libui_sdl/DlgInputConfig.h
@@ -22,7 +22,7 @@
namespace DlgInputConfig
{
-void Open();
+void Open(int type);
}
diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp
index 0c29f6b..733114e 100644
--- a/src/libui_sdl/Platform.cpp
+++ b/src/libui_sdl/Platform.cpp
@@ -95,7 +95,9 @@ const char* PCapLibNames[] =
// TODO: name for npcap in non-WinPCap mode
"wpcap.dll",
#else
- // TODO: Linux lib names
+ // Linux lib names
+ "libpcap.so.1",
+ "libpcap.so",
#endif
NULL
};
diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h
index e5a866d..1af8f59 100644
--- a/src/libui_sdl/libui/ui.h
+++ b/src/libui_sdl/libui/ui.h
@@ -76,6 +76,8 @@ struct uiControl {
void (*SetMinSize)(uiControl*, int, int);
int MinWidth, MinHeight;
+
+ void* UserData;
};
// TOOD add argument names to all arguments
#define uiControl(this) ((uiControl *) (this))
diff --git a/src/libui_sdl/libui/unix/area.c b/src/libui_sdl/libui/unix/area.c
index 40f8624..2da9bab 100644
--- a/src/libui_sdl/libui/unix/area.c
+++ b/src/libui_sdl/libui/unix/area.c
@@ -523,16 +523,26 @@ char* uiKeyName(int scancode)
{
scancode = scancode_normal2unix(scancode);
+ char* ret;
guint* keyvals; int num;
- GdkKeymap* keymap = gdk_keymap_get_default();
- gdk_keymap_get_entries_for_keycode(keymap, scancode, NULL, &keyvals, &num);
-
- // TODO: pick smarter??
- int keyval = keyvals[0];
-
- g_free(keyvals);
+ GdkKeymap* keymap = gdk_keymap_get_for_display(gdk_display_get_default());
+ if (gdk_keymap_get_entries_for_keycode(keymap, scancode, NULL, &keyvals, &num))
+ {
+ // TODO: pick smarter??
+ int keyval = keyvals[0];
+
+ g_free(keyvals);
+
+ ret = gdk_keyval_name(keyval);
+ }
+ else
+ {
+ char tmp[16];
+ sprintf(tmp, "#%03X", scancode);
+ ret = tmp;
+ }
- return uiUnixStrdupText(gdk_keyval_name(keyval));
+ return uiUnixStrdupText(ret);
}
enum {
diff --git a/src/libui_sdl/libui/unix/stddialogs.c b/src/libui_sdl/libui/unix/stddialogs.c
index b793d06..d2b89b9 100644
--- a/src/libui_sdl/libui/unix/stddialogs.c
+++ b/src/libui_sdl/libui/unix/stddialogs.c
@@ -70,6 +70,9 @@ static char *filedialog(GtkWindow *parent, GtkFileChooserAction mode, const gcha
gtk_file_chooser_set_show_hidden(fc, TRUE);
gtk_file_chooser_set_do_overwrite_confirmation(fc, TRUE);
gtk_file_chooser_set_create_folders(fc, TRUE);
+ if (initpath && strlen(initpath)>0)
+ gtk_file_chooser_set_current_folder(fc, initpath);
+
response = gtk_dialog_run(GTK_DIALOG(fcd));
if (response != GTK_RESPONSE_ACCEPT) {
gtk_widget_destroy(fcd);
diff --git a/src/libui_sdl/libui/unix/window.c b/src/libui_sdl/libui/unix/window.c
index a3dde76..04630bc 100644
--- a/src/libui_sdl/libui/unix/window.c
+++ b/src/libui_sdl/libui/unix/window.c
@@ -145,11 +145,16 @@ static void uiWindowShow(uiControl *c)
gtk_window_resize(w->window, width, height);
}
+static void uiWindowSetFocus(uiControl* c)
+{
+ gtk_window_present(GTK_WINDOW(uiWindow(c)->widget));
+}
+
uiUnixControlDefaultHide(uiWindow)
uiUnixControlDefaultEnabled(uiWindow)
uiUnixControlDefaultEnable(uiWindow)
uiUnixControlDefaultDisable(uiWindow)
-uiUnixControlDefaultSetFocus(uiWindow)
+//uiUnixControlDefaultSetFocus(uiWindow)
uiUnixControlDefaultSetMinSize(uiWindow)
// TODO?
uiUnixControlDefaultSetContainer(uiWindow)
diff --git a/src/libui_sdl/libui/windows/button.cpp b/src/libui_sdl/libui/windows/button.cpp
index b83d6ec..aa34bfc 100644
--- a/src/libui_sdl/libui/windows/button.cpp
+++ b/src/libui_sdl/libui/windows/button.cpp
@@ -6,6 +6,9 @@ struct uiButton {
HWND hwnd;
void (*onClicked)(uiButton *, void *);
void *onClickedData;
+
+ SIZE idealSize;
+ int idealSizeCached;
};
static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult)
@@ -41,6 +44,13 @@ static void uiButtonMinimumSize(uiWindowsControl *c, int *width, int *height)
uiWindowsSizing sizing;
int y;
+ if (b->idealSizeCached)
+ {
+ *width = b->idealSize.cx;
+ *height = b->idealSize.cy;
+ return;
+ }
+
// try the comctl32 version 6 way
size.cx = 0; // explicitly ask for ideal size
size.cy = 0;
@@ -48,6 +58,9 @@ static void uiButtonMinimumSize(uiWindowsControl *c, int *width, int *height)
*width = size.cx;
if (*width < buttonMinWidth) *width = buttonMinWidth;
*height = size.cy;
+ b->idealSize.cx = *width;
+ b->idealSize.cy = *height;
+ b->idealSizeCached = true;
return;
}
@@ -60,6 +73,9 @@ static void uiButtonMinimumSize(uiWindowsControl *c, int *width, int *height)
uiWindowsGetSizing(b->hwnd, &sizing);
uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &y);
*height = y;
+ b->idealSize.cx = *width;
+ b->idealSize.cy = *height;
+ b->idealSizeCached = true;
}
static void defaultOnClicked(uiButton *b, void *data)
@@ -75,6 +91,7 @@ char *uiButtonText(uiButton *b)
void uiButtonSetText(uiButton *b, const char *text)
{
uiWindowsSetWindowText(b->hwnd, text);
+ b->idealSizeCached = 0;
// changing the text might necessitate a change in the button's size
uiWindowsControlMinimumSizeChanged(uiWindowsControl(b));
}
@@ -103,5 +120,7 @@ uiButton *uiNewButton(const char *text)
uiWindowsRegisterWM_COMMANDHandler(b->hwnd, onWM_COMMAND, uiControl(b));
uiButtonOnClicked(b, defaultOnClicked, NULL);
+ b->idealSizeCached = 0;
+
return b;
}
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp
index 4c19314..b30c81b 100644
--- a/src/libui_sdl/main.cpp
+++ b/src/libui_sdl/main.cpp
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
+#include <string.h>
#include <SDL2/SDL.h>
#include "libui/ui.h"
@@ -30,6 +31,7 @@
#include "DlgEmuSettings.h"
#include "DlgInputConfig.h"
+#include "DlgAudioSettings.h"
#include "../NDS.h"
#include "../GPU.h"
@@ -52,6 +54,9 @@ const int kScreenLayout[3] = {0, 1, 2};
const int kScreenSizing[4] = {0, 1, 2, 3};
+char* EmuDirectory;
+
+
uiWindow* MainWindow;
uiArea* MainDrawArea;
@@ -104,8 +109,18 @@ uiDrawMatrix BottomScreenTrans;
bool Touching = false;
u32 KeyInputMask;
+bool LidCommand, LidStatus;
SDL_Joystick* Joystick;
+u32 MicBufferLength = 2048;
+s16 MicBuffer[2048];
+u32 MicBufferReadPos, MicBufferWritePos;
+
+u32 MicWavLength;
+s16* MicWavBuffer;
+
+u32 MicCommand;
+
void SetupScreenRects(int width, int height);
@@ -116,7 +131,7 @@ void GetSavestateName(int slot, char* filename, int len);
-bool FileExists(char* name)
+bool FileExists(const char* name)
{
FILE* f = melon_fopen(name, "rb");
if (!f) return false;
@@ -124,6 +139,92 @@ bool FileExists(char* name)
return true;
}
+bool LocalFileExists(const char* name)
+{
+ FILE* f = melon_fopen_local(name, "rb");
+ if (!f) return false;
+ fclose(f);
+ return true;
+}
+
+
+void MicLoadWav(char* name)
+{
+ SDL_AudioSpec format;
+ memset(&format, 0, sizeof(SDL_AudioSpec));
+
+ if (MicWavBuffer) delete[] MicWavBuffer;
+ MicWavBuffer = NULL;
+ MicWavLength = 0;
+
+ u8* buf;
+ u32 len;
+ if (!SDL_LoadWAV(name, &format, &buf, &len))
+ return;
+
+ const u64 dstfreq = 44100;
+
+ if (format.format == AUDIO_S16 || format.format == AUDIO_U16)
+ {
+ int srcinc = format.channels;
+ len /= 2;
+
+ MicWavLength = (len * dstfreq) / format.freq;
+ if (MicWavLength < 735) MicWavLength = 735;
+ MicWavBuffer = new s16[MicWavLength];
+
+ float res_incr = len / (float)MicWavLength;
+ float res_timer = 0;
+ int res_pos = 0;
+
+ for (int i = 0; i < MicWavLength; i++)
+ {
+ u16 val = ((u16*)buf)[res_pos];
+ if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000;
+
+ MicWavBuffer[i] = val;
+
+ res_timer += res_incr;
+ while (res_timer >= 1.0)
+ {
+ res_timer -= 1.0;
+ res_pos += srcinc;
+ }
+ }
+ }
+ else if (format.format == AUDIO_S8 || format.format == AUDIO_U8)
+ {
+ int srcinc = format.channels;
+
+ MicWavLength = (len * dstfreq) / format.freq;
+ if (MicWavLength < 735) MicWavLength = 735;
+ MicWavBuffer = new s16[MicWavLength];
+
+ float res_incr = len / (float)MicWavLength;
+ float res_timer = 0;
+ int res_pos = 0;
+
+ for (int i = 0; i < MicWavLength; i++)
+ {
+ u16 val = buf[res_pos] << 8;
+ if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000;
+
+ MicWavBuffer[i] = val;
+
+ res_timer += res_incr;
+ while (res_timer >= 1.0)
+ {
+ res_timer -= 1.0;
+ res_pos += srcinc;
+ }
+ }
+ }
+ else
+ printf("bad WAV format %08X\n", format.format);
+
+ SDL_FreeWAV(buf);
+}
+
void UpdateWindowTitle(void* data)
{
@@ -136,7 +237,6 @@ void AudioCallback(void* data, Uint8* stream, int len)
// buffer length is 1024 samples
// which is 710 samples at the original sample rate
- //SPU::ReadOutput((s16*)stream, len>>2);
s16 buf_in[710*2];
s16* buf_out = (s16*)stream;
@@ -159,11 +259,13 @@ void AudioCallback(void* data, Uint8* stream, int len)
float res_timer = 0;
int res_pos = 0;
+ int volume = Config::AudioVolume;
+
for (int i = 0; i < 1024; i++)
{
// TODO: interp!!
- buf_out[i*2 ] = buf_in[res_pos*2 ];
- buf_out[i*2+1] = buf_in[res_pos*2+1];
+ buf_out[i*2 ] = (buf_in[res_pos*2 ] * volume) >> 8;
+ buf_out[i*2+1] = (buf_in[res_pos*2+1] * volume) >> 8;
res_timer += res_incr;
while (res_timer >= 1.0)
@@ -174,6 +276,106 @@ void AudioCallback(void* data, Uint8* stream, int len)
}
}
+void MicCallback(void* data, Uint8* stream, int len)
+{
+ if (Config::MicInputType != 1) return;
+
+ s16* input = (s16*)stream;
+ len /= sizeof(s16);
+
+ if ((MicBufferWritePos + len) > MicBufferLength)
+ {
+ u32 len1 = MicBufferLength - MicBufferWritePos;
+ memcpy(&MicBuffer[MicBufferWritePos], &input[0], len1*sizeof(s16));
+ memcpy(&MicBuffer[0], &input[len1], (len - len1)*sizeof(s16));
+ MicBufferWritePos = len - len1;
+ }
+ else
+ {
+ memcpy(&MicBuffer[MicBufferWritePos], input, len*sizeof(s16));
+ MicBufferWritePos += len;
+ }
+}
+
+bool JoyButtonPressed(int btnid, int njoybuttons, Uint8* joybuttons, Uint32 hat)
+{
+ bool pressed;
+ if (btnid == 0x101) // up
+ pressed = (hat & SDL_HAT_UP);
+ else if (btnid == 0x104) // down
+ pressed = (hat & SDL_HAT_DOWN);
+ else if (btnid == 0x102) // right
+ pressed = (hat & SDL_HAT_RIGHT);
+ else if (btnid == 0x108) // left
+ pressed = (hat & SDL_HAT_LEFT);
+ else
+ pressed = (btnid < njoybuttons) ? joybuttons[btnid] : false;
+
+ return pressed;
+}
+
+void FeedMicInput()
+{
+ int type = Config::MicInputType;
+ if ((type != 1 && MicCommand == 0) ||
+ (type == 3 && MicWavBuffer == NULL))
+ {
+ type = 0;
+ MicBufferReadPos = 0;
+ }
+
+ switch (type)
+ {
+ case 0: // no mic
+ NDS::MicInputFrame(NULL, 0);
+ break;
+
+ case 1: // host mic
+ if ((MicBufferReadPos + 735) > MicBufferLength)
+ {
+ s16 tmp[735];
+ u32 len1 = MicBufferLength - MicBufferReadPos;
+ memcpy(&tmp[0], &MicBuffer[MicBufferReadPos], len1*sizeof(s16));
+ memcpy(&tmp[len1], &MicBuffer[0], (735 - len1)*sizeof(s16));
+
+ NDS::MicInputFrame(tmp, 735);
+ MicBufferReadPos = 735 - len1;
+ }
+ else
+ {
+ NDS::MicInputFrame(&MicBuffer[MicBufferReadPos], 735);
+ MicBufferReadPos += 735;
+ }
+ break;
+
+ case 2: // white noise
+ {
+ s16 tmp[735];
+ for (int i = 0; i < 735; i++) tmp[i] = rand() & 0xFFFF;
+ NDS::MicInputFrame(tmp, 735);
+ }
+ break;
+
+ case 3: // WAV
+ if ((MicBufferReadPos + 735) > MicWavLength)
+ {
+ s16 tmp[735];
+ u32 len1 = MicWavLength - MicBufferReadPos;
+ memcpy(&tmp[0], &MicWavBuffer[MicBufferReadPos], len1*sizeof(s16));
+ memcpy(&tmp[len1], &MicWavBuffer[0], (735 - len1)*sizeof(s16));
+
+ NDS::MicInputFrame(tmp, 735);
+ MicBufferReadPos = 735 - len1;
+ }
+ else
+ {
+ NDS::MicInputFrame(&MicWavBuffer[MicBufferReadPos], 735);
+ MicBufferReadPos += 735;
+ }
+ break;
+ }
+}
+
int EmuThreadFunc(void* burp)
{
NDS::Init();
@@ -185,32 +387,18 @@ int EmuThreadFunc(void* burp)
ScreenDrawInited = false;
Touching = false;
+ KeyInputMask = 0xFFF;
+ LidCommand = false;
+ LidStatus = false;
+ MicCommand = 0;
- SDL_AudioSpec whatIwant, whatIget;
- memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
- whatIwant.freq = 47340;
- whatIwant.format = AUDIO_S16LSB;
- whatIwant.channels = 2;
- whatIwant.samples = 1024;
- whatIwant.callback = AudioCallback;
- SDL_AudioDeviceID audio = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, 0);
- if (!audio)
- {
- printf("Audio init failed: %s\n", SDL_GetError());
- }
- else
+ Uint8* joybuttons = NULL; int njoybuttons = 0;
+ if (Joystick)
{
- SDL_PauseAudioDevice(audio, 0);
+ njoybuttons = SDL_JoystickNumButtons(Joystick);
+ if (njoybuttons) joybuttons = new Uint8[njoybuttons];
}
- KeyInputMask = 0xFFF;
-
- // TODO: support more joysticks
- if (SDL_NumJoysticks() > 0)
- Joystick = SDL_JoystickOpen(0);
- else
- Joystick = NULL;
-
u32 nframes = 0;
u32 starttick = SDL_GetTicks();
u32 lasttick = starttick;
@@ -225,6 +413,7 @@ int EmuThreadFunc(void* burp)
{
EmuStatus = 1;
+
// poll input
u32 keymask = KeyInputMask;
u32 joymask = 0xFFF;
@@ -236,28 +425,49 @@ int EmuThreadFunc(void* burp)
Sint16 axisX = SDL_JoystickGetAxis(Joystick, 0);
Sint16 axisY = SDL_JoystickGetAxis(Joystick, 1);
+ for (int i = 0; i < njoybuttons; i++)
+ joybuttons[i] = SDL_JoystickGetButton(Joystick, i);
+
for (int i = 0; i < 12; i++)
{
int btnid = Config::JoyMapping[i];
if (btnid < 0) continue;
- bool pressed;
- if (btnid == 0x101) // up
- pressed = (hat & SDL_HAT_UP) || (axisY <= -16384);
- else if (btnid == 0x104) // down
- pressed = (hat & SDL_HAT_DOWN) || (axisY >= 16384);
- else if (btnid == 0x102) // right
- pressed = (hat & SDL_HAT_RIGHT) || (axisX >= 16384);
- else if (btnid == 0x108) // left
- pressed = (hat & SDL_HAT_LEFT) || (axisX <= -16384);
- else
- pressed = SDL_JoystickGetButton(Joystick, btnid);
+ bool pressed = JoyButtonPressed(btnid, njoybuttons, joybuttons, hat);
+
+ if (i == 4) // right
+ pressed = pressed || (axisX >= 16384);
+ else if (i == 5) // left
+ pressed = pressed || (axisX <= -16384);
+ else if (i == 6) // up
+ pressed = pressed || (axisY <= -16384);
+ else if (i == 7) // down
+ pressed = pressed || (axisY >= 16384);
if (pressed) joymask &= ~(1<<i);
}
+
+ if (JoyButtonPressed(Config::HKJoyMapping[HK_Lid], njoybuttons, joybuttons, hat))
+ {
+ LidStatus = !LidStatus;
+ LidCommand = true;
+ }
+ if (JoyButtonPressed(Config::HKJoyMapping[HK_Mic], njoybuttons, joybuttons, hat))
+ MicCommand |= 2;
+ else
+ MicCommand &= ~2;
}
NDS::SetKeyMask(keymask & joymask);
+ if (LidCommand)
+ {
+ NDS::SetLidClosed(LidStatus);
+ LidCommand = false;
+ }
+
+ // microphone input
+ FeedMicInput();
+
// emulate
u32 nlines = NDS::RunFrame();
@@ -356,9 +566,7 @@ int EmuThreadFunc(void* burp)
EmuStatus = 0;
- if (Joystick) SDL_JoystickClose(Joystick);
-
- if (audio) SDL_CloseAudioDevice(audio);
+ if (joybuttons) delete[] joybuttons;
NDS::DeInit();
@@ -486,6 +694,9 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
for (int i = 0; i < 12; i++)
if (evt->Scancode == Config::KeyMapping[i])
KeyInputMask |= (1<<i);
+
+ if (evt->Scancode == Config::HKKeyMapping[HK_Mic])
+ MicCommand &= ~1;
}
else if (!evt->Repeat)
{
@@ -509,8 +720,16 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
if (evt->Scancode == Config::KeyMapping[i])
KeyInputMask &= ~(1<<i);
- //if (evt->Scancode == 0x58) // F12
- // NDS::debug(0);
+ if (evt->Scancode == Config::HKKeyMapping[HK_Lid])
+ {
+ LidStatus = !LidStatus;
+ LidCommand = true;
+ }
+ if (evt->Scancode == Config::HKKeyMapping[HK_Mic])
+ MicCommand |= 1;
+
+ if (evt->Scancode == 0x57) // F11
+ NDS::debug(0);
}
return 1;
@@ -899,7 +1118,7 @@ void LoadState(int slot)
}
else
{
- char* file = uiOpenFile(MainWindow, "melonDS savestate (any)|*.ml1;*.ml2;*.ml3;*.ml4;*.ml5;*.ml6;*.ml7;*.ml8;*.mln", NULL);
+ char* file = uiOpenFile(MainWindow, "melonDS savestate (any)|*.ml1;*.ml2;*.ml3;*.ml4;*.ml5;*.ml6;*.ml7;*.ml8;*.mln", Config::LastROMFolder);
if (!file)
{
EmuRunning = prevstatus;
@@ -922,6 +1141,8 @@ void LoadState(int slot)
NDS::DoSavestate(backup);
delete backup;
+ bool failed = false;
+
Savestate* state = new Savestate(filename, false);
if (state->Error)
{
@@ -931,25 +1152,29 @@ void LoadState(int slot)
// current state might be crapoed, so restore from sane backup
state = new Savestate("timewarp.mln", false);
+ failed = true;
}
NDS::DoSavestate(state);
delete state;
- if (Config::SavestateRelocSRAM && ROMPath[0]!='\0')
+ if (!failed)
{
- strncpy(PrevSRAMPath, SRAMPath, 1024);
+ if (Config::SavestateRelocSRAM && ROMPath[0]!='\0')
+ {
+ strncpy(PrevSRAMPath, SRAMPath, 1024);
- strncpy(SRAMPath, filename, 1019);
- int len = strlen(SRAMPath);
- strcpy(&SRAMPath[len], ".sav");
- SRAMPath[len+4] = '\0';
+ strncpy(SRAMPath, filename, 1019);
+ int len = strlen(SRAMPath);
+ strcpy(&SRAMPath[len], ".sav");
+ SRAMPath[len+4] = '\0';
- NDS::RelocateSave(SRAMPath, false);
- }
+ NDS::RelocateSave(SRAMPath, false);
+ }
- SavestateLoaded = true;
- uiMenuItemEnable(MenuItem_UndoStateLoad);
+ SavestateLoaded = true;
+ uiMenuItemEnable(MenuItem_UndoStateLoad);
+ }
EmuRunning = prevstatus;
}
@@ -968,7 +1193,7 @@ void SaveState(int slot)
}
else
{
- char* file = uiSaveFile(MainWindow, "melonDS savestate (*.mln)|*.mln", NULL);
+ char* file = uiSaveFile(MainWindow, "melonDS savestate (*.mln)|*.mln", Config::LastROMFolder);
if (!file)
{
EmuRunning = prevstatus;
@@ -1085,12 +1310,17 @@ void OnOpenFile(uiMenuItem* item, uiWindow* window, void* blarg)
EmuRunning = 2;
while (EmuStatus != 2);
- char* file = uiOpenFile(window, "DS ROM (*.nds)|*.nds;*.srl|Any file|*.*", NULL);
+ char* file = uiOpenFile(window, "DS ROM (*.nds)|*.nds;*.srl|Any file|*.*", Config::LastROMFolder);
if (!file)
{
EmuRunning = prevstatus;
return;
}
+
+ int pos = strlen(file)-1;
+ while (file[pos] != '/' && file[pos] != '\\' && pos > 0) pos--;
+ strncpy(Config::LastROMFolder, file, pos);
+ Config::LastROMFolder[pos] = '\0';
TryLoadROM(file, prevstatus);
uiFreeText(file);
@@ -1177,7 +1407,17 @@ void OnOpenEmuSettings(uiMenuItem* item, uiWindow* window, void* blarg)
void OnOpenInputConfig(uiMenuItem* item, uiWindow* window, void* blarg)
{
- DlgInputConfig::Open();
+ DlgInputConfig::Open(0);
+}
+
+void OnOpenHotkeyConfig(uiMenuItem* item, uiWindow* window, void* blarg)
+{
+ DlgInputConfig::Open(1);
+}
+
+void OnOpenAudioSettings(uiMenuItem* item, uiWindow* window, void* blarg)
+{
+ DlgAudioSettings::Open();
}
@@ -1321,6 +1561,19 @@ int main(int argc, char** argv)
printf("melonDS " MELONDS_VERSION "\n");
printf(MELONDS_URL "\n");
+ {
+ int len = strlen(argv[0]);
+ while (len > 0)
+ {
+ if (argv[0][len] == '/') break;
+ if (argv[0][len] == '\\') break;
+ len--;
+ }
+ EmuDirectory = new char[len];
+ strncpy(EmuDirectory, argv[0], len);
+ EmuDirectory[len] = '\0';
+ }
+
// http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
@@ -1348,7 +1601,10 @@ int main(int argc, char** argv)
Config::Load();
- if (!Config::HasConfigFile("bios7.bin") || !Config::HasConfigFile("bios9.bin") || !Config::HasConfigFile("firmware.bin"))
+ if (Config::AudioVolume < 0) Config::AudioVolume = 0;
+ else if (Config::AudioVolume > 256) Config::AudioVolume = 256;
+
+ if (!LocalFileExists("bios7.bin") || !LocalFileExists("bios9.bin") || !LocalFileExists("firmware.bin"))
{
uiMsgBoxError(
NULL,
@@ -1432,10 +1688,16 @@ int main(int argc, char** argv)
MenuItem_Stop = menuitem;
menu = uiNewMenu("Config");
- menuitem = uiMenuAppendItem(menu, "Emu settings");
- uiMenuItemOnClicked(menuitem, OnOpenEmuSettings, NULL);
- menuitem = uiMenuAppendItem(menu, "Input config");
- uiMenuItemOnClicked(menuitem, OnOpenInputConfig, NULL);
+ {
+ menuitem = uiMenuAppendItem(menu, "Emu settings");
+ uiMenuItemOnClicked(menuitem, OnOpenEmuSettings, NULL);
+ menuitem = uiMenuAppendItem(menu, "Input config");
+ uiMenuItemOnClicked(menuitem, OnOpenInputConfig, NULL);
+ menuitem = uiMenuAppendItem(menu, "Hotkey config");
+ uiMenuItemOnClicked(menuitem, OnOpenHotkeyConfig, NULL);
+ menuitem = uiMenuAppendItem(menu, "Audio settings");
+ uiMenuItemOnClicked(menuitem, OnOpenAudioSettings, NULL);
+ }
uiMenuAppendSeparator(menu);
{
uiMenu* submenu = uiNewMenu("Savestate settings");
@@ -1566,6 +1828,53 @@ int main(int argc, char** argv)
OnSetScreenRotation(MenuItem_ScreenRot[ScreenRotation], MainWindow, (void*)&kScreenRot[ScreenRotation]);
+ SDL_AudioSpec whatIwant, whatIget;
+ memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
+ whatIwant.freq = 47340;
+ whatIwant.format = AUDIO_S16LSB;
+ whatIwant.channels = 2;
+ whatIwant.samples = 1024;
+ whatIwant.callback = AudioCallback;
+ SDL_AudioDeviceID audio = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, 0);
+ if (!audio)
+ {
+ printf("Audio init failed: %s\n", SDL_GetError());
+ }
+ else
+ {
+ SDL_PauseAudioDevice(audio, 0);
+ }
+
+ memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
+ whatIwant.freq = 44100;
+ whatIwant.format = AUDIO_S16LSB;
+ whatIwant.channels = 1;
+ whatIwant.samples = 1024;
+ whatIwant.callback = MicCallback;
+ SDL_AudioDeviceID mic = SDL_OpenAudioDevice(NULL, 1, &whatIwant, &whatIget, 0);
+ if (!mic)
+ {
+ printf("Mic init failed: %s\n", SDL_GetError());
+ MicBufferLength = 0;
+ }
+ else
+ {
+ SDL_PauseAudioDevice(mic, 0);
+ }
+
+ memset(MicBuffer, 0, sizeof(MicBuffer));
+ MicBufferReadPos = 0;
+ MicBufferWritePos = 0;
+
+ MicWavBuffer = NULL;
+ if (Config::MicInputType == 3) MicLoadWav(Config::MicWavPath);
+
+ // TODO: support more joysticks
+ if (SDL_NumJoysticks() > 0)
+ Joystick = SDL_JoystickOpen(0);
+ else
+ Joystick = NULL;
+
EmuRunning = 2;
RunningSomething = false;
EmuThread = SDL_CreateThread(EmuThreadFunc, "melonDS magic", NULL);
@@ -1594,6 +1903,12 @@ int main(int argc, char** argv)
EmuRunning = 0;
SDL_WaitThread(EmuThread, NULL);
+ if (Joystick) SDL_JoystickClose(Joystick);
+ if (audio) SDL_CloseAudioDevice(audio);
+ if (mic) SDL_CloseAudioDevice(mic);
+
+ if (MicWavBuffer) delete[] MicWavBuffer;
+
Config::ScreenRotation = ScreenRotation;
Config::ScreenGap = ScreenGap;
Config::ScreenLayout = ScreenLayout;
@@ -1605,6 +1920,7 @@ int main(int argc, char** argv)
uiUninit();
SDL_Quit();
+ delete[] EmuDirectory;
return 0;
}
@@ -1614,41 +1930,35 @@ int main(int argc, char** argv)
int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdshow)
{
- char cmdargs[16][256];
- int arg = 1;
- int j = 0;
- bool inquote = false;
- int len = strlen(cmdline);
- for (int i = 0; i < len; i++)
- {
- char c = cmdline[i];
- if (c == '\0') break;
- if (c == '"') inquote = !inquote;
- if (!inquote && c==' ')
- {
- if (j > 255) j = 255;
- if (arg < 16) cmdargs[arg][j] = '\0';
- arg++;
- j = 0;
- }
- else
- {
- if (arg < 16 && j < 255) cmdargs[arg][j] = c;
- j++;
- }
+ int argc = 0;
+ wchar_t** argv_w = CommandLineToArgvW(GetCommandLineW(), &argc);
+ char* nullarg = "";
+
+ char** argv = new char*[argc];
+ for (int i = 0; i < argc; i++)
+ {
+ int len = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, NULL, 0, NULL, NULL);
+ if (len < 1) return NULL;
+ argv[i] = new char[len];
+ int res = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, argv[i], len, NULL, NULL);
+ if (res != len) { delete[] argv[i]; argv[i] = nullarg; }
+ }
+
+ if (AttachConsole(ATTACH_PARENT_PROCESS))
+ {
+ freopen("CONOUT$", "w", stdout);
+ freopen("CONOUT$", "w", stderr);
+ printf("\n");
}
- if (j > 255) j = 255;
- if (arg < 16) cmdargs[arg][j] = '\0';
- if (len > 0) arg++;
- // FIXME!!
- strncpy(cmdargs[0], "melonDS.exe", 256);
+ int ret = main(argc, argv);
+
+ printf("\n\n>");
- char* cmdargptr[16];
- for (int i = 0; i < 16; i++)
- cmdargptr[i] = &cmdargs[i][0];
+ for (int i = 0; i < argc; i++) if (argv[i] != nullarg) delete[] argv[i];
+ delete[] argv;
- return main(arg, cmdargptr);
+ return ret;
}
#endif