diff options
Diffstat (limited to 'src/libui_sdl')
-rw-r--r-- | src/libui_sdl/DlgAudioSettings.cpp | 183 | ||||
-rw-r--r-- | src/libui_sdl/DlgAudioSettings.h | 29 | ||||
-rw-r--r-- | src/libui_sdl/DlgEmuSettings.cpp | 11 | ||||
-rw-r--r-- | src/libui_sdl/DlgInputConfig.cpp | 252 | ||||
-rw-r--r-- | src/libui_sdl/DlgInputConfig.h | 2 | ||||
-rw-r--r-- | src/libui_sdl/Platform.cpp | 4 | ||||
-rw-r--r-- | src/libui_sdl/libui/ui.h | 2 | ||||
-rw-r--r-- | src/libui_sdl/libui/unix/area.c | 26 | ||||
-rw-r--r-- | src/libui_sdl/libui/unix/stddialogs.c | 3 | ||||
-rw-r--r-- | src/libui_sdl/libui/unix/window.c | 7 | ||||
-rw-r--r-- | src/libui_sdl/libui/windows/button.cpp | 19 | ||||
-rw-r--r-- | src/libui_sdl/main.cpp | 494 |
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 |