From b48fe5909bd9314c271f1cb729c9aa79d88a26f3 Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Sun, 31 Mar 2019 21:54:14 +0200
Subject: * add some GL base to libui (only for Windows for now) * make the
 Codeblocks project a bit less braindead (don't repeat libraries for each
 build target)

---
 melonDS.cbp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index fc5f8df..9f105fc 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -222,6 +222,7 @@
 		<Unit filename="src/libui_sdl/libui/windows/fontbutton.cpp" />
 		<Unit filename="src/libui_sdl/libui/windows/fontdialog.cpp" />
 		<Unit filename="src/libui_sdl/libui/windows/form.cpp" />
+		<Unit filename="src/libui_sdl/libui/windows/gl.cpp" />
 		<Unit filename="src/libui_sdl/libui/windows/graphemes.cpp" />
 		<Unit filename="src/libui_sdl/libui/windows/grid.cpp" />
 		<Unit filename="src/libui_sdl/libui/windows/group.cpp" />
-- 
cgit v1.2.3


From f8751bd1fb83e85e2eb4e91b9c4b032ef0c18cdd Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Mon, 1 Apr 2019 02:51:31 +0200
Subject: first attempt at things

(also fix softrenderer reset)
---
 melonDS.cbp                        |  68 ++++++------------
 src/GPU3D.cpp                      |  20 ++++--
 src/GPU3D.h                        |  14 ++++
 src/GPU3D_OpenGL43.cpp             | 138 +++++++++++++++++++++++++++++++++++++
 src/GPU3D_Soft.cpp                 |   6 +-
 src/Platform.h                     |   2 +
 src/libui_sdl/Platform.cpp         |   7 ++
 src/libui_sdl/libui/ui.h           |   2 +-
 src/libui_sdl/libui/windows/gl.cpp |  69 ++++++++++++++++++-
 src/libui_sdl/main.cpp             |  11 +++
 10 files changed, 275 insertions(+), 62 deletions(-)
 create mode 100644 src/GPU3D_OpenGL43.cpp

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index 9f105fc..0ba8653 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -19,22 +19,6 @@
 				</Compiler>
 				<Linker>
 					<Add option="-m64" />
-					<Add library="SDL2" />
-					<Add library="shell32" />
-					<Add library="comctl32" />
-					<Add library="comdlg32" />
-					<Add library="advapi32" />
-					<Add library="wsock32" />
-					<Add library="oleacc" />
-					<Add library="ole32" />
-					<Add library="usp10" />
-					<Add library="gdi32" />
-					<Add library="d2d1" />
-					<Add library="dwrite" />
-					<Add library="uxtheme" />
-					<Add library="iphlpapi" />
-					<Add library="user32" />
-					<Add library="ws2_32" />
 				</Linker>
 			</Target>
 			<Target title="Release Windows">
@@ -51,22 +35,6 @@
 				<Linker>
 					<Add option="-s" />
 					<Add option="-m64" />
-					<Add library="SDL2" />
-					<Add library="shell32" />
-					<Add library="comctl32" />
-					<Add library="comdlg32" />
-					<Add library="advapi32" />
-					<Add library="wsock32" />
-					<Add library="oleacc" />
-					<Add library="ole32" />
-					<Add library="usp10" />
-					<Add library="gdi32" />
-					<Add library="d2d1" />
-					<Add library="dwrite" />
-					<Add library="uxtheme" />
-					<Add library="iphlpapi" />
-					<Add library="user32" />
-					<Add library="ws2_32" />
 				</Linker>
 			</Target>
 			<Target title="DebugFast Windows">
@@ -82,22 +50,6 @@
 				</Compiler>
 				<Linker>
 					<Add option="-m64" />
-					<Add library="SDL2" />
-					<Add library="shell32" />
-					<Add library="comctl32" />
-					<Add library="comdlg32" />
-					<Add library="advapi32" />
-					<Add library="wsock32" />
-					<Add library="oleacc" />
-					<Add library="ole32" />
-					<Add library="usp10" />
-					<Add library="gdi32" />
-					<Add library="d2d1" />
-					<Add library="dwrite" />
-					<Add library="uxtheme" />
-					<Add library="iphlpapi" />
-					<Add library="user32" />
-					<Add library="ws2_32" />
 				</Linker>
 			</Target>
 		</Build>
@@ -107,6 +59,25 @@
 			<Add option="-pipe" />
 			<Add directory="src" />
 		</Compiler>
+		<Linker>
+			<Add library="SDL2" />
+			<Add library="shell32" />
+			<Add library="comctl32" />
+			<Add library="comdlg32" />
+			<Add library="advapi32" />
+			<Add library="wsock32" />
+			<Add library="oleacc" />
+			<Add library="ole32" />
+			<Add library="usp10" />
+			<Add library="gdi32" />
+			<Add library="d2d1" />
+			<Add library="dwrite" />
+			<Add library="uxtheme" />
+			<Add library="iphlpapi" />
+			<Add library="user32" />
+			<Add library="ws2_32" />
+			<Add library="opengl32" />
+		</Linker>
 		<Unit filename="melon.rc">
 			<Option compilerVar="WINDRES" />
 		</Unit>
@@ -135,6 +106,7 @@
 		<Unit filename="src/GPU2D.h" />
 		<Unit filename="src/GPU3D.cpp" />
 		<Unit filename="src/GPU3D.h" />
+		<Unit filename="src/GPU3D_OpenGL43.cpp" />
 		<Unit filename="src/GPU3D_Soft.cpp" />
 		<Unit filename="src/NDS.cpp" />
 		<Unit filename="src/NDS.h" />
diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp
index 802c9cd..b4211f0 100644
--- a/src/GPU3D.cpp
+++ b/src/GPU3D.cpp
@@ -275,14 +275,16 @@ bool Init()
 
     CmdStallQueue = new FIFO<CmdFIFOEntry>(64);
 
-    if (!SoftRenderer::Init()) return false;
+    //if (!SoftRenderer::Init()) return false;
+    if (!GLRenderer43::Init()) return false;
 
     return true;
 }
 
 void DeInit()
 {
-    SoftRenderer::DeInit();
+    //SoftRenderer::DeInit();
+    GLRenderer43::DeInit();
 
     delete CmdFIFO;
     delete CmdPIPE;
@@ -382,7 +384,8 @@ void Reset()
     FlushAttributes = 0;
 
     ResetRenderingState();
-    SoftRenderer::Reset();
+    //SoftRenderer::Reset();
+    GLRenderer43::Reset();
 }
 
 void DoSavestate(Savestate* file)
@@ -2331,7 +2334,7 @@ void CheckFIFODMA()
 
 void VCount144()
 {
-    SoftRenderer::VCount144();
+    //SoftRenderer::VCount144();
 }
 
 
@@ -2413,17 +2416,20 @@ void VBlank()
 
 void VCount215()
 {
-    SoftRenderer::RenderFrame();
+    //SoftRenderer::RenderFrame();
+    GLRenderer43::RenderFrame();
 }
 
 void RequestLine(int line)
 {
-    return SoftRenderer::RequestLine(line);
+    //return SoftRenderer::RequestLine(line);
+    return GLRenderer43::RequestLine(line);
 }
 
 u32* GetLine(int line)
 {
-    return SoftRenderer::GetLine(line);
+    //return SoftRenderer::GetLine(line);
+    return GLRenderer43::GetLine(line);
 }
 
 
diff --git a/src/GPU3D.h b/src/GPU3D.h
index 279494a..f300da8 100644
--- a/src/GPU3D.h
+++ b/src/GPU3D.h
@@ -132,6 +132,20 @@ u32* GetLine(int line);
 
 }
 
+namespace GLRenderer43
+{
+
+bool Init();
+void DeInit();
+void Reset();
+
+void VCount144();
+void RenderFrame();
+void RequestLine(int line);
+u32* GetLine(int line);
+
+}
+
 }
 
 #endif
diff --git a/src/GPU3D_OpenGL43.cpp b/src/GPU3D_OpenGL43.cpp
new file mode 100644
index 0000000..acb1436
--- /dev/null
+++ b/src/GPU3D_OpenGL43.cpp
@@ -0,0 +1,138 @@
+/*
+    Copyright 2016-2019 Arisotura
+
+    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 <GL/gl.h>
+#include <GL/glext.h>
+
+#include <stdio.h>
+#include <string.h>
+#include "NDS.h"
+#include "GPU.h"
+#include "Platform.h"
+
+namespace GPU3D
+{
+namespace GLRenderer43
+{
+
+PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
+PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
+PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
+
+
+GLuint FramebufferID;
+u8 Framebuffer[256*192*4];
+u8 CurLine[256*4];
+
+
+bool InitGLExtensions()
+{
+#define LOADPROC(type, name)  \
+    name = (PFN##type##PROC)Platform::GL_GetProcAddress(#name); \
+    if (!name) return false;
+
+    LOADPROC(GLGENFRAMEBUFFERS, glGenFramebuffers);
+    LOADPROC(GLBINDFRAMEBUFFER, glBindFramebuffer);
+    LOADPROC(GLFRAMEBUFFERTEXTURE, glFramebufferTexture);
+
+#undef LOADPROC
+    return true;
+}
+
+bool Init()
+{
+    if (!InitGLExtensions()) return false;
+
+    u8* test_tex = new u8[256*192*4];
+    u8* ptr = test_tex;
+    for (int y = 0; y < 192; y++)
+    {
+        for (int x = 0; x < 256; x++)
+        {
+            if ((x & 0x10) ^ (y & 0x10))
+            {
+                *ptr++ = 0x00;
+                *ptr++ = 0x00;
+                *ptr++ = 0x3F;
+                *ptr++ = 0x1F;
+            }
+            else
+            {
+                *ptr++ = 0;
+                *ptr++ = y>>2;
+                *ptr++ = 0x3F;
+                *ptr++ = 0x1F;
+            }
+        }
+    }
+
+    glGenFramebuffers(1, &FramebufferID);
+    glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID);
+
+    GLuint frametex;
+    glGenTextures(1, &frametex);
+    glBindTexture(GL_TEXTURE_2D, frametex);
+    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_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, test_tex);
+    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, frametex, 0);
+
+    return true;
+}
+
+void DeInit()
+{
+    //
+}
+
+void Reset()
+{
+    //
+}
+
+
+void VCount144()
+{
+}
+
+void RenderFrame()
+{
+    //
+}
+
+void RequestLine(int line)
+{
+    //
+}
+
+u32* GetLine(int line)
+{
+    if (line == 0)
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID);
+        glReadBuffer(GL_COLOR_ATTACHMENT0);
+        glReadPixels(0, 0, 256, 192, GL_RGBA, GL_UNSIGNED_BYTE, Framebuffer);
+    }
+
+    return (u32*)&Framebuffer[256*4 * line];
+}
+
+}
+}
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index 29b46e1..8d18a35 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -129,9 +129,9 @@ void DeInit()
 
 void Reset()
 {
-    memset(ColorBuffer, 0, 256*192 * 4);
-    memset(DepthBuffer, 0, 256*192 * 4);
-    memset(AttrBuffer, 0, 256*192 * 4);
+    memset(ColorBuffer, 0, BufferSize * 2 * 4);
+    memset(DepthBuffer, 0, BufferSize * 2 * 4);
+    memset(AttrBuffer, 0, BufferSize * 2 * 4);
 
     PrevIsShadowMask = false;
 
diff --git a/src/Platform.h b/src/Platform.h
index df3335b..ca6971e 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -68,6 +68,8 @@ void Semaphore_Reset(void* sema);
 void Semaphore_Wait(void* sema);
 void Semaphore_Post(void* sema);
 
+void* GL_GetProcAddress(const char* proc);
+
 // local multiplayer comm interface
 // packet type: DS-style TX header (12 bytes) + original 802.11 frame
 bool MP_Init();
diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp
index 6ebe8c3..e3035b3 100644
--- a/src/libui_sdl/Platform.cpp
+++ b/src/libui_sdl/Platform.cpp
@@ -24,6 +24,7 @@
 #include "PlatformConfig.h"
 #include "LAN_Socket.h"
 #include "LAN_PCap.h"
+#include "libui/ui.h"
 #include <string>
 
 #ifdef __WIN32__
@@ -302,6 +303,12 @@ void Semaphore_Post(void* sema)
 }
 
 
+void* GL_GetProcAddress(const char* proc)
+{
+    return uiGLGetProcAddress(proc);
+}
+
+
 bool MP_Init()
 {
     int opt_true = 1;
diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h
index 381b85b..dd1c786 100644
--- a/src/libui_sdl/libui/ui.h
+++ b/src/libui_sdl/libui/ui.h
@@ -604,7 +604,7 @@ _UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayou
 
 typedef struct uiGLContext uiGLContext;
 
-_UI_EXTERN uiGLContext *uiGLNewContext(uiControl* c);
+_UI_EXTERN uiGLContext *uiGLNewContext(uiControl* c, int vermajor, int verminor);
 _UI_EXTERN void uiGLFreeContext(uiGLContext* ctx);
 _UI_EXTERN void uiGLMakeContextCurrent(uiGLContext* ctx);
 _UI_EXTERN void *uiGLGetProcAddress(const char* proc);
diff --git a/src/libui_sdl/libui/windows/gl.cpp b/src/libui_sdl/libui/windows/gl.cpp
index fe21ae4..eb7d33d 100644
--- a/src/libui_sdl/libui/windows/gl.cpp
+++ b/src/libui_sdl/libui/windows/gl.cpp
@@ -1,6 +1,9 @@
 // 31 march 2019
 #include "uipriv_windows.hpp"
 
+#include <GL/gl.h>
+#include <GL/wglext.h>
+
 struct uiGLContext
 {
     uiControl* c;
@@ -11,9 +14,10 @@ struct uiGLContext
 };
 
 
-uiGLContext* uiGLNewContext(uiControl* c)
+uiGLContext* uiGLNewContext(uiControl* c, int vermajor, int verminor)
 {
     uiGLContext* ctx;
+    BOOL res;
 
     ctx = uiNew(uiGLContext);
 
@@ -25,7 +29,10 @@ uiGLContext* uiGLNewContext(uiControl* c)
     else
     {
         // windowless context
-        ctx->hwnd = GetDesktopWindow();
+        //ctx->hwnd = GetDesktopWindow();
+        // nope.
+        uiFree(ctx);
+        return NULL;
     }
 
     PIXELFORMATDESCRIPTOR pfd;
@@ -41,15 +48,71 @@ uiGLContext* uiGLNewContext(uiControl* c)
     pfd.iLayerType = PFD_MAIN_PLANE;
 
     ctx->dc = GetDC(ctx->hwnd);
+    if (!ctx->dc)
+    {
+        uiFree(ctx);
+        return NULL;
+    }
 
     int pixelformat = ChoosePixelFormat(ctx->dc, &pfd);
-    SetPixelFormat(ctx->dc, pixelformat, &pfd);
+    res = SetPixelFormat(ctx->dc, pixelformat, &pfd);
+    if (!res)
+    {
+        ReleaseDC(ctx->hwnd, ctx->dc);
+        uiFree(ctx);
+        return NULL;
+    }
 
     ctx->rc = wglCreateContext(ctx->dc);
+    if (!ctx->rc)
+    {
+        ReleaseDC(ctx->hwnd, ctx->dc);
+        uiFree(ctx);
+        return NULL;
+    }
+
+    wglMakeCurrent(ctx->dc, ctx->rc);
+
+    if (vermajor >= 3)
+    {
+        HGLRC (*wglCreateContextAttribsARB)(HDC,HGLRC,const int*);
+        HGLRC rc_better = NULL;
+
+        wglCreateContextAttribsARB = (HGLRC(*)(HDC,HGLRC,const int*))wglGetProcAddress("wglCreateContextAttribsARB");
+        if (wglCreateContextAttribsARB)
+        {
+            int attribs[15];
+            int i = 0;
+
+            attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
+            attribs[i++] = vermajor;
+            attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB;
+            attribs[i++] = verminor;
+
+            attribs[i] = 0;
+            rc_better = wglCreateContextAttribsARB(ctx->dc, NULL, attribs);
+        }
+
+        wglMakeCurrent(NULL, NULL);
+        wglDeleteContext(ctx->rc);
+
+        if (!rc_better)
+        {
+            ReleaseDC(ctx->hwnd, ctx->dc);
+            uiFree(ctx);
+            return NULL;
+        }
+
+        ctx->rc = rc_better;
+        wglMakeCurrent(ctx->dc, ctx->rc);
+    }
+
+    return ctx;
 }
 
 void uiGLFreeContext(uiGLContext* ctx)
 {
+    wglMakeCurrent(NULL, NULL);
     wglDeleteContext(ctx->rc);
     ReleaseDC(ctx->hwnd, ctx->dc);
     uiFree(ctx);
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp
index 566b346..d892912 100644
--- a/src/libui_sdl/main.cpp
+++ b/src/libui_sdl/main.cpp
@@ -392,6 +392,14 @@ void FeedMicInput()
 
 int EmuThreadFunc(void* burp)
 {
+    // TODO: fail gracefully, support older OpenGL, etc
+    uiGLContext* glctx = uiGLNewContext(uiControl(MainDrawArea), 4, 3); // haw haw haw
+    uiGLMakeContextCurrent(glctx);
+
+    void* testor = uiGLGetProcAddress("glUseProgram");
+    void* testor2 = uiGLGetProcAddress("glBindFramebuffer");
+    printf("OPENGL: %p %p\n", testor, testor2);
+
     NDS::Init();
 
     MainScreenPos[0] = 0;
@@ -616,6 +624,8 @@ int EmuThreadFunc(void* burp)
     NDS::DeInit();
     Platform::LAN_DeInit();
 
+    uiGLFreeContext(glctx);
+
     return 44203;
 }
 
@@ -1652,6 +1662,7 @@ void ApplyNewSettings(int type)
 
     if (type == 0) // general emu settings
     {
+        // TODO!! REMOVE ME
         GPU3D::SoftRenderer::SetupRenderThread();
     }
     else if (type == 1) // wifi settings
-- 
cgit v1.2.3


From b730bb890207d206505c338178fd49d244cd554d Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Sat, 11 May 2019 15:36:42 +0200
Subject: welp

---
 melonDS.cbp                        |   2 +
 src/libui_sdl/DlgVideoSettings.cpp | 150 +++++++++++++++++++++++++++++++++++++
 src/libui_sdl/DlgVideoSettings.h   |  29 +++++++
 src/libui_sdl/main.cpp             |   8 ++
 4 files changed, 189 insertions(+)
 create mode 100644 src/libui_sdl/DlgVideoSettings.cpp
 create mode 100644 src/libui_sdl/DlgVideoSettings.h

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index 0ba8653..b396861 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -131,6 +131,8 @@
 		<Unit filename="src/libui_sdl/DlgEmuSettings.h" />
 		<Unit filename="src/libui_sdl/DlgInputConfig.cpp" />
 		<Unit filename="src/libui_sdl/DlgInputConfig.h" />
+		<Unit filename="src/libui_sdl/DlgVideoSettings.cpp" />
+		<Unit filename="src/libui_sdl/DlgVideoSettings.h" />
 		<Unit filename="src/libui_sdl/DlgWifiSettings.cpp" />
 		<Unit filename="src/libui_sdl/DlgWifiSettings.h" />
 		<Unit filename="src/libui_sdl/LAN_PCap.cpp" />
diff --git a/src/libui_sdl/DlgVideoSettings.cpp b/src/libui_sdl/DlgVideoSettings.cpp
new file mode 100644
index 0000000..f27a80b
--- /dev/null
+++ b/src/libui_sdl/DlgVideoSettings.cpp
@@ -0,0 +1,150 @@
+/*
+    Copyright 2016-2019 Arisotura
+
+    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 "PlatformConfig.h"
+
+#include "DlgVideoSettings.h"
+
+
+//
+
+
+namespace DlgVideoSettings
+{
+
+bool opened;
+uiWindow* win;
+
+//
+
+
+int OnCloseWindow(uiWindow* window, void* blarg)
+{
+    opened = false;
+    return 1;
+}
+
+//
+
+void OnCancel(uiButton* btn, void* blarg)
+{
+    // restore old settings here
+
+    uiControlDestroy(uiControl(win));
+    opened = false;
+}
+
+void OnOk(uiButton* btn, void* blarg)
+{
+    // set config entries here
+
+    Config::Save();
+
+    uiControlDestroy(uiControl(win));
+    opened = false;
+}
+
+void Open()
+{
+    if (opened)
+    {
+        uiControlSetFocus(uiControl(win));
+        return;
+    }
+
+    opened = true;
+    win = uiNewWindow("Video settings - melonDS", 400, 100, 0, 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);
+    }
+
+    //
+
+    uiControlShow(uiControl(win));
+}
+
+}
diff --git a/src/libui_sdl/DlgVideoSettings.h b/src/libui_sdl/DlgVideoSettings.h
new file mode 100644
index 0000000..cd3d1b1
--- /dev/null
+++ b/src/libui_sdl/DlgVideoSettings.h
@@ -0,0 +1,29 @@
+/*
+    Copyright 2016-2019 Arisotura
+
+    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 DLGVIDEOSETTINGS_H
+#define DLGVIDEOSETTINGS_H
+
+namespace DlgVideoSettings
+{
+
+void Open();
+
+}
+
+#endif // DLGVIDEOSETTINGS_H
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp
index b3fce3f..a8a5ceb 100644
--- a/src/libui_sdl/main.cpp
+++ b/src/libui_sdl/main.cpp
@@ -30,6 +30,7 @@
 
 #include "DlgEmuSettings.h"
 #include "DlgInputConfig.h"
+#include "DlgVideoSettings.h"
 #include "DlgAudioSettings.h"
 #include "DlgWifiSettings.h"
 
@@ -1502,6 +1503,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();
@@ -1865,6 +1871,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");
-- 
cgit v1.2.3


From 256b8cb69c751f43a7766eafc6f8798eefa3217e Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Wed, 15 May 2019 19:49:21 +0200
Subject: botch GL support.

---
 melonDS.cbp                              |   2 +
 src/GPU3D_OpenGL43.cpp                   | 124 +------------------------------
 src/OpenGLSupport.cpp                    |  30 ++++++++
 src/OpenGLSupport.h                      | 112 ++++++++++++++++++++++++++++
 src/libui_sdl/libui/windows/areadraw.cpp |   2 +-
 5 files changed, 147 insertions(+), 123 deletions(-)
 create mode 100644 src/OpenGLSupport.cpp
 create mode 100644 src/OpenGLSupport.h

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index b396861..4634513 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -112,6 +112,8 @@
 		<Unit filename="src/NDS.h" />
 		<Unit filename="src/NDSCart.cpp" />
 		<Unit filename="src/NDSCart.h" />
+		<Unit filename="src/OpenGLSupport.cpp" />
+		<Unit filename="src/OpenGLSupport.h" />
 		<Unit filename="src/Platform.h" />
 		<Unit filename="src/RTC.cpp" />
 		<Unit filename="src/RTC.h" />
diff --git a/src/GPU3D_OpenGL43.cpp b/src/GPU3D_OpenGL43.cpp
index 57a80f1..3a2a3f1 100644
--- a/src/GPU3D_OpenGL43.cpp
+++ b/src/GPU3D_OpenGL43.cpp
@@ -16,77 +16,17 @@
     with melonDS. If not, see http://www.gnu.org/licenses/.
 */
 
