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.
This commit is contained in:
Tim Allen 2015-03-07 21:21:47 +11:00
parent a1b2fb0124
commit b4ba95242f
33 changed files with 517 additions and 155 deletions

View File

@ -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/";

View File

@ -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

View File

@ -1,3 +1,5 @@
#include <nall/intrinsics.hpp>
#if defined(HIRO_WINDOWS)
#include "../windows/header.hpp"
#elif defined(HIRO_QT)

View File

@ -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&;

View File

@ -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(),

View File

@ -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; }

View File

@ -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"
{

View File

@ -1,7 +1,9 @@
namespace hiro {
struct pApplication {
#if defined(PLATFORM_XORG)
static XlibDisplay* display;
#endif
static void run();
static bool pendingEvents();

View File

@ -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
}
}

View File

@ -1,11 +1,41 @@
#include <nall/xorg/guard.hpp>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksourcelanguagemanager.h>
#include <gtksourceview/gtksourcestyleschememanager.h>
#include <cairo.h>
#include <X11/Xatom.h>
#include <nall/xorg/guard.hpp>
#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 <winsock2.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <uxtheme.h>
#include <io.h>
#include <shlobj.h>
#include <gdk/gdk.h>
#include <gdk/gdkwin32.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksourcelanguagemanager.h>
#include <gtksourceview/gtksourcestyleschememanager.h>
#include <cairo.h>
#include <nall/windows/registry.hpp>
#include <nall/windows/utf8.hpp>
#endif
#if defined(PLATFORM_XORG)
#include <nall/xorg/guard.hpp>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksourcelanguagemanager.h>
#include <gtksourceview/gtksourcestyleschememanager.h>
#include <cairo.h>
#include <X11/Xatom.h>
#include <nall/xorg/guard.hpp>
#endif

View File

@ -3,7 +3,9 @@ namespace hiro {
auto pKeyboard::poll() -> vector<bool> {
vector<bool> 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<bool> {
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 <hiro/platform/windows/keyboard.hpp>
#endif
map("PrintScreen", XK_Print);
map("ScrollLock", XK_Scroll_Lock);
map("Pause", XK_Pause);
#if defined(PLATFORM_XORG)
#include <hiro/platform/xorg/keyboard.hpp>
#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

View File

@ -4,7 +4,7 @@ struct pKeyboard {
static auto poll() -> vector<bool>;
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;

View File

@ -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;
}

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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 <winsock2.h>

View File

@ -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)

View File

@ -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)); }

View File

@ -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");

View File

@ -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 {

View File

@ -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() {

View File

@ -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";

View File

@ -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 {

View File

@ -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();
}

View File

@ -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}};

View File

@ -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);
}

View File

@ -5,6 +5,7 @@
#include <gba/interface/interface.hpp>
#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& {

View File

@ -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<Emulator::Interface*> emulators;

View File

@ -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
);
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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}};