diff options
Diffstat (limited to 'src/libui_sdl/main.cpp')
-rw-r--r-- | src/libui_sdl/main.cpp | 885 |
1 files changed, 714 insertions, 171 deletions
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index b0e89a6..ed5e80d 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -24,12 +24,16 @@ #include <SDL2/SDL.h> #include "libui/ui.h" +#include "../OpenGLSupport.h" +#include "main_shaders.h" + #include "../types.h" #include "../version.h" #include "PlatformConfig.h" #include "DlgEmuSettings.h" #include "DlgInputConfig.h" +#include "DlgVideoSettings.h" #include "DlgAudioSettings.h" #include "DlgWifiSettings.h" @@ -42,6 +46,8 @@ #include "../Savestate.h" +#include "OSD.h" + // savestate slot mapping // 1-8: regular slots (quick access) @@ -60,6 +66,10 @@ char* EmuDirectory; uiWindow* MainWindow; uiArea* MainDrawArea; +uiAreaHandler MainDrawAreaHandler; + +const u32 kGLVersions[] = {uiGLVersion(3,2), uiGLVersion(3,1), 0}; +uiGLContext* GLContext; int WindowWidth, WindowHeight; @@ -81,6 +91,7 @@ uiMenuItem* MenuItem_ScreenGap[6]; uiMenuItem* MenuItem_ScreenLayout[3]; uiMenuItem* MenuItem_ScreenSizing[4]; +uiMenuItem* MenuItem_ScreenFilter; uiMenuItem* MenuItem_LimitFPS; SDL_Thread* EmuThread; @@ -94,9 +105,28 @@ char PrevSRAMPath[1024]; // for savestate 'undo load' bool SavestateLoaded; +bool Screen_UseGL; + bool ScreenDrawInited = false; -uiDrawBitmap* ScreenBitmap = NULL; -u32 ScreenBuffer[256*384]; +uiDrawBitmap* ScreenBitmap[2] = {NULL,NULL}; + +GLuint GL_ScreenShader[3]; +GLuint GL_ScreenShaderAccel[3]; +GLuint GL_ScreenShaderOSD[3]; +struct +{ + float uScreenSize[2]; + u32 u3DScale; + u32 uFilterMode; + +} GL_ShaderConfig; +GLuint GL_ShaderConfigUBO; +GLuint GL_ScreenVertexArrayID, GL_ScreenVertexBufferID; +float GL_ScreenVertices[2 * 3*2 * 4]; // position/texcoord +GLuint GL_ScreenTexture; +bool GL_ScreenSizeDirty; + +int GL_3DScale; int ScreenGap = 0; int ScreenLayout = 0; @@ -138,7 +168,306 @@ void LoadState(int slot); void UndoStateLoad(); void GetSavestateName(int slot, char* filename, int len); +void CreateMainWindow(bool opengl); +void DestroyMainWindow(); +void RecreateMainWindow(bool opengl); + + + +bool GLScreen_InitShader(GLuint* shader, const char* fs) +{ + if (!OpenGL_BuildShaderProgram(kScreenVS, fs, shader, "ScreenShader")) + return false; + + glBindAttribLocation(shader[2], 0, "vPosition"); + glBindAttribLocation(shader[2], 1, "vTexcoord"); + glBindFragDataLocation(shader[2], 0, "oColor"); + + if (!OpenGL_LinkShaderProgram(shader)) + return false; + + GLuint uni_id; + + uni_id = glGetUniformBlockIndex(shader[2], "uConfig"); + glUniformBlockBinding(shader[2], uni_id, 16); + + glUseProgram(shader[2]); + uni_id = glGetUniformLocation(shader[2], "ScreenTex"); + glUniform1i(uni_id, 0); + uni_id = glGetUniformLocation(shader[2], "_3DTex"); + glUniform1i(uni_id, 1); + + return true; +} + +bool GLScreen_InitOSDShader(GLuint* shader) +{ + if (!OpenGL_BuildShaderProgram(kScreenVS_OSD, kScreenFS_OSD, shader, "ScreenShaderOSD")) + return false; + + glBindAttribLocation(shader[2], 0, "vPosition"); + glBindFragDataLocation(shader[2], 0, "oColor"); + + if (!OpenGL_LinkShaderProgram(shader)) + return false; + + GLuint uni_id; + + uni_id = glGetUniformBlockIndex(shader[2], "uConfig"); + glUniformBlockBinding(shader[2], uni_id, 16); + + glUseProgram(shader[2]); + uni_id = glGetUniformLocation(shader[2], "OSDTex"); + glUniform1i(uni_id, 0); + + return true; +} + +bool GLScreen_Init() +{ + // TODO: consider using epoxy? + if (!OpenGL_Init()) + return false; + + const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string + const GLubyte* version = glGetString(GL_VERSION); // version as a string + printf("OpenGL: renderer: %s\n", renderer); + printf("OpenGL: version: %s\n", version); + + if (!GLScreen_InitShader(GL_ScreenShader, kScreenFS)) + return false; + if (!GLScreen_InitShader(GL_ScreenShaderAccel, kScreenFS_Accel)) + return false; + if (!GLScreen_InitOSDShader(GL_ScreenShaderOSD)) + return false; + + memset(&GL_ShaderConfig, 0, sizeof(GL_ShaderConfig)); + + glGenBuffers(1, &GL_ShaderConfigUBO); + glBindBuffer(GL_UNIFORM_BUFFER, GL_ShaderConfigUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(GL_ShaderConfig), &GL_ShaderConfig, GL_STATIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, 16, GL_ShaderConfigUBO); + + glGenBuffers(1, &GL_ScreenVertexBufferID); + glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID); + glBufferData(GL_ARRAY_BUFFER, sizeof(GL_ScreenVertices), NULL, GL_STATIC_DRAW); + + glGenVertexArrays(1, &GL_ScreenVertexArrayID); + glBindVertexArray(GL_ScreenVertexArrayID); + glEnableVertexAttribArray(0); // position + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0)); + glEnableVertexAttribArray(1); // texcoord + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4)); + + glGenTextures(1, &GL_ScreenTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 256*3 + 1, 192*2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL); + + GL_ScreenSizeDirty = true; + + return true; +} + +void GLScreen_DeInit() +{ + glDeleteTextures(1, &GL_ScreenTexture); + + glDeleteVertexArrays(1, &GL_ScreenVertexArrayID); + glDeleteBuffers(1, &GL_ScreenVertexBufferID); + + OpenGL_DeleteShaderProgram(GL_ScreenShader); + OpenGL_DeleteShaderProgram(GL_ScreenShaderAccel); + OpenGL_DeleteShaderProgram(GL_ScreenShaderOSD); +} + +void GLScreen_DrawScreen() +{ + float scale = uiGLGetFramebufferScale(GLContext); + + if (GL_ScreenSizeDirty) + { + GL_ScreenSizeDirty = false; + + GL_ShaderConfig.uScreenSize[0] = WindowWidth; + GL_ShaderConfig.uScreenSize[1] = WindowHeight; + GL_ShaderConfig.u3DScale = GL_3DScale; + + glBindBuffer(GL_UNIFORM_BUFFER, GL_ShaderConfigUBO); + void* unibuf = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); + if (unibuf) memcpy(unibuf, &GL_ShaderConfig, sizeof(GL_ShaderConfig)); + glUnmapBuffer(GL_UNIFORM_BUFFER); + + float scwidth, scheight; + + float x0, y0, x1, y1; + float s0, s1, s2, s3; + float t0, t1, t2, t3; + +#define SETVERTEX(i, x, y, s, t) \ + GL_ScreenVertices[4*(i) + 0] = x; \ + GL_ScreenVertices[4*(i) + 1] = y; \ + GL_ScreenVertices[4*(i) + 2] = s; \ + GL_ScreenVertices[4*(i) + 3] = t; + + x0 = TopScreenRect.X; + y0 = TopScreenRect.Y; + x1 = TopScreenRect.X + TopScreenRect.Width; + y1 = TopScreenRect.Y + TopScreenRect.Height; + + scwidth = 256; + scheight = 192; + + switch (ScreenRotation) + { + case 0: + s0 = 0; t0 = 0; + s1 = scwidth; t1 = 0; + s2 = 0; t2 = scheight; + s3 = scwidth; t3 = scheight; + break; + + case 1: + s0 = 0; t0 = scheight; + s1 = 0; t1 = 0; + s2 = scwidth; t2 = scheight; + s3 = scwidth; t3 = 0; + break; + + case 2: + s0 = scwidth; t0 = scheight; + s1 = 0; t1 = scheight; + s2 = scwidth; t2 = 0; + s3 = 0; t3 = 0; + break; + + case 3: + s0 = scwidth; t0 = 0; + s1 = scwidth; t1 = scheight; + s2 = 0; t2 = 0; + s3 = 0; t3 = scheight; + break; + } + + SETVERTEX(0, x0, y0, s0, t0); + SETVERTEX(1, x1, y1, s3, t3); + SETVERTEX(2, x1, y0, s1, t1); + SETVERTEX(3, x0, y0, s0, t0); + SETVERTEX(4, x0, y1, s2, t2); + SETVERTEX(5, x1, y1, s3, t3); + + x0 = BottomScreenRect.X; + y0 = BottomScreenRect.Y; + x1 = BottomScreenRect.X + BottomScreenRect.Width; + y1 = BottomScreenRect.Y + BottomScreenRect.Height; + + scwidth = 256; + scheight = 192; + + switch (ScreenRotation) + { + case 0: + s0 = 0; t0 = 192; + s1 = scwidth; t1 = 192; + s2 = 0; t2 = 192+scheight; + s3 = scwidth; t3 = 192+scheight; + break; + + case 1: + s0 = 0; t0 = 192+scheight; + s1 = 0; t1 = 192; + s2 = scwidth; t2 = 192+scheight; + s3 = scwidth; t3 = 192; + break; + + case 2: + s0 = scwidth; t0 = 192+scheight; + s1 = 0; t1 = 192+scheight; + s2 = scwidth; t2 = 192; + s3 = 0; t3 = 192; + break; + + case 3: + s0 = scwidth; t0 = 192; + s1 = scwidth; t1 = 192+scheight; + s2 = 0; t2 = 192; + s3 = 0; t3 = 192+scheight; + break; + } + + SETVERTEX(6, x0, y0, s0, t0); + SETVERTEX(7, x1, y1, s3, t3); + SETVERTEX(8, x1, y0, s1, t1); + SETVERTEX(9, x0, y0, s0, t0); + SETVERTEX(10, x0, y1, s2, t2); + SETVERTEX(11, x1, y1, s3, t3); + +#undef SETVERTEX + + glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GL_ScreenVertices), GL_ScreenVertices); + } + + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glViewport(0, 0, WindowWidth*scale, WindowHeight*scale); + + if (GPU3D::Renderer == 0) + OpenGL_UseShaderProgram(GL_ScreenShader); + else + OpenGL_UseShaderProgram(GL_ScreenShaderAccel); + + glBindFramebuffer(GL_FRAMEBUFFER, uiGLGetFramebuffer(GLContext)); + + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + + if (RunningSomething) + { + int frontbuf = GPU::FrontBuffer; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture); + + if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) + { + if (GPU3D::Renderer == 0) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); + } + else + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); + } + } + + glActiveTexture(GL_TEXTURE1); + if (GPU3D::Renderer != 0) + GPU3D::GLRenderer::SetupAccelFrame(); + + glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID); + glBindVertexArray(GL_ScreenVertexArrayID); + glDrawArrays(GL_TRIANGLES, 0, 4*3); + } + OpenGL_UseShaderProgram(GL_ScreenShaderOSD); + OSD::Update(true, NULL); + + glFlush(); + uiGLSwapBuffers(GLContext); +} void MicLoadWav(char* name) { @@ -402,7 +731,17 @@ int EmuThreadFunc(void* burp) MainScreenPos[2] = 0; AutoScreenSizing = 0; - ScreenDrawInited = false; + if (Screen_UseGL) + { + uiGLMakeContextCurrent(GLContext); + GPU3D::InitRenderer(true); + uiGLMakeContextCurrent(NULL); + } + else + { + GPU3D::InitRenderer(false); + } + Touching = false; KeyInputMask = 0xFFF; HotkeyMask = 0; @@ -537,10 +876,11 @@ int EmuThreadFunc(void* burp) // microphone input FeedMicInput(); - // emulate - u32 nlines = NDS::RunFrame(); - - if (EmuRunning == 0) break; + if (Screen_UseGL) + { + uiGLBegin(GLContext); + uiGLMakeContextCurrent(GLContext); + } // auto screen layout { @@ -571,13 +911,20 @@ int EmuThreadFunc(void* burp) } } - memcpy(ScreenBuffer, GPU::Framebuffer, 256*384*4); + // emulate + u32 nlines = NDS::RunFrame(); + + if (EmuRunning == 0) break; + + if (Screen_UseGL) + { + GLScreen_DrawScreen(); + uiGLEnd(GLContext); + } uiAreaQueueRedrawAll(MainDrawArea); // framerate limiter based off SDL2_gfx - float framerate; - if (nlines == 263) framerate = 1000.0f / 60.0f; - else framerate = ((1000.0f * nlines) / 263.0f) / 60.0f; + float framerate = (1000.0f * nlines) / (60.0f * 263.0f); fpslimitcount++; u32 curtick = SDL_GetTicks(); @@ -626,9 +973,20 @@ int EmuThreadFunc(void* burp) if (EmuRunning == 2) { + if (Screen_UseGL) + { + uiGLBegin(GLContext); + uiGLMakeContextCurrent(GLContext); + GLScreen_DrawScreen(); + uiGLEnd(GLContext); + //uiGLMakeContextCurrent(NULL); + //uiQueueMain(norp, NULL); + } uiAreaQueueRedrawAll(MainDrawArea); } + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + EmuStatus = EmuRunning; SDL_Delay(100); @@ -639,9 +997,21 @@ int EmuThreadFunc(void* burp) if (joybuttons) delete[] joybuttons; + if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + NDS::DeInit(); Platform::LAN_DeInit(); + if (Screen_UseGL) + { + OSD::DeInit(true); + GLScreen_DeInit(); + } + else + OSD::DeInit(false); + + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + return 44203; } @@ -650,26 +1020,35 @@ void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params) { if (!ScreenDrawInited) { - ScreenBitmap = uiDrawNewBitmap(params->Context, 256, 384); + if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); + if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]); + ScreenDrawInited = true; + ScreenBitmap[0] = uiDrawNewBitmap(params->Context, 256, 192, 0); + ScreenBitmap[1] = uiDrawNewBitmap(params->Context, 256, 192, 0); } - if (!ScreenBitmap) return; + int frontbuf = GPU::FrontBuffer; + if (!ScreenBitmap[0] || !ScreenBitmap[1]) return; + if (!GPU::Framebuffer[frontbuf][0] || !GPU::Framebuffer[frontbuf][1]) return; uiRect top = {0, 0, 256, 192}; - uiRect bot = {0, 192, 256, 192}; + uiRect bot = {0, 0, 256, 192}; - uiDrawBitmapUpdate(ScreenBitmap, ScreenBuffer); + uiDrawBitmapUpdate(ScreenBitmap[0], GPU::Framebuffer[frontbuf][0]); + uiDrawBitmapUpdate(ScreenBitmap[1], GPU::Framebuffer[frontbuf][1]); uiDrawSave(params->Context); uiDrawTransform(params->Context, &TopScreenTrans); - uiDrawBitmapDraw(params->Context, ScreenBitmap, &top, &TopScreenRect, Config::ScreenFilter==1); + uiDrawBitmapDraw(params->Context, ScreenBitmap[0], &top, &TopScreenRect, Config::ScreenFilter==1); uiDrawRestore(params->Context); uiDrawSave(params->Context); uiDrawTransform(params->Context, &BottomScreenTrans); - uiDrawBitmapDraw(params->Context, ScreenBitmap, &bot, &BottomScreenRect, Config::ScreenFilter==1); + uiDrawBitmapDraw(params->Context, ScreenBitmap[1], &bot, &BottomScreenRect, Config::ScreenFilter==1); uiDrawRestore(params->Context); + + OSD::Update(false, params); } void OnAreaMouseEvent(uiAreaHandler* handler, uiArea* area, uiAreaMouseEvent* evt) @@ -820,7 +1199,8 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) } if (evt->Scancode == 0x57) // F11 - NDS::debug(0); + OSD::AddMessage(0x00FFFF, "OSD test"); + //NDS::debug(0); } return 1; @@ -847,7 +1227,7 @@ void SetupScreenRects(int width, int height) else sizemode = ScreenSizing; - int screenW, screenH; + int screenW, screenH, gap; if (sideways) { screenW = 192; @@ -859,6 +1239,8 @@ void SetupScreenRects(int width, int height) screenH = 192; } + gap = ScreenGap; + uiRect *topscreen, *bottomscreen; if (ScreenRotation == 1 || ScreenRotation == 2) { @@ -878,7 +1260,7 @@ void SetupScreenRects(int width, int height) int heightreq; int startX = 0; - width -= ScreenGap; + width -= gap; if (sizemode == 0) // even { @@ -916,7 +1298,7 @@ void SetupScreenRects(int width, int height) topscreen->X = startX; topscreen->Y = ((height - heightreq) / 2) + (heightreq - topscreen->Height); - bottomscreen->X = topscreen->X + topscreen->Width + ScreenGap; + bottomscreen->X = topscreen->X + topscreen->Width + gap; if (sizemode == 1) { @@ -937,7 +1319,7 @@ void SetupScreenRects(int width, int height) int widthreq; int startY = 0; - height -= ScreenGap; + height -= gap; if (sizemode == 0) // even { @@ -975,7 +1357,7 @@ void SetupScreenRects(int width, int height) topscreen->Y = startY; topscreen->X = (width - topscreen->Width) / 2; - bottomscreen->Y = topscreen->Y + topscreen->Height + ScreenGap; + bottomscreen->Y = topscreen->Y + topscreen->Height + gap; if (sizemode == 1) { @@ -1045,6 +1427,8 @@ void SetupScreenRects(int width, int height) } break; } + + GL_ScreenSizeDirty = true; } void SetMinSize(int w, int h) @@ -1072,20 +1456,30 @@ void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height) WindowWidth = width; WindowHeight = height; - int max = uiWindowMaximized(MainWindow); - int min = uiWindowMinimized(MainWindow); + int ismax = uiWindowMaximized(MainWindow); + int ismin = uiWindowMinimized(MainWindow); - Config::WindowMaximized = max; - if (!max && !min) + Config::WindowMaximized = ismax; + if (!ismax && !ismin) { Config::WindowWidth = width; Config::WindowHeight = height; } + + OSD::WindowResized(Screen_UseGL); } void Run() { + if (GPU3D::Renderer != Config::_3DRenderer) + { + if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + GPU3D::DeInitRenderer(); + GPU3D::InitRenderer(Screen_UseGL); + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + } + EmuRunning = 1; RunningSomething = true; @@ -1135,7 +1529,6 @@ void Stop(bool internal) uiMenuItemDisable(MenuItem_Stop); uiMenuItemSetChecked(MenuItem_Pause, 0); - memset(ScreenBuffer, 0, 256*384*4); uiAreaQueueRedrawAll(MainDrawArea); SDL_PauseAudioDevice(AudioDevice, 1); @@ -1239,6 +1632,11 @@ void LoadState(int slot) if (!Platform::FileExists(filename)) { + char msg[64]; + if (slot > 0) sprintf(msg, "State slot %d is empty", slot); + else sprintf(msg, "State file does not exist"); + OSD::AddMessage(0xFFA0A0, msg); + EmuRunning = prevstatus; return; } @@ -1279,6 +1677,11 @@ void LoadState(int slot) NDS::RelocateSave(SRAMPath, false); } + char msg[64]; + if (slot > 0) sprintf(msg, "State loaded from slot %d", slot); + else sprintf(msg, "State loaded from file"); + OSD::AddMessage(0, msg); + SavestateLoaded = true; uiMenuItemEnable(MenuItem_UndoStateLoad); } @@ -1338,6 +1741,11 @@ void SaveState(int slot) } } + char msg[64]; + if (slot > 0) sprintf(msg, "State saved to slot %d", slot); + else sprintf(msg, "State saved to file"); + OSD::AddMessage(0, msg); + EmuRunning = prevstatus; } @@ -1362,15 +1770,29 @@ void UndoStateLoad() NDS::RelocateSave(SRAMPath, false); } + OSD::AddMessage(0, "State load undone"); + EmuRunning = prevstatus; } +void CloseAllDialogs() +{ + DlgAudioSettings::Close(); + DlgEmuSettings::Close(); + DlgInputConfig::Close(0); + DlgInputConfig::Close(1); + DlgVideoSettings::Close(); + DlgWifiSettings::Close(); +} + + int OnCloseWindow(uiWindow* window, void* blarg) { EmuRunning = 3; while (EmuStatus != 3); + CloseAllDialogs(); uiQuit(); return 1; } @@ -1407,7 +1829,8 @@ void OnCloseByMenu(uiMenuItem* item, uiWindow* window, void* blarg) EmuRunning = 3; while (EmuStatus != 3); - uiControlDestroy(uiControl(window)); + CloseAllDialogs(); + DestroyMainWindow(); uiQuit(); } @@ -1528,6 +1951,11 @@ void OnOpenHotkeyConfig(uiMenuItem* item, uiWindow* window, void* blarg) DlgInputConfig::Open(1); } +void OnOpenVideoSettings(uiMenuItem* item, uiWindow* window, void* blarg) +{ + DlgVideoSettings::Open(); +} + void OnOpenAudioSettings(uiMenuItem* item, uiWindow* window, void* blarg) { DlgAudioSettings::Open(); @@ -1549,26 +1977,31 @@ void EnsureProperMinSize() { bool isHori = (ScreenRotation == 1 || ScreenRotation == 3); + int w0 = 256; + int h0 = 192; + int w1 = 256; + int h1 = 192; + if (ScreenLayout == 0) // natural { if (isHori) - SetMinSize(384+ScreenGap, 256); + SetMinSize(h0+ScreenGap+h1, std::max(w0,w1)); else - SetMinSize(256, 384+ScreenGap); + SetMinSize(std::max(w0,w1), h0+ScreenGap+h1); } else if (ScreenLayout == 1) // vertical { if (isHori) - SetMinSize(192, 512+ScreenGap); + SetMinSize(std::max(h0,h1), w0+ScreenGap+w1); else - SetMinSize(256, 384+ScreenGap); + SetMinSize(std::max(w0,w1), h0+ScreenGap+h1); } else // horizontal { if (isHori) - SetMinSize(384+ScreenGap, 256); + SetMinSize(h0+ScreenGap+h1, std::max(w0,w1)); else - SetMinSize(512+ScreenGap, 192); + SetMinSize(w0+ScreenGap+w1, std::max(h0,h1)); } } @@ -1580,6 +2013,8 @@ void OnSetScreenSize(uiMenuItem* item, uiWindow* window, void* param) int w = 256*factor; int h = 192*factor; + // FIXME + if (ScreenLayout == 0) // natural { if (isHori) @@ -1690,15 +2125,20 @@ void OnSetLimitFPS(uiMenuItem* item, uiWindow* window, void* blarg) void ApplyNewSettings(int type) { - if (!RunningSomething) return; + if (!RunningSomething && type != 2) return; int prevstatus = EmuRunning; - EmuRunning = 2; - while (EmuStatus != 2); + EmuRunning = 3; + while (EmuStatus != 3); - if (type == 0) // general emu settings + if (type == 0) // 3D renderer settings { - GPU3D::SoftRenderer::SetupRenderThread(); + if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + GPU3D::UpdateRendererConfig(); + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + + GL_3DScale = Config::GL_ScaleFactor; // dorp + GL_ScreenSizeDirty = true; } else if (type == 1) // wifi settings { @@ -1711,112 +2151,47 @@ void ApplyNewSettings(int type) Platform::LAN_DeInit(); Platform::LAN_Init(); } - - EmuRunning = prevstatus; -} - - -int main(int argc, char** argv) -{ - srand(time(NULL)); - - printf("melonDS " MELONDS_VERSION "\n"); - printf(MELONDS_URL "\n"); - - if (argc > 0 && strlen(argv[0]) > 0) + else if (type == 2) // video output method { - int len = strlen(argv[0]); - while (len > 0) + bool usegl = Config::ScreenUseGL || (Config::_3DRenderer != 0); + if (usegl != Screen_UseGL) { - if (argv[0][len] == '/') break; - if (argv[0][len] == '\\') break; - len--; - } - if (len > 0) - { - EmuDirectory = new char[len+1]; - strncpy(EmuDirectory, argv[0], len); - EmuDirectory[len] = '\0'; - } - else - { - EmuDirectory = new char[2]; - strcpy(EmuDirectory, "."); - } - } - else - { - EmuDirectory = new char[2]; - strcpy(EmuDirectory, "."); - } - - // http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl - SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + if (RunningSomething) + { + if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + GPU3D::DeInitRenderer(); + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + } - if (SDL_Init(SDL_INIT_HAPTIC) < 0) - { - printf("SDL couldn't init rumble\n"); - } - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) - { - printf("SDL shat itself :(\n"); - return 1; - } + if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + OSD::DeInit(Screen_UseGL); + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); - SDL_JoystickEventState(SDL_ENABLE); + Screen_UseGL = usegl; + RecreateMainWindow(usegl); - uiInitOptions ui_opt; - memset(&ui_opt, 0, sizeof(uiInitOptions)); - const char* ui_err = uiInit(&ui_opt); - if (ui_err != NULL) - { - printf("libui shat itself :( %s\n", ui_err); - uiFreeInitError(ui_err); - return 1; + if (RunningSomething) + { + if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + GPU3D::InitRenderer(Screen_UseGL); + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + } + } } - - Config::Load(); - - if (Config::AudioVolume < 0) Config::AudioVolume = 0; - else if (Config::AudioVolume > 256) Config::AudioVolume = 256; - - if (!Platform::LocalFileExists("bios7.bin") || - !Platform::LocalFileExists("bios9.bin") || - !Platform::LocalFileExists("firmware.bin")) + else if (type == 3) // 3D renderer { - uiMsgBoxError( - NULL, - "BIOS/Firmware not found", - "One or more of the following required files don't exist or couldn't be accessed:\n\n" - "bios7.bin -- ARM7 BIOS\n" - "bios9.bin -- ARM9 BIOS\n" - "firmware.bin -- firmware image\n\n" - "Dump the files from your DS and place them in the directory you run melonDS from.\n" - "Make sure that the files can be accessed."); - - uiUninit(); - SDL_Quit(); - return 0; + if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + GPU3D::DeInitRenderer(); + GPU3D::InitRenderer(Screen_UseGL); + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); } - { - FILE* f = Platform::OpenLocalFile("romlist.bin", "rb"); - if (f) - { - u32 data; - fread(&data, 4, 1, f); - fclose(f); + EmuRunning = prevstatus; +} - if ((data >> 24) == 0) // old CRC-based list - { - uiMsgBoxError(NULL, - "Your version of romlist.bin is outdated.", - "Save memory type detection will not work correctly.\n\n" - "You should use the latest version of romlist.bin (provided in melonDS release packages)."); - } - } - } +void CreateMainWindowMenu() +{ uiMenu* menu; uiMenuItem* menuitem; @@ -1891,6 +2266,8 @@ int main(int argc, char** argv) uiMenuItemOnClicked(menuitem, OnOpenInputConfig, NULL); menuitem = uiMenuAppendItem(menu, "Hotkey config"); uiMenuItemOnClicked(menuitem, OnOpenHotkeyConfig, NULL); + menuitem = uiMenuAppendItem(menu, "Video settings"); + uiMenuItemOnClicked(menuitem, OnOpenVideoSettings, NULL); menuitem = uiMenuAppendItem(menu, "Audio settings"); uiMenuItemOnClicked(menuitem, OnOpenAudioSettings, NULL); menuitem = uiMenuAppendItem(menu, "Wifi settings"); @@ -1972,24 +2349,19 @@ int main(int argc, char** argv) uiMenuAppendSubmenu(menu, submenu); } - menuitem = uiMenuAppendCheckItem(menu, "Screen filtering"); - uiMenuItemOnClicked(menuitem, OnSetScreenFiltering, NULL); - uiMenuItemSetChecked(menuitem, Config::ScreenFilter==1); + + MenuItem_ScreenFilter = uiMenuAppendCheckItem(menu, "Screen filtering"); + uiMenuItemOnClicked(MenuItem_ScreenFilter, OnSetScreenFiltering, NULL); MenuItem_LimitFPS = uiMenuAppendCheckItem(menu, "Limit framerate"); uiMenuItemOnClicked(MenuItem_LimitFPS, OnSetLimitFPS, NULL); - uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1); - - - int w = Config::WindowWidth; - int h = Config::WindowHeight; - //if (w < 256) w = 256; - //if (h < 384) h = 384; - - WindowWidth = w; - WindowHeight = h; +} - MainWindow = uiNewWindow("melonDS " MELONDS_VERSION, w, h, Config::WindowMaximized, 1, 1); +void CreateMainWindow(bool opengl) +{ + MainWindow = uiNewWindow("melonDS " MELONDS_VERSION, + WindowWidth, WindowHeight, + Config::WindowMaximized, 1, 1); uiWindowOnClosing(MainWindow, OnCloseWindow, NULL); uiWindowSetDropTarget(MainWindow, 1); @@ -1998,28 +2370,189 @@ int main(int argc, char** argv) uiWindowOnGetFocus(MainWindow, OnGetFocus, NULL); uiWindowOnLoseFocus(MainWindow, OnLoseFocus, NULL); - //uiMenuItemDisable(MenuItem_SaveState); - //uiMenuItemDisable(MenuItem_LoadState); - for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]); - for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_LoadStateSlot[i]); - uiMenuItemDisable(MenuItem_UndoStateLoad); - - uiMenuItemDisable(MenuItem_Pause); - uiMenuItemDisable(MenuItem_Reset); - uiMenuItemDisable(MenuItem_Stop); + ScreenDrawInited = false; + bool opengl_good = opengl; - uiAreaHandler areahandler; - areahandler.Draw = OnAreaDraw; - areahandler.MouseEvent = OnAreaMouseEvent; - areahandler.MouseCrossed = OnAreaMouseCrossed; - areahandler.DragBroken = OnAreaDragBroken; - areahandler.KeyEvent = OnAreaKeyEvent; - areahandler.Resize = OnAreaResize; + if (!opengl) MainDrawArea = uiNewArea(&MainDrawAreaHandler); + else MainDrawArea = uiNewGLArea(&MainDrawAreaHandler, kGLVersions); - MainDrawArea = uiNewArea(&areahandler); uiWindowSetChild(MainWindow, uiControl(MainDrawArea)); uiControlSetMinSize(uiControl(MainDrawArea), 256, 384); - uiAreaSetBackgroundColor(MainDrawArea, 0, 0, 0); // TODO: make configurable? + uiAreaSetBackgroundColor(MainDrawArea, 0, 0, 0); + + uiControlShow(uiControl(MainWindow)); + uiControlSetFocus(uiControl(MainDrawArea)); + + if (opengl_good) + { + GLContext = uiAreaGetGLContext(MainDrawArea); + if (!GLContext) opengl_good = false; + } + if (opengl_good) + { + uiGLMakeContextCurrent(GLContext); + if (!GLScreen_Init()) opengl_good = false; + if (opengl_good) + { + OpenGL_UseShaderProgram(GL_ScreenShaderOSD); + OSD::Init(true); + } + uiGLMakeContextCurrent(NULL); + } + + if (opengl && !opengl_good) + { + printf("OpenGL: initialization failed\n"); + RecreateMainWindow(false); + Screen_UseGL = false; + } + + if (!opengl) OSD::Init(false); +} + +void DestroyMainWindow() +{ + uiControlDestroy(uiControl(MainWindow)); + + if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); + if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]); + + ScreenBitmap[0] = NULL; + ScreenBitmap[1] = NULL; +} + +void RecreateMainWindow(bool opengl) +{ + int winX, winY, maxi; + uiWindowPosition(MainWindow, &winX, &winY); + maxi = uiWindowMaximized(MainWindow); + DestroyMainWindow(); + CreateMainWindow(opengl); + uiWindowSetPosition(MainWindow, winX, winY); + uiWindowSetMaximized(MainWindow, maxi); +} + + +int main(int argc, char** argv) +{ + srand(time(NULL)); + + printf("melonDS " MELONDS_VERSION "\n"); + printf(MELONDS_URL "\n"); + + if (argc > 0 && strlen(argv[0]) > 0) + { + int len = strlen(argv[0]); + while (len > 0) + { + if (argv[0][len] == '/') break; + if (argv[0][len] == '\\') break; + len--; + } + if (len > 0) + { + EmuDirectory = new char[len+1]; + strncpy(EmuDirectory, argv[0], len); + EmuDirectory[len] = '\0'; + } + else + { + EmuDirectory = new char[2]; + strcpy(EmuDirectory, "."); + } + } + else + { + EmuDirectory = new char[2]; + strcpy(EmuDirectory, "."); + } + + // http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl + SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + + if (SDL_Init(SDL_INIT_HAPTIC) < 0) + { + printf("SDL couldn't init rumble\n"); + } + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) + { + printf("SDL shat itself :(\n"); + return 1; + } + + SDL_JoystickEventState(SDL_ENABLE); + + uiInitOptions ui_opt; + memset(&ui_opt, 0, sizeof(uiInitOptions)); + const char* ui_err = uiInit(&ui_opt); + if (ui_err != NULL) + { + printf("libui shat itself :( %s\n", ui_err); + uiFreeInitError(ui_err); + return 1; + } + + Config::Load(); + + if (Config::AudioVolume < 0) Config::AudioVolume = 0; + else if (Config::AudioVolume > 256) Config::AudioVolume = 256; + + if (!Platform::LocalFileExists("bios7.bin") || + !Platform::LocalFileExists("bios9.bin") || + !Platform::LocalFileExists("firmware.bin")) + { + uiMsgBoxError( + NULL, + "BIOS/Firmware not found", + "One or more of the following required files don't exist or couldn't be accessed:\n\n" + "bios7.bin -- ARM7 BIOS\n" + "bios9.bin -- ARM9 BIOS\n" + "firmware.bin -- firmware image\n\n" + "Dump the files from your DS and place them in the directory you run melonDS from.\n" + "Make sure that the files can be accessed."); + + uiUninit(); + SDL_Quit(); + return 0; + } + + { + FILE* f = Platform::OpenLocalFile("romlist.bin", "rb"); + if (f) + { + u32 data; + fread(&data, 4, 1, f); + fclose(f); + + if ((data >> 24) == 0) // old CRC-based list + { + uiMsgBoxError(NULL, + "Your version of romlist.bin is outdated.", + "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(); + + MainDrawAreaHandler.Draw = OnAreaDraw; + MainDrawAreaHandler.MouseEvent = OnAreaMouseEvent; + MainDrawAreaHandler.MouseCrossed = OnAreaMouseCrossed; + MainDrawAreaHandler.DragBroken = OnAreaDragBroken; + MainDrawAreaHandler.KeyEvent = OnAreaKeyEvent; + MainDrawAreaHandler.Resize = OnAreaResize; + + WindowWidth = Config::WindowWidth; + WindowHeight = Config::WindowHeight; + + Screen_UseGL = Config::ScreenUseGL || (Config::_3DRenderer != 0); + + GL_3DScale = Config::GL_ScaleFactor; + if (GL_3DScale < 1) GL_3DScale = 1; + else if (GL_3DScale > 8) GL_3DScale = 8; + + CreateMainWindow(Screen_UseGL); ScreenRotation = Config::ScreenRotation; ScreenGap = Config::ScreenGap; @@ -2032,6 +2565,14 @@ int main(int argc, char** argv) SANITIZE(ScreenSizing, 0, 3); #undef SANITIZE + for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]); + for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_LoadStateSlot[i]); + uiMenuItemDisable(MenuItem_UndoStateLoad); + + uiMenuItemDisable(MenuItem_Pause); + uiMenuItemDisable(MenuItem_Reset); + uiMenuItemDisable(MenuItem_Stop); + uiMenuItemSetChecked(MenuItem_SavestateSRAMReloc, Config::SavestateRelocSRAM?1:0); uiMenuItemSetChecked(MenuItem_ScreenRot[ScreenRotation], 1); @@ -2046,6 +2587,9 @@ int main(int argc, char** argv) OnSetScreenRotation(MenuItem_ScreenRot[ScreenRotation], MainWindow, (void*)&kScreenRot[ScreenRotation]); + uiMenuItemSetChecked(MenuItem_ScreenFilter, Config::ScreenFilter==1); + uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1); + SDL_AudioSpec whatIwant, whatIget; memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); whatIwant.freq = 47340; @@ -2114,8 +2658,6 @@ int main(int argc, char** argv) } } - uiControlShow(uiControl(MainWindow)); - uiControlSetFocus(uiControl(MainDrawArea)); uiMain(); EmuRunning = 0; @@ -2127,6 +2669,9 @@ int main(int argc, char** argv) if (MicWavBuffer) delete[] MicWavBuffer; + if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); + if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]); + Config::ScreenRotation = ScreenRotation; Config::ScreenGap = ScreenGap; Config::ScreenLayout = ScreenLayout; @@ -2134,8 +2679,6 @@ int main(int argc, char** argv) Config::Save(); - if (ScreenBitmap) uiDrawFreeBitmap(ScreenBitmap); - uiUninit(); SDL_Quit(); delete[] EmuDirectory; |