diff options
Diffstat (limited to 'src/libui_sdl')
-rw-r--r-- | src/libui_sdl/CMakeLists.txt | 12 | ||||
-rw-r--r-- | src/libui_sdl/DlgInputConfig.cpp | 37 | ||||
-rw-r--r-- | src/libui_sdl/DlgVideoSettings.cpp | 32 | ||||
-rw-r--r-- | src/libui_sdl/PlatformConfig.cpp | 6 | ||||
-rw-r--r-- | src/libui_sdl/PlatformConfig.h | 2 | ||||
-rw-r--r-- | src/libui_sdl/libui/ui.h | 1 | ||||
-rw-r--r-- | src/libui_sdl/libui/unix/gl.c | 5 | ||||
-rw-r--r-- | src/libui_sdl/libui/windows/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/libui_sdl/libui/windows/gl.cpp | 35 | ||||
-rw-r--r-- | src/libui_sdl/libui/windows/window.cpp | 2 | ||||
-rw-r--r-- | src/libui_sdl/main.cpp | 242 |
11 files changed, 298 insertions, 78 deletions
diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index 63e9f48..64206bf 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -14,6 +14,10 @@ SET(SOURCES_LIBUI OSD.cpp ) +if (WIN32) + set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -i <SOURCE> -o <OBJECT>") +endif() + option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON) set(BUILD_SHARED_LIBS OFF) add_subdirectory(libui) @@ -39,11 +43,11 @@ if (UNIX) ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER}) add_custom_command(OUTPUT melon_grc.c - COMMAND glib-compile-resources --sourcedir="${CMAKE_SOURCE_DIR}" - --target="${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c" + COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} + --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c --generate-source "${CMAKE_SOURCE_DIR}/melon_grc.xml" - COMMAND glib-compile-resources --sourcedir="${CMAKE_SOURCE_DIR}" - --target="${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h" + COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} + --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h --generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml") if (CMAKE_SYSTEM_NAME STREQUAL "Linux") diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp index 8882275..a80e2ec 100644 --- a/src/libui_sdl/DlgInputConfig.cpp +++ b/src/libui_sdl/DlgInputConfig.cpp @@ -125,21 +125,30 @@ void JoyMappingName(int id, char* str) return; } - if (id & 0x100) + bool hasbtn = ((id & 0xFFFF) != 0xFFFF); + + if (hasbtn) { - int hatnum = ((id >> 4) & 0xF) + 1; + if (id & 0x100) + { + int hatnum = ((id >> 4) & 0xF) + 1; - switch (id & 0xF) + switch (id & 0xF) + { + case 0x1: sprintf(str, "Hat %d up", hatnum); break; + case 0x2: sprintf(str, "Hat %d right", hatnum); break; + case 0x4: sprintf(str, "Hat %d down", hatnum); break; + case 0x8: sprintf(str, "Hat %d left", hatnum); break; + } + } + else { - case 0x1: sprintf(str, "Hat %d up", hatnum); break; - case 0x2: sprintf(str, "Hat %d right", hatnum); break; - case 0x4: sprintf(str, "Hat %d down", hatnum); break; - case 0x8: sprintf(str, "Hat %d left", hatnum); break; + sprintf(str, "Button %d", (id & 0xFFFF) + 1); } } else { - sprintf(str, "Button %d", (id & 0xFFFF) + 1); + strcpy(str, ""); } if (id & 0x10000) @@ -151,9 +160,9 @@ void JoyMappingName(int id, char* str) switch ((id >> 20) & 0xF) { - case 0: sprintf(str, "%s / Axis %d +", tmp, axisnum); break; - case 1: sprintf(str, "%s / Axis %d -", tmp, axisnum); break; - case 2: sprintf(str, "%s / Trigger %d", tmp, axisnum); break; + case 0: sprintf(str, "%s%sAxis %d +", tmp, hasbtn?" / ":"", axisnum); break; + case 1: sprintf(str, "%s%sAxis %d -", tmp, hasbtn?" / ":"", axisnum); break; + case 2: sprintf(str, "%s%sTrigger %d", tmp, hasbtn?" / ":"", axisnum); break; } } } @@ -223,10 +232,12 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) // set key. if (evt->Scancode != 0x1 || evt->Modifiers != 0) // ESC { + int mod = (dlg->type == 0) ? 0 : evt->Modifiers; + if (evt->Scancode == 0xE && evt->Modifiers == 0) // backspace dlg->keymap[dlg->pollid] = -1; else - dlg->keymap[dlg->pollid] = evt->Scancode | (evt->Modifiers << 16); + dlg->keymap[dlg->pollid] = evt->Scancode | (mod << 16); } char keyname[64]; @@ -287,7 +298,7 @@ Uint32 JoyPoll(Uint32 interval, void* param) } int oldmap; - if (dlg->joymap[id] == -1) oldmap = 0; + if (dlg->joymap[id] == -1) oldmap = 0xFFFF; else oldmap = dlg->joymap[id]; int nbuttons = SDL_JoystickNumButtons(joy); diff --git a/src/libui_sdl/DlgVideoSettings.cpp b/src/libui_sdl/DlgVideoSettings.cpp index 7d876e2..ff88ba8 100644 --- a/src/libui_sdl/DlgVideoSettings.cpp +++ b/src/libui_sdl/DlgVideoSettings.cpp @@ -39,12 +39,14 @@ uiWindow* win; uiRadioButtons* rbRenderer; uiCheckbox* cbGLDisplay; +uiCheckbox* cbVSync; uiCheckbox* cbThreaded3D; uiCombobox* cbResolution; uiCheckbox* cbAntialias; int old_renderer; int old_gldisplay; +int old_vsync; int old_threaded3D; int old_resolution; int old_antialias; @@ -89,6 +91,11 @@ void RevertSettings() { Config::ScreenUseGL = old_gldisplay; } + if (old_vsync != Config::ScreenVSync) + { + Config::ScreenVSync = old_vsync; + //ApplyNewSettings(4); + } if (old_usegl != new_usegl) { apply2 = true; @@ -130,21 +137,33 @@ void OnRendererChanged(uiRadioButtons* rb, void* blarg) UpdateControls(); bool new_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + + if (new_usegl) uiControlEnable(uiControl(cbVSync)); + else uiControlDisable(uiControl(cbVSync)); + if (new_usegl != old_usegl) ApplyNewSettings(2); else ApplyNewSettings(3); - + uiControlSetFocus(uiControl(win)); } void OnGLDisplayChanged(uiCheckbox* cb, void* blarg) { Config::ScreenUseGL = uiCheckboxChecked(cb); + if (Config::ScreenUseGL) uiControlEnable(uiControl(cbVSync)); + else uiControlDisable(uiControl(cbVSync)); ApplyNewSettings(2); uiControlSetFocus(uiControl(win)); } +void OnVSyncChanged(uiCheckbox* cb, void* blarg) +{ + Config::ScreenVSync = uiCheckboxChecked(cb); + //ApplyNewSettings(4); +} + void OnThreaded3DChanged(uiCheckbox* cb, void* blarg) { Config::Threaded3D = uiCheckboxChecked(cb); @@ -232,6 +251,10 @@ void Open() cbGLDisplay = uiNewCheckbox("OpenGL display"); uiCheckboxOnToggled(cbGLDisplay, OnGLDisplayChanged, NULL); uiBoxAppend(in_ctrl, uiControl(cbGLDisplay), 0); + + cbVSync = uiNewCheckbox("VSync"); + uiCheckboxOnToggled(cbVSync, OnVSyncChanged, NULL); + uiBoxAppend(in_ctrl, uiControl(cbVSync), 0); } { @@ -300,17 +323,24 @@ void Open() old_renderer = Config::_3DRenderer; old_gldisplay = Config::ScreenUseGL; + old_vsync = Config::ScreenVSync; old_threaded3D = Config::Threaded3D; old_resolution = Config::GL_ScaleFactor; old_antialias = Config::GL_Antialias; uiCheckboxSetChecked(cbGLDisplay, Config::ScreenUseGL); + uiCheckboxSetChecked(cbVSync, Config::ScreenVSync); uiCheckboxSetChecked(cbThreaded3D, Config::Threaded3D); uiComboboxSetSelected(cbResolution, Config::GL_ScaleFactor-1); //uiCheckboxSetChecked(cbAntialias, Config::GL_Antialias); uiRadioButtonsSetSelected(rbRenderer, Config::_3DRenderer); UpdateControls(); + if (Config::ScreenUseGL || Config::_3DRenderer != 0) + uiControlEnable(uiControl(cbVSync)); + else + uiControlDisable(uiControl(cbVSync)); + uiControlShow(uiControl(win)); } diff --git a/src/libui_sdl/PlatformConfig.cpp b/src/libui_sdl/PlatformConfig.cpp index 7f45b59..c8ec19f 100644 --- a/src/libui_sdl/PlatformConfig.cpp +++ b/src/libui_sdl/PlatformConfig.cpp @@ -43,9 +43,11 @@ int ScreenSizing; int ScreenFilter; int ScreenUseGL; +int ScreenVSync; int ScreenRatio; int LimitFPS; +int AudioSync; int ShowOSD; int DirectBoot; @@ -118,9 +120,11 @@ ConfigEntry PlatformConfigFile[] = {"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0}, {"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0}, + {"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0}, {"ScreenRatio", 0, &ScreenRatio, 0, NULL, 0}, - {"LimitFPS", 0, &LimitFPS, 1, NULL, 0}, + {"LimitFPS", 0, &LimitFPS, 0, NULL, 0}, + {"AudioSync", 0, &AudioSync, 1, NULL, 0}, {"ShowOSD", 0, &ShowOSD, 1, NULL, 0}, {"DirectBoot", 0, &DirectBoot, 1, NULL, 0}, diff --git a/src/libui_sdl/PlatformConfig.h b/src/libui_sdl/PlatformConfig.h index 2c59e5d..842e72a 100644 --- a/src/libui_sdl/PlatformConfig.h +++ b/src/libui_sdl/PlatformConfig.h @@ -54,9 +54,11 @@ extern int ScreenSizing; extern int ScreenFilter; extern int ScreenUseGL; +extern int ScreenVSync; extern int ScreenRatio; extern int LimitFPS; +extern int AudioSync; extern int ShowOSD; extern int DirectBoot; diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h index e15c127..03aef5d 100644 --- a/src/libui_sdl/libui/ui.h +++ b/src/libui_sdl/libui/ui.h @@ -620,6 +620,7 @@ _UI_EXTERN void *uiGLGetProcAddress(const char* proc); _UI_EXTERN int uiGLGetFramebuffer(uiGLContext* ctx); _UI_EXTERN float uiGLGetFramebufferScale(uiGLContext* ctx); _UI_EXTERN void uiGLSwapBuffers(uiGLContext* ctx); +_UI_EXTERN void uiGLSetVSync(int sync); _UI_ENUM(uiModifiers) { diff --git a/src/libui_sdl/libui/unix/gl.c b/src/libui_sdl/libui/unix/gl.c index e1665ee..e15cf4f 100644 --- a/src/libui_sdl/libui/unix/gl.c +++ b/src/libui_sdl/libui/unix/gl.c @@ -193,6 +193,11 @@ void uiGLSwapBuffers(uiGLContext* ctx) ctx->backbuffer = ctx->backbuffer ? 0 : 1; } +void uiGLSetVSync(int sync) +{ + // TODO +} + void uiGLMakeContextCurrent(uiGLContext* ctx) { if (!ctx) diff --git a/src/libui_sdl/libui/windows/CMakeLists.txt b/src/libui_sdl/libui/windows/CMakeLists.txt index 9d5313a..24d4ad9 100644 --- a/src/libui_sdl/libui/windows/CMakeLists.txt +++ b/src/libui_sdl/libui/windows/CMakeLists.txt @@ -73,7 +73,7 @@ macro(_handle_static) add_custom_command( TARGET libui POST_BUILD COMMAND - ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:libui,BINARY_DIR>/CMakeFiles/libui.dir/windows/resources.rc.* ${_LIBUI_STATIC_RES} + ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:libui,BINARY_DIR>/CMakeFiles/libui.dir/windows/resources.rc.obj ${_LIBUI_STATIC_RES} COMMENT "Copying libui.res") endmacro() diff --git a/src/libui_sdl/libui/windows/gl.cpp b/src/libui_sdl/libui/windows/gl.cpp index c621721..07ef19b 100644 --- a/src/libui_sdl/libui/windows/gl.cpp +++ b/src/libui_sdl/libui/windows/gl.cpp @@ -3,6 +3,7 @@ #include "area.hpp" #include <GL/gl.h> +#include <GL/glext.h> #include <GL/wglext.h> struct uiGLContext @@ -159,3 +160,37 @@ float uiGLGetFramebufferScale(uiGLContext* ctx) // TODO return 1; } + +void uiGLSetVSync(int sync) +{ + static PFNWGLSWAPINTERVALEXTPROC _wglSwapIntervalEXT = NULL; + static bool symloaded = false; + + if (!symloaded) + { + PFNGLGETSTRINGIPROC _glGetStringi = (PFNGLGETSTRINGIPROC)wglGetProcAddress("glGetStringi"); + if (_glGetStringi == NULL) return; + + GLint numext; + glGetIntegerv(GL_NUM_EXTENSIONS, &numext); + + bool hasswapctrl = false; + for (GLint i = 0; i < numext; i++) + { + const char* ext = (const char*)_glGetStringi(GL_EXTENSIONS, i); + if (!stricmp(ext, "WGL_EXT_swap_control")) + { + hasswapctrl = true; + break; + } + } + + if (hasswapctrl) + _wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); + + symloaded = true; + } + + if (_wglSwapIntervalEXT) + _wglSwapIntervalEXT(sync); +} diff --git a/src/libui_sdl/libui/windows/window.cpp b/src/libui_sdl/libui/windows/window.cpp index 18d1171..a8f7f23 100644 --- a/src/libui_sdl/libui/windows/window.cpp +++ b/src/libui_sdl/libui/windows/window.cpp @@ -95,7 +95,7 @@ static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARA // not a menu if (lParam != 0) break; - if (HIWORD(wParam) != 0) + if (HIWORD(wParam) != 0 || LOWORD(wParam) <= IDCANCEL) break; runMenuEvent(LOWORD(wParam), uiWindow(w)); return 0; diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 34e838c..d3f9024 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -93,6 +93,7 @@ uiMenuItem* MenuItem_ScreenSizing[4]; uiMenuItem* MenuItem_ScreenFilter; uiMenuItem* MenuItem_LimitFPS; +uiMenuItem* MenuItem_AudioSync; uiMenuItem* MenuItem_ShowOSD; SDL_Thread* EmuThread; @@ -129,6 +130,8 @@ bool GL_ScreenSizeDirty; int GL_3DScale; +bool GL_VSyncStatus; + int ScreenGap = 0; int ScreenLayout = 0; int ScreenSizing = 0; @@ -158,8 +161,13 @@ bool LidStatus; int JoystickID; SDL_Joystick* Joystick; +int AudioFreq; +float AudioSampleFrac; SDL_AudioDeviceID AudioDevice, MicDevice; +SDL_cond* AudioSync; +SDL_mutex* AudioSyncLock; + u32 MicBufferLength = 2048; s16 MicBuffer[2048]; u32 MicBufferReadPos, MicBufferWritePos; @@ -236,6 +244,8 @@ bool GLScreen_InitOSDShader(GLuint* shader) bool GLScreen_Init() { + GL_VSyncStatus = Config::ScreenVSync; + // TODO: consider using epoxy? if (!OpenGL_Init()) return false; @@ -298,6 +308,13 @@ void GLScreen_DeInit() void GLScreen_DrawScreen() { + bool vsync = Config::ScreenVSync && !HotkeyDown(HK_FastForward); + if (vsync != GL_VSyncStatus) + { + GL_VSyncStatus = vsync; + uiGLSetVSync(vsync); + } + float scale = uiGLGetFramebufferScale(GLContext); glBindFramebuffer(GL_FRAMEBUFFER, uiGLGetFramebuffer(GLContext)); @@ -560,26 +577,42 @@ void MicLoadWav(char* name) void AudioCallback(void* data, Uint8* stream, int len) { - // resampling: - // buffer length is 1024 samples - // which is 710 samples at the original sample rate + len /= (sizeof(s16) * 2); + + // resample incoming audio to match the output sample rate - s16 buf_in[710*2]; + float f_len_in = (len * 32823.6328125) / (float)AudioFreq; + f_len_in += AudioSampleFrac; + int len_in = (int)floor(f_len_in); + AudioSampleFrac = f_len_in - len_in; + + s16 buf_in[1024*2]; s16* buf_out = (s16*)stream; - int num_in = SPU::ReadOutput(buf_in, 710); - int num_out = 1024; + int num_in; + int num_out = len; + + SDL_LockMutex(AudioSyncLock); + num_in = SPU::ReadOutput(buf_in, len_in); + SDL_CondSignal(AudioSync); + SDL_UnlockMutex(AudioSyncLock); + + if (num_in < 1) + { + memset(stream, 0, len*sizeof(s16)*2); + return; + } int margin = 6; - if (num_in < 710-margin) + if (num_in < len_in-margin) { int last = num_in-1; if (last < 0) last = 0; - for (int i = num_in; i < 710-margin; i++) + for (int i = num_in; i < len_in-margin; i++) ((u32*)buf_in)[i] = ((u32*)buf_in)[last]; - num_in = 710-margin; + num_in = len_in-margin; } float res_incr = num_in / (float)num_out; @@ -588,12 +621,22 @@ void AudioCallback(void* data, Uint8* stream, int len) int volume = Config::AudioVolume; - for (int i = 0; i < 1024; i++) + for (int i = 0; i < len; i++) { - // TODO: interp!! buf_out[i*2 ] = (buf_in[res_pos*2 ] * volume) >> 8; buf_out[i*2+1] = (buf_in[res_pos*2+1] * volume) >> 8; + /*s16 s_l = buf_in[res_pos*2 ]; + s16 s_r = buf_in[res_pos*2+1]; + + float a = res_timer; + float b = 1.0 - a; + s_l = (s_l * a) + (buf_in[(res_pos-1)*2 ] * b); + s_r = (s_r * a) + (buf_in[(res_pos-1)*2+1] * b); + + buf_out[i*2 ] = (s_l * volume) >> 8; + buf_out[i*2+1] = (s_r * volume) >> 8;*/ + res_timer += res_incr; while (res_timer >= 1.0) { @@ -710,26 +753,31 @@ bool JoystickButtonDown(int val) { if (val == -1) return false; - if (val & 0x100) + bool hasbtn = ((val & 0xFFFF) != 0xFFFF); + + if (hasbtn) { - int hatnum = (val >> 4) & 0xF; - int hatdir = val & 0xF; - Uint8 hatval = SDL_JoystickGetHat(Joystick, hatnum); + if (val & 0x100) + { + int hatnum = (val >> 4) & 0xF; + int hatdir = val & 0xF; + Uint8 hatval = SDL_JoystickGetHat(Joystick, hatnum); - bool pressed = false; - if (hatdir == 0x1) pressed = (hatval & SDL_HAT_UP); - else if (hatdir == 0x4) pressed = (hatval & SDL_HAT_DOWN); - else if (hatdir == 0x2) pressed = (hatval & SDL_HAT_RIGHT); - else if (hatdir == 0x8) pressed = (hatval & SDL_HAT_LEFT); + bool pressed = false; + if (hatdir == 0x1) pressed = (hatval & SDL_HAT_UP); + else if (hatdir == 0x4) pressed = (hatval & SDL_HAT_DOWN); + else if (hatdir == 0x2) pressed = (hatval & SDL_HAT_RIGHT); + else if (hatdir == 0x8) pressed = (hatval & SDL_HAT_LEFT); - if (pressed) return true; - } - else - { - int btnnum = val & 0xFFFF; - Uint8 btnval = SDL_JoystickGetButton(Joystick, btnnum); + if (pressed) return true; + } + else + { + int btnnum = val & 0xFFFF; + Uint8 btnval = SDL_JoystickGetButton(Joystick, btnnum); - if (btnval) return true; + if (btnval) return true; + } } if (val & 0x10000) @@ -833,6 +881,7 @@ bool JoyButtonHeld(int btnid, int njoybuttons, Uint8* joybuttons, Uint32 hat) void UpdateWindowTitle(void* data) { + if (EmuStatus == 0) return; uiWindowSetTitle(MainWindow, (const char*)data); } @@ -875,6 +924,10 @@ int EmuThreadFunc(void* burp) u32 lasttick = starttick; u32 lastmeasuretick = lasttick; u32 fpslimitcount = 0; + u64 perfcount = SDL_GetPerformanceCounter(); + u64 perffreq = SDL_GetPerformanceFrequency(); + float samplesleft = 0; + u32 nsamples = 0; char melontitle[100]; while (EmuRunning != 0) @@ -886,6 +939,7 @@ int EmuThreadFunc(void* burp) Config::LimitFPS = !Config::LimitFPS; uiQueueMain(UpdateFPSLimit, NULL); } + // TODO: similar hotkeys for video/audio sync? if (HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL); if (HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL); @@ -954,25 +1008,46 @@ int EmuThreadFunc(void* burp) } uiAreaQueueRedrawAll(MainDrawArea); - // framerate limiter based off SDL2_gfx - float framerate = (1000.0f * nlines) / (60.0f * 263.0f); - - fpslimitcount++; - u32 curtick = SDL_GetTicks(); - u32 delay = curtick - lasttick; - lasttick = curtick; + bool fastforward = HotkeyDown(HK_FastForward); - bool limitfps = Config::LimitFPS && !HotkeyDown(HK_FastForward); - - u32 wantedtick = starttick + (u32)((float)fpslimitcount * framerate); - if (curtick < wantedtick && limitfps) + if (Config::AudioSync && !fastforward) { - SDL_Delay(wantedtick - curtick); + SDL_LockMutex(AudioSyncLock); + while (SPU::GetOutputSize() > 1024) + { + int ret = SDL_CondWaitTimeout(AudioSync, AudioSyncLock, 500); + if (ret == SDL_MUTEX_TIMEDOUT) break; + } + SDL_UnlockMutex(AudioSyncLock); } else { - fpslimitcount = 0; - starttick = curtick; + // ensure the audio FIFO doesn't overflow + //SPU::TrimOutput(); + } + + float framerate = (1000.0f * nlines) / (60.0f * 263.0f); + + { + u32 curtick = SDL_GetTicks(); + u32 delay = curtick - lasttick; + + bool limitfps = Config::LimitFPS && !fastforward; + if (limitfps) + { + float wantedtickF = starttick + (framerate * (fpslimitcount+1)); + u32 wantedtick = (u32)ceil(wantedtickF); + if (curtick < wantedtick) SDL_Delay(wantedtick - curtick); + + lasttick = SDL_GetTicks(); + fpslimitcount++; + if ((abs(wantedtickF - (float)wantedtick) < 0.001312) || (fpslimitcount > 60)) + { + fpslimitcount = 0; + nsamples = 0; + starttick = lasttick; + } + } } nframes++; @@ -1044,6 +1119,12 @@ int EmuThreadFunc(void* burp) return 44203; } +void StopEmuThread() +{ + EmuRunning = 0; + SDL_WaitThread(EmuThread, NULL); +} + void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params) { @@ -1155,13 +1236,13 @@ void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area) { } -bool EventMatchesKey(uiAreaKeyEvent* evt, int val) +bool EventMatchesKey(uiAreaKeyEvent* evt, int val, bool checkmod) { if (val == -1) return false; int key = val & 0xFFFF; int mod = val >> 16; - return evt->Scancode == key && evt->Modifiers == mod; + return evt->Scancode == key && (!checkmod || evt->Modifiers == mod); } int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) @@ -1175,11 +1256,11 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (evt->Up) { for (int i = 0; i < 12; i++) - if (EventMatchesKey(evt, Config::KeyMapping[i])) + if (EventMatchesKey(evt, Config::KeyMapping[i], false)) KeyInputMask |= (1<<i); for (int i = 0; i < HK_MAX; i++) - if (EventMatchesKey(evt, Config::HKKeyMapping[i])) + if (EventMatchesKey(evt, Config::HKKeyMapping[i], true)) KeyHotkeyMask &= ~(1<<i); } else if (!evt->Repeat) @@ -1202,16 +1283,16 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) } for (int i = 0; i < 12; i++) - if (EventMatchesKey(evt, Config::KeyMapping[i])) + if (EventMatchesKey(evt, Config::KeyMapping[i], false)) KeyInputMask &= ~(1<<i); for (int i = 0; i < HK_MAX; i++) - if (EventMatchesKey(evt, Config::HKKeyMapping[i])) + if (EventMatchesKey(evt, Config::HKKeyMapping[i], true)) KeyHotkeyMask |= (1<<i); // REMOVE ME - if (evt->Scancode == 0x57) // F11 - NDS::debug(0); + //if (evt->Scancode == 0x57) // F11 + // NDS::debug(0); } return 1; @@ -1486,6 +1567,8 @@ void Run() EmuRunning = 1; RunningSomething = true; + SPU::InitOutput(); + AudioSampleFrac = 0; SDL_PauseAudioDevice(AudioDevice, 0); SDL_PauseAudioDevice(MicDevice, 0); @@ -1524,6 +1607,7 @@ void TogglePause(void* blarg) EmuRunning = 2; uiMenuItemSetChecked(MenuItem_Pause, 1); + SPU::DrainOutput(); SDL_PauseAudioDevice(AudioDevice, 1); SDL_PauseAudioDevice(MicDevice, 1); @@ -1535,6 +1619,8 @@ void TogglePause(void* blarg) EmuRunning = 1; uiMenuItemSetChecked(MenuItem_Pause, 0); + SPU::InitOutput(); + AudioSampleFrac = 0; SDL_PauseAudioDevice(AudioDevice, 0); SDL_PauseAudioDevice(MicDevice, 0); @@ -1585,6 +1671,7 @@ void Stop(bool internal) uiAreaQueueRedrawAll(MainDrawArea); + SPU::DrainOutput(); SDL_PauseAudioDevice(AudioDevice, 1); SDL_PauseAudioDevice(MicDevice, 1); @@ -1849,6 +1936,7 @@ int OnCloseWindow(uiWindow* window, void* blarg) while (EmuStatus != 3); CloseAllDialogs(); + StopEmuThread(); uiQuit(); return 1; } @@ -1886,6 +1974,7 @@ void OnCloseByMenu(uiMenuItem* item, uiWindow* window, void* blarg) while (EmuStatus != 3); CloseAllDialogs(); + StopEmuThread(); DestroyMainWindow(); uiQuit(); } @@ -2143,6 +2232,13 @@ void OnSetLimitFPS(uiMenuItem* item, uiWindow* window, void* blarg) else Config::LimitFPS = false; } +void OnSetAudioSync(uiMenuItem* item, uiWindow* window, void* blarg) +{ + int chk = uiMenuItemChecked(item); + if (chk != 0) Config::AudioSync = true; + else Config::AudioSync = false; +} + void OnSetShowOSD(uiMenuItem* item, uiWindow* window, void* blarg) { int chk = uiMenuItemChecked(item); @@ -2206,6 +2302,19 @@ void ApplyNewSettings(int type) GPU3D::InitRenderer(Screen_UseGL); if (Screen_UseGL) uiGLMakeContextCurrent(NULL); } + /*else if (type == 4) // vsync + { + if (Screen_UseGL) + { + uiGLMakeContextCurrent(GLContext); + uiGLSetVSync(Config::ScreenVSync); + uiGLMakeContextCurrent(NULL); + } + else + { + // TODO eventually: VSync for non-GL screen? + } + }*/ EmuRunning = prevstatus; } @@ -2374,11 +2483,16 @@ void CreateMainWindowMenu() MenuItem_ScreenFilter = uiMenuAppendCheckItem(menu, "Screen filtering"); uiMenuItemOnClicked(MenuItem_ScreenFilter, OnSetScreenFiltering, NULL); + MenuItem_ShowOSD = uiMenuAppendCheckItem(menu, "Show OSD"); + uiMenuItemOnClicked(MenuItem_ShowOSD, OnSetShowOSD, NULL); + + uiMenuAppendSeparator(menu); + MenuItem_LimitFPS = uiMenuAppendCheckItem(menu, "Limit framerate"); uiMenuItemOnClicked(MenuItem_LimitFPS, OnSetLimitFPS, NULL); - MenuItem_ShowOSD = uiMenuAppendCheckItem(menu, "Show OSD"); - uiMenuItemOnClicked(MenuItem_ShowOSD, OnSetShowOSD, NULL); + MenuItem_AudioSync = uiMenuAppendCheckItem(menu, "Audio sync"); + uiMenuItemOnClicked(MenuItem_AudioSync, OnSetAudioSync, NULL); } void CreateMainWindow(bool opengl) @@ -2415,6 +2529,7 @@ void CreateMainWindow(bool opengl) if (opengl_good) { uiGLMakeContextCurrent(GLContext); + uiGLSetVSync(Config::ScreenVSync); if (!GLScreen_Init()) opengl_good = false; if (opengl_good) { @@ -2539,7 +2654,6 @@ int main(int argc, char** argv) SDL_Quit(); return 0; } - { FILE* f = Platform::OpenLocalFile("romlist.bin", "rb"); if (f) @@ -2556,6 +2670,13 @@ int main(int argc, char** argv) "You should use the latest version of romlist.bin (provided in melonDS release packages)."); } } + else + { + uiMsgBoxError(NULL, + "romlist.bin not found.", + "Save memory type detection will not work correctly.\n\n" + "You should use the latest version of romlist.bin (provided in melonDS release packages)."); + } } CreateMainWindowMenu(); @@ -2613,22 +2734,29 @@ int main(int argc, char** argv) uiMenuItemSetChecked(MenuItem_ScreenFilter, Config::ScreenFilter==1); uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1); + uiMenuItemSetChecked(MenuItem_AudioSync, Config::AudioSync==1); uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1); + AudioSync = SDL_CreateCond(); + AudioSyncLock = SDL_CreateMutex(); + + AudioFreq = 48000; // TODO: make configurable? SDL_AudioSpec whatIwant, whatIget; memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); - whatIwant.freq = 47340; + whatIwant.freq = AudioFreq; whatIwant.format = AUDIO_S16LSB; whatIwant.channels = 2; whatIwant.samples = 1024; whatIwant.callback = AudioCallback; - AudioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, 0); + AudioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); if (!AudioDevice) { printf("Audio init failed: %s\n", SDL_GetError()); } else { + AudioFreq = whatIget.freq; + printf("Audio output frequency: %d Hz\n", AudioFreq); SDL_PauseAudioDevice(AudioDevice, 1); } @@ -2683,13 +2811,13 @@ int main(int argc, char** argv) uiMain(); - EmuRunning = 0; - SDL_WaitThread(EmuThread, NULL); - if (Joystick) SDL_JoystickClose(Joystick); if (AudioDevice) SDL_CloseAudioDevice(AudioDevice); if (MicDevice) SDL_CloseAudioDevice(MicDevice); + SDL_DestroyCond(AudioSync); + SDL_DestroyMutex(AudioSyncLock); + if (MicWavBuffer) delete[] MicWavBuffer; if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); |