-#include <GL/gl.h>
-#include <GL/glext.h>
-
 #include <stdio.h>
 #include <string.h>
 #include "NDS.h"
 #include "GPU.h"
-#include "Platform.h"
+#include "OpenGLSupport.h"
 
 namespace GPU3D
 {
 namespace GLRenderer43
 {
 
-PFNGLGENFRAMEBUFFERSPROC        glGenFramebuffers;
-PFNGLDELETEFRAMEBUFFERSPROC     glDeleteFramebuffers;
-PFNGLBINDFRAMEBUFFERPROC        glBindFramebuffer;
-PFNGLFRAMEBUFFERTEXTUREPROC     glFramebufferTexture;
-PFNGLBLITFRAMEBUFFERPROC        glBlitFramebuffer;
-
-PFNGLGENBUFFERSPROC             glGenBuffers;
-PFNGLDELETEBUFFERSPROC          glDeleteBuffers;
-PFNGLBINDBUFFERPROC             glBindBuffer;
-PFNGLMAPBUFFERPROC              glMapBuffer;
-PFNGLMAPBUFFERRANGEPROC         glMapBufferRange;
-PFNGLUNMAPBUFFERPROC            glUnmapBuffer;
-PFNGLBUFFERDATAPROC             glBufferData;
-PFNGLBUFFERSUBDATAPROC          glBufferSubData;
-PFNGLBINDBUFFERBASEPROC         glBindBufferBase;
-
-PFNGLGENVERTEXARRAYSPROC            glGenVertexArrays;
-PFNGLDELETEVERTEXARRAYSPROC         glDeleteVertexArrays;
-PFNGLBINDVERTEXARRAYPROC            glBindVertexArray;
-PFNGLENABLEVERTEXATTRIBARRAYPROC    glEnableVertexAttribArray;
-PFNGLDISABLEVERTEXATTRIBARRAYPROC   glDisableVertexAttribArray;
-PFNGLVERTEXATTRIBPOINTERPROC        glVertexAttribPointer;
-PFNGLVERTEXATTRIBIPOINTERPROC       glVertexAttribIPointer;
-
-PFNGLCREATESHADERPROC           glCreateShader;
-PFNGLSHADERSOURCEPROC           glShaderSource;
-PFNGLCOMPILESHADERPROC          glCompileShader;
-PFNGLCREATEPROGRAMPROC          glCreateProgram;
-PFNGLATTACHSHADERPROC           glAttachShader;
-PFNGLLINKPROGRAMPROC            glLinkProgram;
-PFNGLUSEPROGRAMPROC             glUseProgram;
-PFNGLGETSHADERIVPROC            glGetShaderiv;
-PFNGLGETSHADERINFOLOGPROC       glGetShaderInfoLog;
-PFNGLGETPROGRAMIVPROC           glGetProgramiv;
-PFNGLGETPROGRAMINFOLOGPROC      glGetProgramInfoLog;
-PFNGLDELETESHADERPROC           glDeleteShader;
-PFNGLDELETEPROGRAMPROC          glDeleteProgram;
-
-PFNGLUNIFORM1UIPROC             glUniform1ui;
-PFNGLUNIFORM4UIPROC             glUniform4ui;
-PFNGLUNIFORMBLOCKBINDINGPROC    glUniformBlockBinding;
-
-PFNGLACTIVETEXTUREPROC          glActiveTexture;
-PFNGLBINDIMAGETEXTUREPROC       glBindImageTexture;
-
-PFNGLDRAWBUFFERSPROC            glDrawBuffers;
-
-PFNGLBLENDFUNCSEPARATEIPROC      glBlendFuncSeparatei;
-PFNGLBLENDEQUATIONSEPARATEIPROC  glBlendEquationSeparatei;
-
-PFNGLCOLORMASKIPROC             glColorMaski;
-
-PFNGLMEMORYBARRIERPROC          glMemoryBarrier;
-
-PFNGLGETSTRINGIPROC             glGetStringi;
-
-
 // GL version requirements
 // * explicit uniform location: 4.3 (or extension)
 // * texelFetch: 3.0 (GLSL 1.30)     (3.2/1.50 for MS)
@@ -792,67 +732,7 @@ bool ChunkedRendering = false;
 
 bool InitGLExtensions()
 {
-#define LOADPROC(type, name)  \
-    name = (PFN##type##PROC)Platform::GL_GetProcAddress(#name); \
-    if (!name) { printf("OpenGL: " #name " not found\n"); return false; }
-
-    LOADPROC(GLGENFRAMEBUFFERS, glGenFramebuffers);
-    LOADPROC(GLDELETEFRAMEBUFFERS, glDeleteFramebuffers);
-    LOADPROC(GLBINDFRAMEBUFFER, glBindFramebuffer);
-    LOADPROC(GLFRAMEBUFFERTEXTURE, glFramebufferTexture);
-    LOADPROC(GLBLITFRAMEBUFFER, glBlitFramebuffer);
-
-    LOADPROC(GLGENBUFFERS, glGenBuffers);
-    LOADPROC(GLDELETEBUFFERS, glDeleteBuffers);
-    LOADPROC(GLBINDBUFFER, glBindBuffer);
-    LOADPROC(GLMAPBUFFER, glMapBuffer);
-    LOADPROC(GLMAPBUFFERRANGE, glMapBufferRange);
-    LOADPROC(GLUNMAPBUFFER, glUnmapBuffer);
-    LOADPROC(GLBUFFERDATA, glBufferData);
-    LOADPROC(GLBUFFERSUBDATA, glBufferSubData);
-    LOADPROC(GLBINDBUFFERBASE, glBindBufferBase);
-
-    LOADPROC(GLGENVERTEXARRAYS, glGenVertexArrays);
-    LOADPROC(GLDELETEVERTEXARRAYS, glDeleteVertexArrays);
-    LOADPROC(GLBINDVERTEXARRAY, glBindVertexArray);
-    LOADPROC(GLENABLEVERTEXATTRIBARRAY, glEnableVertexAttribArray);
-    LOADPROC(GLDISABLEVERTEXATTRIBARRAY, glDisableVertexAttribArray);
-    LOADPROC(GLVERTEXATTRIBPOINTER, glVertexAttribPointer);
-    LOADPROC(GLVERTEXATTRIBIPOINTER, glVertexAttribIPointer);
-
-    LOADPROC(GLCREATESHADER, glCreateShader);
-    LOADPROC(GLSHADERSOURCE, glShaderSource);
-    LOADPROC(GLCOMPILESHADER, glCompileShader);
-    LOADPROC(GLCREATEPROGRAM, glCreateProgram);
-    LOADPROC(GLATTACHSHADER, glAttachShader);
-    LOADPROC(GLLINKPROGRAM, glLinkProgram);
-    LOADPROC(GLUSEPROGRAM, glUseProgram);
-    LOADPROC(GLGETSHADERIV, glGetShaderiv);
-    LOADPROC(GLGETSHADERINFOLOG, glGetShaderInfoLog);
-    LOADPROC(GLGETPROGRAMIV, glGetProgramiv);
-    LOADPROC(GLGETPROGRAMINFOLOG, glGetProgramInfoLog);
-    LOADPROC(GLDELETESHADER, glDeleteShader);
-    LOADPROC(GLDELETEPROGRAM, glDeleteProgram);
-
-    LOADPROC(GLUNIFORM1UI, glUniform1ui);
-    LOADPROC(GLUNIFORM4UI, glUniform4ui);
-    LOADPROC(GLUNIFORMBLOCKBINDING, glUniformBlockBinding);
-
-    LOADPROC(GLACTIVETEXTURE, glActiveTexture);
-    LOADPROC(GLBINDIMAGETEXTURE, glBindImageTexture);
-
-    LOADPROC(GLDRAWBUFFERS, glDrawBuffers);
-
-    LOADPROC(GLBLENDFUNCSEPARATEI, glBlendFuncSeparatei);
-    LOADPROC(GLBLENDEQUATIONSEPARATEI, glBlendEquationSeparatei);
-
-    LOADPROC(GLCOLORMASKI, glColorMaski);
-
-    LOADPROC(GLMEMORYBARRIER, glMemoryBarrier);
-
-    LOADPROC(GLGETSTRINGI, glGetStringi);
-
-#undef LOADPROC
+    if (!OpenGL_Init()) return false;
     return true;
 }
 
diff --git a/src/OpenGLSupport.cpp b/src/OpenGLSupport.cpp
new file mode 100644
index 0000000..c22fd1c
--- /dev/null
+++ b/src/OpenGLSupport.cpp
@@ -0,0 +1,30 @@
+/*
+    Copyright 2016-2019 Arisotura
+
+    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 "OpenGLSupport.h"
+
+
+DO_PROCLIST(DECLPROC);
+
+
+bool OpenGL_Init()
+{
+    DO_PROCLIST(LOADPROC);
+
+    return true;
+}
diff --git a/src/OpenGLSupport.h b/src/OpenGLSupport.h
new file mode 100644
index 0000000..10ba1e5
--- /dev/null
+++ b/src/OpenGLSupport.h
@@ -0,0 +1,112 @@
+/*
+    Copyright 2016-2019 Arisotura
+
+    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 OPENGLSUPPORT_H
+#define OPENGLSUPPORT_H
+
+#include <stdio.h>
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#include "Platform.h"
+
+
+// here, have some macro magic
+// we at the melonDS company really love macro magic
+// also, suggestion to the fine folks who write the OpenGL headers:
+// pls make the type names follow the same capitalization as their
+// matching function names, so this is more convenient to deal with
+
+#define DECLPROC(type, name)  \
+    PFN##type##PROC name ;
+
+#define DECLPROC_EXT(type, name)  \
+    extern PFN##type##PROC name ;
+
+#define LOADPROC(type, name)  \
+    name = (PFN##type##PROC)Platform::GL_GetProcAddress(#name); \
+    if (!name) { printf("OpenGL: " #name " not found\n"); return false; }
+
+
+// if you need more OpenGL functions, add them to the macronator here
+// TODO: handle conditionally loading certain functions for different GL versions
+
+#define DO_PROCLIST(func) \
+    func(GLGENFRAMEBUFFERS, glGenFramebuffers); \
+    func(GLDELETEFRAMEBUFFERS, glDeleteFramebuffers); \
+    func(GLBINDFRAMEBUFFER, glBindFramebuffer); \
+    func(GLFRAMEBUFFERTEXTURE, glFramebufferTexture); \
+    func(GLBLITFRAMEBUFFER, glBlitFramebuffer); \
+     \
+    func(GLGENBUFFERS, glGenBuffers); \
+    func(GLDELETEBUFFERS, glDeleteBuffers); \
+    func(GLBINDBUFFER, glBindBuffer); \
+    func(GLMAPBUFFER, glMapBuffer); \
+    func(GLMAPBUFFERRANGE, glMapBufferRange); \
+    func(GLUNMAPBUFFER, glUnmapBuffer); \
+    func(GLBUFFERDATA, glBufferData); \
+    func(GLBUFFERSUBDATA, glBufferSubData); \
+    func(GLBINDBUFFERBASE, glBindBufferBase); \
+     \
+    func(GLGENVERTEXARRAYS, glGenVertexArrays); \
+    func(GLDELETEVERTEXARRAYS, glDeleteVertexArrays); \
+    func(GLBINDVERTEXARRAY, glBindVertexArray); \
+    func(GLENABLEVERTEXATTRIBARRAY, glEnableVertexAttribArray); \
+    func(GLDISABLEVERTEXATTRIBARRAY, glDisableVertexAttribArray); \
+    func(GLVERTEXATTRIBPOINTER, glVertexAttribPointer); \
+    func(GLVERTEXATTRIBIPOINTER, glVertexAttribIPointer); \
+     \
+    func(GLCREATESHADER, glCreateShader); \
+    func(GLSHADERSOURCE, glShaderSource); \
+    func(GLCOMPILESHADER, glCompileShader); \
+    func(GLCREATEPROGRAM, glCreateProgram); \
+    func(GLATTACHSHADER, glAttachShader); \
+    func(GLLINKPROGRAM, glLinkProgram); \
+    func(GLUSEPROGRAM, glUseProgram); \
+    func(GLGETSHADERIV, glGetShaderiv); \
+    func(GLGETSHADERINFOLOG, glGetShaderInfoLog); \
+    func(GLGETPROGRAMIV, glGetProgramiv); \
+    func(GLGETPROGRAMINFOLOG, glGetProgramInfoLog); \
+    func(GLDELETESHADER, glDeleteShader); \
+    func(GLDELETEPROGRAM, glDeleteProgram); \
+     \
+    func(GLUNIFORM1UI, glUniform1ui); \
+    func(GLUNIFORM4UI, glUniform4ui); \
+    func(GLUNIFORMBLOCKBINDING, glUniformBlockBinding); \
+     \
+    func(GLACTIVETEXTURE, glActiveTexture); \
+    func(GLBINDIMAGETEXTURE, glBindImageTexture); \
+     \
+    func(GLDRAWBUFFERS, glDrawBuffers); \
+     \
+    func(GLBLENDFUNCSEPARATEI, glBlendFuncSeparatei); \
+    func(GLBLENDEQUATIONSEPARATEI, glBlendEquationSeparatei); \
+     \
+    func(GLCOLORMASKI, glColorMaski); \
+     \
+    func(GLMEMORYBARRIER, glMemoryBarrier); \
+     \
+    func(GLGETSTRINGI, glGetStringi); \
+
+
+DO_PROCLIST(DECLPROC_EXT);
+
+
+bool OpenGL_Init();
+
+#endif // OPENGLSUPPORT_H
diff --git a/src/libui_sdl/libui/windows/areadraw.cpp b/src/libui_sdl/libui/windows/areadraw.cpp
index 6b4845a..f369255 100644
--- a/src/libui_sdl/libui/windows/areadraw.cpp
+++ b/src/libui_sdl/libui/windows/areadraw.cpp
@@ -9,7 +9,7 @@ static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *clip)
 
 	if (a->openGL)
     {
-        (*(ah->Draw))(ah, a, &dp);
+        //(*(ah->Draw))(ah, a, &dp);
         return S_OK;
     }
 
-- 
cgit v1.2.3


From f2725791d8c3b5f00ddc830691ed556b48f2f508 Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Thu, 16 May 2019 00:30:55 +0200
Subject: preliminary, shitty, code for drawing the main window with OpenGL

---
 melonDS.cbp                        |   1 +
 src/GPU3D_OpenGL43.cpp             |   7 +-
 src/OpenGLSupport.cpp              |  85 ++++++++++++++
 src/OpenGLSupport.h                |   4 +
 src/libui_sdl/libui/windows/gl.cpp |   2 +-
 src/libui_sdl/main.cpp             | 227 ++++++++++++++++++++++++++++++++++++-
 src/libui_sdl/main_shaders.h       |  72 ++++++++++++
 7 files changed, 392 insertions(+), 6 deletions(-)
 create mode 100644 src/libui_sdl/main_shaders.h

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index 4634513..ff01ebf 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -230,6 +230,7 @@
 		<Unit filename="src/libui_sdl/libui/windows/winpublic.cpp" />
 		<Unit filename="src/libui_sdl/libui/windows/winutil.cpp" />
 		<Unit filename="src/libui_sdl/main.cpp" />
+		<Unit filename="src/libui_sdl/main_shaders.h" />
 		<Unit filename="src/pcap/bluetooth.h" />
 		<Unit filename="src/pcap/bpf.h" />
 		<Unit filename="src/pcap/can_socketcan.h" />
diff --git a/src/GPU3D_OpenGL43.cpp b/src/GPU3D_OpenGL43.cpp
index 3a2a3f1..b3e0856 100644
--- a/src/GPU3D_OpenGL43.cpp
+++ b/src/GPU3D_OpenGL43.cpp
@@ -732,7 +732,8 @@ bool ChunkedRendering = false;
 
 bool InitGLExtensions()
 {
-    if (!OpenGL_Init()) return false;
+    // TODO move this elsewhere!!
+    //if (!OpenGL_Init()) return false;
     return true;
 }
 
@@ -1385,7 +1386,7 @@ void VCount144()
 }
 
 void RenderFrame()
-{
+{return;
     ShaderConfig.uScreenSize[0] = ScreenW;
     ShaderConfig.uScreenSize[1] = ScreenH;
     ShaderConfig.uDispCnt = RenderDispCnt;
@@ -1544,7 +1545,7 @@ void RenderFrame()
 u32* GetLine(int line)
 {
     int stride = 256 << (ScaleFactor*2);
-
+return &Framebuffer[stride * line];
     if (!ChunkedRendering)
     {
         if (line == 0)
diff --git a/src/OpenGLSupport.cpp b/src/OpenGLSupport.cpp
index c22fd1c..81a008b 100644
--- a/src/OpenGLSupport.cpp
+++ b/src/OpenGLSupport.cpp
@@ -28,3 +28,88 @@ bool OpenGL_Init()
 
     return true;
 }
+
+bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name)
+{
+    int len;
+    int res;
+
+    ids[0] = glCreateShader(GL_VERTEX_SHADER);
+    len = strlen(vs);
+    glShaderSource(ids[0], 1, &vs, &len);
+    glCompileShader(ids[0]);
+
+    glGetShaderiv(ids[0], GL_COMPILE_STATUS, &res);
+    if (res != GL_TRUE)
+    {
+        glGetShaderiv(ids[0], GL_INFO_LOG_LENGTH, &res);
+        if (res < 1) res = 1024;
+        char* log = new char[res+1];
+        glGetShaderInfoLog(ids[0], res+1, NULL, log);
+        printf("OpenGL: failed to compile vertex shader %s: %s\n", name, log);
+        printf("shader source:\n--\n%s\n--\n", vs);
+        delete[] log;
+
+        glDeleteShader(ids[0]);
+
+        return false;
+    }
+
+    ids[1] = glCreateShader(GL_FRAGMENT_SHADER);
+    len = strlen(fs);
+    glShaderSource(ids[1], 1, &fs, &len);
+    glCompileShader(ids[1]);
+
+    glGetShaderiv(ids[1], GL_COMPILE_STATUS, &res);
+    if (res != GL_TRUE)
+    {
+        glGetShaderiv(ids[1], GL_INFO_LOG_LENGTH, &res);
+        if (res < 1) res = 1024;
+        char* log = new char[res+1];
+        glGetShaderInfoLog(ids[1], res+1, NULL, log);
+        printf("OpenGL: failed to compile fragment shader %s: %s\n", name, log);
+        //printf("shader source:\n--\n%s\n--\n", fs);
+        delete[] log;
+
+        glDeleteShader(ids[0]);
+        glDeleteShader(ids[1]);
+
+        return false;
+    }
+
+    ids[2] = glCreateProgram();
+    glAttachShader(ids[2], ids[0]);
+    glAttachShader(ids[2], ids[1]);
+    glLinkProgram(ids[2]);
+
+    glGetProgramiv(ids[2], GL_LINK_STATUS, &res);
+    if (res != GL_TRUE)
+    {
+        glGetProgramiv(ids[2], GL_INFO_LOG_LENGTH, &res);
+        if (res < 1) res = 1024;
+        char* log = new char[res+1];
+        glGetProgramInfoLog(ids[2], res+1, NULL, log);
+        printf("OpenGL: failed to link program %s: %s\n", name, log);
+        delete[] log;
+
+        glDeleteShader(ids[0]);
+        glDeleteShader(ids[1]);
+        glDeleteProgram(ids[2]);
+
+        return false;
+    }
+
+    return true;
+}
+
+void OpenGL_DeleteShaderProgram(GLuint* ids)
+{
+    glDeleteShader(ids[0]);
+    glDeleteShader(ids[1]);
+    glDeleteProgram(ids[2]);
+}
+
+void OpenGL_UseShaderProgram(GLuint* ids)
+{
+    glUseProgram(ids[2]);
+}
diff --git a/src/OpenGLSupport.h b/src/OpenGLSupport.h
index 10ba1e5..2cee741 100644
--- a/src/OpenGLSupport.h
+++ b/src/OpenGLSupport.h
@@ -109,4 +109,8 @@ DO_PROCLIST(DECLPROC_EXT);
 
 bool OpenGL_Init();
 
+bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name);
+void OpenGL_DeleteShaderProgram(GLuint* ids);
+void OpenGL_UseShaderProgram(GLuint* ids);
+
 #endif // OPENGLSUPPORT_H
diff --git a/src/libui_sdl/libui/windows/gl.cpp b/src/libui_sdl/libui/windows/gl.cpp
index 67eaeda..832a2e5 100644
--- a/src/libui_sdl/libui/windows/gl.cpp
+++ b/src/libui_sdl/libui/windows/gl.cpp
@@ -39,7 +39,7 @@ uiGLContext* uiGLNewContext(uiControl* c, int vermajor, int verminor)
     memset(&pfd, 0, sizeof(pfd));
     pfd.nSize = sizeof(pfd);
     pfd.nVersion = 1;
-    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
     pfd.iPixelType = PFD_TYPE_RGBA;
     pfd.cColorBits = 24;
     pfd.cAlphaBits = 8;
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp
index b39f493..23e6617 100644
--- a/src/libui_sdl/main.cpp
+++ b/src/libui_sdl/main.cpp
@@ -24,6 +24,9 @@
 #include <SDL2/SDL.h>
 #include "libui/ui.h"
 
+#include "../OpenGLSupport.h"
+#include "main_shaders.h"
+
 #include "../types.h"
 #include "../version.h"
 #include "PlatformConfig.h"
@@ -97,6 +100,19 @@ bool SavestateLoaded;
 bool ScreenDrawInited = false;
 uiDrawBitmap* ScreenBitmap[2] = {NULL,NULL};
 
+GLuint GL_ScreenShader[3];
+struct
+{
+    float uScreenSize[2];
+    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 ScreenScale[3];
 int ScreenScaleMode;
 
@@ -141,6 +157,204 @@ void GetSavestateName(int slot, char* filename, int len);
 
 
 
+bool GLDrawing_Init()
+{
+    if (!OpenGL_Init())
+        return false;
+
+    if (!OpenGL_BuildShaderProgram(kScreenVS, kScreenFS, GL_ScreenShader, "ScreenShader"))
+        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);
+    glUniformBlockBinding(GL_ScreenShader[2], 0, 16);
+
+    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, 1024, 1536, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL);
+
+    GL_ScreenSizeDirty = true;
+
+    return true;
+}
+
+void GLDrawing_DeInit()
+{
+    glDeleteTextures(1, &GL_ScreenTexture);
+
+    glDeleteVertexArrays(1, &GL_ScreenVertexArrayID);
+    glDeleteBuffers(1, &GL_ScreenVertexBufferID);
+
+    OpenGL_DeleteShaderProgram(GL_ScreenShader);
+}
+
+void GLDrawing_DrawScreen()
+{
+    if (GL_ScreenSizeDirty)
+    {
+        GL_ScreenSizeDirty = false;
+
+        GL_ShaderConfig.uScreenSize[0] = WindowWidth;
+        GL_ShaderConfig.uScreenSize[1] = WindowHeight;
+
+        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;
+        scwidth = 512;
+        scheight = 384;
+
+        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;
+
+        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);
+
+        // TODO: adjust scwidth/scheight
+
+        x0 = BottomScreenRect.X;
+        y0 = BottomScreenRect.Y;
+        x1 = BottomScreenRect.X + BottomScreenRect.Width;
+        y1 = BottomScreenRect.Y + BottomScreenRect.Height;
+
+        switch (ScreenRotation)
+        {
+        case 0:
+            s0 = 0; t0 = 768;
+            s1 = scwidth; t1 = 768;
+            s2 = 0; t2 = 768+scheight;
+            s3 = scwidth; t3 = 768+scheight;
+            break;
+
+        case 1:
+            s0 = 0; t0 = 768+scheight;
+            s1 = 0; t1 = 768;
+            s2 = scwidth; t2 = 768+scheight;
+            s3 = scwidth; t3 = 768;
+            break;
+
+        case 2:
+            s0 = scwidth; t0 = 768+scheight;
+            s1 = 0; t1 = 768+scheight;
+            s2 = scwidth; t2 = 768;
+            s3 = 0; t3 = 768;
+            break;
+
+        case 3:
+            s0 = scwidth; t0 = 768;
+            s1 = scwidth; t1 = 768+scheight;
+            s2 = 0; t2 = 768;
+            s3 = 0; t3 = 768+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_BLEND);
+
+    glViewport(0, 0, WindowWidth, WindowHeight);
+
+    OpenGL_UseShaderProgram(GL_ScreenShader);
+
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+    glClearColor(0, 1, 0, 1);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    int frontbuf = GPU::FrontBuffer;
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 512, 384, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 768, 512, 384, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
+
+    glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
+    glBindVertexArray(GL_ScreenVertexArrayID);
+    glDrawArrays(GL_TRIANGLES, 0, 4*3);
+
+    uiGLSwapBuffers(GLContext);
+    uiAreaQueueRedrawAll(MainDrawArea);
+}
+
 void MicLoadWav(char* name)
 {
     SDL_AudioSpec format;
@@ -397,6 +611,8 @@ void FeedMicInput()
 int EmuThreadFunc(void* burp)
 {
     uiGLMakeContextCurrent(GLContext);
+    GLDrawing_Init();
+
     NDS::Init();
 
     MainScreenPos[0] = 0;
@@ -567,7 +783,9 @@ int EmuThreadFunc(void* burp)
 
             if (EmuRunning == 0) break;
 
-            uiAreaQueueRedrawAll(MainDrawArea);
+            GLDrawing_DrawScreen();
+
+            //uiAreaQueueRedrawAll(MainDrawArea);
             //uiGLSwapBuffers(GLContext);
 
             // framerate limiter based off SDL2_gfx
@@ -622,6 +840,7 @@ int EmuThreadFunc(void* burp)
             {
                 //uiAreaQueueRedrawAll(MainDrawArea);
                 //uiGLSwapBuffers(GLContext);
+                GLDrawing_DrawScreen();
             }
 
             EmuStatus = EmuRunning;
@@ -637,6 +856,8 @@ int EmuThreadFunc(void* burp)
     NDS::DeInit();
     Platform::LAN_DeInit();
 
+    GLDrawing_DeInit();
+
     return 44203;
 }
 
@@ -1058,6 +1279,8 @@ void SetupScreenRects(int width, int height)
         }
         break;
     }
+
+    GL_ScreenSizeDirty = true;
 }
 
 void SetMinSize(int w, int h)
@@ -2063,7 +2286,7 @@ int main(int argc, char** argv)
     areahandler.Resize = OnAreaResize;
 
     ScreenDrawInited = false;
-    MainDrawArea = uiNewArea(&areahandler, 0);
+    MainDrawArea = uiNewArea(&areahandler, 1);
     uiWindowSetChild(MainWindow, uiControl(MainDrawArea));
     uiControlSetMinSize(uiControl(MainDrawArea), 256, 384);
     uiAreaSetBackgroundColor(MainDrawArea, 0, 0, 0); // TODO: make configurable?
diff --git a/src/libui_sdl/main_shaders.h b/src/libui_sdl/main_shaders.h
new file mode 100644
index 0000000..dcf79d9
--- /dev/null
+++ b/src/libui_sdl/main_shaders.h
@@ -0,0 +1,72 @@
+/*
+    Copyright 2016-2019 Arisotura
+
+    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 MAIN_SHADERS_H
+#define MAIN_SHADERS_H
+
+const char* kScreenVS = R"(#version 420
+
+layout(std140, binding=0) uniform uConfig
+{
+    vec2 uScreenSize;
+    uint uFilterMode;
+};
+
+layout(location=0) in vec2 vPosition;
+layout(location=1) in vec2 vTexcoord;
+
+smooth out vec2 fTexcoord;
+
+void main()
+{
+    vec4 fpos;
+    fpos.xy = ((vPosition.xy * 2.0) / uScreenSize) - 1.0;
+    fpos.y *= -1;
+    fpos.z = 0.0;
+    fpos.w = 1.0;
+
+    gl_Position = fpos;
+    fTexcoord = vTexcoord;
+}
+)";
+
+const char* kScreenFS = R"(#version 420
+
+layout(std140, binding=0) uniform uConfig
+{
+    vec2 uScreenSize;
+    uint uFilterMode;
+};
+
+layout(binding=0) uniform usampler2D ScreenTex;
+
+smooth in vec2 fTexcoord;
+
+layout(location=0) out vec4 oColor;
+
+void main()
+{
+    uvec4 pixel = texelFetch(ScreenTex, ivec2(fTexcoord), 0);
+
+    // TODO: filters
+
+    oColor = vec4(vec3(pixel.bgr) / 255.0, 1.0);
+}
+)";
+
+#endif // MAIN_SHADERS_H
-- 
cgit v1.2.3


From c81bcccadc9ac8394ba8d4a836d7c954dd528751 Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Thu, 16 May 2019 16:27:45 +0200
Subject: BAHAHAHAHAHAHAHAA

---
 melonDS.cbp                  |   1 +
 src/GPU.cpp                  |  40 +--
 src/GPU.h                    |   2 +-
 src/GPU2D.cpp                | 169 +++++++-----
 src/GPU2D.h                  |   4 +-
 src/GPU3D.cpp                |   4 +-
 src/GPU3D.h                  |   9 +-
 src/GPU3D_OpenGL43.cpp       | 641 +-----------------------------------------
 src/GPU3D_OpenGL43_shaders.h | 645 +++++++++++++++++++++++++++++++++++++++++++
 src/GPU3D_Soft.cpp           |   7 +-
 src/libui_sdl/main.cpp       |  19 +-
 11 files changed, 813 insertions(+), 728 deletions(-)
 create mode 100644 src/GPU3D_OpenGL43_shaders.h

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index ff01ebf..0bdac7f 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -107,6 +107,7 @@
 		<Unit filename="src/GPU3D.cpp" />
 		<Unit filename="src/GPU3D.h" />
 		<Unit filename="src/GPU3D_OpenGL43.cpp" />
+		<Unit filename="src/GPU3D_OpenGL43_shaders.h" />
 		<Unit filename="src/GPU3D_Soft.cpp" />
 		<Unit filename="src/NDS.cpp" />
 		<Unit filename="src/NDS.h" />
diff --git a/src/GPU.cpp b/src/GPU.cpp
index f4e9fd4..1d073f5 100644
--- a/src/GPU.cpp
+++ b/src/GPU.cpp
@@ -74,6 +74,7 @@ u32 VRAMMap_ARM7[2];
 int FrontBuffer;
 u32* Framebuffer[2][2];
 int FBScale[2];
+bool Accelerated;
 
 GPU2D* GPU2D_A;
 GPU2D* GPU2D_B;
@@ -88,9 +89,8 @@ bool Init()
     FrontBuffer = 0;
     Framebuffer[0][0] = NULL; Framebuffer[0][1] = NULL;
     Framebuffer[1][0] = NULL; Framebuffer[1][1] = NULL;
-    FBScale[0] = -1; FBScale[1] = -1;
-    //SetFramebufferScale(1);
-    SetFramebufferScale(1, 1);
+    FBScale[0] = -1; FBScale[1] = -1; Accelerated = false;
+    SetDisplaySettings(0, 0, false);
 
     return true;
 }
@@ -247,13 +247,15 @@ void AssignFramebuffers()
     }
 }
 
-void SetFramebufferScale(int top, int bottom)
-{
-    if (top != FBScale[0])
+void SetDisplaySettings(int topscale, int bottomscale, bool accel)
+{accel=true;
+    if (topscale != FBScale[0] || accel != Accelerated)
     {
-        FBScale[0] = top;
+        FBScale[0] = accel ? 0 : topscale;
 
-        int fbsize = (256 * 192) << (FBScale[0] * 2);
+        int fbsize;
+        if (accel) fbsize = 256*3 * 192;
+        else       fbsize = (256 * 192) << (FBScale[0] * 2);
         if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
         if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
         Framebuffer[0][0] = new u32[fbsize];
@@ -266,21 +268,23 @@ void SetFramebufferScale(int top, int bottom)
         if (NDS::PowerControl9 & (1<<15))
         {
             GPU2D_A->SetFramebuffer(Framebuffer[backbuf][0]);
-            GPU2D_A->SetScale(FBScale[0]);
-            GPU3D::SetScale(FBScale[0]);
+            GPU2D_A->SetDisplaySettings(FBScale[0], accel);
+            GPU3D::SetDisplaySettings(topscale, accel);
         }
         else
         {
             GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
-            GPU2D_B->SetScale(FBScale[0]);
+            GPU2D_B->SetDisplaySettings(FBScale[0], accel);
         }
     }
 
-    if (bottom != FBScale[1])
+    if (bottomscale != FBScale[1] || accel != Accelerated)
     {
-        FBScale[1] = bottom;
+        FBScale[1] = accel ? 0 : bottomscale;
 
-        int fbsize = (256 * 192) << (FBScale[1] * 2);
+        int fbsize;
+        if (accel) fbsize = 256*3 * 192;
+        else       fbsize = (256 * 192) << (FBScale[1] * 2);
         if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
         if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
         Framebuffer[0][1] = new u32[fbsize];
@@ -293,15 +297,17 @@ void SetFramebufferScale(int top, int bottom)
         if (NDS::PowerControl9 & (1<<15))
         {
             GPU2D_B->SetFramebuffer(Framebuffer[backbuf][1]);
-            GPU2D_B->SetScale(FBScale[1]);
+            GPU2D_B->SetDisplaySettings(FBScale[1], accel);
         }
         else
         {
             GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
-            GPU2D_A->SetScale(FBScale[1]);
-            GPU3D::SetScale(FBScale[1]);
+            GPU2D_A->SetDisplaySettings(FBScale[1], accel);
+            GPU3D::SetDisplaySettings(bottomscale, accel);
         }
     }
+
+    Accelerated = accel;
 }
 
 
diff --git a/src/GPU.h b/src/GPU.h
index 2e47fc4..cfa8d7d 100644
--- a/src/GPU.h
+++ b/src/GPU.h
@@ -75,7 +75,7 @@ void Stop();
 
 void DoSavestate(Savestate* file);
 
-void SetFramebufferScale(int top, int bottom);
+void SetDisplaySettings(int topscale, int bottomscale, bool accel);
 
 
 void MapVRAM_AB(u32 bank, u8 cnt);
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp
index 3a99964..34c17ff 100644
--- a/src/GPU2D.cpp
+++ b/src/GPU2D.cpp
@@ -82,7 +82,6 @@
 GPU2D::GPU2D(u32 num)
 {
     Num = num;
-    SetScale(0);
 }
 
 GPU2D::~GPU2D()
@@ -216,12 +215,16 @@ void GPU2D::SetFramebuffer(u32* buf)
     Framebuffer = buf;
 }
 
-void GPU2D::SetScale(int scale)
+void GPU2D::SetDisplaySettings(int scale, bool accel)
 {
+    if (accel) scale = 0;
+    Accelerated = accel;
+
     LineScale = scale;
     LineStride = 256 << (scale*2);
 
-    if      (scale == 1) DrawPixel = DrawPixel_2x;
+    if (Accelerated)     DrawPixel = DrawPixel_Accel;
+    else if (scale == 1) DrawPixel = DrawPixel_2x;
     else if (scale == 2) DrawPixel = DrawPixel_4x;
     else                 DrawPixel = DrawPixel_1x;
 }
@@ -623,7 +626,8 @@ u32 GPU2D::ColorBrightnessDown(u32 val, u32 factor)
 
 void GPU2D::DrawScanline(u32 line)
 {
-    u32* dst = &Framebuffer[LineStride * line];
+    int stride = Accelerated ? (256*3) : LineStride;
+    u32* dst = &Framebuffer[stride * line];
 
     int n3dline = line;
     line = GPU::VCount;
@@ -652,7 +656,7 @@ void GPU2D::DrawScanline(u32 line)
     u32 dispmode = DispCnt >> 16;
     dispmode &= (Num ? 0x1 : 0x3);
 
-    if (Num == 0)
+    if (Num == 0 && !Accelerated)
         _3DLine = GPU3D::GetLine(n3dline);
 
     // always render regular graphics
@@ -663,13 +667,13 @@ void GPU2D::DrawScanline(u32 line)
     case 0: // screen off
         {
             for (int i = 0; i < LineStride; i++)
-                dst[i] = 0xFF3F3F3F;
+                dst[i] = 0x003F3F3F;
         }
         break;
 
     case 1: // regular display
         {
-            for (int i = 0; i < LineStride; i+=2)
+            for (int i = 0; i < stride; i+=2)
                 *(u64*)&dst[i] = *(u64*)&BGOBJLine[i];
         }
         break;
@@ -783,6 +787,8 @@ void GPU2D::DrawScanline(u32 line)
             DoCapture(line, capwidth);
     }
 
+    if (Accelerated) return;
+
     // master brightness
     if (dispmode != 0)
     {
@@ -861,6 +867,8 @@ void GPU2D::DoCapture(u32 line, u32 width)
     u16* dst = (u16*)GPU::VRAM[dstvram];
     u32 dstaddr = (((CaptureCnt >> 18) & 0x3) << 14) + (line * width);
 
+    // TODO: handle 3D in accelerated mode!!
+
     u32* srcA;
     if (CaptureCnt & (1<<24))
         srcA = _3DLine;
@@ -1272,88 +1280,91 @@ void GPU2D::DrawScanline_Mode1(u32 line)
     // color special effects
     // can likely be optimized
 
-    u32 bldcnteffect = (BlendCnt >> 6) & 0x3;
-
-    for (int i = 0; i < LineStride; i++)
+    if (!Accelerated)
     {
-        int j = (i >> LineScale) & 0xFF;
+        u32 bldcnteffect = (BlendCnt >> 6) & 0x3;
 
-        u32 val1 = BGOBJLine[i];
-        u32 val2 = BGOBJLine[4096+i];
+        for (int i = 0; i < LineStride; i++)
+        {
+            int j = (i >> LineScale) & 0xFF;
 
-        u32 coloreffect, eva, evb;
+            u32 val1 = BGOBJLine[i];
+            u32 val2 = BGOBJLine[4096+i];
 
-        u32 flag1 = val1 >> 24;
-        u32 flag2 = val2 >> 24;
+            u32 coloreffect, eva, evb;
 
-        u32 target2;
-        if (flag2 & 0x80)      target2 = 0x1000;
-        else if (flag2 & 0x40) target2 = 0x0100;
-        else                   target2 = flag2 << 8;
+            u32 flag1 = val1 >> 24;
+            u32 flag2 = val2 >> 24;
 
-        if ((flag1 & 0x80) && (BlendCnt & target2))
-        {
-            // sprite blending
+            u32 target2;
+            if (flag2 & 0x80)      target2 = 0x1000;
+            else if (flag2 & 0x40) target2 = 0x0100;
+            else                   target2 = flag2 << 8;
 
-            coloreffect = 1;
+            if ((flag1 & 0x80) && (BlendCnt & target2))
+            {
+                // sprite blending
+
+                coloreffect = 1;
 
-            if (flag1 & 0x40)
+                if (flag1 & 0x40)
+                {
+                    eva = flag1 & 0x1F;
+                    evb = 16 - eva;
+                }
+                else
+                {
+                    eva = EVA;
+                    evb = EVB;
+                }
+            }
+            else if ((flag1 & 0x40) && (BlendCnt & target2))
             {
-                eva = flag1 & 0x1F;
-                evb = 16 - eva;
+                // 3D layer blending
+
+                BGOBJLine[i] = ColorBlend5(val1, val2);
+                continue;
             }
             else
             {
-                eva = EVA;
-                evb = EVB;
-            }
-        }
-        else if ((flag1 & 0x40) && (BlendCnt & target2))
-        {
-            // 3D layer blending
-
-            BGOBJLine[i] = ColorBlend5(val1, val2);
-            continue;
-        }
-        else
-        {
-            if (flag1 & 0x80)      flag1 = 0x10;
-            else if (flag1 & 0x40) flag1 = 0x01;
+                if (flag1 & 0x80)      flag1 = 0x10;
+                else if (flag1 & 0x40) flag1 = 0x01;
 
-            if ((BlendCnt & flag1) && (WindowMask[j] & 0x20))
-            {
-                if ((bldcnteffect == 1) && (BlendCnt & target2))
+                if ((BlendCnt & flag1) && (WindowMask[j] & 0x20))
                 {
-                    coloreffect = 1;
-                    eva = EVA;
-                    evb = EVB;
+                    if ((bldcnteffect == 1) && (BlendCnt & target2))
+                    {
+                        coloreffect = 1;
+                        eva = EVA;
+                        evb = EVB;
+                    }
+                    else if (bldcnteffect >= 2)
+                        coloreffect = bldcnteffect;
+                    else
+                        coloreffect = 0;
                 }
-                else if (bldcnteffect >= 2)
-                    coloreffect = bldcnteffect;
                 else
                     coloreffect = 0;
             }
-            else
-                coloreffect = 0;
-        }
 
-        switch (coloreffect)
-        {
-        case 0:
-            BGOBJLine[i] = val1;
-            break;
+            switch (coloreffect)
+            {
+            case 0:
+                BGOBJLine[i] = val1;
+                break;
 
-        case 1:
-            BGOBJLine[i] = ColorBlend4(val1, val2, eva, evb);
-            break;
+            case 1:
+                BGOBJLine[i] = ColorBlend4(val1, val2, eva, evb);
+                break;
 
-        case 2:
-            BGOBJLine[i] = ColorBrightnessUp(val1, EVY);
-            break;
+            case 2:
+                BGOBJLine[i] = ColorBrightnessUp(val1, EVY);
+                break;
 
-        case 3:
-            BGOBJLine[i] = ColorBrightnessDown(val1, EVY);
-            break;
+            case 3:
+                BGOBJLine[i] = ColorBrightnessDown(val1, EVY);
+                break;
+            }
         }
     }
 
@@ -1429,6 +1440,17 @@ void GPU2D::DrawPixel_4x(u32* dst, u16 color, u32 flag)
     *(u64*)(dst+3072+2) = val;
 }
 
+void GPU2D::DrawPixel_Accel(u32* dst, u16 color, u32 flag)
+{
+    u8 r = (color & 0x001F) << 1;
+    u8 g = (color & 0x03E0) >> 4;
+    u8 b = (color & 0x7C00) >> 9;
+
+    *(dst+512) = *(dst+256);
+    *(dst+256) = *dst;
+    *dst = r | (g << 8) | (b << 16) | flag;
+}
+
 void GPU2D::DrawBG_3D()
 {
     u16 xoff = BGXPos[0];
@@ -1445,7 +1467,18 @@ void GPU2D::DrawBG_3D()
         iend -= (xoff & 0xFF);
     }
 
-    if (LineScale == 1)
+    if (Accelerated)
+    {
+        for (; i < iend; i++)
+        {
+            if (!(WindowMask[i] & 0x01)) continue;
+
+            BGOBJLine[i+512] = BGOBJLine[i+256];
+            BGOBJLine[i+256] = BGOBJLine[i];
+            BGOBJLine[i] = 0x40000000; // 3D-layer placeholder
+        }
+    }
+    else if (LineScale == 1)
     {
         for (; i < iend; i++)
         {
diff --git a/src/GPU2D.h b/src/GPU2D.h
index aca1f7e..fc420a5 100644
--- a/src/GPU2D.h
+++ b/src/GPU2D.h
@@ -31,7 +31,7 @@ public:
 
     void SetEnabled(bool enable) { Enabled = enable; }
     void SetFramebuffer(u32* buf);
-    void SetScale(int scale);
+    void SetDisplaySettings(int scale, bool accel);
 
     u8 Read8(u32 addr);
     u16 Read16(u32 addr);
@@ -71,6 +71,7 @@ private:
 
     u32 LineStride;
     u32 LineScale;
+    bool Accelerated;
 
     u32 BGOBJLine[1024*4 * 2];
     u32* _3DLine;
@@ -136,6 +137,7 @@ private:
     static void DrawPixel_1x(u32* dst, u16 color, u32 flag);
     static void DrawPixel_2x(u32* dst, u16 color, u32 flag);
     static void DrawPixel_4x(u32* dst, u16 color, u32 flag);
+    static void DrawPixel_Accel(u32* dst, u16 color, u32 flag);
     void (*DrawPixel)(u32* dst, u16 color, u32 flag);
 
     void DrawBG_3D();
diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp
index 8c0588d..61629a7 100644
--- a/src/GPU3D.cpp
+++ b/src/GPU3D.cpp
@@ -607,9 +607,9 @@ void SetEnabled(bool geometry, bool rendering)
     if (!rendering) ResetRenderingState();
 }
 
-void SetScale(int scale)
+void SetDisplaySettings(int scale, bool accel)
 {
-    GLRenderer43::SetScale(scale);
+    GLRenderer43::SetDisplaySettings(scale, accel);
 }
 
 
diff --git a/src/GPU3D.h b/src/GPU3D.h
index 68bc696..2fe5bee 100644
--- a/src/GPU3D.h
+++ b/src/GPU3D.h
@@ -97,7 +97,7 @@ void Reset();
 void DoSavestate(Savestate* file);
 
 void SetEnabled(bool geometry, bool rendering);
-void SetScale(int scale);
+void SetDisplaySettings(int scale, bool accel);
 
 void ExecuteCommand();
 
@@ -110,6 +110,7 @@ void VCount144();
 void VBlank();
 void VCount215();
 u32* GetLine(int line);
+void SetupAccelFrame();
 
 void WriteToGXFIFO(u32 val);
 
@@ -127,13 +128,14 @@ bool Init();
 void DeInit();
 void Reset();
 
-void SetScale(int scale);
+void SetDisplaySettings(int scale, bool accel);
 
 void SetupRenderThread();
 
 void VCount144();
 void RenderFrame();
 u32* GetLine(int line);
+void SetupAccelFrame();
 
 }
 
@@ -144,11 +146,12 @@ bool Init();
 void DeInit();
 void Reset();
 
-void SetScale(int scale);
+void SetDisplaySettings(int scale, bool accel);
 
 void VCount144();
 void RenderFrame();
 u32* GetLine(int line);
+void SetupAccelFrame();
 
 }
 
diff --git a/src/GPU3D_OpenGL43.cpp b/src/GPU3D_OpenGL43.cpp
index e76db7f..6db9a18 100644
--- a/src/GPU3D_OpenGL43.cpp
+++ b/src/GPU3D_OpenGL43.cpp
@@ -21,6 +21,7 @@
 #include "NDS.h"
 #include "GPU.h"
 #include "OpenGLSupport.h"
+#include "GPU3D_OpenGL43_shaders.h"
 
 namespace GPU3D
 {
@@ -33,631 +34,6 @@ namespace GLRenderer43
 // * UBO: 3.1
 // * glMemoryBarrier: 4.2
 
-// TODO: consider other way to handle uniforms (UBO?)
-
-#define kShaderHeader "#version 430"
-
-
-const char* kClearVS = kShaderHeader R"(
-
-layout(location=0) in vec2 vPosition;
-
-layout(location=1) uniform uint uDepth;
-
-void main()
-{
-    float fdepth = (float(uDepth) / 8388608.0) - 1.0;
-    gl_Position = vec4(vPosition, fdepth, 1.0);
-}
-)";
-
-const char* kClearFS = kShaderHeader R"(
-
-layout(location=0) uniform uvec4 uColor;
-layout(location=2) uniform uint uOpaquePolyID;
-layout(location=3) uniform uint uFogFlag;
-
-layout(location=0) out vec4 oColor;
-layout(location=1) out uvec3 oAttr;
-
-void main()
-{
-    oColor = vec4(uColor).bgra / 31.0;
-    oAttr.r = 0;
-    oAttr.g = uOpaquePolyID;
-    oAttr.b = 0;
-}
-)";
-
-
-const char* kRenderVSCommon = R"(
-
-layout(std140, binding=0) uniform uConfig
-{
-    vec2 uScreenSize;
-    uint uDispCnt;
-    vec4 uToonColors[32];
-};
-
-layout(location=0) in uvec4 vPosition;
-layout(location=1) in uvec4 vColor;
-layout(location=2) in ivec2 vTexcoord;
-layout(location=3) in uvec3 vPolygonAttr;
-
-smooth out vec4 fColor;
-smooth out vec2 fTexcoord;
-flat out uvec3 fPolygonAttr;
-)";
-
-const char* kRenderFSCommon = R"(
-
-layout(binding=0) uniform usampler2D TexMem;
-layout(binding=1) uniform sampler2D TexPalMem;
-
-layout(std140, binding=0) uniform uConfig
-{
-    vec2 uScreenSize;
-    uint uDispCnt;
-    vec4 uToonColors[32];
-};
-
-smooth in vec4 fColor;
-smooth in vec2 fTexcoord;
-flat in uvec3 fPolygonAttr;
-
-layout(location=0) out vec4 oColor;
-layout(location=1) out uvec3 oAttr;
-
-int TexcoordWrap(int c, int maxc, uint mode)
-{
-    if ((mode & (1<<0)) != 0)
-    {
-        if ((mode & (1<<2)) != 0 && (c & maxc) != 0)
-            return (maxc-1) - (c & (maxc-1));
-        else
-            return (c & (maxc-1));
-    }
-    else
-        return clamp(c, 0, maxc-1);
-}
-
-vec4 TextureFetch_A3I5(ivec2 addr, ivec4 st, uint wrapmode)
-{
-    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
-    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
-
-    addr.x += ((st.y * st.z) + st.x);
-    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
-
-    pixel.a = (pixel.r & 0xE0);
-    pixel.a = (pixel.a >> 3) + (pixel.a >> 6);
-    pixel.r &= 0x1F;
-
-    addr.y = (addr.y << 3) + int(pixel.r);
-    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-
-    return vec4(color.rgb, float(pixel.a)/31.0);
-}
-
-vec4 TextureFetch_I2(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
-{
-    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
-    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
-
-    addr.x += ((st.y * st.z) + st.x) >> 2;
-    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
-    pixel.r >>= (2 * (st.x & 3));
-    pixel.r &= 0x03;
-
-    addr.y = (addr.y << 2) + int(pixel.r);
-    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-
-    return vec4(color.rgb, max(step(1,pixel.r),alpha0));
-}
-
-vec4 TextureFetch_I4(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
-{
-    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
-    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
-
-    addr.x += ((st.y * st.z) + st.x) >> 1;
-    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
-    if ((st.x & 1) != 0) pixel.r >>= 4;
-    else                 pixel.r &= 0x0F;
-
-    addr.y = (addr.y << 3) + int(pixel.r);
-    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-
-    return vec4(color.rgb, max(step(1,pixel.r),alpha0));
-}
-
-vec4 TextureFetch_I8(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
-{
-    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
-    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
-
-    addr.x += ((st.y * st.z) + st.x);
-    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
-
-    addr.y = (addr.y << 3) + int(pixel.r);
-    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-
-    return vec4(color.rgb, max(step(1,pixel.r),alpha0));
-}
-
-vec4 TextureFetch_Compressed(ivec2 addr, ivec4 st, uint wrapmode)
-{
-    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
-    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
-
-    addr.x += ((st.y & 0x3FC) * (st.z>>2)) + (st.x & 0x3FC) + (st.y & 0x3);
-    uvec4 p = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
-    uint val = (p.r >> (2 * (st.x & 0x3))) & 0x3;
-
-    int slot1addr = 0x20000 + ((addr.x & 0x1FFFC) >> 1);
-    if (addr.x >= 0x40000) slot1addr += 0x10000;
-
-    uint palinfo;
-    p = texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0);
-    palinfo = p.r;
-    slot1addr++;
-    p = texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0);
-    palinfo |= (p.r << 8);
-
-    addr.y = (addr.y << 3) + ((int(palinfo) & 0x3FFF) << 1);
-    palinfo >>= 14;
-
-    if (val == 0)
-    {
-        vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-        return vec4(color.rgb, 1.0);
-    }
-    else if (val == 1)
-    {
-        addr.y++;
-        vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-        return vec4(color.rgb, 1.0);
-    }
-    else if (val == 2)
-    {
-        if (palinfo == 1)
-        {
-            vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-            addr.y++;
-            vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-            return vec4((color0.rgb + color1.rgb) / 2.0, 1.0);
-        }
-        else if (palinfo == 3)
-        {
-            vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-            addr.y++;
-            vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-            return vec4((color0.rgb*5.0 + color1.rgb*3.0) / 8.0, 1.0);
-        }
-        else
-        {
-            addr.y += 2;
-            vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-            return vec4(color.rgb, 1.0);
-        }
-    }
-    else
-    {
-        if (palinfo == 2)
-        {
-            addr.y += 3;
-            vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-            return vec4(color.rgb, 1.0);
-        }
-        else if (palinfo == 3)
-        {
-            vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-            addr.y++;
-            vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-            return vec4((color0.rgb*3.0 + color1.rgb*5.0) / 8.0, 1.0);
-        }
-        else
-        {
-            return vec4(0.0);
-        }
-    }
-}
-
-vec4 TextureFetch_A5I3(ivec2 addr, ivec4 st, uint wrapmode)
-{
-    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
-    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
-
-    addr.x += ((st.y * st.z) + st.x);
-    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
-
-    pixel.a = (pixel.r & 0xF8) >> 3;
-    pixel.r &= 0x07;
-
-    addr.y = (addr.y << 3) + int(pixel.r);
-    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
-
-    return vec4(color.rgb, float(pixel.a)/31.0);
-}
-
-vec4 TextureFetch_Direct(ivec2 addr, ivec4 st, uint wrapmode)
-{
-    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
-    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
-
-    addr.x += ((st.y * st.z) + st.x) << 1;
-    uvec4 pixelL = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
-    addr.x++;
-    uvec4 pixelH = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
-
-    vec4 color;
-    color.r = float(pixelL.r & 0x1F) / 31.0;
-    color.g = float((pixelL.r >> 5) | ((pixelH.r & 0x03) << 3)) / 31.0;
-    color.b = float((pixelH.r & 0x7C) >> 2) / 31.0;
-    color.a = float(pixelH.r >> 7);
-
-    return color;
-}
-
-vec4 TextureLookup_Nearest(vec2 st)
-{
-    uint attr = fPolygonAttr.y;
-    uint paladdr = fPolygonAttr.z;
-
-    float alpha0;
-    if ((attr & (1<<29)) != 0) alpha0 = 0.0;
-    else                       alpha0 = 1.0;
-
-    int tw = 8 << int((attr >> 20) & 0x7);
-    int th = 8 << int((attr >> 23) & 0x7);
-    ivec4 st_full = ivec4(ivec2(st), tw, th);
-
-    ivec2 vramaddr = ivec2(int(attr & 0xFFFF) << 3, int(paladdr));
-    uint wrapmode = attr >> 16;
-
-    uint type = (attr >> 26) & 0x7;
-    if      (type == 5) return TextureFetch_Compressed(vramaddr, st_full, wrapmode);
-    else if (type == 2) return TextureFetch_I2        (vramaddr, st_full, wrapmode, alpha0);
-    else if (type == 3) return TextureFetch_I4        (vramaddr, st_full, wrapmode, alpha0);
-    else if (type == 4) return TextureFetch_I8        (vramaddr, st_full, wrapmode, alpha0);
-    else if (type == 1) return TextureFetch_A3I5      (vramaddr, st_full, wrapmode);
-    else if (type == 6) return TextureFetch_A5I3      (vramaddr, st_full, wrapmode);
-    else                return TextureFetch_Direct    (vramaddr, st_full, wrapmode);
-}
-
-vec4 TextureLookup_Linear(vec2 texcoord)
-{
-    ivec2 intpart = ivec2(texcoord);
-    vec2 fracpart = fract(texcoord);
-
-    uint attr = fPolygonAttr.y;
-    uint paladdr = fPolygonAttr.z;
-
-    float alpha0;
-    if ((attr & (1<<29)) != 0) alpha0 = 0.0;
-    else                       alpha0 = 1.0;
-
-    int tw = 8 << int((attr >> 20) & 0x7);
-    int th = 8 << int((attr >> 23) & 0x7);
-    ivec4 st_full = ivec4(intpart, tw, th);
-
-    ivec2 vramaddr = ivec2(int(attr & 0xFFFF) << 3, int(paladdr));
-    uint wrapmode = attr >> 16;
-
-    vec4 A, B, C, D;
-    uint type = (attr >> 26) & 0x7;
-    if (type == 5)
-    {
-        A = TextureFetch_Compressed(vramaddr, st_full                 , wrapmode);
-        B = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
-        C = TextureFetch_Compressed(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
-        D = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
-    }
-    else if (type == 2)
-    {
-        A = TextureFetch_I2(vramaddr, st_full                 , wrapmode, alpha0);
-        B = TextureFetch_I2(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
-        C = TextureFetch_I2(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
-        D = TextureFetch_I2(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
-    }
-    else if (type == 3)
-    {
-        A = TextureFetch_I4(vramaddr, st_full                 , wrapmode, alpha0);
-        B = TextureFetch_I4(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
-        C = TextureFetch_I4(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
-        D = TextureFetch_I4(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
-    }
-    else if (type == 4)
-    {
-        A = TextureFetch_I8(vramaddr, st_full                 , wrapmode, alpha0);
-        B = TextureFetch_I8(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
-        C = TextureFetch_I8(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
-        D = TextureFetch_I8(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
-    }
-    else if (type == 1)
-    {
-        A = TextureFetch_A3I5(vramaddr, st_full                 , wrapmode);
-        B = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
-        C = TextureFetch_A3I5(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
-        D = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
-    }
-    else if (type == 6)
-    {
-        A = TextureFetch_A5I3(vramaddr, st_full                 , wrapmode);
-        B = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
-        C = TextureFetch_A5I3(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
-        D = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
-    }
-    else
-    {
-        A = TextureFetch_Direct(vramaddr, st_full                 , wrapmode);
-        B = TextureFetch_Direct(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
-        C = TextureFetch_Direct(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
-        D = TextureFetch_Direct(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
-    }
-
-    float fx = fracpart.x;
-    vec4 AB;
-    if (A.a < (0.5/31.0) && B.a < (0.5/31.0))
-        AB = vec4(0);
-    else
-    {
-        //if (A.a < (0.5/31.0) || B.a < (0.5/31.0))
-        //    fx = step(0.5, fx);
-
-        AB = mix(A, B, fx);
-    }
-
-    fx = fracpart.x;
-    vec4 CD;
-    if (C.a < (0.5/31.0) && D.a < (0.5/31.0))
-        CD = vec4(0);
-    else
-    {
-        //if (C.a < (0.5/31.0) || D.a < (0.5/31.0))
-        //    fx = step(0.5, fx);
-
-        CD = mix(C, D, fx);
-    }
-
-    fx = fracpart.y;
-    vec4 ret;
-    if (AB.a < (0.5/31.0) && CD.a < (0.5/31.0))
-        ret = vec4(0);
-    else
-    {
-        //if (AB.a < (0.5/31.0) || CD.a < (0.5/31.0))
-        //    fx = step(0.5, fx);
-
-        ret = mix(AB, CD, fx);
-    }
-
-    return ret;
-}
-
-vec4 FinalColor()
-{
-    vec4 col;
-    vec4 vcol = fColor;
-    uint blendmode = (fPolygonAttr.x >> 4) & 0x3;
-
-    if (blendmode == 2)
-    {
-        if ((uDispCnt & (1<<1)) == 0)
-        {
-            // toon
-            vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
-            vcol.rgb = tooncolor;
-        }
-        else
-        {
-            // highlight
-            vcol.rgb = vcol.rrr;
-        }
-    }
-
-    if ((((fPolygonAttr.y >> 26) & 0x7) == 0) || ((uDispCnt & (1<<0)) == 0))
-    {
-        // no texture
-        col = vcol;
-    }
-    else
-    {
-        vec4 tcol = TextureLookup_Nearest(fTexcoord);
-        //vec4 tcol = TextureLookup_Linear(fTexcoord);
-
-        if ((blendmode & 1) != 0)
-        {
-            // decal
-            col.rgb = (tcol.rgb * tcol.a) + (vcol.rgb * (1.0-tcol.a));
-            col.a = vcol.a;
-        }
-        else
-        {
-            // modulate
-            col = vcol * tcol;
-        }
-    }
-
-    if (blendmode == 2)
-    {
-        if ((uDispCnt & (1<<1)) != 0)
-        {
-            vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
-            col.rgb = min(col.rgb + tooncolor, 1.0);
-        }
-    }
-
-    return col.bgra;
-}
-)";
-
-
-const char* kRenderVS_Z = R"(
-
-void main()
-{
-    uint attr = vPolygonAttr.x;
-    uint zshift = (attr >> 16) & 0x1F;
-
-    vec4 fpos;
-    fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
-    fpos.z = (float(vPosition.z << zshift) / 8388608.0) - 1.0;
-    fpos.w = float(vPosition.w) / 65536.0f;
-    fpos.xyz *= fpos.w;
-
-    fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
-    fTexcoord = vec2(vTexcoord) / 16.0;
-    fPolygonAttr = vPolygonAttr;
-
-    gl_Position = fpos;
-}
-)";
-
-const char* kRenderVS_W = R"(
-
-smooth out float fZ;
-
-void main()
-{
-    uint attr = vPolygonAttr.x;
-    uint zshift = (attr >> 16) & 0x1F;
-
-    vec4 fpos;
-    fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
-    fZ = float(vPosition.z << zshift) / 16777216.0;
-    fpos.w = float(vPosition.w) / 65536.0f;
-    fpos.xy *= fpos.w;
-
-    fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
-    fTexcoord = vec2(vTexcoord) / 16.0;
-    fPolygonAttr = vPolygonAttr;
-
-    gl_Position = fpos;
-}
-)";
-
-
-const char* kRenderFS_ZO = R"(
-
-void main()
-{
-    vec4 col = FinalColor();
-    if (col.a < 30.5/31) discard;
-
-    oColor = col;
-    oAttr.g = (fPolygonAttr.x >> 24) & 0x3F;
-}
-)";
-
-const char* kRenderFS_WO = R"(
-
-smooth in float fZ;
-
-void main()
-{
-    vec4 col = FinalColor();
-    if (col.a < 30.5/31) discard;
-
-    oColor = col;
-    oAttr.g = (fPolygonAttr.x >> 24) & 0x3F;
-    gl_FragDepth = fZ;
-}
-)";
-
-const char* kRenderFS_ZT = R"(
-
-void main()
-{
-    vec4 col = FinalColor();
-    if (col.a < 0.5/31) discard;
-    if (col.a >= 30.5/31) discard;
-
-    oColor = col;
-    oAttr.g = 0xFF;
-}
-)";
-
-const char* kRenderFS_WT = R"(
-
-smooth in float fZ;
-
-void main()
-{
-    vec4 col = FinalColor();
-    if (col.a < 0.5/31) discard;
-    if (col.a >= 30.5/31) discard;
-
-    oColor = col;
-    oAttr.g = 0xFF;
-    gl_FragDepth = fZ;
-}
-)";
-
-const char* kRenderFS_ZSM = R"(
-
-void main()
-{
-    oColor = vec4(0,0,0,1);
-    oAttr.g = 0xFF;
-    oAttr.b = 1;
-}
-)";
-
-const char* kRenderFS_WSM = R"(
-
-smooth in float fZ;
-
-void main()
-{
-    oColor = vec4(0,0,0,1);
-    oAttr.g = 0xFF;
-    oAttr.b = 1;
-    gl_FragDepth = fZ;
-}
-)";
-
-const char* kRenderFS_ZS = R"(
-
-layout(binding=2) uniform usampler2D iAttrTex;
-//layout(origin_upper_left) in vec4 gl_FragCoord;
-
-void main()
-{
-    vec4 col = FinalColor();
-    if (col.a < 0.5/31) discard;
-    if (col.a >= 30.5/31) discard;
-
-    uvec4 iAttr = texelFetch(iAttrTex, ivec2(gl_FragCoord.xy), 0);
-    if (iAttr.b != 1) discard;
-    if (iAttr.g == ((fPolygonAttr.x >> 24) & 0x3F)) discard;
-
-    oColor = col;
-}
-)";
-
-const char* kRenderFS_WS = R"(
-
-layout(binding=2) uniform usampler2D iAttrTex;
-//layout(origin_upper_left) in vec4 gl_FragCoord;
-
-smooth in float fZ;
-
-void main()
-{
-    vec4 col = FinalColor();
-    if (col.a < 0.5/31) discard;
-    if (col.a >= 30.5/31) discard;
-
-    uvec4 iAttr = texelFetch(iAttrTex, ivec2(gl_FragCoord.xy), 0);
-    if (iAttr.b != 1) discard;
-    if (iAttr.g == ((fPolygonAttr.x >> 24) & 0x3F)) discard;
-
-    oColor = col;
-    gl_FragDepth = fZ;
-}
-)";
-
 
 enum
 {
@@ -721,6 +97,7 @@ GLuint TexMemID;
 GLuint TexPalMemID;
 
 int ScaleFactor;
+bool Accelerated;
 int ScreenW, ScreenH;
 
 GLuint FramebufferTex[4];
@@ -968,9 +345,10 @@ void Reset()
     //
 }
 
-void SetScale(int scale)
+void SetDisplaySettings(int scale, bool accel)
 {
     ScaleFactor = scale;
+    Accelerated = accel;
 
     // TODO: antialiasing setting
     ScreenW = 256 << scale;
@@ -986,10 +364,12 @@ void SetScale(int scale)
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW/2, ScreenH/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 
     glBindBuffer(GL_PIXEL_PACK_BUFFER, PixelbufferID);
-    glBufferData(GL_PIXEL_PACK_BUFFER, ScreenW*ScreenH*4, NULL, GL_DYNAMIC_READ);
+    if (accel) glBufferData(GL_PIXEL_PACK_BUFFER, ScreenW*ScreenH*4, NULL, GL_DYNAMIC_READ);
+    else       glBufferData(GL_PIXEL_PACK_BUFFER, 256*192, NULL, GL_DYNAMIC_READ);
 
     if (Framebuffer) delete[] Framebuffer;
-    Framebuffer = new u32[ScreenW*ScreenH];
+    if (accel) Framebuffer = new u32[256*192];
+    else       Framebuffer = new u32[ScreenW*ScreenH];
 }
 
 
@@ -1533,5 +913,10 @@ u32* GetLine(int line)
     return &Framebuffer[stride * line];
 }
 
+void SetupAccelFrame()
+{
+    //
+}
+
 }
 }
diff --git a/src/GPU3D_OpenGL43_shaders.h b/src/GPU3D_OpenGL43_shaders.h
new file mode 100644
index 0000000..8a69566
--- /dev/null
+++ b/src/GPU3D_OpenGL43_shaders.h
@@ -0,0 +1,645 @@
+/*
+    Copyright 2016-2019 Arisotura
+
+    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 GPU3D_OPENGL43_SHADERS_H
+#define GPU3D_OPENGL43_SHADERS_H
+
+#define kShaderHeader "#version 430"
+
+
+const char* kClearVS = kShaderHeader R"(
+
+layout(location=0) in vec2 vPosition;
+
+layout(location=1) uniform uint uDepth;
+
+void main()
+{
+    float fdepth = (float(uDepth) / 8388608.0) - 1.0;
+    gl_Position = vec4(vPosition, fdepth, 1.0);
+}
+)";
+
+const char* kClearFS = kShaderHeader R"(
+
+layout(location=0) uniform uvec4 uColor;
+layout(location=2) uniform uint uOpaquePolyID;
+layout(location=3) uniform uint uFogFlag;
+
+layout(location=0) out vec4 oColor;
+layout(location=1) out uvec3 oAttr;
+
+void main()
+{
+    oColor = vec4(uColor).bgra / 31.0;
+    oAttr.r = 0;
+    oAttr.g = uOpaquePolyID;
+    oAttr.b = 0;
+}
+)";
+
+
+const char* kRenderVSCommon = R"(
+
+layout(std140, binding=0) uniform uConfig
+{
+    vec2 uScreenSize;
+    uint uDispCnt;
+    vec4 uToonColors[32];
+};
+
+layout(location=0) in uvec4 vPosition;
+layout(location=1) in uvec4 vColor;
+layout(location=2) in ivec2 vTexcoord;
+layout(location=3) in uvec3 vPolygonAttr;
+
+smooth out vec4 fColor;
+smooth out vec2 fTexcoord;
+flat out uvec3 fPolygonAttr;
+)";
+
+const char* kRenderFSCommon = R"(
+
+layout(binding=0) uniform usampler2D TexMem;
+layout(binding=1) uniform sampler2D TexPalMem;
+
+layout(std140, binding=0) uniform uConfig
+{
+    vec2 uScreenSize;
+    uint uDispCnt;
+    vec4 uToonColors[32];
+};
+
+smooth in vec4 fColor;
+smooth in vec2 fTexcoord;
+flat in uvec3 fPolygonAttr;
+
+layout(location=0) out vec4 oColor;
+layout(location=1) out uvec3 oAttr;
+
+int TexcoordWrap(int c, int maxc, uint mode)
+{
+    if ((mode & (1<<0)) != 0)
+    {
+        if ((mode & (1<<2)) != 0 && (c & maxc) != 0)
+            return (maxc-1) - (c & (maxc-1));
+        else
+            return (c & (maxc-1));
+    }
+    else
+        return clamp(c, 0, maxc-1);
+}
+
+vec4 TextureFetch_A3I5(ivec2 addr, ivec4 st, uint wrapmode)
+{
+    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
+    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
+
+    addr.x += ((st.y * st.z) + st.x);
+    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
+
+    pixel.a = (pixel.r & 0xE0);
+    pixel.a = (pixel.a >> 3) + (pixel.a >> 6);
+    pixel.r &= 0x1F;
+
+    addr.y = (addr.y << 3) + int(pixel.r);
+    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+
+    return vec4(color.rgb, float(pixel.a)/31.0);
+}
+
+vec4 TextureFetch_I2(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
+{
+    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
+    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
+
+    addr.x += ((st.y * st.z) + st.x) >> 2;
+    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
+    pixel.r >>= (2 * (st.x & 3));
+    pixel.r &= 0x03;
+
+    addr.y = (addr.y << 2) + int(pixel.r);
+    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+
+    return vec4(color.rgb, max(step(1,pixel.r),alpha0));
+}
+
+vec4 TextureFetch_I4(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
+{
+    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
+    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
+
+    addr.x += ((st.y * st.z) + st.x) >> 1;
+    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
+    if ((st.x & 1) != 0) pixel.r >>= 4;
+    else                 pixel.r &= 0x0F;
+
+    addr.y = (addr.y << 3) + int(pixel.r);
+    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+
+    return vec4(color.rgb, max(step(1,pixel.r),alpha0));
+}
+
+vec4 TextureFetch_I8(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
+{
+    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
+    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
+
+    addr.x += ((st.y * st.z) + st.x);
+    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
+
+    addr.y = (addr.y << 3) + int(pixel.r);
+    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+
+    return vec4(color.rgb, max(step(1,pixel.r),alpha0));
+}
+
+vec4 TextureFetch_Compressed(ivec2 addr, ivec4 st, uint wrapmode)
+{
+    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
+    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
+
+    addr.x += ((st.y & 0x3FC) * (st.z>>2)) + (st.x & 0x3FC) + (st.y & 0x3);
+    uvec4 p = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
+    uint val = (p.r >> (2 * (st.x & 0x3))) & 0x3;
+
+    int slot1addr = 0x20000 + ((addr.x & 0x1FFFC) >> 1);
+    if (addr.x >= 0x40000) slot1addr += 0x10000;
+
+    uint palinfo;
+    p = texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0);
+    palinfo = p.r;
+    slot1addr++;
+    p = texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0);
+    palinfo |= (p.r << 8);
+
+    addr.y = (addr.y << 3) + ((int(palinfo) & 0x3FFF) << 1);
+    palinfo >>= 14;
+
+    if (val == 0)
+    {
+        vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+        return vec4(color.rgb, 1.0);
+    }
+    else if (val == 1)
+    {
+        addr.y++;
+        vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+        return vec4(color.rgb, 1.0);
+    }
+    else if (val == 2)
+    {
+        if (palinfo == 1)
+        {
+            vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+            addr.y++;
+            vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+            return vec4((color0.rgb + color1.rgb) / 2.0, 1.0);
+        }
+        else if (palinfo == 3)
+        {
+            vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+            addr.y++;
+            vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+            return vec4((color0.rgb*5.0 + color1.rgb*3.0) / 8.0, 1.0);
+        }
+        else
+        {
+            addr.y += 2;
+            vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+            return vec4(color.rgb, 1.0);
+        }
+    }
+    else
+    {
+        if (palinfo == 2)
+        {
+            addr.y += 3;
+            vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+            return vec4(color.rgb, 1.0);
+        }
+        else if (palinfo == 3)
+        {
+            vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+            addr.y++;
+            vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+            return vec4((color0.rgb*3.0 + color1.rgb*5.0) / 8.0, 1.0);
+        }
+        else
+        {
+            return vec4(0.0);
+        }
+    }
+}
+
+vec4 TextureFetch_A5I3(ivec2 addr, ivec4 st, uint wrapmode)
+{
+    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
+    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
+
+    addr.x += ((st.y * st.z) + st.x);
+    uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
+
+    pixel.a = (pixel.r & 0xF8) >> 3;
+    pixel.r &= 0x07;
+
+    addr.y = (addr.y << 3) + int(pixel.r);
+    vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
+
+    return vec4(color.rgb, float(pixel.a)/31.0);
+}
+
+vec4 TextureFetch_Direct(ivec2 addr, ivec4 st, uint wrapmode)
+{
+    st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
+    st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
+
+    addr.x += ((st.y * st.z) + st.x) << 1;
+    uvec4 pixelL = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
+    addr.x++;
+    uvec4 pixelH = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
+
+    vec4 color;
+    color.r = float(pixelL.r & 0x1F) / 31.0;
+    color.g = float((pixelL.r >> 5) | ((pixelH.r & 0x03) << 3)) / 31.0;
+    color.b = float((pixelH.r & 0x7C) >> 2) / 31.0;
+    color.a = float(pixelH.r >> 7);
+
+    return color;
+}
+
+vec4 TextureLookup_Nearest(vec2 st)
+{
+    uint attr = fPolygonAttr.y;
+    uint paladdr = fPolygonAttr.z;
+
+    float alpha0;
+    if ((attr & (1<<29)) != 0) alpha0 = 0.0;
+    else                       alpha0 = 1.0;
+
+    int tw = 8 << int((attr >> 20) & 0x7);
+    int th = 8 << int((attr >> 23) & 0x7);
+    ivec4 st_full = ivec4(ivec2(st), tw, th);
+
+    ivec2 vramaddr = ivec2(int(attr & 0xFFFF) << 3, int(paladdr));
+    uint wrapmode = attr >> 16;
+
+    uint type = (attr >> 26) & 0x7;
+    if      (type == 5) return TextureFetch_Compressed(vramaddr, st_full, wrapmode);
+    else if (type == 2) return TextureFetch_I2        (vramaddr, st_full, wrapmode, alpha0);
+    else if (type == 3) return TextureFetch_I4        (vramaddr, st_full, wrapmode, alpha0);
+    else if (type == 4) return TextureFetch_I8        (vramaddr, st_full, wrapmode, alpha0);
+    else if (type == 1) return TextureFetch_A3I5      (vramaddr, st_full, wrapmode);
+    else if (type == 6) return TextureFetch_A5I3      (vramaddr, st_full, wrapmode);
+    else                return TextureFetch_Direct    (vramaddr, st_full, wrapmode);
+}
+
+vec4 TextureLookup_Linear(vec2 texcoord)
+{
+    ivec2 intpart = ivec2(texcoord);
+    vec2 fracpart = fract(texcoord);
+
+    uint attr = fPolygonAttr.y;
+    uint paladdr = fPolygonAttr.z;
+
+    float alpha0;
+    if ((attr & (1<<29)) != 0) alpha0 = 0.0;
+    else                       alpha0 = 1.0;
+
+    int tw = 8 << int((attr >> 20) & 0x7);
+    int th = 8 << int((attr >> 23) & 0x7);
+    ivec4 st_full = ivec4(intpart, tw, th);
+
+    ivec2 vramaddr = ivec2(int(attr & 0xFFFF) << 3, int(paladdr));
+    uint wrapmode = attr >> 16;
+
+    vec4 A, B, C, D;
+    uint type = (attr >> 26) & 0x7;
+    if (type == 5)
+    {
+        A = TextureFetch_Compressed(vramaddr, st_full                 , wrapmode);
+        B = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
+        C = TextureFetch_Compressed(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
+        D = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
+    }
+    else if (type == 2)
+    {
+        A = TextureFetch_I2(vramaddr, st_full                 , wrapmode, alpha0);
+        B = TextureFetch_I2(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
+        C = TextureFetch_I2(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
+        D = TextureFetch_I2(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
+    }
+    else if (type == 3)
+    {
+        A = TextureFetch_I4(vramaddr, st_full                 , wrapmode, alpha0);
+        B = TextureFetch_I4(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
+        C = TextureFetch_I4(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
+        D = TextureFetch_I4(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
+    }
+    else if (type == 4)
+    {
+        A = TextureFetch_I8(vramaddr, st_full                 , wrapmode, alpha0);
+        B = TextureFetch_I8(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
+        C = TextureFetch_I8(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
+        D = TextureFetch_I8(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
+    }
+    else if (type == 1)
+    {
+        A = TextureFetch_A3I5(vramaddr, st_full                 , wrapmode);
+        B = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
+        C = TextureFetch_A3I5(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
+        D = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
+    }
+    else if (type == 6)
+    {
+        A = TextureFetch_A5I3(vramaddr, st_full                 , wrapmode);
+        B = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
+        C = TextureFetch_A5I3(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
+        D = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
+    }
+    else
+    {
+        A = TextureFetch_Direct(vramaddr, st_full                 , wrapmode);
+        B = TextureFetch_Direct(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
+        C = TextureFetch_Direct(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
+        D = TextureFetch_Direct(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
+    }
+
+    float fx = fracpart.x;
+    vec4 AB;
+    if (A.a < (0.5/31.0) && B.a < (0.5/31.0))
+        AB = vec4(0);
+    else
+    {
+        //if (A.a < (0.5/31.0) || B.a < (0.5/31.0))
+        //    fx = step(0.5, fx);
+
+        AB = mix(A, B, fx);
+    }
+
+    fx = fracpart.x;
+    vec4 CD;
+    if (C.a < (0.5/31.0) && D.a < (0.5/31.0))
+        CD = vec4(0);
+    else
+    {
+        //if (C.a < (0.5/31.0) || D.a < (0.5/31.0))
+        //    fx = step(0.5, fx);
+
+        CD = mix(C, D, fx);
+    }
+
+    fx = fracpart.y;
+    vec4 ret;
+    if (AB.a < (0.5/31.0) && CD.a < (0.5/31.0))
+        ret = vec4(0);
+    else
+    {
+        //if (AB.a < (0.5/31.0) || CD.a < (0.5/31.0))
+        //    fx = step(0.5, fx);
+
+        ret = mix(AB, CD, fx);
+    }
+
+    return ret;
+}
+
+vec4 FinalColor()
+{
+    vec4 col;
+    vec4 vcol = fColor;
+    uint blendmode = (fPolygonAttr.x >> 4) & 0x3;
+
+    if (blendmode == 2)
+    {
+        if ((uDispCnt & (1<<1)) == 0)
+        {
+            // toon
+            vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
+            vcol.rgb = tooncolor;
+        }
+        else
+        {
+            // highlight
+            vcol.rgb = vcol.rrr;
+        }
+    }
+
+    if ((((fPolygonAttr.y >> 26) & 0x7) == 0) || ((uDispCnt & (1<<0)) == 0))
+    {
+        // no texture
+        col = vcol;
+    }
+    else
+    {
+        vec4 tcol = TextureLookup_Nearest(fTexcoord);
+        //vec4 tcol = TextureLookup_Linear(fTexcoord);
+
+        if ((blendmode & 1) != 0)
+        {
+            // decal
+            col.rgb = (tcol.rgb * tcol.a) + (vcol.rgb * (1.0-tcol.a));
+            col.a = vcol.a;
+        }
+        else
+        {
+            // modulate
+            col = vcol * tcol;
+        }
+    }
+
+    if (blendmode == 2)
+    {
+        if ((uDispCnt & (1<<1)) != 0)
+        {
+            vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
+            col.rgb = min(col.rgb + tooncolor, 1.0);
+        }
+    }
+
+    return col.bgra;
+}
+)";
+
+
+const char* kRenderVS_Z = R"(
+
+void main()
+{
+    uint attr = vPolygonAttr.x;
+    uint zshift = (attr >> 16) & 0x1F;
+
+    vec4 fpos;
+    fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
+    fpos.z = (float(vPosition.z << zshift) / 8388608.0) - 1.0;
+    fpos.w = float(vPosition.w) / 65536.0f;
+    fpos.xyz *= fpos.w;
+
+    fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
+    fTexcoord = vec2(vTexcoord) / 16.0;
+    fPolygonAttr = vPolygonAttr;
+
+    gl_Position = fpos;
+}
+)";
+
+const char* kRenderVS_W = R"(
+
+smooth out float fZ;
+
+void main()
+{
+    uint attr = vPolygonAttr.x;
+    uint zshift = (attr >> 16) & 0x1F;
+
+    vec4 fpos;
+    fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
+    fZ = float(vPosition.z << zshift) / 16777216.0;
+    fpos.w = float(vPosition.w) / 65536.0f;
+    fpos.xy *= fpos.w;
+
+    fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
+    fTexcoord = vec2(vTexcoord) / 16.0;
+    fPolygonAttr = vPolygonAttr;
+
+    gl_Position = fpos;
+}
+)";
+
+
+const char* kRenderFS_ZO = R"(
+
+void main()
+{
+    vec4 col = FinalColor();
+    if (col.a < 30.5/31) discard;
+
+    oColor = col;
+    oAttr.g = (fPolygonAttr.x >> 24) & 0x3F;
+}
+)";
+
+const char* kRenderFS_WO = R"(
+
+smooth in float fZ;
+
+void main()
+{
+    vec4 col = FinalColor();
+    if (col.a < 30.5/31) discard;
+
+    oColor = col;
+    oAttr.g = (fPolygonAttr.x >> 24) & 0x3F;
+    gl_FragDepth = fZ;
+}
+)";
+
+const char* kRenderFS_ZT = R"(
+
+void main()
+{
+    vec4 col = FinalColor();
+    if (col.a < 0.5/31) discard;
+    if (col.a >= 30.5/31) discard;
+
+    oColor = col;
+    oAttr.g = 0xFF;
+}
+)";
+
+const char* kRenderFS_WT = R"(
+
+smooth in float fZ;
+
+void main()
+{
+    vec4 col = FinalColor();
+    if (col.a < 0.5/31) discard;
+    if (col.a >= 30.5/31) discard;
+
+    oColor = col;
+    oAttr.g = 0xFF;
+    gl_FragDepth = fZ;
+}
+)";
+
+const char* kRenderFS_ZSM = R"(
+
+void main()
+{
+    oColor = vec4(0,0,0,1);
+    oAttr.g = 0xFF;
+    oAttr.b = 1;
+}
+)";
+
+const char* kRenderFS_WSM = R"(
+
+smooth in float fZ;
+
+void main()
+{
+    oColor = vec4(0,0,0,1);
+    oAttr.g = 0xFF;
+    oAttr.b = 1;
+    gl_FragDepth = fZ;
+}
+)";
+
+const char* kRenderFS_ZS = R"(
+
+layout(binding=2) uniform usampler2D iAttrTex;
+//layout(origin_upper_left) in vec4 gl_FragCoord;
+
+void main()
+{
+    vec4 col = FinalColor();
+    if (col.a < 0.5/31) discard;
+    if (col.a >= 30.5/31) discard;
+
+    uvec4 iAttr = texelFetch(iAttrTex, ivec2(gl_FragCoord.xy), 0);
+    if (iAttr.b != 1) discard;
+    if (iAttr.g == ((fPolygonAttr.x >> 24) & 0x3F)) discard;
+
+    oColor = col;
+}
+)";
+
+const char* kRenderFS_WS = R"(
+
+layout(binding=2) uniform usampler2D iAttrTex;
+//layout(origin_upper_left) in vec4 gl_FragCoord;
+
+smooth in float fZ;
+
+void main()
+{
+    vec4 col = FinalColor();
+    if (col.a < 0.5/31) discard;
+    if (col.a >= 30.5/31) discard;
+
+    uvec4 iAttr = texelFetch(iAttrTex, ivec2(gl_FragCoord.xy), 0);
+    if (iAttr.b != 1) discard;
+    if (iAttr.g == ((fPolygonAttr.x >> 24) & 0x3F)) discard;
+
+    oColor = col;
+    gl_FragDepth = fZ;
+}
+)";
+
+#endif // GPU3D_OPENGL43_SHADERS_H
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index ac5cd93..20283d3 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -138,7 +138,7 @@ void Reset()
     SetupRenderThread();
 }
 
-void SetScale(int scale)
+void SetDisplaySettings(int scale, bool accel)
 {
     printf("SOFT RENDERER SCALE FACTOR: TODO!!!\n");
 }
@@ -2122,5 +2122,10 @@ u32* GetLine(int line)
     return &ColorBuffer[(line * ScanlineWidth) + FirstPixelOffset];
 }
 
+void SetupAccelFrame()
+{
+    // TODO
+}
+
 }
 }
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp
index 47f5f13..b77d67f 100644
--- a/src/libui_sdl/main.cpp
+++ b/src/libui_sdl/main.cpp
@@ -240,8 +240,8 @@ void GLDrawing_DrawScreen()
         x1 = TopScreenRect.X + TopScreenRect.Width;
         y1 = TopScreenRect.Y + TopScreenRect.Height;
 
-        scwidth = 256 << ScreenScale[0];
-        scheight = 192 << ScreenScale[0];
+        scwidth = 256;// << ScreenScale[0];
+        scheight = 192;// << ScreenScale[0];
 
         switch (ScreenRotation)
         {
@@ -286,8 +286,8 @@ void GLDrawing_DrawScreen()
         x1 = BottomScreenRect.X + BottomScreenRect.Width;
         y1 = BottomScreenRect.Y + BottomScreenRect.Height;
 
-        scwidth = 256 << ScreenScale[1];
-        scheight = 192 << ScreenScale[1];
+        scwidth = 256;// << ScreenScale[1];
+        scheight = 192;// << ScreenScale[1];
 
         switch (ScreenRotation)
         {
@@ -349,9 +349,13 @@ void GLDrawing_DrawScreen()
     int frontbuf = GPU::FrontBuffer;
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture);
-    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256<<ScreenScale[0], 192<<ScreenScale[0], GL_RGBA_INTEGER,
+    /*glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256<<ScreenScale[0], 192<<ScreenScale[0], GL_RGBA_INTEGER,
                     GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 768, 256<<ScreenScale[1], 192<<ScreenScale[1], GL_RGBA_INTEGER,
+                    GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);*/
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3, 192, GL_RGBA_INTEGER,
+                    GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 768, 256*3, 192, GL_RGBA_INTEGER,
                     GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
 
     glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
@@ -633,7 +637,8 @@ int EmuThreadFunc(void* burp)
     ScreenScale[0] = ScreenScale[2];
     ScreenScale[1] = ScreenScale[2];
 
-    int lastscale[2] = {-1, -1};
+    int lastscale[2] = {ScreenScale[0], ScreenScale[1]};
+    GPU::SetDisplaySettings(ScreenScale[0], ScreenScale[1], false);
 
     Touching = false;
     KeyInputMask = 0xFFF;
@@ -782,7 +787,7 @@ int EmuThreadFunc(void* burp)
             if (ScreenScale[0] != lastscale[0] ||
                 ScreenScale[1] != lastscale[1])
             {
-                GPU::SetFramebufferScale(ScreenScale[0], ScreenScale[1]);
+                GPU::SetDisplaySettings(ScreenScale[0], ScreenScale[1], false);
                 ScreenDrawInited = false;
             }
 
-- 
cgit v1.2.3


From c835b24f07a317ea435b742ec2fae12dc619c01b Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Tue, 21 May 2019 14:53:22 +0200
Subject: modify libui GL support so that it will be compatible with GTK

---
 melonDS.cbp                          |  4 +--
 src/libui_sdl/DlgInputConfig.cpp     |  2 +-
 src/libui_sdl/libui/ui.h             | 11 +++++--
 src/libui_sdl/libui/windows/area.cpp | 56 ++++++++++++++++++++++++++++++++++--
 src/libui_sdl/libui/windows/area.hpp |  5 ++++
 src/libui_sdl/libui/windows/gl.cpp   | 33 ++++++++++-----------
 src/libui_sdl/main.cpp               | 37 ++++++++++--------------
 7 files changed, 101 insertions(+), 47 deletions(-)

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index 0bdac7f..bb4d8c7 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -106,8 +106,8 @@
 		<Unit filename="src/GPU2D.h" />
 		<Unit filename="src/GPU3D.cpp" />
 		<Unit filename="src/GPU3D.h" />
-		<Unit filename="src/GPU3D_OpenGL43.cpp" />
-		<Unit filename="src/GPU3D_OpenGL43_shaders.h" />
+		<Unit filename="src/GPU3D_OpenGL.cpp" />
+		<Unit filename="src/GPU3D_OpenGL_shaders.h" />
 		<Unit filename="src/GPU3D_Soft.cpp" />
 		<Unit filename="src/NDS.cpp" />
 		<Unit filename="src/NDS.h" />
diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp
index 4c464f1..513bd90 100644
--- a/src/libui_sdl/DlgInputConfig.cpp
+++ b/src/libui_sdl/DlgInputConfig.cpp
@@ -432,7 +432,7 @@ void Open(int type)
         uiLabel* dummy = uiNewLabel("");
         uiBoxAppend(in_ctrl, uiControl(dummy), 1);
 
-        dlg->keypresscatcher = uiNewArea(&dlg->areahandler, 0);
+        dlg->keypresscatcher = uiNewArea(&dlg->areahandler);
         uiControl(dlg->keypresscatcher)->UserData = dlg;
         uiBoxAppend(in_ctrl, uiControl(dlg->keypresscatcher), 0);
 
diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h
index 2641f30..09092a1 100644
--- a/src/libui_sdl/libui/ui.h
+++ b/src/libui_sdl/libui/ui.h
@@ -326,6 +326,10 @@ _UI_ENUM(uiWindowResizeEdge) {
 	// TODO way to bring up the system menu instead?
 };
 
+#define uiGLVersion(major, minor)  ((major) | ((minor)<<16))
+#define uiGLVerMajor(ver)          ((ver) & 0xFFFF)
+#define uiGLVerMinor(ver)          ((ver) >> 16)
+
 #define uiArea(this) ((uiArea *) (this))
 // TODO give a better name
 // TODO document the types of width and height
@@ -341,7 +345,8 @@ _UI_EXTERN void uiAreaScrollTo(uiArea *a, double x, double y, double width, doub
 _UI_EXTERN void uiAreaBeginUserWindowMove(uiArea *a);
 _UI_EXTERN void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge);
 _UI_EXTERN void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b);
-_UI_EXTERN uiArea *uiNewArea(uiAreaHandler *ah, int opengl);
+_UI_EXTERN uiArea *uiNewArea(uiAreaHandler *ah);
+_UI_EXTERN uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions);
 _UI_EXTERN uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height);
 
 struct uiAreaDrawParams {
@@ -604,9 +609,9 @@ _UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayou
 
 typedef struct uiGLContext uiGLContext;
 
-_UI_EXTERN uiGLContext *uiGLNewContext(uiControl* c, int vermajor, int verminor);
-_UI_EXTERN void uiGLFreeContext(uiGLContext* ctx);
+_UI_EXTERN uiGLContext *uiAreaGetGLContext(uiArea* a);
 _UI_EXTERN void uiGLMakeContextCurrent(uiGLContext* ctx);
+_UI_EXTERN unsigned int uiGLGetVersion(uiGLContext* ctx);
 _UI_EXTERN void *uiGLGetProcAddress(const char* proc);
 _UI_EXTERN void uiGLSwapBuffers(uiGLContext* ctx);
 
diff --git a/src/libui_sdl/libui/windows/area.cpp b/src/libui_sdl/libui/windows/area.cpp
index 99c843e..72d5145 100644
--- a/src/libui_sdl/libui/windows/area.cpp
+++ b/src/libui_sdl/libui/windows/area.cpp
@@ -61,7 +61,15 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
 
 // control implementation
 
-uiWindowsControlAllDefaults(uiArea)
+uiWindowsControlAllDefaultsExceptDestroy(uiArea)
+
+static void uiAreaDestroy(uiControl *c)
+{
+    uiArea* a = uiArea(c);
+    if (a->openGL && a->glcontext) freeGLContext(a->glcontext);
+    uiWindowsEnsureDestroyWindow(a->hwnd);
+    uiFreeControl(c);
+}
 
 static void uiAreaMinimumSize(uiWindowsControl *c, int *width, int *height)
 {
@@ -181,7 +189,7 @@ void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b)
 }
 
 
-uiArea *uiNewArea(uiAreaHandler *ah, int opengl)
+uiArea *uiNewArea(uiAreaHandler *ah)
 {
 	uiArea *a;
 
@@ -203,7 +211,49 @@ uiArea *uiNewArea(uiAreaHandler *ah, int opengl)
 
     uiAreaSetBackgroundColor(a, -1, -1, -1);
 
-    a->openGL = opengl;
+    a->openGL = 0;
+
+	return a;
+}
+
+uiGLContext *uiAreaGetGLContext(uiArea* a)
+{
+    if (!a->openGL) userbug("trying to get GL context from non-GL area");
+
+    return a->glcontext;
+}
+
+uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions)
+{
+	uiArea *a;
+
+	uiWindowsNewControl(uiArea, a);
+
+	a->width = -1;
+	a->height = -1;
+
+	a->ah = ah;
+	a->scrolling = FALSE;
+	clickCounterReset(&(a->cc));
+
+	// a->hwnd is assigned in areaWndProc()
+	uiWindowsEnsureCreateControlHWND(0,
+		areaClass, L"",
+		0,
+		hInstance, a,
+		FALSE);
+
+    uiAreaSetBackgroundColor(a, -1, -1, -1);
+
+    a->openGL = 1;
+
+    for (int i = 0; req_versions[i]; i++)
+    {
+        int major = uiGLVerMajor(req_versions[i]);
+        int minor = uiGLVerMinor(req_versions[i]);
+        a->glcontext = createGLContext(a, major, minor);
+        if (a->glcontext) break;
+    }
 
 	return a;
 }
diff --git a/src/libui_sdl/libui/windows/area.hpp b/src/libui_sdl/libui/windows/area.hpp
index f8abd4f..cfc45a4 100644
--- a/src/libui_sdl/libui/windows/area.hpp
+++ b/src/libui_sdl/libui/windows/area.hpp
@@ -29,6 +29,7 @@ struct uiArea {
 	int bgR, bgG, bgB;
 
 	int openGL;
+	uiGLContext* glcontext;
 
 	ID2D1HwndRenderTarget *rt;
 };
@@ -49,3 +50,7 @@ extern BOOL areaDoEvents(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRE
 extern void loadAreaSize(uiArea *a, double *width, double *height);
 extern void pixelsToDIP(uiArea *a, double *x, double *y);
 extern void dipToPixels(uiArea *a, double *x, double *y);
+
+// gl.cpp
+extern uiGLContext* createGLContext(uiArea* a, int vermajor, int verminor);
+extern void freeGLContext(uiGLContext* c);
diff --git a/src/libui_sdl/libui/windows/gl.cpp b/src/libui_sdl/libui/windows/gl.cpp
index 832a2e5..1e3732c 100644
--- a/src/libui_sdl/libui/windows/gl.cpp
+++ b/src/libui_sdl/libui/windows/gl.cpp
@@ -1,39 +1,31 @@
 // 31 march 2019
 #include "uipriv_windows.hpp"
+#include "area.hpp"
 
 #include <GL/gl.h>
 #include <GL/wglext.h>
 
 struct uiGLContext
 {
-    uiControl* c;
+    uiArea* a;
 
     HWND hwnd;
     HDC dc;
     HGLRC rc;
+
+    unsigned int version;
 };
 
 
-uiGLContext* uiGLNewContext(uiControl* c, int vermajor, int verminor)
+uiGLContext* createGLContext(uiArea* a, int vermajor, int verminor)
 {
     uiGLContext* ctx;
     BOOL res;
 
     ctx = uiNew(uiGLContext);
 
-    ctx->c = c;
-    if (c)
-    {
-        ctx->hwnd = (HWND)c->Handle(c); // welp
-    }
-    else
-    {
-        // windowless context
-        //ctx->hwnd = GetDesktopWindow();
-        // nope.
-        uiFree(ctx);
-        return NULL;
-    }
+    ctx->a = a;
+    ctx->hwnd = a->hwnd;
 
     PIXELFORMATDESCRIPTOR pfd;
     memset(&pfd, 0, sizeof(pfd));
@@ -103,6 +95,7 @@ uiGLContext* uiGLNewContext(uiControl* c, int vermajor, int verminor)
             return NULL;
         }
 
+        ctx->version = uiGLVersion(vermajor, verminor);
         ctx->rc = rc_better;
         wglMakeCurrent(ctx->dc, ctx->rc);
     }
@@ -110,8 +103,9 @@ uiGLContext* uiGLNewContext(uiControl* c, int vermajor, int verminor)
     return ctx;
 }
 
