aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl')
-rw-r--r--src/libui_sdl/CMakeLists.txt1
-rw-r--r--src/libui_sdl/DlgInputConfig.cpp70
-rw-r--r--src/libui_sdl/OSD.cpp423
-rw-r--r--src/libui_sdl/OSD.h35
-rw-r--r--src/libui_sdl/PlatformConfig.cpp14
-rw-r--r--src/libui_sdl/PlatformConfig.h3
-rw-r--r--src/libui_sdl/font.h135
-rw-r--r--src/libui_sdl/libui/ui.h2
-rw-r--r--src/libui_sdl/libui/unix/draw.c4
-rw-r--r--src/libui_sdl/libui/windows/draw.cpp5
-rw-r--r--src/libui_sdl/main.cpp145
-rw-r--r--src/libui_sdl/main_shaders.h51
12 files changed, 851 insertions, 37 deletions
diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt
index e9a54e2..63e9f48 100644
--- a/src/libui_sdl/CMakeLists.txt
+++ b/src/libui_sdl/CMakeLists.txt
@@ -11,6 +11,7 @@ SET(SOURCES_LIBUI
DlgInputConfig.cpp
DlgVideoSettings.cpp
DlgWifiSettings.cpp
+ OSD.cpp
)
option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON)
diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp
index 98cdf8c..392eb44 100644
--- a/src/libui_sdl/DlgInputConfig.cpp
+++ b/src/libui_sdl/DlgInputConfig.cpp
@@ -49,6 +49,7 @@ typedef struct
int pollid;
uiButton* pollbtn;
+ SDL_TimerID timer;
} InputDlgData;
@@ -58,12 +59,27 @@ char dskeylabels[12][8] = {"A:", "B:", "Select:", "Start:", "Right:", "Left:", "
int identity[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
-char hotkeylabels[HK_MAX][32] = {"Close/open lid:", "Microphone:"};
+char hotkeylabels[HK_MAX][32] = {"Close/open lid:", "Microphone:", "Fast forward:", "Fast forward (toggle):"};
int openedmask;
InputDlgData inputdlg[2];
+void KeyMappingName(int id, char* str)
+{
+ if (id < 0)
+ {
+ strcpy(str, "None");
+ return;
+ }
+
+ char* keyname = uiKeyName(id);
+ strncpy(str, keyname, 31);
+ uiFreeText(keyname);
+
+ str[31] = '\0';
+}
+
void JoyMappingName(int id, char* str)
{
if (id < 0)
@@ -134,7 +150,7 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
return 1;
}
- char keyname[16];
+ char keyname[32];
JoyMappingName(dlg->joymap[id], keyname);
uiButtonSetText(dlg->pollbtn, keyname);
uiControlEnable(uiControl(dlg->pollbtn));
@@ -150,12 +166,17 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
{
// set key.
if (evt->Scancode != 0x1) // ESC
- dlg->keymap[dlg->pollid] = evt->Scancode;
+ {
+ if (evt->Scancode == 0xE) // backspace
+ dlg->keymap[dlg->pollid] = -1;
+ else
+ dlg->keymap[dlg->pollid] = evt->Scancode;
+ }
- char* keyname = uiKeyName(dlg->keymap[dlg->pollid]);
+ char keyname[32];
+ KeyMappingName(dlg->keymap[dlg->pollid], keyname);
uiButtonSetText(dlg->pollbtn, keyname);
uiControlEnable(uiControl(dlg->pollbtn));
- uiFreeText(keyname);
dlg->pollid = -1;
@@ -170,7 +191,7 @@ void FinishJoyMapping(void* param)
InputDlgData* dlg = (InputDlgData*)param;
int id = dlg->pollid & 0xFF;
- char keyname[16];
+ char keyname[32];
JoyMappingName(dlg->joymap[id], keyname);
uiButtonSetText(dlg->pollbtn, keyname);
uiControlEnable(uiControl(dlg->pollbtn));
@@ -184,14 +205,27 @@ Uint32 JoyPoll(Uint32 interval, void* param)
{
InputDlgData* dlg = (InputDlgData*)param;
- if (dlg->pollid < 0x100) return 0;
+ if (dlg->pollid < 0x100)
+ {
+ dlg->timer = 0;
+ return 0;
+ }
+
int id = dlg->pollid & 0xFF;
- if (id > 12) return 0;
+ if (id > 12)
+ {
+ dlg->timer = 0;
+ return 0;
+ }
SDL_JoystickUpdate();
SDL_Joystick* joy = Joystick;
- if (!joy) return 0;
+ if (!joy)
+ {
+ dlg->timer = 0;
+ return 0;
+ }
int nbuttons = SDL_JoystickNumButtons(joy);
for (int i = 0; i < nbuttons; i++)
@@ -200,6 +234,7 @@ Uint32 JoyPoll(Uint32 interval, void* param)
{
dlg->joymap[id] = i;
uiQueueMain(FinishJoyMapping, dlg);
+ dlg->timer = 0;
return 0;
}
}
@@ -214,10 +249,11 @@ Uint32 JoyPoll(Uint32 interval, void* param)
dlg->joymap[id] = 0x100 | blackhat;
uiQueueMain(FinishJoyMapping, dlg);
+ dlg->timer = 0;
return 0;
}
- return 100;
+ return interval;
}
@@ -262,7 +298,7 @@ void OnJoyStartConfig(uiButton* btn, void* data)
uiButtonSetText(btn, "[press button]");
uiControlDisable(uiControl(btn));
- SDL_AddTimer(100, JoyPoll, dlg);
+ dlg->timer = SDL_AddTimer(100, JoyPoll, dlg);
uiControlSetFocus(uiControl(dlg->keypresscatcher));
}
@@ -271,6 +307,7 @@ int OnCloseWindow(uiWindow* window, void* blarg)
{
InputDlgData* dlg = (InputDlgData*)(uiControl(window)->UserData);
openedmask &= ~(1 << dlg->type);
+ if (dlg->timer) SDL_RemoveTimer(dlg->timer);
return 1;
}
@@ -292,6 +329,7 @@ void OnCancel(uiButton* btn, void* data)
uiControlDestroy(uiControl(dlg->win));
openedmask &= ~(1 << dlg->type);
+ if (dlg->timer) SDL_RemoveTimer(dlg->timer);
}
void OnOk(uiButton* btn, void* data)
@@ -313,6 +351,7 @@ void OnOk(uiButton* btn, void* data)
uiControlDestroy(uiControl(dlg->win));
openedmask &= ~(1 << dlg->type);
+ if (dlg->timer) SDL_RemoveTimer(dlg->timer);
}
void Open(int type)
@@ -330,6 +369,7 @@ void Open(int type)
dlg->type = type;
dlg->pollid = -1;
+ dlg->timer = 0;
if (type == 0)
{
@@ -386,15 +426,14 @@ void Open(int type)
uiGridAppend(b_key, uiControl(label), 0, i, 1, 1, 1, uiAlignStart, 1, uiAlignCenter);
uiControlSetMinSize(uiControl(label), width, 1);
- char* keyname = uiKeyName(dlg->keymap[j]);
+ char keyname[32];
+ KeyMappingName(dlg->keymap[j], keyname);
uiButton* btn = uiNewButton(keyname);
uiControl(btn)->UserData = dlg;
uiGridAppend(b_key, uiControl(btn), 1, i, 1, 1, 1, uiAlignFill, 1, uiAlignCenter);
uiButtonOnClicked(btn, OnKeyStartConfig, (type==0) ? &dskeyorder[i] : &identity[i]);
uiControlSetMinSize(uiControl(btn), width, 1);
-
- uiFreeText(keyname);
}
uiGroup* g_joy = uiNewGroup("Joystick");
@@ -410,7 +449,7 @@ void Open(int type)
uiGridAppend(b_joy, uiControl(label), 0, i, 1, 1, 1, uiAlignStart, 1, uiAlignCenter);
uiControlSetMinSize(uiControl(label), width, 1);
- char keyname[16];
+ char keyname[32];
JoyMappingName(dlg->joymap[j], keyname);
uiButton* btn = uiNewButton(keyname);
@@ -456,6 +495,7 @@ void Close(int type)
uiControlDestroy(uiControl(inputdlg[type].win));
openedmask &= ~(1<<type);
+ if (inputdlg[type].timer) SDL_RemoveTimer(inputdlg[type].timer);
}
}
diff --git a/src/libui_sdl/OSD.cpp b/src/libui_sdl/OSD.cpp
new file mode 100644
index 0000000..c8d5f83
--- /dev/null
+++ b/src/libui_sdl/OSD.cpp
@@ -0,0 +1,423 @@
+/*
+ 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 <stdio.h>
+#include <string.h>
+#include <deque>
+#include <SDL2/SDL.h>
+#include "../types.h"
+
+#include "libui/ui.h"
+#include "../OpenGLSupport.h"
+
+#include "OSD.h"
+#include "font.h"
+
+extern int WindowWidth, WindowHeight;
+
+namespace OSD
+{
+
+const u32 kOSDMargin = 6;
+
+struct Item
+{
+ Uint32 Timestamp;
+ char Text[256];
+ u32 Color;
+
+ u32 Width, Height;
+ u32* Bitmap;
+
+ bool DrawBitmapLoaded;
+ uiDrawBitmap* DrawBitmap;
+
+ bool GLTextureLoaded;
+ GLuint GLTexture;
+
+};
+
+std::deque<Item> ItemQueue;
+
+GLint uOSDPos, uOSDSize;
+GLuint OSDVertexArray;
+GLuint OSDVertexBuffer;
+
+volatile bool Rendering;
+
+
+bool Init(bool opengl)
+{
+ if (opengl)
+ {
+ GLuint prog; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&prog);
+ uOSDPos = glGetUniformLocation(prog, "uOSDPos");
+ uOSDSize = glGetUniformLocation(prog, "uOSDSize");
+
+ float vertices[6*2] =
+ {
+ 0, 0,
+ 1, 1,
+ 1, 0,
+ 0, 0,
+ 0, 1,
+ 1, 1
+ };
+
+ glGenBuffers(1, &OSDVertexBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ glGenVertexArrays(1, &OSDVertexArray);
+ glBindVertexArray(OSDVertexArray);
+ glEnableVertexAttribArray(0); // position
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
+ }
+
+ return true;
+}
+
+void DeInit(bool opengl)
+{
+ for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
+ {
+ Item& item = *it;
+
+ if (item.DrawBitmapLoaded && item.DrawBitmap) uiDrawFreeBitmap(item.DrawBitmap);
+ if (item.GLTextureLoaded && opengl) glDeleteTextures(1, &item.GLTexture);
+ if (item.Bitmap) delete[] item.Bitmap;
+
+ it = ItemQueue.erase(it);
+ }
+}
+
+
+int FindBreakPoint(const char* text, int i)
+{
+ // i = character that went out of bounds
+
+ for (int j = i; j >= 0; j--)
+ {
+ if (text[j] == ' ')
+ return j;
+ }
+
+ return i;
+}
+
+void LayoutText(const char* text, u32* width, u32* height, int* breaks)
+{
+ u32 w = 0;
+ u32 h = 14;
+ u32 totalw = 0;
+ u32 maxw = WindowWidth - (kOSDMargin*2);
+ int lastbreak = -1;
+ int numbrk = 0;
+ u16* ptr;
+
+ memset(breaks, 0, sizeof(int)*64);
+
+ for (int i = 0; text[i] != '\0'; )
+ {
+ int glyphsize;
+ if (text[i] == ' ')
+ {
+ glyphsize = 6;
+ }
+ else
+ {
+ u32 ch = text[i];
+ if (ch < 0x10 || ch > 0x7E) ch = 0x7F;
+
+ ptr = &font[(ch-0x10) << 4];
+ glyphsize = ptr[0];
+ if (!glyphsize) glyphsize = 6;
+ else glyphsize += 2; // space around the character
+ }
+
+ w += glyphsize;
+ if (w > maxw)
+ {
+ // wrap shit as needed
+ if (text[i] == ' ')
+ {
+ if (numbrk >= 64) break;
+ breaks[numbrk++] = i;
+ i++;
+ }
+ else
+ {
+ int brk = FindBreakPoint(text, i);
+ if (brk != lastbreak) i = brk;
+
+ if (numbrk >= 64) break;
+ breaks[numbrk++] = i;
+
+ lastbreak = brk;
+ }
+
+ w = 0;
+ h += 14;
+ }
+ else
+ i++;
+
+ if (w > totalw) totalw = w;
+ }
+
+ *width = totalw;
+ *height = h;
+}
+
+u32 RainbowColor(u32 inc)
+{
+ // inspired from Acmlmboard
+
+ if (inc < 100) return 0xFFFF9B9B + (inc << 8);
+ else if (inc < 200) return 0xFFFFFF9B - ((inc-100) << 16);
+ else if (inc < 300) return 0xFF9BFF9B + (inc-200);
+ else if (inc < 400) return 0xFF9BFFFF - ((inc-300) << 8);
+ else if (inc < 500) return 0xFF9B9BFF + ((inc-400) << 16);
+ else return 0xFFFF9BFF - (inc-500);
+}
+
+void RenderText(u32 color, const char* text, Item* item)
+{
+ u32 w, h;
+ int breaks[64];
+
+ bool rainbow = (color == 0);
+ u32 rainbowinc = (text[0] * 17) % 600;
+
+ color |= 0xFF000000;
+ const u32 shadow = 0xE0000000;
+
+ LayoutText(text, &w, &h, breaks);
+
+ item->Width = w;
+ item->Height = h;
+ item->Bitmap = new u32[w*h];
+ memset(item->Bitmap, 0, w*h*sizeof(u32));
+
+ u32 x = 0, y = 1;
+ u32 maxw = WindowWidth - (kOSDMargin*2);
+ int curline = 0;
+ u16* ptr;
+
+ for (int i = 0; text[i] != '\0'; )
+ {
+ int glyphsize;
+ if (text[i] == ' ')
+ {
+ x += 6;
+ }
+ else
+ {
+ u32 ch = text[i];
+ if (ch < 0x10 || ch > 0x7E) ch = 0x7F;
+
+ ptr = &font[(ch-0x10) << 4];
+ int glyphsize = ptr[0];
+ if (!glyphsize) x += 6;
+ else
+ {
+ x++;
+
+ if (rainbow)
+ {
+ color = RainbowColor(rainbowinc);
+ rainbowinc = (rainbowinc + 30) % 600;
+ }
+
+ // draw character
+ for (int cy = 0; cy < 12; cy++)
+ {
+ u16 val = ptr[4+cy];
+
+ for (int cx = 0; cx < glyphsize; cx++)
+ {
+ if (val & (1<<cx))
+ item->Bitmap[((y+cy) * w) + x+cx] = color;
+ }
+ }
+
+ x += glyphsize;
+ x++;
+ }
+ }
+
+ i++;
+ if (breaks[curline] && i >= breaks[curline])
+ {
+ i = breaks[curline++];
+ if (text[i] == ' ') i++;
+
+ x = 0;
+ y += 14;
+ }
+ }
+
+ // shadow
+ for (y = 0; y < h; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ u32 val;
+
+ val = item->Bitmap[(y * w) + x];
+ if ((val >> 24) == 0xFF) continue;
+
+ if (x > 0) val = item->Bitmap[(y * w) + x-1];
+ if (x < w-1) val |= item->Bitmap[(y * w) + x+1];
+ if (y > 0)
+ {
+ if (x > 0) val |= item->Bitmap[((y-1) * w) + x-1];
+ val |= item->Bitmap[((y-1) * w) + x];
+ if (x < w-1) val |= item->Bitmap[((y-1) * w) + x+1];
+ }
+ if (y < h-1)
+ {
+ if (x > 0) val |= item->Bitmap[((y+1) * w) + x-1];
+ val |= item->Bitmap[((y+1) * w) + x];
+ if (x < w-1) val |= item->Bitmap[((y+1) * w) + x+1];
+ }
+
+ if ((val >> 24) == 0xFF)
+ item->Bitmap[(y * w) + x] = shadow;
+ }
+ }
+}
+
+
+void AddMessage(u32 color, const char* text)
+{
+ while (Rendering);
+
+ Item item;
+
+ item.Timestamp = SDL_GetTicks();
+ strncpy(item.Text, text, 255); item.Text[255] = '\0';
+ item.Color = color;
+ item.Bitmap = NULL;
+
+ item.DrawBitmapLoaded = false;
+ item.GLTextureLoaded = false;
+
+ ItemQueue.push_back(item);
+}
+
+void WindowResized(bool opengl)
+{
+ /*for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
+ {
+ Item& item = *it;
+
+ if (item->DrawBitmapLoaded && item->DrawBitmap) uiDrawFreeBitmap(item->DrawBitmap);
+ //if (item->GLTextureLoaded && opengl) glDeleteTextures(1, &item->GLTexture);
+
+ item->DrawBitmapLoaded = false;
+ item->GLTextureLoaded = false;
+
+ if (item->Bitmap) delete[] item->Bitmap;
+
+ it++;
+ }*/
+}
+
+void Update(bool opengl, uiAreaDrawParams* params)
+{
+ Rendering = true;
+
+ Uint32 tick_now = SDL_GetTicks();
+ Uint32 tick_min = tick_now - 2500;
+ u32 y = kOSDMargin;
+
+ if (opengl)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer);
+ glBindVertexArray(OSDVertexArray);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
+ {
+ Item& item = *it;
+
+ if (item.Timestamp < tick_min)
+ {
+ if (item.DrawBitmapLoaded && item.DrawBitmap) uiDrawFreeBitmap(item.DrawBitmap);
+ if (item.GLTextureLoaded && opengl) glDeleteTextures(1, &item.GLTexture);
+ if (item.Bitmap) delete[] item.Bitmap;
+
+ it = ItemQueue.erase(it);
+ continue;
+ }
+
+ if (!item.Bitmap)
+ {
+ RenderText(item.Color, item.Text, &item);
+ }
+
+ if (opengl)
+ {
+ if (!item.GLTextureLoaded)
+ {
+ glGenTextures(1, &item.GLTexture);
+ glBindTexture(GL_TEXTURE_2D, item.GLTexture);
+ 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, item.Width, item.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, item.Bitmap);
+
+ item.GLTextureLoaded = true;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, item.GLTexture);
+ glUniform2i(uOSDPos, kOSDMargin, y);
+ glUniform2i(uOSDSize, item.Width, item.Height);
+ glDrawArrays(GL_TRIANGLES, 0, 2*3);
+ }
+ else
+ {
+ if (!item.DrawBitmapLoaded)
+ {
+ item.DrawBitmap = uiDrawNewBitmap(params->Context, item.Width, item.Height, 1);
+ uiDrawBitmapUpdate(item.DrawBitmap, item.Bitmap);
+
+ item.DrawBitmapLoaded = true;
+ }
+
+ uiRect rc_src = {0, 0, item.Width, item.Height};
+ uiRect rc_dst = {kOSDMargin, y, item.Width, item.Height};
+
+ uiDrawBitmapDraw(params->Context, item.DrawBitmap, &rc_src, &rc_dst, 0);
+ }
+
+ y += item.Height;
+ it++;
+ }
+
+ Rendering = false;
+}
+
+}
diff --git a/src/libui_sdl/OSD.h b/src/libui_sdl/OSD.h
new file mode 100644
index 0000000..afe403f
--- /dev/null
+++ b/src/libui_sdl/OSD.h
@@ -0,0 +1,35 @@
+/*
+ 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 OSD_H
+#define OSD_H
+
+namespace OSD
+{
+
+bool Init(bool opengl);
+void DeInit(bool opengl);
+
+void AddMessage(u32 color, const char* text);
+
+void WindowResized(bool opengl);
+void Update(bool opengl, uiAreaDrawParams* params);
+
+}
+
+#endif // OSD_H
diff --git a/src/libui_sdl/PlatformConfig.cpp b/src/libui_sdl/PlatformConfig.cpp
index f700ecb..5708fc8 100644
--- a/src/libui_sdl/PlatformConfig.cpp
+++ b/src/libui_sdl/PlatformConfig.cpp
@@ -88,11 +88,15 @@ ConfigEntry PlatformConfigFile[] =
{"Joy_X", 0, &JoyMapping[10], -1, NULL, 0},
{"Joy_Y", 0, &JoyMapping[11], -1, NULL, 0},
- {"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0E, NULL, 0},
- {"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], 0x35, NULL, 0},
-
- {"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, NULL, 0},
- {"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, NULL, 0},
+ {"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0D, NULL, 0},
+ {"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], 0x35, NULL, 0},
+ {"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], 0x0F, NULL, 0},
+ {"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0},
+
+ {"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, NULL, 0},
+ {"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, NULL, 0},
+ {"HKJoy_FastForward", 0, &HKJoyMapping[HK_FastForward], -1, NULL, 0},
+ {"HKJoy_FastForwardToggle", 0, &HKJoyMapping[HK_FastForwardToggle], -1, NULL, 0},
{"WindowWidth", 0, &WindowWidth, 256, NULL, 0},
{"WindowHeight", 0, &WindowHeight, 384, NULL, 0},
diff --git a/src/libui_sdl/PlatformConfig.h b/src/libui_sdl/PlatformConfig.h
index 013a0a7..be29c17 100644
--- a/src/libui_sdl/PlatformConfig.h
+++ b/src/libui_sdl/PlatformConfig.h
@@ -25,7 +25,8 @@ enum
{
HK_Lid = 0,
HK_Mic,
-
+ HK_FastForward,
+ HK_FastForwardToggle,
HK_MAX
};
diff --git a/src/libui_sdl/font.h b/src/libui_sdl/font.h
new file mode 100644
index 0000000..8647b7a
--- /dev/null
+++ b/src/libui_sdl/font.h
@@ -0,0 +1,135 @@
+/*
+ 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 FONT_H
+#define FONT_H
+unsigned short font[] = {
+ 12, 0, 0, 0,0x0C03, 0x0E07, 0x070E, 0x039C, 0x01F8, 0x00F0, 0x00F0, 0x01F8, 0x039C, 0x070E, 0x0E07, 0x0C03,
+ 12, 0, 0, 0,0x01C0, 0x00E0, 0x0060, 0x0860, 0x0C60, 0x0FE0, 0x07F0, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, 0x0003, 0x0003, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x01EF, 0x01EF, 0x018C, 0x01CE, 0x00E7, 0x0063, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x00CC, 0x00CC, 0x03FF, 0x03FF, 0x00CC, 0x00CC, 0x03FF, 0x03FF, 0x00CC, 0x00CC, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x0018, 0x00FE, 0x00FF, 0x001B, 0x007F, 0x00FE, 0x00D8, 0x00FF, 0x007F, 0x0018, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0306, 0x038F, 0x01CF, 0x00E6, 0x0070, 0x0038, 0x019C, 0x03CE, 0x03C7, 0x0183, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x007C, 0x00FE, 0x00C6, 0x00EE, 0x007C, 0x037E, 0x03E7, 0x01F3, 0x03BF, 0x031E, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x000F, 0x000F, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x000C, 0x000E, 0x0007, 0x0003, 0x0003, 0x0003, 0x0003, 0x0007, 0x000E, 0x000C, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x000C, 0x000C, 0x000C, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0030, 0x0333, 0x03B7, 0x01FE, 0x00FC, 0x00FC, 0x01FE, 0x03B7, 0x0333, 0x0030, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0030, 0x0030, 0x0030, 0x0030, 0x03FF, 0x03FF, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000F, 0x000F, 0x000C, 0x000E, 0x0007, 0x0003,
+ 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x03FF, 0x03FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 3, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0007, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0300, 0x0380, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x0006, 0x0007, 0x0007, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x000F, 0x000F, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C0, 0x00FE, 0x007F, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x007F, 0x00FF, 0x00C0, 0x00C0, 0x007C, 0x00FC, 0x00C0, 0x00C0, 0x00FF, 0x007F, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x00FF, 0x00FE, 0x0060, 0x0060, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x00FF, 0x00FF, 0x0003, 0x0003, 0x007F, 0x00FF, 0x00C0, 0x00C0, 0x00FF, 0x007F, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x007E, 0x007F, 0x0003, 0x0003, 0x007F, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x00FF, 0x00FF, 0x00C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000C, 0x000C, 0x000C, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x00FE, 0x00C0, 0x00C0, 0x00FE, 0x007E, 0x0000, 0x0000,
+ 3, 0, 0, 0,0x0000, 0x0000, 0x0007, 0x0007, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0000, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x0000, 0x0000, 0x000E, 0x000E, 0x0000, 0x0000, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000,
+ 6, 0, 0, 0,0x0030, 0x0038, 0x001C, 0x000E, 0x0007, 0x0007, 0x000E, 0x001C, 0x0038, 0x0030, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x007F, 0x007F, 0x0000, 0x0000, 0x007F, 0x007F, 0x0000, 0x0000, 0x0000,
+ 6, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00F0, 0x0078, 0x0018, 0x0000, 0x0018, 0x0018, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x00FC, 0x01FE, 0x0387, 0x0333, 0x037B, 0x03FB, 0x01F3, 0x0007, 0x03FE, 0x03FC, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x00FE, 0x01FF, 0x0183, 0x0183, 0x0183, 0x01FF, 0x01FF, 0x0183, 0x0183, 0x0183, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x00FE, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x00FF, 0x00FE, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x007F, 0x00FF, 0x01C3, 0x0183, 0x0183, 0x0183, 0x0183, 0x01C3, 0x00FF, 0x007F, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x01FF, 0x01FF, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0003, 0x0003, 0x01FF, 0x01FF, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x01FF, 0x01FF, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x01FE, 0x01FF, 0x0003, 0x0003, 0x01F3, 0x01F3, 0x0183, 0x0183, 0x01FF, 0x00FE, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x0183, 0x0183, 0x0183, 0x0183, 0x01FF, 0x01FF, 0x0183, 0x0183, 0x0183, 0x0183, 0x0000, 0x0000,
+ 6, 0, 0, 0,0x003F, 0x003F, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x003F, 0x003F, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x01F0, 0x01F0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x0183, 0x01C3, 0x00E3, 0x0073, 0x003F, 0x003F, 0x0073, 0x00E3, 0x01C3, 0x0183, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x007F, 0x007F, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0303, 0x0387, 0x03CF, 0x03FF, 0x037B, 0x0333, 0x0303, 0x0303, 0x0303, 0x0303, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0303, 0x0307, 0x030F, 0x031F, 0x033B, 0x0373, 0x03E3, 0x03C3, 0x0383, 0x0303, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x01FE, 0x03FF, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x03FF, 0x01FE, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x01FE, 0x03FF, 0x0303, 0x0303, 0x0333, 0x0373, 0x03E3, 0x01C3, 0x03FF, 0x037E, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0073, 0x00E3, 0x01C3, 0x0183, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x01FE, 0x01FF, 0x0003, 0x0003, 0x01FF, 0x03FE, 0x0300, 0x0300, 0x03FE, 0x01FE, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x03FF, 0x03FF, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000,
+ 9, 0, 0, 0,0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x01FF, 0x00FE, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0303, 0x0303, 0x0303, 0x0303, 0x0333, 0x037B, 0x03FF, 0x03CF, 0x0387, 0x0303, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0078, 0x00FC, 0x01CE, 0x0387, 0x0303, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x03FF, 0x03FF, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x03FF, 0x03FF, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x000F, 0x000F, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x000F, 0x000F, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0300, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x000F, 0x000F, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000F, 0x000F, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x0018, 0x003C, 0x007E, 0x00E7, 0x00C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03FF, 0x03FF,
+ 4, 0, 0, 0,0x000F, 0x000F, 0x0003, 0x0007, 0x000E, 0x000C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x003E, 0x007E, 0x0060, 0x007E, 0x007F, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x007F, 0x003F, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0003, 0x0003, 0x0003, 0x0003, 0x007F, 0x007E, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0060, 0x0060, 0x0060, 0x007E, 0x007F, 0x0063, 0x0063, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x003E, 0x007F, 0x0063, 0x007F, 0x003F, 0x0003, 0x003F, 0x003E, 0x0000, 0x0000,
+ 6, 0, 0, 0,0x003C, 0x003E, 0x0006, 0x0006, 0x001F, 0x001F, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0063, 0x0063, 0x007F, 0x007E, 0x0060, 0x0060, 0x007E, 0x003E,
+ 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0000, 0x0000,
+ 2, 0, 0, 0,0x0003, 0x0003, 0x0000, 0x0000, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0060, 0x0060, 0x0000, 0x0000, 0x0060, 0x0060, 0x0060, 0x0060, 0x0060, 0x0063, 0x007F, 0x003E,
+ 8, 0, 0, 0,0x0003, 0x0003, 0x00E3, 0x0073, 0x003B, 0x001F, 0x001F, 0x003B, 0x0073, 0x00E3, 0x0000, 0x0000,
+ 4, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x000F, 0x000E, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0000, 0x0000, 0x01FF, 0x03FF, 0x0333, 0x0333, 0x0333, 0x0333, 0x0333, 0x0333, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x003F, 0x007F, 0x0063, 0x0063, 0x007F, 0x003F, 0x0003, 0x0003, 0x0003, 0x0003,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0063, 0x0063, 0x007F, 0x007E, 0x0060, 0x0060, 0x0060, 0x0060,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x003B, 0x007F, 0x0067, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0003, 0x007F, 0x00FE, 0x00C0, 0x00FE, 0x007E, 0x0000, 0x0000,
+ 6, 0, 0, 0,0x0006, 0x0006, 0x003F, 0x003F, 0x0006, 0x0006, 0x0006, 0x0006, 0x003E, 0x003C, 0x0000, 0x0000,
+ 7, 0, 0, 0,0x0000, 0x0000, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0303, 0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0303, 0x0333, 0x037B, 0x03FF, 0x03CF, 0x0387, 0x0303, 0x0000, 0x0000,
+ 8, 0, 0, 0,0x0000, 0x0000, 0x00C3, 0x00E7, 0x007E, 0x003C, 0x003C, 0x007E, 0x00E7, 0x00C3, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0307, 0x038E, 0x01DC, 0x00F8, 0x0070, 0x0038, 0x001C, 0x000E, 0x0006,
+ 8, 0, 0, 0,0x0000, 0x0000, 0x00FF, 0x00FF, 0x0070, 0x0038, 0x001C, 0x000E, 0x00FF, 0x00FF, 0x0000, 0x0000,
+ 6, 0, 0, 0,0x0038, 0x003C, 0x000C, 0x000C, 0x000F, 0x000F, 0x000C, 0x000C, 0x003C, 0x0038, 0x0000, 0x0000,
+ 2, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
+ 6, 0, 0, 0,0x0007, 0x000F, 0x000C, 0x000C, 0x003C, 0x003C, 0x000C, 0x000C, 0x000F, 0x0007, 0x0000, 0x0000,
+ 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x031C, 0x03BE, 0x01F7, 0x00E3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 11, 0, 0, 0,0x0555, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0555, 0x0000,
+};
+#endif
diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h
index 47da54b..e15c127 100644
--- a/src/libui_sdl/libui/ui.h
+++ b/src/libui_sdl/libui/ui.h
@@ -516,7 +516,7 @@ _UI_EXTERN void uiDrawSave(uiDrawContext *c);
_UI_EXTERN void uiDrawRestore(uiDrawContext *c);
// bitmap API
-_UI_EXTERN uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height);
+_UI_EXTERN uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha);
_UI_EXTERN void uiDrawBitmapUpdate(uiDrawBitmap* bmp, const void* data);
_UI_EXTERN void uiDrawBitmapDraw(uiDrawContext* c, uiDrawBitmap* bmp, uiRect* srcrect, uiRect* dstrect, int filter);
_UI_EXTERN void uiDrawFreeBitmap(uiDrawBitmap* bmp);
diff --git a/src/libui_sdl/libui/unix/draw.c b/src/libui_sdl/libui/unix/draw.c
index e55397e..5befcd3 100644
--- a/src/libui_sdl/libui/unix/draw.c
+++ b/src/libui_sdl/libui/unix/draw.c
@@ -143,13 +143,13 @@ void uiDrawRestore(uiDrawContext *c)
// bitmap API
-uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height)
+uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha)
{
uiDrawBitmap* bmp;
bmp = uiNew(uiDrawBitmap);
- bmp->bmp = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
+ bmp->bmp = cairo_image_surface_create(alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, width, height);
if (cairo_surface_status(bmp->bmp) != CAIRO_STATUS_SUCCESS)
implbug("error creating bitmap: %s",
cairo_status_to_string(cairo_surface_status(bmp->bmp)));
diff --git a/src/libui_sdl/libui/windows/draw.cpp b/src/libui_sdl/libui/windows/draw.cpp
index 11a777d..9a815b9 100644
--- a/src/libui_sdl/libui/windows/draw.cpp
+++ b/src/libui_sdl/libui/windows/draw.cpp
@@ -522,7 +522,7 @@ void uiDrawRestore(uiDrawContext *c)
// bitmap API
-uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height)
+uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha)
{
uiDrawBitmap* bmp;
HRESULT hr;
@@ -532,7 +532,8 @@ uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height)
D2D1_BITMAP_PROPERTIES bp2 = D2D1::BitmapProperties();
bp2.dpiX = 0;
bp2.dpiY = 0;
- bp2.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
+ bp2.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+ alpha ? D2D1_ALPHA_MODE_PREMULTIPLIED : D2D1_ALPHA_MODE_IGNORE);
//c->rt->BeginDraw();
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp
index 5408586..ed5e80d 100644
--- a/src/libui_sdl/main.cpp
+++ b/src/libui_sdl/main.cpp
@@ -46,6 +46,8 @@
#include "../Savestate.h"
+#include "OSD.h"
+
// savestate slot mapping
// 1-8: regular slots (quick access)
@@ -110,6 +112,7 @@ uiDrawBitmap* ScreenBitmap[2] = {NULL,NULL};
GLuint GL_ScreenShader[3];
GLuint GL_ScreenShaderAccel[3];
+GLuint GL_ScreenShaderOSD[3];
struct
{
float uScreenSize[2];
@@ -156,6 +159,7 @@ s16* MicWavBuffer;
u32 MicCommand;
+bool HotkeyFPSToggle = false;
void SetupScreenRects(int width, int height);
@@ -196,6 +200,29 @@ bool GLScreen_InitShader(GLuint* shader, const char* fs)
return true;
}
+bool GLScreen_InitOSDShader(GLuint* shader)
+{
+ if (!OpenGL_BuildShaderProgram(kScreenVS_OSD, kScreenFS_OSD, shader, "ScreenShaderOSD"))
+ return false;
+
+ glBindAttribLocation(shader[2], 0, "vPosition");
+ glBindFragDataLocation(shader[2], 0, "oColor");
+
+ if (!OpenGL_LinkShaderProgram(shader))
+ return false;
+
+ GLuint uni_id;
+
+ uni_id = glGetUniformBlockIndex(shader[2], "uConfig");
+ glUniformBlockBinding(shader[2], uni_id, 16);
+
+ glUseProgram(shader[2]);
+ uni_id = glGetUniformLocation(shader[2], "OSDTex");
+ glUniform1i(uni_id, 0);
+
+ return true;
+}
+
bool GLScreen_Init()
{
// TODO: consider using epoxy?
@@ -211,6 +238,8 @@ bool GLScreen_Init()
return false;
if (!GLScreen_InitShader(GL_ScreenShaderAccel, kScreenFS_Accel))
return false;
+ if (!GLScreen_InitOSDShader(GL_ScreenShaderOSD))
+ return false;
memset(&GL_ShaderConfig, 0, sizeof(GL_ShaderConfig));
@@ -253,6 +282,7 @@ void GLScreen_DeInit()
OpenGL_DeleteShaderProgram(GL_ScreenShader);
OpenGL_DeleteShaderProgram(GL_ScreenShaderAccel);
+ OpenGL_DeleteShaderProgram(GL_ScreenShaderOSD);
}
void GLScreen_DrawScreen()
@@ -394,7 +424,7 @@ void GLScreen_DrawScreen()
else
OpenGL_UseShaderProgram(GL_ScreenShaderAccel);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, uiGLGetFramebuffer(GLContext));
+ glBindFramebuffer(GL_FRAMEBUFFER, uiGLGetFramebuffer(GLContext));
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
@@ -432,6 +462,9 @@ void GLScreen_DrawScreen()
glDrawArrays(GL_TRIANGLES, 0, 4*3);
}
+ OpenGL_UseShaderProgram(GL_ScreenShaderOSD);
+ OSD::Update(true, NULL);
+
glFlush();
uiGLSwapBuffers(GLContext);
}
@@ -707,7 +740,6 @@ int EmuThreadFunc(void* burp)
else
{
GPU3D::InitRenderer(false);
- GPU::SetDisplaySettings(false);
}
Touching = false;
@@ -807,6 +839,27 @@ int EmuThreadFunc(void* burp)
HotkeyMask |= 0x1;
}
+ if (JoyButtonPressed(Config::HKJoyMapping[HK_FastForwardToggle], njoybuttons, joybuttons, joyhat))
+ {
+ HotkeyFPSToggle = !HotkeyFPSToggle;
+ Config::LimitFPS = !Config::LimitFPS;
+ uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1);
+ }
+
+ if (!HotkeyFPSToggle) // For fast forward (hold) hotkey
+ {
+ if (JoyButtonHeld(Config::HKJoyMapping[HK_FastForward], njoybuttons, joybuttons, joyhat))
+ {
+ Config::LimitFPS = false;
+ uiMenuItemSetChecked(MenuItem_LimitFPS, false);
+ }
+ else if (!Config::LimitFPS)
+ {
+ Config::LimitFPS = true;
+ uiMenuItemSetChecked(MenuItem_LimitFPS, true);
+ }
+ }
+
if (JoyButtonHeld(Config::HKJoyMapping[HK_Mic], njoybuttons, joybuttons, joyhat))
MicCommand |= 2;
else
@@ -944,10 +997,20 @@ int EmuThreadFunc(void* burp)
if (joybuttons) delete[] joybuttons;
+ if (Screen_UseGL) uiGLMakeContextCurrent(GLContext);
+
NDS::DeInit();
Platform::LAN_DeInit();
- if (Screen_UseGL) GLScreen_DeInit();
+ if (Screen_UseGL)
+ {
+ OSD::DeInit(true);
+ GLScreen_DeInit();
+ }
+ else
+ OSD::DeInit(false);
+
+ if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
return 44203;
}
@@ -961,8 +1024,8 @@ void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params)
if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]);
ScreenDrawInited = true;
- ScreenBitmap[0] = uiDrawNewBitmap(params->Context, 256, 192);
- ScreenBitmap[1] = uiDrawNewBitmap(params->Context, 256, 192);
+ ScreenBitmap[0] = uiDrawNewBitmap(params->Context, 256, 192, 0);
+ ScreenBitmap[1] = uiDrawNewBitmap(params->Context, 256, 192, 0);
}
int frontbuf = GPU::FrontBuffer;
@@ -984,6 +1047,8 @@ void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params)
uiDrawTransform(params->Context, &BottomScreenTrans);
uiDrawBitmapDraw(params->Context, ScreenBitmap[1], &bot, &BottomScreenRect, Config::ScreenFilter==1);
uiDrawRestore(params->Context);
+
+ OSD::Update(false, params);
}
void OnAreaMouseEvent(uiAreaHandler* handler, uiArea* area, uiAreaMouseEvent* evt)
@@ -1083,6 +1148,19 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
if (evt->Scancode == Config::HKKeyMapping[HK_Mic])
MicCommand &= ~1;
+
+ if (evt->Scancode == Config::HKKeyMapping[HK_FastForwardToggle])
+ {
+ HotkeyFPSToggle = !HotkeyFPSToggle;
+ Config::LimitFPS = !Config::LimitFPS;
+ uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1);
+ }
+
+ if (evt->Scancode == Config::HKKeyMapping[HK_FastForward] && !HotkeyFPSToggle)
+ {
+ Config::LimitFPS = true;
+ uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1);
+ }
}
else if (!evt->Repeat)
{
@@ -1114,8 +1192,15 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
if (evt->Scancode == Config::HKKeyMapping[HK_Mic])
MicCommand |= 1;
+ if (evt->Scancode == Config::HKKeyMapping[HK_FastForward] && !HotkeyFPSToggle)
+ {
+ Config::LimitFPS = false;
+ uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1);
+ }
+
if (evt->Scancode == 0x57) // F11
- NDS::debug(0);
+ OSD::AddMessage(0x00FFFF, "OSD test");
+ //NDS::debug(0);
}
return 1;
@@ -1371,20 +1456,30 @@ void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height)
WindowWidth = width;
WindowHeight = height;
- int max = uiWindowMaximized(MainWindow);
- int min = uiWindowMinimized(MainWindow);
+ int ismax = uiWindowMaximized(MainWindow);
+ int ismin = uiWindowMinimized(MainWindow);
- Config::WindowMaximized = max;
- if (!max && !min)
+ Config::WindowMaximized = ismax;
+ if (!ismax && !ismin)
{
Config::WindowWidth = width;
Config::WindowHeight = height;
}
+
+ OSD::WindowResized(Screen_UseGL);
}
void Run()
{
+ if (GPU3D::Renderer != Config::_3DRenderer)
+ {
+ if (Screen_UseGL) uiGLMakeContextCurrent(GLContext);
+ GPU3D::DeInitRenderer();
+ GPU3D::InitRenderer(Screen_UseGL);
+ if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
+ }
+
EmuRunning = 1;
RunningSomething = true;
@@ -1537,6 +1632,11 @@ void LoadState(int slot)
if (!Platform::FileExists(filename))
{
+ char msg[64];
+ if (slot > 0) sprintf(msg, "State slot %d is empty", slot);
+ else sprintf(msg, "State file does not exist");
+ OSD::AddMessage(0xFFA0A0, msg);
+
EmuRunning = prevstatus;
return;
}
@@ -1577,6 +1677,11 @@ void LoadState(int slot)
NDS::RelocateSave(SRAMPath, false);
}
+ char msg[64];
+ if (slot > 0) sprintf(msg, "State loaded from slot %d", slot);
+ else sprintf(msg, "State loaded from file");
+ OSD::AddMessage(0, msg);
+
SavestateLoaded = true;
uiMenuItemEnable(MenuItem_UndoStateLoad);
}
@@ -1636,6 +1741,11 @@ void SaveState(int slot)
}
}
+ char msg[64];
+ if (slot > 0) sprintf(msg, "State saved to slot %d", slot);
+ else sprintf(msg, "State saved to file");
+ OSD::AddMessage(0, msg);
+
EmuRunning = prevstatus;
}
@@ -1660,6 +1770,8 @@ void UndoStateLoad()
NDS::RelocateSave(SRAMPath, false);
}
+ OSD::AddMessage(0, "State load undone");
+
EmuRunning = prevstatus;
}
@@ -2008,6 +2120,7 @@ void OnSetLimitFPS(uiMenuItem* item, uiWindow* window, void* blarg)
int chk = uiMenuItemChecked(item);
if (chk != 0) Config::LimitFPS = true;
else Config::LimitFPS = false;
+ HotkeyFPSToggle = !Config::LimitFPS; // ensure that the hotkey toggle indicator is synced with this menu item
}
void ApplyNewSettings(int type)
@@ -2050,6 +2163,10 @@ void ApplyNewSettings(int type)
if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
}
+ if (Screen_UseGL) uiGLMakeContextCurrent(GLContext);
+ OSD::DeInit(Screen_UseGL);
+ if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
+
Screen_UseGL = usegl;
RecreateMainWindow(usegl);
@@ -2232,6 +2349,7 @@ void CreateMainWindowMenu()
uiMenuAppendSubmenu(menu, submenu);
}
+
MenuItem_ScreenFilter = uiMenuAppendCheckItem(menu, "Screen filtering");
uiMenuItemOnClicked(MenuItem_ScreenFilter, OnSetScreenFiltering, NULL);
@@ -2274,6 +2392,11 @@ void CreateMainWindow(bool opengl)
{
uiGLMakeContextCurrent(GLContext);
if (!GLScreen_Init()) opengl_good = false;
+ if (opengl_good)
+ {
+ OpenGL_UseShaderProgram(GL_ScreenShaderOSD);
+ OSD::Init(true);
+ }
uiGLMakeContextCurrent(NULL);
}
@@ -2283,6 +2406,8 @@ void CreateMainWindow(bool opengl)
RecreateMainWindow(false);
Screen_UseGL = false;
}
+
+ if (!opengl) OSD::Init(false);
}
void DestroyMainWindow()
diff --git a/src/libui_sdl/main_shaders.h b/src/libui_sdl/main_shaders.h
index f03931c..6504520 100644
--- a/src/libui_sdl/main_shaders.h
+++ b/src/libui_sdl/main_shaders.h
@@ -36,7 +36,7 @@ smooth out vec2 fTexcoord;
void main()
{
vec4 fpos;
- fpos.xy = ((vPosition.xy * 2.0) / uScreenSize) - 1.0;
+ fpos.xy = ((vPosition * 2.0) / uScreenSize) - 1.0;
fpos.y *= -1;
fpos.z = 0.0;
fpos.w = 1.0;
@@ -198,4 +198,53 @@ void main()
}
)";
+
+const char* kScreenVS_OSD = R"(#version 140
+
+layout(std140) uniform uConfig
+{
+ vec2 uScreenSize;
+ uint u3DScale;
+ uint uFilterMode;
+};
+
+uniform ivec2 uOSDPos;
+uniform ivec2 uOSDSize;
+
+in vec2 vPosition;
+
+smooth out vec2 fTexcoord;
+
+void main()
+{
+ vec4 fpos;
+
+ vec2 osdpos = (vPosition * vec2(uOSDSize));
+ fTexcoord = osdpos;
+ osdpos += uOSDPos;
+
+ fpos.xy = ((osdpos * 2.0) / uScreenSize) - 1.0;
+ fpos.y *= -1;
+ fpos.z = 0.0;
+ fpos.w = 1.0;
+
+ gl_Position = fpos;
+}
+)";
+
+const char* kScreenFS_OSD = R"(#version 140
+
+uniform sampler2D OSDTex;
+
+smooth in vec2 fTexcoord;
+
+out vec4 oColor;
+
+void main()
+{
+ vec4 pixel = texelFetch(OSDTex, ivec2(fTexcoord), 0);
+ oColor = pixel.bgra;
+}
+)";
+
#endif // MAIN_SHADERS_H