From b4ba95242f8a5cf155df3c7210121ab5abc3163b Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sat, 7 Mar 2015 21:21:47 +1100 Subject: [PATCH] Update to v094r13 release. byuu says: This version polishes up the input dialogue (reset, erase, disable button when item not focused, split device ID from mapping name), adds color emulation toggle, and add dummy menu items for remaining features (to be filled in later.) Also, it now compiles cleanly on Windows with GTK. I didn't test with TDM-GCC-32, because for god knows what reason, the 32-bit version ships with headers from Windows 95 OSR2 only. So I built with TDM-GCC-64 with arch=x86. And uh, apparently, moving or resizing a window causes a Visual C++ runtime exception in the GTK+ DLLs. This doesn't happen with trance or renshuu built with TDM-GCC-32. So, yeah, like I said, don't use -m32. --- emulator/emulator.hpp | 2 +- hiro/GNUmakefile | 25 ++- hiro/core/core.cpp | 2 + hiro/core/core.hpp | 1 + hiro/core/window.cpp | 11 ++ hiro/extension/shared.hpp | 1 + hiro/gtk/application.cpp | 26 +++- hiro/gtk/application.hpp | 2 + hiro/gtk/desktop.cpp | 8 + hiro/gtk/header.hpp | 52 +++++-- hiro/gtk/keyboard.cpp | 143 +++--------------- hiro/gtk/keyboard.hpp | 2 +- hiro/gtk/mouse.cpp | 19 +++ hiro/gtk/widget/viewport.cpp | 6 + hiro/platform/windows/keyboard.hpp | 119 +++++++++++++++ hiro/platform/xorg/keyboard.hpp | 119 +++++++++++++++ hiro/windows/header.hpp | 8 +- nall/GNUmakefile | 1 + nall/platform.hpp | 2 - target-tomoko/configuration/configuration.cpp | 2 + target-tomoko/configuration/configuration.hpp | 2 + target-tomoko/input/input.cpp | 9 ++ target-tomoko/input/input.hpp | 1 + target-tomoko/library/manager.cpp | 2 +- target-tomoko/presentation/presentation.cpp | 30 +++- target-tomoko/presentation/presentation.hpp | 21 +++ target-tomoko/program/media.cpp | 4 +- target-tomoko/program/program.cpp | 3 + target-tomoko/program/program.hpp | 4 + target-tomoko/program/utility.cpp | 12 ++ target-tomoko/settings/input.cpp | 27 +++- target-tomoko/settings/settings.cpp | 4 +- target-tomoko/settings/settings.hpp | 2 +- 33 files changed, 517 insertions(+), 155 deletions(-) create mode 100644 hiro/platform/windows/keyboard.hpp create mode 100644 hiro/platform/xorg/keyboard.hpp create mode 100644 target-tomoko/program/utility.cpp diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index 85460f30..2a1951f0 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "094.12"; + static const char Version[] = "094.13"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; static const char Website[] = "http://byuu.org/"; diff --git a/hiro/GNUmakefile b/hiro/GNUmakefile index 1be0edb0..585eeab0 100644 --- a/hiro/GNUmakefile +++ b/hiro/GNUmakefile @@ -2,11 +2,28 @@ ifeq ($(platform),) hiroflags = $(cppflags) $(flags) -DHIRO_REFERENCE hirolink = else ifeq ($(platform),windows) - hiroflags = $(cppflags) $(flags) -DHIRO_WINDOWS - hirolink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -luxtheme -lmsimg32 -lshlwapi + ifeq ($(hiro),) + hiro := windows + endif + + ifeq ($(hiro),windows) + hiroflags = $(cppflags) $(flags) -DHIRO_WINDOWS + hirolink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -luxtheme -lmsimg32 -lshlwapi + endif + + ifeq ($(hiro),gtk) + hiroflags = $(cppflags) $(flags) -DHIRO_GTK $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0) + hirolink = $(shell pkg-config --libs gtk+-2.0 gtksourceview-2.0) + endif else ifeq ($(platform),macosx) - hiroflags = $(objcppflags) $(flags) -DHIRO_COCOA - hirolink = -framework Cocoa -framework Carbon + ifeq ($(hiro),) + hiro := cocoa + endif + + ifeq ($(hiro),cocoa) + hiroflags = $(objcppflags) $(flags) -DHIRO_COCOA + hirolink = -framework Cocoa -framework Carbon + endif else ifeq ($(hiro),) hiro := gtk diff --git a/hiro/core/core.cpp b/hiro/core/core.cpp index 531b94d7..79011b6b 100644 --- a/hiro/core/core.cpp +++ b/hiro/core/core.cpp @@ -1,3 +1,5 @@ +#include + #if defined(HIRO_WINDOWS) #include "../windows/header.hpp" #elif defined(HIRO_QT) diff --git a/hiro/core/core.hpp b/hiro/core/core.hpp index 47e3d6e1..8a19e249 100644 --- a/hiro/core/core.hpp +++ b/hiro/core/core.hpp @@ -508,6 +508,7 @@ struct mWindow : mObject { auto setFullScreen(bool fullScreen = true) -> type&; auto setGeometry(Geometry geometry) -> type&; auto setModal(bool modal = true) -> type&; + auto setPlacement(double x, double y) -> type&; auto setPosition(Position position) -> type&; auto setResizable(bool resizable = true) -> type&; auto setSize(Size size) -> type&; diff --git a/hiro/core/window.cpp b/hiro/core/window.cpp index 964ae940..389f0c6f 100644 --- a/hiro/core/window.cpp +++ b/hiro/core/window.cpp @@ -236,6 +236,17 @@ auto mWindow::setModal(bool modal) -> type& { return *this; } +auto mWindow::setPlacement(double x, double y) -> type& { + x = max(0.0, min(1.0, x)); + y = max(0.0, min(1.0, y)); + auto workspace = Desktop::workspace(); + auto geometry = frameGeometry(); + signed left = x * (workspace.width() - geometry.width()); + signed top = y * (workspace.height() - geometry.height()); + setFramePosition({left, top}); + return *this; +} + auto mWindow::setPosition(Position position) -> type& { return setGeometry({ position.x(), position.y(), diff --git a/hiro/extension/shared.hpp b/hiro/extension/shared.hpp index 0572e862..73d065f4 100644 --- a/hiro/extension/shared.hpp +++ b/hiro/extension/shared.hpp @@ -112,6 +112,7 @@ struct Window : sWindow { auto setFullScreen(bool fullScreen = true) -> type& { return self().setFullScreen(fullScreen), *this; } auto setGeometry(Geometry geometry) -> type& { return self().setGeometry(geometry), *this; } auto setModal(bool modal = true) -> type& { return self().setModal(modal), *this; } + auto setPlacement(double x, double y) -> type& { return self().setPlacement(x, y), *this; } auto setPosition(Position position) -> type& { return self().setPosition(position), *this; } auto setResizable(bool resizable = true) -> type& { return self().setResizable(resizable), *this; } auto setSize(Size size) -> type& { return self().setSize(size), *this; } diff --git a/hiro/gtk/application.cpp b/hiro/gtk/application.cpp index 1cd3dfa9..63ad90a4 100644 --- a/hiro/gtk/application.cpp +++ b/hiro/gtk/application.cpp @@ -1,6 +1,8 @@ namespace hiro { +#if defined(PLATFORM_XORG) XlibDisplay* pApplication::display = nullptr; +#endif void pApplication::run() { if(Application::state.onMain) { @@ -24,10 +26,19 @@ void pApplication::processEvents() { void pApplication::quit() { //if gtk_main() was invoked, call gtk_main_quit() if(gtk_main_level()) gtk_main_quit(); + + #if defined(PLATFORM_XORG) + //todo: Keyboard::poll() is being called after Application::quit(); + //so if display is closed; this causes a segfault + //XCloseDisplay(display); + //display = nullptr; + #endif } void pApplication::initialize() { + #if defined(PLATFORM_XORG) display = XOpenDisplay(nullptr); + #endif settings = new Settings; settings->load(); @@ -48,11 +59,24 @@ void pApplication::initialize() { strcpy(argv[1], "--g-fatal-warnings"); #endif char** argvp = argv; - gtk_init(&argc, &argvp); + gtk_init(&argc, &argvp); GtkSettings* gtkSettings = gtk_settings_get_default(); + + //allow buttons to show icons + g_type_class_unref(g_type_class_ref(GTK_TYPE_BUTTON)); g_object_set(gtkSettings, "gtk-button-images", true, nullptr); + #if defined(PLATFORM_WINDOWS) + //there is a serious bug in GTK 2.24 for Windows with the "ime" (Windows IME) input method: + //by default, it will be impossible to type in text fields at all. + //there are various tricks to get around this; but they are unintuitive and unreliable. + //the "ime" method is chosen when various international system locales (eg Japanese) are selected. + //here, we override the default input method to use the "Simple" type instead to avoid the bug. + //obviously, this has a drawback: in-place editing for IMEs will not work in this mode. + g_object_set(gtkSettings, "gtk-im-module", "gtk-im-context-simple", nullptr); + #endif + gtk_rc_parse_string(R"( style "HiroWindow" { diff --git a/hiro/gtk/application.hpp b/hiro/gtk/application.hpp index 4fd5d573..269937ce 100644 --- a/hiro/gtk/application.hpp +++ b/hiro/gtk/application.hpp @@ -1,7 +1,9 @@ namespace hiro { struct pApplication { + #if defined(PLATFORM_XORG) static XlibDisplay* display; + #endif static void run(); static bool pendingEvents(); diff --git a/hiro/gtk/desktop.cpp b/hiro/gtk/desktop.cpp index 25b03fee..4cd551f4 100644 --- a/hiro/gtk/desktop.cpp +++ b/hiro/gtk/desktop.cpp @@ -8,6 +8,13 @@ Size pDesktop::size() { } Geometry pDesktop::workspace() { + #if defined(PLATFORM_WINDOWS) + RECT rc; + SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); + return {rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top}; + #endif + + #if defined(PLATFORM_XORG) XlibDisplay* display = XOpenDisplay(nullptr); int screen = DefaultScreen(display); @@ -35,6 +42,7 @@ Geometry pDesktop::workspace() { gdk_screen_get_width(gdk_screen_get_default()), gdk_screen_get_height(gdk_screen_get_default()) }; + #endif } } diff --git a/hiro/gtk/header.hpp b/hiro/gtk/header.hpp index 8e691ab5..0820f9ad 100644 --- a/hiro/gtk/header.hpp +++ b/hiro/gtk/header.hpp @@ -1,11 +1,41 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#if defined(PLATFORM_WINDOWS) + #define UNICODE + #define WINVER 0x0601 + #define _WIN32_WINNT WINVER + #define _WIN32_IE WINVER + #define __MSVCRT_VERSION__ WINVER + #define NOMINMAX + #define TBS_TRANSPARENTBKGND 0x1000 + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif + +#if defined(PLATFORM_XORG) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif diff --git a/hiro/gtk/keyboard.cpp b/hiro/gtk/keyboard.cpp index 0223ccf3..34895a1a 100644 --- a/hiro/gtk/keyboard.cpp +++ b/hiro/gtk/keyboard.cpp @@ -3,7 +3,9 @@ namespace hiro { auto pKeyboard::poll() -> vector { vector result; char state[256]; + #if defined(PLATFORM_XORG) XQueryKeymap(pApplication::display, state); + #endif for(auto& code : settings->keycodes) { result.append(_pressed(state, code)); } @@ -12,15 +14,26 @@ auto pKeyboard::poll() -> vector { auto pKeyboard::pressed(unsigned code) -> bool { char state[256]; + #if defined(PLATFORM_XORG) XQueryKeymap(pApplication::display, state); + #endif return _pressed(state, code); } -auto pKeyboard::_pressed(char* state, uint16_t code) -> bool { +auto pKeyboard::_pressed(const char* state, uint16_t code) -> bool { uint8_t lo = code >> 0; uint8_t hi = code >> 8; + + #if defined(PLATFORM_WINDOWS) + if(lo && GetAsyncKeyState(lo) & 0x8000) return true; + if(hi && GetAsyncKeyState(hi) & 0x8000) return true; + #endif + + #if defined(PLATFORM_XORG) if(lo && state[lo >> 3] & (1 << (lo & 7))) return true; if(hi && state[hi >> 3] & (1 << (hi & 7))) return true; + #endif + return false; } @@ -208,134 +221,24 @@ auto pKeyboard::_translate(unsigned code) -> signed { auto pKeyboard::initialize() -> void { auto append = [](unsigned lo, unsigned hi = 0) { + #if defined(PLATFORM_XORG) lo = lo ? (uint8_t)XKeysymToKeycode(pApplication::display, lo) : 0; hi = hi ? (uint8_t)XKeysymToKeycode(pApplication::display, hi) : 0; + #endif settings->keycodes.append(lo | (hi << 8)); }; #define map(name, ...) if(key == name) { append(__VA_ARGS__); continue; } for(auto& key : Keyboard::keys) { - map("Escape", XK_Escape); - map("F1", XK_F1); - map("F2", XK_F2); - map("F3", XK_F3); - map("F4", XK_F4); - map("F5", XK_F5); - map("F6", XK_F6); - map("F7", XK_F7); - map("F8", XK_F8); - map("F9", XK_F9); - map("F10", XK_F10); - map("F11", XK_F11); - map("F12", XK_F12); + #if defined(PLATFORM_WINDOWS) + #include + #endif - map("PrintScreen", XK_Print); - map("ScrollLock", XK_Scroll_Lock); - map("Pause", XK_Pause); + #if defined(PLATFORM_XORG) + #include + #endif - map("Insert", XK_Insert); - map("Delete", XK_Delete); - map("Home", XK_Home); - map("End", XK_End); - map("PageUp", XK_Prior); - map("PageDown", XK_Next); - - map("Up", XK_Up); - map("Down", XK_Down); - map("Left", XK_Left); - map("Right", XK_Right); - - map("Grave", XK_asciitilde); - map("1", XK_1); - map("2", XK_2); - map("3", XK_3); - map("4", XK_4); - map("5", XK_5); - map("6", XK_6); - map("7", XK_7); - map("8", XK_8); - map("9", XK_9); - map("0", XK_0); - map("Dash", XK_minus); - map("Equal", XK_equal); - map("Backspace", XK_BackSpace); - - map("Tab", XK_Tab); - map("CapsLock", XK_Caps_Lock); - map("LeftEnter", XK_Return); - map("LeftShift", XK_Shift_L); - map("RightShift", XK_Shift_R); - map("LeftControl", XK_Control_L); - map("RightControl", XK_Control_R); - map("LeftAlt", XK_Alt_L); - map("RightAlt", XK_Alt_R); - map("LeftSuper", XK_Super_L); - map("RightSuper", XK_Super_R); - map("Menu", XK_Menu); - map("Space", XK_space); - - map("OpenBracket", XK_bracketleft); - map("CloseBracket", XK_bracketright); - map("Backslash", XK_backslash); - map("Semicolon", XK_semicolon); - map("Apostrophe", XK_apostrophe); - map("Comma", XK_comma); - map("Period", XK_period); - map("Slash", XK_slash); - - map("A", XK_A); - map("B", XK_B); - map("C", XK_C); - map("D", XK_D); - map("E", XK_E); - map("F", XK_F); - map("G", XK_G); - map("H", XK_H); - map("I", XK_I); - map("J", XK_J); - map("K", XK_K); - map("L", XK_L); - map("M", XK_M); - map("N", XK_N); - map("O", XK_O); - map("P", XK_P); - map("Q", XK_Q); - map("R", XK_R); - map("S", XK_S); - map("T", XK_T); - map("U", XK_U); - map("V", XK_V); - map("W", XK_W); - map("X", XK_X); - map("Y", XK_Y); - map("Z", XK_Z); - - map("NumLock", XK_Num_Lock); - map("Divide", XK_KP_Divide); - map("Multiply", XK_KP_Multiply); - map("Subtract", XK_KP_Subtract); - map("Add", XK_KP_Add); - map("RightEnter", XK_KP_Enter); - map("Point", XK_KP_Decimal); - - map("One", XK_KP_1); - map("Two", XK_KP_2); - map("Three", XK_KP_3); - map("Four", XK_KP_4); - map("Five", XK_KP_5); - map("Six", XK_KP_6); - map("Seven", XK_KP_7); - map("Eight", XK_KP_8); - map("Nine", XK_KP_9); - map("Zero", XK_KP_0); - - map("Shift", XK_Shift_L, XK_Shift_R); - map("Control", XK_Control_L, XK_Control_R); - map("Alt", XK_Alt_L, XK_Alt_R); - map("Super", XK_Super_L, XK_Super_R); - map("Enter", XK_Return, XK_KP_Enter); - - print("[phoenix/gtk] error: unhandled key: ", key, "\n"); + //print("[phoenix/gtk] warning: unhandled key: ", key, "\n"); append(0); } #undef map diff --git a/hiro/gtk/keyboard.hpp b/hiro/gtk/keyboard.hpp index 06e5387c..9257ca92 100644 --- a/hiro/gtk/keyboard.hpp +++ b/hiro/gtk/keyboard.hpp @@ -4,7 +4,7 @@ struct pKeyboard { static auto poll() -> vector; static auto pressed(unsigned code) -> bool; - static auto _pressed(char* state, uint16_t code) -> bool; + static auto _pressed(const char* state, uint16_t code) -> bool; static auto _translate(unsigned code) -> signed; static auto initialize() -> void; diff --git a/hiro/gtk/mouse.cpp b/hiro/gtk/mouse.cpp index 0e6a6c94..ae9ab4e9 100644 --- a/hiro/gtk/mouse.cpp +++ b/hiro/gtk/mouse.cpp @@ -1,14 +1,31 @@ namespace hiro { auto pMouse::position() -> Position { + #if defined(PLATFORM_WINDOWS) + POINT point = {0}; + GetCursorPos(&point); + return {point.x, point.y}; + #endif + + #if defined(PLATFORM_XORG) XlibWindow root, child; int rootx, rooty, winx, winy; unsigned int mask; XQueryPointer(pApplication::display, DefaultRootWindow(pApplication::display), &root, &child, &rootx, &rooty, &winx, &winy, &mask); return {rootx, rooty}; + #endif } auto pMouse::pressed(Mouse::Button button) -> bool { + #if defined(PLATFORM_WINDOWS) + switch(button) { + case Mouse::Button::Left: return GetAsyncKeyState(VK_LBUTTON) & 0x8000; + case Mouse::Button::Middle: return GetAsyncKeyState(VK_MBUTTON) & 0x8000; + case Mouse::Button::Right: return GetAsyncKeyState(VK_RBUTTON) & 0x8000; + } + #endif + + #if defined(PLATFORM_XORG) XlibWindow root, child; int rootx, rooty, winx, winy; unsigned int mask; @@ -18,6 +35,8 @@ auto pMouse::pressed(Mouse::Button button) -> bool { case Mouse::Button::Middle: return mask & Button2Mask; case Mouse::Button::Right: return mask & Button3Mask; } + #endif + return false; } diff --git a/hiro/gtk/widget/viewport.cpp b/hiro/gtk/widget/viewport.cpp index f6a27c94..7a8d393a 100644 --- a/hiro/gtk/widget/viewport.cpp +++ b/hiro/gtk/widget/viewport.cpp @@ -65,7 +65,13 @@ auto pViewport::destruct() -> void { } auto pViewport::handle() const -> uintptr_t { + #if defined(PLATFORM_WINDOWS) + return (uintptr_t)GDK_WINDOW_HWND(gtk_widget_get_window(gtkWidget)); + #endif + + #if defined(PLATFORM_XORG) return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget)); + #endif } auto pViewport::setDroppable(bool droppable) -> void { diff --git a/hiro/platform/windows/keyboard.hpp b/hiro/platform/windows/keyboard.hpp new file mode 100644 index 00000000..88b914a4 --- /dev/null +++ b/hiro/platform/windows/keyboard.hpp @@ -0,0 +1,119 @@ +map("Escape", VK_ESCAPE); +map("F1", VK_F1); +map("F2", VK_F2); +map("F3", VK_F3); +map("F4", VK_F4); +map("F5", VK_F5); +map("F6", VK_F6); +map("F7", VK_F7); +map("F8", VK_F8); +map("F9", VK_F9); +map("F10", VK_F10); +map("F11", VK_F11); +map("F12", VK_F12); + +map("PrintScreen", VK_SNAPSHOT); +map("ScrollLock", VK_SCROLL); +map("Pause", VK_PAUSE); + +map("Insert", VK_INSERT); +map("Delete", VK_DELETE); +map("Home", VK_HOME); +map("End", VK_END); +map("PageUp", VK_PRIOR); +map("PageDown", VK_NEXT); + +map("Up", VK_UP); +map("Down", VK_DOWN); +map("Left", VK_LEFT); +map("Right", VK_RIGHT); + +map("Grave", VK_OEM_3); +map("1", '1'); +map("2", '2'); +map("3", '3'); +map("4", '4'); +map("5", '5'); +map("6", '6'); +map("7", '7'); +map("8", '8'); +map("9", '9'); +map("0", '0'); +map("Dash", VK_OEM_MINUS); +map("Equal", VK_OEM_PLUS); +map("Backspace", VK_BACK); + +map("Tab", VK_TAB); +map("CapsLock", VK_CAPITAL); +map("LeftEnter", VK_RETURN); +map("LeftShift", VK_LSHIFT); +map("RightShift", VK_RSHIFT); +map("LeftControl", VK_LCONTROL); +map("RightControl", VK_RCONTROL); +map("LeftAlt", VK_LMENU); +map("RightAlt", VK_RMENU); +map("LeftSuper", VK_LWIN); +map("RightSuper", VK_RWIN); +map("Menu", VK_APPS); +map("Space", VK_SPACE); + +map("OpenBracket", VK_OEM_4); +map("CloseBracket", VK_OEM_6); +map("Backslash", VK_OEM_5); +map("Semicolon", VK_OEM_1); +map("Apostrophe", VK_OEM_7); +map("Comma", VK_OEM_COMMA); +map("Period", VK_OEM_PERIOD); +map("Slash", VK_OEM_2); + +map("A", 'A'); +map("B", 'B'); +map("C", 'C'); +map("D", 'D'); +map("E", 'E'); +map("F", 'F'); +map("G", 'G'); +map("H", 'H'); +map("I", 'I'); +map("J", 'J'); +map("K", 'K'); +map("L", 'L'); +map("M", 'M'); +map("N", 'N'); +map("O", 'O'); +map("P", 'P'); +map("Q", 'Q'); +map("R", 'R'); +map("S", 'S'); +map("T", 'T'); +map("U", 'U'); +map("V", 'V'); +map("W", 'W'); +map("X", 'X'); +map("Y", 'Y'); +map("Z", 'Z'); + +map("NumLock", VK_NUMLOCK); +map("Divide", VK_DIVIDE); +map("Multiply", VK_MULTIPLY); +map("Subtract", VK_SUBTRACT); +map("Add", VK_ADD); +//map("RightEnter", ...); +map("Point", VK_DECIMAL); + +map("One", VK_NUMPAD1); +map("Two", VK_NUMPAD2); +map("Three", VK_NUMPAD3); +map("Four", VK_NUMPAD4); +map("Five", VK_NUMPAD5); +map("Six", VK_NUMPAD6); +map("Seven", VK_NUMPAD7); +map("Eight", VK_NUMPAD8); +map("Nine", VK_NUMPAD9); +map("Zero", VK_NUMPAD0); + +map("Shift", VK_LSHIFT, VK_RSHIFT); +map("Control", VK_LCONTROL, VK_RCONTROL); +map("Alt", VK_LMENU, VK_RMENU); +map("Super", VK_LWIN, VK_RWIN); +map("Enter", VK_RETURN); diff --git a/hiro/platform/xorg/keyboard.hpp b/hiro/platform/xorg/keyboard.hpp new file mode 100644 index 00000000..3a0fb676 --- /dev/null +++ b/hiro/platform/xorg/keyboard.hpp @@ -0,0 +1,119 @@ +map("Escape", XK_Escape); +map("F1", XK_F1); +map("F2", XK_F2); +map("F3", XK_F3); +map("F4", XK_F4); +map("F5", XK_F5); +map("F6", XK_F6); +map("F7", XK_F7); +map("F8", XK_F8); +map("F9", XK_F9); +map("F10", XK_F10); +map("F11", XK_F11); +map("F12", XK_F12); + +map("PrintScreen", XK_Print); +map("ScrollLock", XK_Scroll_Lock); +map("Pause", XK_Pause); + +map("Insert", XK_Insert); +map("Delete", XK_Delete); +map("Home", XK_Home); +map("End", XK_End); +map("PageUp", XK_Prior); +map("PageDown", XK_Next); + +map("Up", XK_Up); +map("Down", XK_Down); +map("Left", XK_Left); +map("Right", XK_Right); + +map("Grave", XK_asciitilde); +map("1", XK_1); +map("2", XK_2); +map("3", XK_3); +map("4", XK_4); +map("5", XK_5); +map("6", XK_6); +map("7", XK_7); +map("8", XK_8); +map("9", XK_9); +map("0", XK_0); +map("Dash", XK_minus); +map("Equal", XK_equal); +map("Backspace", XK_BackSpace); + +map("Tab", XK_Tab); +map("CapsLock", XK_Caps_Lock); +map("LeftEnter", XK_Return); +map("LeftShift", XK_Shift_L); +map("RightShift", XK_Shift_R); +map("LeftControl", XK_Control_L); +map("RightControl", XK_Control_R); +map("LeftAlt", XK_Alt_L); +map("RightAlt", XK_Alt_R); +map("LeftSuper", XK_Super_L); +map("RightSuper", XK_Super_R); +map("Menu", XK_Menu); +map("Space", XK_space); + +map("OpenBracket", XK_bracketleft); +map("CloseBracket", XK_bracketright); +map("Backslash", XK_backslash); +map("Semicolon", XK_semicolon); +map("Apostrophe", XK_apostrophe); +map("Comma", XK_comma); +map("Period", XK_period); +map("Slash", XK_slash); + +map("A", XK_A); +map("B", XK_B); +map("C", XK_C); +map("D", XK_D); +map("E", XK_E); +map("F", XK_F); +map("G", XK_G); +map("H", XK_H); +map("I", XK_I); +map("J", XK_J); +map("K", XK_K); +map("L", XK_L); +map("M", XK_M); +map("N", XK_N); +map("O", XK_O); +map("P", XK_P); +map("Q", XK_Q); +map("R", XK_R); +map("S", XK_S); +map("T", XK_T); +map("U", XK_U); +map("V", XK_V); +map("W", XK_W); +map("X", XK_X); +map("Y", XK_Y); +map("Z", XK_Z); + +map("NumLock", XK_Num_Lock); +map("Divide", XK_KP_Divide); +map("Multiply", XK_KP_Multiply); +map("Subtract", XK_KP_Subtract); +map("Add", XK_KP_Add); +map("RightEnter", XK_KP_Enter); +map("Point", XK_KP_Decimal); + +map("One", XK_KP_1); +map("Two", XK_KP_2); +map("Three", XK_KP_3); +map("Four", XK_KP_4); +map("Five", XK_KP_5); +map("Six", XK_KP_6); +map("Seven", XK_KP_7); +map("Eight", XK_KP_8); +map("Nine", XK_KP_9); +map("Zero", XK_KP_0); + +map("Shift", XK_Shift_L, XK_Shift_R); +map("Control", XK_Control_L, XK_Control_R); +map("Alt", XK_Alt_L, XK_Alt_R); +map("Super", XK_Super_L, XK_Super_R); +map("Enter", XK_Return, XK_KP_Enter); diff --git a/hiro/windows/header.hpp b/hiro/windows/header.hpp index 43717c23..d50ce963 100644 --- a/hiro/windows/header.hpp +++ b/hiro/windows/header.hpp @@ -1,8 +1,8 @@ #define UNICODE -#define WINVER 0x0501 -#define _WIN32_WINNT 0x0501 -#define _WIN32_IE 0x0600 -#define __MSVCRT_VERSION__ 0x0601 +#define WINVER 0x0601 +#define _WIN32_WINNT WINVER +#define _WIN32_IE WINVER +#define __MSVCRT_VERSION__ WINVER #define NOMINMAX #include diff --git a/nall/GNUmakefile b/nall/GNUmakefile index e51a20a8..efcc3bff 100644 --- a/nall/GNUmakefile +++ b/nall/GNUmakefile @@ -41,6 +41,7 @@ link := ifeq ($(compiler),) ifeq ($(platform),windows) compiler := g++ + cppflags := -x c++ -std=gnu++14 else ifeq ($(platform),macosx) compiler := clang++ else ifeq ($(platform),bsd) diff --git a/nall/platform.hpp b/nall/platform.hpp index 2cc2c0c0..717cd4a6 100644 --- a/nall/platform.hpp +++ b/nall/platform.hpp @@ -61,10 +61,8 @@ namespace Math { #undef interface #define dllexport __declspec(dllexport) #define MSG_NOSIGNAL 0 - __declspec(dllimport) auto _fileno(FILE*) -> int; inline auto access(const char* path, int amode) -> int { return _waccess(nall::utf16_t(path), amode); } - inline auto fileno(FILE* stream) -> int { return _fileno(stream); } inline auto getcwd(char* buf, size_t size) -> char* { wchar_t wpath[PATH_MAX] = L""; if(!_wgetcwd(wpath, size)) return nullptr; strcpy(buf, nall::utf8_t(wpath)); return buf; } inline auto mkdir(const char* path, int mode) -> int { return _wmkdir(nall::utf16_t(path)); } inline auto putenv(const char* value) -> int { return _wputenv(nall::utf16_t(value)); } diff --git a/target-tomoko/configuration/configuration.cpp b/target-tomoko/configuration/configuration.cpp index 63e1f1af..6c289e19 100644 --- a/target-tomoko/configuration/configuration.cpp +++ b/target-tomoko/configuration/configuration.cpp @@ -9,6 +9,8 @@ ConfigurationManager::ConfigurationManager() { video.append(video.synchronize, "Synchronize"); video.append(video.scale, "Scale"); video.append(video.aspectCorrection, "AspectCorrection"); + video.append(video.filter, "Filter"); + video.append(video.colorEmulation, "ColorEmulation"); append(video, "Video"); audio.append(audio.driver, "Driver"); diff --git a/target-tomoko/configuration/configuration.hpp b/target-tomoko/configuration/configuration.hpp index 31be1576..0f4015a2 100644 --- a/target-tomoko/configuration/configuration.hpp +++ b/target-tomoko/configuration/configuration.hpp @@ -7,6 +7,8 @@ struct ConfigurationManager : Configuration::Document { bool synchronize = false; string scale = "Normal"; bool aspectCorrection = true; + string filter = "Blur"; + bool colorEmulation = true; } video; struct Audio : Configuration::Node { diff --git a/target-tomoko/input/input.cpp b/target-tomoko/input/input.cpp index 1020455b..9097c8dd 100644 --- a/target-tomoko/input/input.cpp +++ b/target-tomoko/input/input.cpp @@ -19,6 +19,8 @@ auto InputMapping::bind() -> void { } auto InputMapping::bind(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool { + if(device.group[group].input[input].name == "Escape") return unbind(), true; + this->assignment = {hex(device.id), "/", group, "/", input, "/", device.group[group].input[input].name}; this->device = &device; this->group = group; @@ -31,6 +33,13 @@ auto InputMapping::poll() -> int16 { return 0; } +auto InputMapping::unbind() -> void { + this->assignment = "None"; + this->device = nullptr; + this->group = 0; + this->input = 0; +} + // InputManager::InputManager() { diff --git a/target-tomoko/input/input.hpp b/target-tomoko/input/input.hpp index 83e528d3..f749a57e 100644 --- a/target-tomoko/input/input.hpp +++ b/target-tomoko/input/input.hpp @@ -2,6 +2,7 @@ struct InputMapping { auto bind() -> void; auto bind(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool; auto poll() -> int16; + auto unbind() -> void; string name; string assignment = "None"; diff --git a/target-tomoko/library/manager.cpp b/target-tomoko/library/manager.cpp index 731469a7..57a488b9 100644 --- a/target-tomoko/library/manager.cpp +++ b/target-tomoko/library/manager.cpp @@ -15,7 +15,7 @@ LibraryManager::LibraryManager() { setTitle("Library"); setSize({640, 800}); - setPosition({0, 0}); + setPlacement(0.0, 0.0); } auto LibraryManager::show(const string& type) -> void { diff --git a/target-tomoko/presentation/presentation.cpp b/target-tomoko/presentation/presentation.cpp index 1f95b30e..f5d6f421 100644 --- a/target-tomoko/presentation/presentation.cpp +++ b/target-tomoko/presentation/presentation.cpp @@ -39,10 +39,22 @@ Presentation::Presentation() { config().video.scale = "Large"; resizeViewport(); }); + videoFilterMenu.setText("Video Filter"); + MenuRadioItem::group({videoFilterNone, videoFilterBlur}); + if(config().video.filter == "None") videoFilterNone.setChecked(); + if(config().video.filter == "Blur") videoFilterBlur.setChecked(); + videoFilterNone.setText("None").onActivate([&] { config().video.filter = "None"; program->updateVideoFilter(); }); + videoFilterBlur.setText("Blur").onActivate([&] { config().video.filter = "Blur"; program->updateVideoFilter(); }); + colorEmulation.setText("Color Emulation").setChecked(config().video.colorEmulation).onToggle([&] { + config().video.colorEmulation = colorEmulation.checked(); + program->updateVideoPalette(); + }); aspectCorrection.setText("Aspect Correction").setChecked(config().video.aspectCorrection).onToggle([&] { config().video.aspectCorrection = aspectCorrection.checked(); resizeViewport(); }); + maskOverscan.setText("Mask Overscan").onToggle([&] { + }); synchronizeVideo.setText("Synchronize Video").setChecked(config().video.synchronize).onToggle([&] { config().video.synchronize = synchronizeVideo.checked(); video.set(Video::Synchronize, config().video.synchronize); @@ -60,7 +72,21 @@ Presentation::Presentation() { settingsManager->setFocused(); }); - toolsMenu.setText("Tools"); + toolsMenu.setText("Tools").setVisible(false); + saveStateMenu.setText("Save State"); + saveSlot1.setText("Slot 1").onActivate([&] {}); + saveSlot2.setText("Slot 2").onActivate([&] {}); + saveSlot3.setText("Slot 3").onActivate([&] {}); + saveSlot4.setText("Slot 4").onActivate([&] {}); + saveSlot5.setText("Slot 5").onActivate([&] {}); + loadStateMenu.setText("Load State"); + loadSlot1.setText("Slot 1").onActivate([&] {}); + loadSlot2.setText("Slot 2").onActivate([&] {}); + loadSlot3.setText("Slot 3").onActivate([&] {}); + loadSlot4.setText("Slot 4").onActivate([&] {}); + loadSlot5.setText("Slot 5").onActivate([&] {}); + stateManager.setText("State Manager").onActivate([&] {}); + cheatEditor.setText("Cheat Editor").onActivate([&] {}); statusBar.setFont(Font::sans(8, "Bold")); @@ -88,7 +114,7 @@ auto Presentation::resizeViewport() -> void { } setSize({width, height}); - setCentered(); + setPlacement(0.5, 0.5); if(!program->activeEmulator) drawSplashScreen(); } diff --git a/target-tomoko/presentation/presentation.hpp b/target-tomoko/presentation/presentation.hpp index a27fbe16..26b77993 100644 --- a/target-tomoko/presentation/presentation.hpp +++ b/target-tomoko/presentation/presentation.hpp @@ -18,6 +18,12 @@ struct Presentation : Window { MenuRadioItem videoScaleLarge{&videoScaleMenu}; MenuSeparator videoScaleSeparator{&videoScaleMenu}; MenuCheckItem aspectCorrection{&videoScaleMenu}; + MenuCheckItem maskOverscan{&videoScaleMenu}; + Menu videoFilterMenu{&settingsMenu}; + MenuRadioItem videoFilterNone{&videoFilterMenu}; + MenuRadioItem videoFilterBlur{&videoFilterMenu}; + MenuSeparator videoFilterSeparator{&videoFilterMenu}; + MenuCheckItem colorEmulation{&videoFilterMenu}; MenuSeparator settingsMenuSeparator1{&settingsMenu}; MenuCheckItem synchronizeVideo{&settingsMenu}; MenuCheckItem synchronizeAudio{&settingsMenu}; @@ -25,6 +31,21 @@ struct Presentation : Window { MenuSeparator settingsMenuSeparator2{&settingsMenu}; MenuItem showConfiguration{&settingsMenu}; Menu toolsMenu{&menuBar}; + Menu saveStateMenu{&toolsMenu}; + MenuItem saveSlot1{&saveStateMenu}; + MenuItem saveSlot2{&saveStateMenu}; + MenuItem saveSlot3{&saveStateMenu}; + MenuItem saveSlot4{&saveStateMenu}; + MenuItem saveSlot5{&saveStateMenu}; + Menu loadStateMenu{&toolsMenu}; + MenuItem loadSlot1{&loadStateMenu}; + MenuItem loadSlot2{&loadStateMenu}; + MenuItem loadSlot3{&loadStateMenu}; + MenuItem loadSlot4{&loadStateMenu}; + MenuItem loadSlot5{&loadStateMenu}; + MenuSeparator toolsMenuSeparator{&toolsMenu}; + MenuItem stateManager{&toolsMenu}; + MenuItem cheatEditor{&toolsMenu}; VerticalLayout layout{this}; Viewport viewport{&layout, Size{~0, ~0}}; diff --git a/target-tomoko/program/media.cpp b/target-tomoko/program/media.cpp index f03390ca..a2aae4d7 100644 --- a/target-tomoko/program/media.cpp +++ b/target-tomoko/program/media.cpp @@ -20,13 +20,14 @@ auto Program::loadMedia(Emulator::Interface& _emulator, Emulator::Interface::Med mediaPaths(media.id) = location; setEmulator(&_emulator); - emulator().paletteUpdate(Emulator::Interface::PaletteMode::Standard); + updateVideoPalette(); emulator().load(media.id); emulator().power(); presentation->resizeViewport(); presentation->setTitle(emulator().title()); presentation->systemMenu.setVisible(true); + presentation->toolsMenu.setVisible(true); } auto Program::unloadMedia() -> void { @@ -37,4 +38,5 @@ auto Program::unloadMedia() -> void { presentation->setTitle({"tomoko v", Emulator::Version}); presentation->systemMenu.setVisible(false); + presentation->toolsMenu.setVisible(false); } diff --git a/target-tomoko/program/program.cpp b/target-tomoko/program/program.cpp index 456516d3..0412e336 100644 --- a/target-tomoko/program/program.cpp +++ b/target-tomoko/program/program.cpp @@ -5,6 +5,7 @@ #include #include "interface.cpp" #include "media.cpp" +#include "utility.cpp" Program* program = nullptr; Program::Program() { @@ -50,6 +51,8 @@ Program::Program() { dsp.setResamplerFrequency(96000); presentation->drawSplashScreen(); + + updateVideoFilter(); } auto Program::emulator() -> Emulator::Interface& { diff --git a/target-tomoko/program/program.hpp b/target-tomoko/program/program.hpp index 0c3cb313..14b54589 100644 --- a/target-tomoko/program/program.hpp +++ b/target-tomoko/program/program.hpp @@ -24,6 +24,10 @@ struct Program : Emulator::Interface::Bind { auto loadMedia(Emulator::Interface& interface, Emulator::Interface::Media& media, const string& location) -> void; auto unloadMedia() -> void; + //utility.cpp + auto updateVideoFilter() -> void; + auto updateVideoPalette() -> void; + DSP dsp; vector emulators; diff --git a/target-tomoko/program/utility.cpp b/target-tomoko/program/utility.cpp new file mode 100644 index 00000000..815c3227 --- /dev/null +++ b/target-tomoko/program/utility.cpp @@ -0,0 +1,12 @@ +auto Program::updateVideoFilter() -> void { + if(config().video.filter == "None") video.set(Video::Filter, Video::FilterNearest); + if(config().video.filter == "Blur") video.set(Video::Filter, Video::FilterLinear); +} + +auto Program::updateVideoPalette() -> void { + if(!activeEmulator) return; + emulator().paletteUpdate(config().video.colorEmulation + ? Emulator::Interface::PaletteMode::Emulation + : Emulator::Interface::PaletteMode::Standard + ); +} diff --git a/target-tomoko/settings/input.cpp b/target-tomoko/settings/input.cpp index 1db9df71..a74b9e51 100644 --- a/target-tomoko/settings/input.cpp +++ b/target-tomoko/settings/input.cpp @@ -9,10 +9,22 @@ InputSettings::InputSettings(TabFrame* parent) : TabFrameItem(parent) { emulatorList.onChange([&] { reloadPorts(); }); portList.onChange([&] { reloadDevices(); }); deviceList.onChange([&] { reloadMappings(); }); - mappingList.onActivate([&] { assignMapping(); }); + mappingList.onActivate([&] { assignMapping(); }).onChange([&] { + eraseButton.setEnabled((bool)mappingList.selected()); + }); mappingList.setHeaderVisible(); - resetButton.setText("Reset"); - eraseButton.setText("Erase"); + resetButton.setText("Reset").onActivate([&] { + if(MessageDialog("Are you sure you want to erase all mappings for this device?").setParent(*settingsManager).question() == 0) { + for(auto& mapping : activeDevice().mappings) mapping->unbind(); + refreshMappings(); + } + }); + eraseButton.setText("Erase").onActivate([&] { + if(auto mapping = mappingList.selected()) { + activeDevice().mappings[mapping->offset()]->unbind(); + refreshMappings(); + } + }); reloadPorts(); } @@ -45,9 +57,11 @@ auto InputSettings::reloadDevices() -> void { } auto InputSettings::reloadMappings() -> void { + eraseButton.setEnabled(false); mappingList.reset(); mappingList.append(ListViewColumn().setText("Name")); - mappingList.append(ListViewColumn().setText("Mapping")); + mappingList.append(ListViewColumn().setText("Mapping").setWidth(~0)); + mappingList.append(ListViewColumn().setText("Device")); for(auto& mapping : activeDevice().mappings) { mappingList.append(ListViewItem().setText(0, mapping->name)); } @@ -57,7 +71,10 @@ auto InputSettings::reloadMappings() -> void { auto InputSettings::refreshMappings() -> void { unsigned position = 0; for(auto& mapping : activeDevice().mappings) { - mappingList.item(position++)->setText(1, mapping->assignment); + auto path = mapping->assignment.split("/"); + string assignment = path.takeLast(); + string device = path(0); + mappingList.item(position++)->setText(1, assignment).setText(2, device); } mappingList.resizeColumns(); } diff --git a/target-tomoko/settings/settings.cpp b/target-tomoko/settings/settings.cpp index 3edb4f1c..4ad76e16 100644 --- a/target-tomoko/settings/settings.cpp +++ b/target-tomoko/settings/settings.cpp @@ -10,6 +10,8 @@ SettingsManager::SettingsManager() { statusBar.setFont(Font::sans(8, "Bold")); setTitle("Configuration Settings"); - setPosition({0, 0}); setSize({600, 400}); + setPlacement(0.0, 1.0); + + input.mappingList.resizeColumns(); } diff --git a/target-tomoko/settings/settings.hpp b/target-tomoko/settings/settings.hpp index 947b41be..fa394c02 100644 --- a/target-tomoko/settings/settings.hpp +++ b/target-tomoko/settings/settings.hpp @@ -28,7 +28,7 @@ struct AdvancedSettings : TabFrameItem { AdvancedSettings(TabFrame*); VerticalLayout layout{this}; - Label driverLabel{&layout, Size{~0, 0}, 0}; + Label driverLabel{&layout, Size{~0, 0}, 2}; HorizontalLayout driverLayout{&layout, Size{~0, 0}}; Label videoLabel{&driverLayout, Size{0, 0}}; ComboButton videoDriver{&driverLayout, Size{~0, 0}};