-void uiGLFreeContext(uiGLContext* ctx)
+void freeGLContext(uiGLContext* ctx)
 {
+    if (ctx == NULL) return;
     wglMakeCurrent(NULL, NULL);
     wglDeleteContext(ctx->rc);
     ReleaseDC(ctx->hwnd, ctx->dc);
@@ -130,6 +124,12 @@ void uiGLMakeContextCurrent(uiGLContext* ctx)
     int res = wglMakeCurrent(ctx->dc, ctx->rc);
 }
 
+unsigned int uiGLGetVersion(uiGLContext* ctx)
+{
+    if (ctx == NULL) return 0;
+    return ctx->version;
+}
+
 void *uiGLGetProcAddress(const char* proc)
 {
     return (void*)wglGetProcAddress(proc);
@@ -137,5 +137,6 @@ void *uiGLGetProcAddress(const char* proc)
 
 void uiGLSwapBuffers(uiGLContext* ctx)
 {
+    if (ctx == NULL) return;
     SwapBuffers(ctx->dc);
 }
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp
index c68f323..b499da7 100644
--- a/src/libui_sdl/main.cpp
+++ b/src/libui_sdl/main.cpp
@@ -64,6 +64,9 @@ char* EmuDirectory;
 
 uiWindow* MainWindow;
 uiArea* MainDrawArea;
+uiAreaHandler MainDrawAreaHandler;
+
+const u32 kGLVersions[] = {uiGLVersion(3,1), 0};
 uiGLContext* GLContext;
 
 int WindowWidth, WindowHeight;
@@ -1792,7 +1795,7 @@ void OnOpenHotkeyConfig(uiMenuItem* item, uiWindow* window, void* blarg)
 {
     DlgInputConfig::Open(1);
 }
-uiAreaHandler eeareahandler;
+
 void OnOpenVideoSettings(uiMenuItem* item, uiWindow* window, void* blarg)
 {
     //DlgVideoSettings::Open();
@@ -1805,25 +1808,17 @@ void OnOpenVideoSettings(uiMenuItem* item, uiWindow* window, void* blarg)
     GPU3D::GLRenderer::DeInit();
     GLDrawing_DeInit();
     uiGLMakeContextCurrent(NULL);
-    uiGLFreeContext(GLContext);
 
     uiWindowSetChild(MainWindow, NULL);
     uiControlDestroy(uiControl(MainDrawArea));
 
 
-    eeareahandler.Draw = OnAreaDraw;
-    eeareahandler.MouseEvent = OnAreaMouseEvent;
-    eeareahandler.MouseCrossed = OnAreaMouseCrossed;
-    eeareahandler.DragBroken = OnAreaDragBroken;
-    eeareahandler.KeyEvent = OnAreaKeyEvent;
-    eeareahandler.Resize = OnAreaResize;
-
-    MainDrawArea = uiNewArea(&eeareahandler, 1);
+    MainDrawArea = uiNewGLArea(&MainDrawAreaHandler, kGLVersions);
     uiWindowSetChild(MainWindow, uiControl(MainDrawArea));
     uiControlSetMinSize(uiControl(MainDrawArea), 256, 384);
     uiAreaSetBackgroundColor(MainDrawArea, 0, 0, 0);
     //uiControlShow(uiControl(MainDrawArea));
-    GLContext = uiGLNewContext(uiControl(MainDrawArea), 3, 1);
+    GLContext = uiAreaGetGLContext(MainDrawArea);
 
     uiGLMakeContextCurrent(GLContext);
     GLDrawing_Init();
@@ -2343,16 +2338,16 @@ int main(int argc, char** argv)
     uiMenuItemDisable(MenuItem_Reset);
     uiMenuItemDisable(MenuItem_Stop);
 
-    uiAreaHandler areahandler;
-    areahandler.Draw = OnAreaDraw;
-    areahandler.MouseEvent = OnAreaMouseEvent;
-    areahandler.MouseCrossed = OnAreaMouseCrossed;
-    areahandler.DragBroken = OnAreaDragBroken;
-    areahandler.KeyEvent = OnAreaKeyEvent;
-    areahandler.Resize = OnAreaResize;
+    MainDrawAreaHandler.Draw = OnAreaDraw;
+    MainDrawAreaHandler.MouseEvent = OnAreaMouseEvent;
+    MainDrawAreaHandler.MouseCrossed = OnAreaMouseCrossed;
+    MainDrawAreaHandler.DragBroken = OnAreaDragBroken;
+    MainDrawAreaHandler.KeyEvent = OnAreaKeyEvent;
+    MainDrawAreaHandler.Resize = OnAreaResize;
 
     ScreenDrawInited = false;
-    MainDrawArea = uiNewArea(&areahandler, 1);
+    //MainDrawArea = uiNewArea(&MainDrawAreaHandler);
+    MainDrawArea = uiNewGLArea(&MainDrawAreaHandler, kGLVersions);
     uiWindowSetChild(MainWindow, uiControl(MainDrawArea));
     uiControlSetMinSize(uiControl(MainDrawArea), 256, 384);
     uiAreaSetBackgroundColor(MainDrawArea, 0, 0, 0); // TODO: make configurable?
@@ -2383,7 +2378,7 @@ int main(int argc, char** argv)
     OnSetScreenRotation(MenuItem_ScreenRot[ScreenRotation], MainWindow, (void*)&kScreenRot[ScreenRotation]);
 
     // TODO: fail gracefully, support older OpenGL, etc
-    GLContext = uiGLNewContext(uiControl(MainDrawArea), 3, 1); // haw haw haw
+    GLContext = uiAreaGetGLContext(MainDrawArea);
     uiGLMakeContextCurrent(GLContext);
 
     void* testor = uiGLGetProcAddress("glUseProgram");
@@ -2472,8 +2467,6 @@ int main(int argc, char** argv)
 
     if (MicWavBuffer) delete[] MicWavBuffer;
 
-    uiGLFreeContext(GLContext);
-
     Config::ScreenRotation = ScreenRotation;
     Config::ScreenGap = ScreenGap;
     Config::ScreenLayout = ScreenLayout;
-- 
cgit v1.2.3


From 3e760a2e34990e9f0e416550091783a7d6695e60 Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Fri, 31 May 2019 22:03:59 +0200
Subject: add LTO to Release build under Codeblocks

---
 melonDS.cbp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index bb4d8c7..b517353 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -30,6 +30,7 @@
 				<Compiler>
 					<Add option="-O3" />
 					<Add option="-m64" />
+					<Add option="-flto" />
 					<Add option="-D_FILE_OFFSET_BITS=64" />
 				</Compiler>
 				<Linker>
-- 
cgit v1.2.3


From 6de19645f8fdd309cdf9f53d846b70f45ed66e62 Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Sun, 2 Jun 2019 14:57:59 +0200
Subject: fix potential crash when running the software renderer (oops)

---
 melonDS.cbp   | 2 ++
 src/GPU2D.cpp | 8 +++++---
 2 files changed, 7 insertions(+), 3 deletions(-)

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index b517353..3003b84 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -143,6 +143,8 @@
 		<Unit filename="src/libui_sdl/LAN_PCap.h" />
 		<Unit filename="src/libui_sdl/LAN_Socket.cpp" />
 		<Unit filename="src/libui_sdl/LAN_Socket.h" />
+		<Unit filename="src/libui_sdl/OSD.cpp" />
+		<Unit filename="src/libui_sdl/OSD.h" />
 		<Unit filename="src/libui_sdl/Platform.cpp" />
 		<Unit filename="src/libui_sdl/PlatformConfig.cpp" />
 		<Unit filename="src/libui_sdl/PlatformConfig.h" />
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp
index 212372c..c51b252 100644
--- a/src/GPU2D.cpp
+++ b/src/GPU2D.cpp
@@ -882,10 +882,12 @@ void GPU2D::VBlankEnd()
     OBJMosaicY = 0;
     OBJMosaicYMax = OBJMosaicSize[1];
 
-    // TODO: make optional
-    if ((Num == 0) && (CaptureCnt & (1<<31)) && (((CaptureCnt >> 29) & 0x3) != 1))
+    if (GPU3D::Renderer != 0)
     {
-        GPU3D::GLRenderer::PrepareCaptureFrame();
+        if ((Num == 0) && (CaptureCnt & (1<<31)) && (((CaptureCnt >> 29) & 0x3) != 1))
+        {
+            GPU3D::GLRenderer::PrepareCaptureFrame();
+        }
     }
 }
 
-- 
cgit v1.2.3


From 0aca7a68281150f1f0ec9f596f838dccdae55b72 Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Sun, 2 Jun 2019 15:29:37 +0200
Subject: I guess adding font.h can't hurt

---
 melonDS.cbp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'melonDS.cbp')

diff --git a/melonDS.cbp b/melonDS.cbp
index 3003b84..0af2f4a 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -148,6 +148,7 @@
 		<Unit filename="src/libui_sdl/Platform.cpp" />
 		<Unit filename="src/libui_sdl/PlatformConfig.cpp" />
 		<Unit filename="src/libui_sdl/PlatformConfig.h" />
+		<Unit filename="src/libui_sdl/font.h" />
 		<Unit filename="src/libui_sdl/libui/common/areaevents.c">
 			<Option compilerVar="CC" />
 		</Unit>
-- 
cgit v1.2.3