@@ -23,6 +23,97 @@ if [ "$TRAVIS_BRANCH" = "master" ]; then
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        # move SDL2 libs into folder for deployment
 | 
					        # move SDL2 libs into folder for deployment
 | 
				
			||||||
        dylibbundler -b -x "${REV_NAME}/citra" -cd -d "${REV_NAME}/libs" -p "@executable_path/libs/"
 | 
					        dylibbundler -b -x "${REV_NAME}/citra" -cd -d "${REV_NAME}/libs" -p "@executable_path/libs/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Make the changes to make the citra-qt app standalone (i.e. not dependent on the current brew installation).
 | 
				
			||||||
 | 
					        # To do this, the absolute references to each and every QT framework must be re-written to point to the local frameworks
 | 
				
			||||||
 | 
					        # (in the Contents/Frameworks folder).
 | 
				
			||||||
 | 
					        # The "install_name_tool" is used to do so.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Coreutils is a hack to coerce Homebrew to point to the absolute Cellar path (symlink dereferenced). i.e:
 | 
				
			||||||
 | 
					        # ls -l /usr/local/opt/qt5:: /usr/local/opt/qt5 -> ../Cellar/qt5/5.6.1-1
 | 
				
			||||||
 | 
					        # grealpath ../Cellar/qt5/5.6.1-1:: /usr/local/Cellar/qt5/5.6.1-1
 | 
				
			||||||
 | 
					        brew install coreutils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        REV_NAME_ALT=$REV_NAME/
 | 
				
			||||||
 | 
					        # grealpath is located in coreutils, there is no "realpath" for OS X :(
 | 
				
			||||||
 | 
					        QT_BREWS_PATH=$(grealpath "$(brew --prefix qt5)")
 | 
				
			||||||
 | 
					        BREW_PATH=$(brew --prefix)
 | 
				
			||||||
 | 
					        QT_VERSION_NUM=5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $BREW_PATH/opt/qt5/bin/macdeployqt "${REV_NAME_ALT}citra-qt.app" \
 | 
				
			||||||
 | 
					            -executable="${REV_NAME_ALT}citra-qt.app/Contents/MacOS/citra-qt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # These are the files that macdeployqt packed into Contents/Frameworks/ - we don't want those, so we replace them.
 | 
				
			||||||
 | 
					        declare -a macos_libs=("QtCore" "QtWidgets" "QtGui" "QtOpenGL" "QtPrintSupport")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for macos_lib in "${macos_libs[@]}"
 | 
				
			||||||
 | 
					        do
 | 
				
			||||||
 | 
					            SC_FRAMEWORK_PART=$macos_lib.framework/Versions/$QT_VERSION_NUM/$macos_lib
 | 
				
			||||||
 | 
					            # Replace macdeployqt versions of the Frameworks with our own (from /usr/local/opt/qt5/lib/)
 | 
				
			||||||
 | 
					            cp "$BREW_PATH/opt/qt5/lib/$SC_FRAMEWORK_PART" "${REV_NAME_ALT}citra-qt.app/Contents/Frameworks/$SC_FRAMEWORK_PART"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Replace references within the embedded Framework files with "internal" versions.
 | 
				
			||||||
 | 
					            for macos_lib2 in "${macos_libs[@]}"
 | 
				
			||||||
 | 
					            do
 | 
				
			||||||
 | 
					                # Since brew references both the non-symlinked and symlink paths of QT5, it needs to be duplicated.
 | 
				
			||||||
 | 
					                # /usr/local/Cellar/qt5/5.6.1-1/lib and /usr/local/opt/qt5/lib both resolve to the same files.
 | 
				
			||||||
 | 
					                # So the two lines below are effectively duplicates when resolved as a path, but as strings, they aren't.
 | 
				
			||||||
 | 
					                RM_FRAMEWORK_PART=$macos_lib2.framework/Versions/$QT_VERSION_NUM/$macos_lib2
 | 
				
			||||||
 | 
					                install_name_tool -change \
 | 
				
			||||||
 | 
					                    $QT_BREWS_PATH/lib/$RM_FRAMEWORK_PART \
 | 
				
			||||||
 | 
					                    @executable_path/../Frameworks/$RM_FRAMEWORK_PART \
 | 
				
			||||||
 | 
					                    "${REV_NAME_ALT}citra-qt.app/Contents/Frameworks/$SC_FRAMEWORK_PART"
 | 
				
			||||||
 | 
					                install_name_tool -change \
 | 
				
			||||||
 | 
					                    "$BREW_PATH/opt/qt5/lib/$RM_FRAMEWORK_PART" \
 | 
				
			||||||
 | 
					                    @executable_path/../Frameworks/$RM_FRAMEWORK_PART \
 | 
				
			||||||
 | 
					                    "${REV_NAME_ALT}citra-qt.app/Contents/Frameworks/$SC_FRAMEWORK_PART"
 | 
				
			||||||
 | 
					            done
 | 
				
			||||||
 | 
					        done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Handles `This application failed to start because it could not find or load the Qt platform plugin "cocoa"`
 | 
				
			||||||
 | 
					        # Which manifests itself as:
 | 
				
			||||||
 | 
					        # "Exception Type: EXC_CRASH (SIGABRT) | Exception Codes: 0x0000000000000000, 0x0000000000000000 | Exception Note: EXC_CORPSE_NOTIFY"
 | 
				
			||||||
 | 
					        # There may be more dylibs needed to be fixed...
 | 
				
			||||||
 | 
					        declare -a macos_plugins=("Plugins/platforms/libqcocoa.dylib")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for macos_lib in "${macos_plugins[@]}"
 | 
				
			||||||
 | 
					        do
 | 
				
			||||||
 | 
					            install_name_tool -id @executable_path/../$macos_lib "${REV_NAME_ALT}citra-qt.app/Contents/$macos_lib"
 | 
				
			||||||
 | 
					            for macos_lib2 in "${macos_libs[@]}"
 | 
				
			||||||
 | 
					            do
 | 
				
			||||||
 | 
					                RM_FRAMEWORK_PART=$macos_lib2.framework/Versions/$QT_VERSION_NUM/$macos_lib2
 | 
				
			||||||
 | 
					                install_name_tool -change \
 | 
				
			||||||
 | 
					                    $QT_BREWS_PATH/lib/$RM_FRAMEWORK_PART \
 | 
				
			||||||
 | 
					                    @executable_path/../Frameworks/$RM_FRAMEWORK_PART \
 | 
				
			||||||
 | 
					                    "${REV_NAME_ALT}citra-qt.app/Contents/$macos_lib"
 | 
				
			||||||
 | 
					                install_name_tool -change \
 | 
				
			||||||
 | 
					                    "$BREW_PATH/opt/qt5/lib/$RM_FRAMEWORK_PART" \
 | 
				
			||||||
 | 
					                    @executable_path/../Frameworks/$RM_FRAMEWORK_PART \
 | 
				
			||||||
 | 
					                    "${REV_NAME_ALT}citra-qt.app/Contents/$macos_lib"
 | 
				
			||||||
 | 
					            done
 | 
				
			||||||
 | 
					        done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for macos_lib in "${macos_libs[@]}"
 | 
				
			||||||
 | 
					        do
 | 
				
			||||||
 | 
					            # Debugging info for Travis-CI
 | 
				
			||||||
 | 
					            otool -L "${REV_NAME_ALT}citra-qt.app/Contents/Frameworks/$macos_lib.framework/Versions/$QT_VERSION_NUM/$macos_lib"
 | 
				
			||||||
 | 
					        done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Make the citra-qt.app application launch a debugging terminal.
 | 
				
			||||||
 | 
					        # Store away the actual binary
 | 
				
			||||||
 | 
					        mv ${REV_NAME_ALT}citra-qt.app/Contents/MacOS/citra-qt ${REV_NAME_ALT}citra-qt.app/Contents/MacOS/citra-qt-bin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cat > ${REV_NAME_ALT}citra-qt.app/Contents/MacOS/citra-qt <<EOL
 | 
				
			||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					cd "\`dirname "\$0"\`"
 | 
				
			||||||
 | 
					chmod +x citra-qt-bin
 | 
				
			||||||
 | 
					open citra-qt-bin --args "\$@"
 | 
				
			||||||
 | 
					EOL
 | 
				
			||||||
 | 
					        # Content that will serve as the launching script for citra (within the .app folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Make the launching script executable
 | 
				
			||||||
 | 
					        chmod +x ${REV_NAME_ALT}citra-qt.app/Contents/MacOS/citra-qt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Copy documentation
 | 
					    # Copy documentation
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,11 +66,6 @@ message(STATUS "Target architecture: ${ARCHITECTURE}")
 | 
				
			|||||||
if (NOT MSVC)
 | 
					if (NOT MSVC)
 | 
				
			||||||
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -Wno-attributes")
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -Wno-attributes")
 | 
				
			||||||
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
 | 
					    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (ARCHITECTURE_x86_64)
 | 
					 | 
				
			||||||
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
 | 
					 | 
				
			||||||
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse4.1")
 | 
					 | 
				
			||||||
    endif()
 | 
					 | 
				
			||||||
else()
 | 
					else()
 | 
				
			||||||
    # Silence "deprecation" warnings
 | 
					    # Silence "deprecation" warnings
 | 
				
			||||||
    add_definitions(/D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_WARNINGS)
 | 
					    add_definitions(/D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_WARNINGS)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								externals/cmake-modules/FindSDL2.cmake
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								externals/cmake-modules/FindSDL2.cmake
									
									
									
									
										vendored
									
									
								
							@@ -3,6 +3,7 @@
 | 
				
			|||||||
# SDL2_LIBRARY, the name of the library to link against
 | 
					# SDL2_LIBRARY, the name of the library to link against
 | 
				
			||||||
# SDL2_FOUND, if false, do not try to link to SDL2
 | 
					# SDL2_FOUND, if false, do not try to link to SDL2
 | 
				
			||||||
# SDL2_INCLUDE_DIR, where to find SDL.h
 | 
					# SDL2_INCLUDE_DIR, where to find SDL.h
 | 
				
			||||||
 | 
					# SDL2_DLL_DIR, where to find SDL2.dll if it exists
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This module responds to the the flag:
 | 
					# This module responds to the the flag:
 | 
				
			||||||
# SDL2_BUILDING_LIBRARY
 | 
					# SDL2_BUILDING_LIBRARY
 | 
				
			||||||
@@ -149,6 +150,14 @@ FIND_LIBRARY(SDL2_LIBRARY_TEMP
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
IF(SDL2_LIBRARY_TEMP)
 | 
					IF(SDL2_LIBRARY_TEMP)
 | 
				
			||||||
 | 
					    if(MSVC)
 | 
				
			||||||
 | 
					        get_filename_component(SDL2_DLL_DIR_TEMP ${SDL2_LIBRARY_TEMP} DIRECTORY)
 | 
				
			||||||
 | 
					        if(EXISTS ${SDL2_DLL_DIR_TEMP}/SDL2.dll)
 | 
				
			||||||
 | 
					            set(SDL2_DLL_DIR ${SDL2_DLL_DIR_TEMP})
 | 
				
			||||||
 | 
					            unset(SDL2_DLL_DIR_TEMP)
 | 
				
			||||||
 | 
					        endif()
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FIND_PATH(SDL2_INCLUDE_DIR SDL.h
 | 
					    FIND_PATH(SDL2_INCLUDE_DIR SDL.h
 | 
				
			||||||
        HINTS
 | 
					        HINTS
 | 
				
			||||||
        $ENV{SDL2DIR}
 | 
					        $ENV{SDL2DIR}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ set(SRCS
 | 
				
			|||||||
            configure_dialog.cpp
 | 
					            configure_dialog.cpp
 | 
				
			||||||
            configure_general.cpp
 | 
					            configure_general.cpp
 | 
				
			||||||
            configure_system.cpp
 | 
					            configure_system.cpp
 | 
				
			||||||
 | 
					            configure_input.cpp
 | 
				
			||||||
            game_list.cpp
 | 
					            game_list.cpp
 | 
				
			||||||
            hotkeys.cpp
 | 
					            hotkeys.cpp
 | 
				
			||||||
            main.cpp
 | 
					            main.cpp
 | 
				
			||||||
@@ -54,6 +55,7 @@ set(HEADERS
 | 
				
			|||||||
            configure_dialog.h
 | 
					            configure_dialog.h
 | 
				
			||||||
            configure_general.h
 | 
					            configure_general.h
 | 
				
			||||||
            configure_system.h
 | 
					            configure_system.h
 | 
				
			||||||
 | 
					            configure_input.h
 | 
				
			||||||
            game_list.h
 | 
					            game_list.h
 | 
				
			||||||
            game_list_p.h
 | 
					            game_list_p.h
 | 
				
			||||||
            hotkeys.h
 | 
					            hotkeys.h
 | 
				
			||||||
@@ -72,6 +74,7 @@ set(UIS
 | 
				
			|||||||
            configure_debug.ui
 | 
					            configure_debug.ui
 | 
				
			||||||
            configure_general.ui
 | 
					            configure_general.ui
 | 
				
			||||||
            configure_system.ui
 | 
					            configure_system.ui
 | 
				
			||||||
 | 
					            configure_input.ui
 | 
				
			||||||
            hotkeys.ui
 | 
					            hotkeys.ui
 | 
				
			||||||
            main.ui
 | 
					            main.ui
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
	<key>CFBundleDevelopmentRegion</key>
 | 
						<key>CFBundleDevelopmentRegion</key>
 | 
				
			||||||
	<string>English</string>
 | 
						<string>English</string>
 | 
				
			||||||
	<key>CFBundleExecutable</key>
 | 
						<key>CFBundleExecutable</key>
 | 
				
			||||||
	<string>$(EXECUTABLE_NAME)</string>
 | 
						<string>${EXECUTABLE_NAME}</string>
 | 
				
			||||||
	<key>CFBundleGetInfoString</key>
 | 
						<key>CFBundleGetInfoString</key>
 | 
				
			||||||
	<string></string>
 | 
						<string></string>
 | 
				
			||||||
	<key>CFBundleIconFile</key>
 | 
						<key>CFBundleIconFile</key>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,14 +3,11 @@
 | 
				
			|||||||
// Refer to the license.txt file included.
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QSettings>
 | 
					#include <QSettings>
 | 
				
			||||||
#include <QString>
 | 
					 | 
				
			||||||
#include <QStringList>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "citra_qt/config.h"
 | 
					#include "citra_qt/config.h"
 | 
				
			||||||
#include "citra_qt/ui_settings.h"
 | 
					#include "citra_qt/ui_settings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "common/file_util.h"
 | 
					#include "common/file_util.h"
 | 
				
			||||||
#include "core/settings.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Config::Config() {
 | 
					Config::Config() {
 | 
				
			||||||
    // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
 | 
					    // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
 | 
				
			||||||
@@ -21,7 +18,7 @@ Config::Config() {
 | 
				
			|||||||
    Reload();
 | 
					    Reload();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> defaults = {
 | 
					const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> Config::defaults = {
 | 
				
			||||||
    // directly mapped keys
 | 
					    // directly mapped keys
 | 
				
			||||||
    Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X,
 | 
					    Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X,
 | 
				
			||||||
    Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2,
 | 
					    Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2,
 | 
				
			||||||
@@ -109,7 +106,7 @@ void Config::ReadValues() {
 | 
				
			|||||||
            UISettings::values.shortcuts.emplace_back(
 | 
					            UISettings::values.shortcuts.emplace_back(
 | 
				
			||||||
                        UISettings::Shortcut(group + "/" + hotkey,
 | 
					                        UISettings::Shortcut(group + "/" + hotkey,
 | 
				
			||||||
                                             UISettings::ContextualShortcut(qt_config->value("KeySeq").toString(),
 | 
					                                             UISettings::ContextualShortcut(qt_config->value("KeySeq").toString(),
 | 
				
			||||||
                                                                           qt_config->value("Context").toInt())));
 | 
					                                                                            qt_config->value("Context").toInt())));
 | 
				
			||||||
            qt_config->endGroup();
 | 
					            qt_config->endGroup();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -191,7 +188,7 @@ void Config::SaveValues() {
 | 
				
			|||||||
    qt_config->endGroup();
 | 
					    qt_config->endGroup();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qt_config->beginGroup("Shortcuts");
 | 
					    qt_config->beginGroup("Shortcuts");
 | 
				
			||||||
    for (auto shortcut : UISettings::values.shortcuts ) {
 | 
					    for (auto shortcut : UISettings::values.shortcuts) {
 | 
				
			||||||
        qt_config->setValue(shortcut.first + "/KeySeq", shortcut.second.first);
 | 
					        qt_config->setValue(shortcut.first + "/KeySeq", shortcut.second.first);
 | 
				
			||||||
        qt_config->setValue(shortcut.first + "/Context", shortcut.second.second);
 | 
					        qt_config->setValue(shortcut.first + "/Context", shortcut.second.second);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,13 @@
 | 
				
			|||||||
// Copyright 2014 Citra Emulator Project
 | 
					// Copyright 2014 Citra Emulator Project
 | 
				
			||||||
// Licensed under GPLv2 or any later version
 | 
					// Licensed under GPLv2 or any later version
 | 
				
			||||||
// Refer to the license.txt file included.
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <QVariant>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "core/settings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class QSettings;
 | 
					class QSettings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,4 +23,5 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void Reload();
 | 
					    void Reload();
 | 
				
			||||||
    void Save();
 | 
					    void Save();
 | 
				
			||||||
 | 
					    static const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> defaults;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@
 | 
				
			|||||||
       <string>System</string>
 | 
					       <string>System</string>
 | 
				
			||||||
      </attribute>
 | 
					      </attribute>
 | 
				
			||||||
     </widget>
 | 
					     </widget>
 | 
				
			||||||
     <widget class="QWidget" name="inputTab">
 | 
					     <widget class="ConfigureInput" name="inputTab">
 | 
				
			||||||
      <attribute name="title">
 | 
					      <attribute name="title">
 | 
				
			||||||
       <string>Input</string>
 | 
					       <string>Input</string>
 | 
				
			||||||
      </attribute>
 | 
					      </attribute>
 | 
				
			||||||
@@ -80,6 +80,12 @@
 | 
				
			|||||||
   <header>configure_debug.h</header>
 | 
					   <header>configure_debug.h</header>
 | 
				
			||||||
   <container>1</container>
 | 
					   <container>1</container>
 | 
				
			||||||
  </customwidget>
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					   <customwidget>
 | 
				
			||||||
 | 
					     <class>ConfigureInput</class>
 | 
				
			||||||
 | 
					     <extends>QWidget</extends>
 | 
				
			||||||
 | 
					     <header>configure_input.h</header>
 | 
				
			||||||
 | 
					     <container>1</container>
 | 
				
			||||||
 | 
					   </customwidget>
 | 
				
			||||||
 </customwidgets>
 | 
					 </customwidgets>
 | 
				
			||||||
 <resources/>
 | 
					 <resources/>
 | 
				
			||||||
 <connections>
 | 
					 <connections>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,6 +30,7 @@ void ConfigureDialog::setConfiguration() {
 | 
				
			|||||||
void ConfigureDialog::applyConfiguration() {
 | 
					void ConfigureDialog::applyConfiguration() {
 | 
				
			||||||
    ui->generalTab->applyConfiguration();
 | 
					    ui->generalTab->applyConfiguration();
 | 
				
			||||||
    ui->systemTab->applyConfiguration();
 | 
					    ui->systemTab->applyConfiguration();
 | 
				
			||||||
 | 
					    ui->inputTab->applyConfiguration();
 | 
				
			||||||
    ui->audioTab->applyConfiguration();
 | 
					    ui->audioTab->applyConfiguration();
 | 
				
			||||||
    ui->debugTab->applyConfiguration();
 | 
					    ui->debugTab->applyConfiguration();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										149
									
								
								src/citra_qt/configure_input.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/citra_qt/configure_input.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
				
			|||||||
 | 
					// Copyright 2016 Citra Emulator Project
 | 
				
			||||||
 | 
					// Licensed under GPLv2 or any later version
 | 
				
			||||||
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <QTimer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "citra_qt/configure_input.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ConfigureInput::ConfigureInput(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
 | 
				
			||||||
 | 
					    ui->setupUi(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Initialize mapping of input enum to UI button.
 | 
				
			||||||
 | 
					    input_mapping = {
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::A, ui->buttonA) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::B, ui->buttonB) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::X, ui->buttonX) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::Y, ui->buttonY) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::L, ui->buttonL) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::R, ui->buttonR) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::ZL, ui->buttonZL) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::ZR, ui->buttonZR) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::START, ui->buttonStart) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::SELECT, ui->buttonSelect) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::HOME, ui->buttonHome) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::DUP, ui->buttonDpadUp) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::DDOWN, ui->buttonDpadDown) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::DLEFT, ui->buttonDpadLeft) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::DRIGHT, ui->buttonDpadRight) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CUP, ui->buttonCStickUp) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CDOWN, ui->buttonCStickDown) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CLEFT, ui->buttonCStickLeft) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CRIGHT, ui->buttonCStickRight) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CIRCLE_UP, ui->buttonCircleUp) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CIRCLE_DOWN, ui->buttonCircleDown) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CIRCLE_LEFT, ui->buttonCircleLeft) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CIRCLE_RIGHT, ui->buttonCircleRight) },
 | 
				
			||||||
 | 
					        { std::make_pair(Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod) },
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Attach handle click method to each button click.
 | 
				
			||||||
 | 
					    for (const auto& entry : input_mapping) {
 | 
				
			||||||
 | 
					        connect(entry.second, SIGNAL(released()), this, SLOT(handleClick()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    connect(ui->buttonRestoreDefaults, SIGNAL(released()), this, SLOT(restoreDefaults()));
 | 
				
			||||||
 | 
					    setFocusPolicy(Qt::ClickFocus);
 | 
				
			||||||
 | 
					    timer = new QTimer(this);
 | 
				
			||||||
 | 
					    timer->setSingleShot(true);
 | 
				
			||||||
 | 
					    connect(timer, &QTimer::timeout, this, [&]() { key_pressed = Qt::Key_Escape; setKey(); });
 | 
				
			||||||
 | 
					    this->setConfiguration();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureInput::handleClick() {
 | 
				
			||||||
 | 
					    QPushButton* sender = qobject_cast<QPushButton*>(QObject::sender());
 | 
				
			||||||
 | 
					    previous_mapping = sender->text();
 | 
				
			||||||
 | 
					    sender->setText(tr("[waiting]"));
 | 
				
			||||||
 | 
					    sender->setFocus();
 | 
				
			||||||
 | 
					    grabKeyboard();
 | 
				
			||||||
 | 
					    grabMouse();
 | 
				
			||||||
 | 
					    changing_button = sender;
 | 
				
			||||||
 | 
					    timer->start(5000); //Cancel after 5 seconds
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureInput::applyConfiguration() {
 | 
				
			||||||
 | 
					    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
 | 
				
			||||||
 | 
					        int value = getKeyValue(input_mapping[Settings::NativeInput::Values(i)]->text());
 | 
				
			||||||
 | 
					        Settings::values.input_mappings[Settings::NativeInput::All[i]] = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Settings::Apply();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureInput::setConfiguration() {
 | 
				
			||||||
 | 
					    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
 | 
				
			||||||
 | 
					        QString keyValue = getKeyName(Settings::values.input_mappings[i]);
 | 
				
			||||||
 | 
					        input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureInput::keyPressEvent(QKeyEvent* event) {
 | 
				
			||||||
 | 
					    if (!changing_button)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    if (!event || event->key() == Qt::Key_unknown)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    key_pressed = event->key();
 | 
				
			||||||
 | 
					    timer->stop();
 | 
				
			||||||
 | 
					    setKey();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureInput::setKey() {
 | 
				
			||||||
 | 
					    const QString key_value = getKeyName(key_pressed);
 | 
				
			||||||
 | 
					    if (key_pressed == Qt::Key_Escape)
 | 
				
			||||||
 | 
					        changing_button->setText(previous_mapping);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        changing_button->setText(key_value);
 | 
				
			||||||
 | 
					    removeDuplicates(key_value);
 | 
				
			||||||
 | 
					    key_pressed = Qt::Key_unknown;
 | 
				
			||||||
 | 
					    releaseKeyboard();
 | 
				
			||||||
 | 
					    releaseMouse();
 | 
				
			||||||
 | 
					    changing_button = nullptr;
 | 
				
			||||||
 | 
					    previous_mapping = nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString ConfigureInput::getKeyName(int key_code) const {
 | 
				
			||||||
 | 
					    if (key_code == Qt::Key_Shift)
 | 
				
			||||||
 | 
					        return tr("Shift");
 | 
				
			||||||
 | 
					    if (key_code == Qt::Key_Control)
 | 
				
			||||||
 | 
					        return tr("Ctrl");
 | 
				
			||||||
 | 
					    if (key_code == Qt::Key_Alt)
 | 
				
			||||||
 | 
					        return tr("Alt");
 | 
				
			||||||
 | 
					    if (key_code == Qt::Key_Meta)
 | 
				
			||||||
 | 
					        return "";
 | 
				
			||||||
 | 
					    if (key_code == -1)
 | 
				
			||||||
 | 
					        return "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return QKeySequence(key_code).toString();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Qt::Key ConfigureInput::getKeyValue(const QString& text) const {
 | 
				
			||||||
 | 
					    if (text == "Shift")
 | 
				
			||||||
 | 
					        return Qt::Key_Shift;
 | 
				
			||||||
 | 
					    if (text == "Ctrl")
 | 
				
			||||||
 | 
					        return Qt::Key_Control;
 | 
				
			||||||
 | 
					    if (text == "Alt")
 | 
				
			||||||
 | 
					        return Qt::Key_Alt;
 | 
				
			||||||
 | 
					    if (text == "Meta")
 | 
				
			||||||
 | 
					        return Qt::Key_unknown;
 | 
				
			||||||
 | 
					    if (text == "")
 | 
				
			||||||
 | 
					        return Qt::Key_unknown;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Qt::Key(QKeySequence(text)[0]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureInput::removeDuplicates(const QString& newValue) {
 | 
				
			||||||
 | 
					    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
 | 
				
			||||||
 | 
					        if (changing_button != input_mapping[Settings::NativeInput::Values(i)]) {
 | 
				
			||||||
 | 
					            const QString oldValue = input_mapping[Settings::NativeInput::Values(i)]->text();
 | 
				
			||||||
 | 
					            if (newValue == oldValue)
 | 
				
			||||||
 | 
					                input_mapping[Settings::NativeInput::Values(i)]->setText("");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureInput::restoreDefaults() {
 | 
				
			||||||
 | 
					    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
 | 
				
			||||||
 | 
					        const QString keyValue = getKeyName(Config::defaults[i].toInt());
 | 
				
			||||||
 | 
					        input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										63
									
								
								src/citra_qt/configure_input.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/citra_qt/configure_input.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					// Copyright 2016 Citra Emulator Project
 | 
				
			||||||
 | 
					// Licensed under GPLv2 or any later version
 | 
				
			||||||
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QWidget>
 | 
				
			||||||
 | 
					#include <QKeyEvent>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "citra_qt/config.h"
 | 
				
			||||||
 | 
					#include "core/settings.h"
 | 
				
			||||||
 | 
					#include "ui_configure_input.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class QPushButton;
 | 
				
			||||||
 | 
					class QString;
 | 
				
			||||||
 | 
					class QTimer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ui {
 | 
				
			||||||
 | 
					    class ConfigureInput;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConfigureInput : public QWidget {
 | 
				
			||||||
 | 
					    Q_OBJECT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit ConfigureInput(QWidget* parent = nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Save all button configurations to settings file
 | 
				
			||||||
 | 
					    void applyConfiguration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    std::unique_ptr<Ui::ConfigureInput> ui;
 | 
				
			||||||
 | 
					    std::map<Settings::NativeInput::Values, QPushButton*> input_mapping;
 | 
				
			||||||
 | 
					    int key_pressed;
 | 
				
			||||||
 | 
					    QPushButton* changing_button = nullptr; ///< button currently waiting for key press.
 | 
				
			||||||
 | 
					    QString previous_mapping;
 | 
				
			||||||
 | 
					    QTimer* timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Load configuration settings into button text
 | 
				
			||||||
 | 
					    void setConfiguration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Check all inputs for duplicate keys. Clears out any other button with the same value as this button's new value.
 | 
				
			||||||
 | 
					    void removeDuplicates(const QString& newValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Handle key press event for input tab when a button is 'waiting'.
 | 
				
			||||||
 | 
					    void keyPressEvent(QKeyEvent* event) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Convert key ASCII value to its' letter/name
 | 
				
			||||||
 | 
					    QString getKeyName(int key_code) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Convert letter/name of key to its ASCII value.
 | 
				
			||||||
 | 
					    Qt::Key getKeyValue(const QString& text) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Set button text to name of key pressed.
 | 
				
			||||||
 | 
					    void setKey();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
					    /// Event handler for all button released() event.
 | 
				
			||||||
 | 
					    void handleClick();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Restore all buttons to their default values.
 | 
				
			||||||
 | 
					    void restoreDefaults();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										593
									
								
								src/citra_qt/configure_input.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										593
									
								
								src/citra_qt/configure_input.ui
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,593 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<ui version="4.0">
 | 
				
			||||||
 | 
					 <class>ConfigureInput</class>
 | 
				
			||||||
 | 
					 <widget class="QWidget" name="ConfigureInput">
 | 
				
			||||||
 | 
					  <property name="geometry">
 | 
				
			||||||
 | 
					   <rect>
 | 
				
			||||||
 | 
					    <x>0</x>
 | 
				
			||||||
 | 
					    <y>0</y>
 | 
				
			||||||
 | 
					    <width>370</width>
 | 
				
			||||||
 | 
					    <height>534</height>
 | 
				
			||||||
 | 
					   </rect>
 | 
				
			||||||
 | 
					  </property>
 | 
				
			||||||
 | 
					  <property name="windowTitle">
 | 
				
			||||||
 | 
					   <string>ConfigureInput</string>
 | 
				
			||||||
 | 
					  </property>
 | 
				
			||||||
 | 
					  <layout class="QVBoxLayout" name="verticalLayout_5">
 | 
				
			||||||
 | 
					   <item>
 | 
				
			||||||
 | 
					    <layout class="QGridLayout" name="gridLayout_7">
 | 
				
			||||||
 | 
					     <item row="0" column="0">
 | 
				
			||||||
 | 
					      <widget class="QGroupBox" name="faceButtons">
 | 
				
			||||||
 | 
					       <property name="title">
 | 
				
			||||||
 | 
					        <string>Face Buttons</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="flat">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="checkable">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <layout class="QGridLayout" name="gridLayout">
 | 
				
			||||||
 | 
					        <item row="0" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>A:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonA">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="0" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_2">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_2">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>B:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonB">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_3">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_3">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>X:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonX">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_4">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_4">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Y:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonY">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					       </layout>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					     </item>
 | 
				
			||||||
 | 
					     <item row="0" column="1">
 | 
				
			||||||
 | 
					      <widget class="QGroupBox" name="faceButtons_2">
 | 
				
			||||||
 | 
					       <property name="title">
 | 
				
			||||||
 | 
					        <string>Directional Pad</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="flat">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="checkable">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <layout class="QGridLayout" name="gridLayout_2">
 | 
				
			||||||
 | 
					        <item row="1" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_12">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_34">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Up:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonDpadUp">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_9">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_35">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Down:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonDpadDown">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="0" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_10">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_32">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Left:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonDpadLeft">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="0" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_11">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_33">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Right:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonDpadRight">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					       </layout>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					     </item>
 | 
				
			||||||
 | 
					     <item row="1" column="0">
 | 
				
			||||||
 | 
					      <widget class="QGroupBox" name="faceButtons_3">
 | 
				
			||||||
 | 
					       <property name="title">
 | 
				
			||||||
 | 
					        <string>Shoulder Buttons</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="flat">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="checkable">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <layout class="QGridLayout" name="gridLayout_3">
 | 
				
			||||||
 | 
					        <item row="0" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_13">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_17">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>L:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonL">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="0" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_14">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_19">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>R:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonR">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_15">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_20">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>ZL:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonZL">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_16">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_18">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>ZR:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonZR">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					       </layout>
 | 
				
			||||||
 | 
					       <zorder></zorder>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					     </item>
 | 
				
			||||||
 | 
					     <item row="1" column="1">
 | 
				
			||||||
 | 
					      <widget class="QGroupBox" name="faceButtons_4">
 | 
				
			||||||
 | 
					       <property name="title">
 | 
				
			||||||
 | 
					        <string>Circle Pad</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="flat">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="checkable">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <layout class="QGridLayout" name="gridLayout_4">
 | 
				
			||||||
 | 
					        <item row="0" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_17">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_21">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Left:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCircleLeft">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="0" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_18">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_23">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Right:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCircleRight">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_19">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_24">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Up:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCircleUp">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_20">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_22">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Down:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCircleDown">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					       </layout>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					     </item>
 | 
				
			||||||
 | 
					     <item row="2" column="0">
 | 
				
			||||||
 | 
					      <widget class="QGroupBox" name="faceButtons_5">
 | 
				
			||||||
 | 
					       <property name="title">
 | 
				
			||||||
 | 
					        <string>C-Stick</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="flat">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="checkable">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <layout class="QGridLayout" name="gridLayout_5">
 | 
				
			||||||
 | 
					        <item row="0" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_21">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_25">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Left:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCStickLeft">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="0" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_22">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_27">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Right:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCStickRight">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_23">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_28">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Up:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCStickUp">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_24">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_26">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Down:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCStickDown">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					       </layout>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					     </item>
 | 
				
			||||||
 | 
					     <item row="2" column="1">
 | 
				
			||||||
 | 
					      <widget class="QGroupBox" name="faceButtons_6">
 | 
				
			||||||
 | 
					       <property name="title">
 | 
				
			||||||
 | 
					        <string>Misc.</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="flat">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="checkable">
 | 
				
			||||||
 | 
					        <bool>false</bool>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <layout class="QGridLayout" name="gridLayout_6">
 | 
				
			||||||
 | 
					        <item row="0" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_25">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_29">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Start:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonStart">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="0" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_26">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_30">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Select:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonSelect">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="0">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_27">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_31">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Home:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonHome">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item row="1" column="1">
 | 
				
			||||||
 | 
					         <layout class="QVBoxLayout" name="verticalLayout_28">
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QLabel" name="label_34">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>Circle Mod:</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					          <item>
 | 
				
			||||||
 | 
					           <widget class="QPushButton" name="buttonCircleMod">
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string/>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </widget>
 | 
				
			||||||
 | 
					          </item>
 | 
				
			||||||
 | 
					         </layout>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					       </layout>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					     </item>
 | 
				
			||||||
 | 
					    </layout>
 | 
				
			||||||
 | 
					   </item>
 | 
				
			||||||
 | 
					   <item>
 | 
				
			||||||
 | 
					    <layout class="QHBoxLayout" name="horizontalLayout">
 | 
				
			||||||
 | 
					     <item>
 | 
				
			||||||
 | 
					      <spacer name="horizontalSpacer">
 | 
				
			||||||
 | 
					       <property name="orientation">
 | 
				
			||||||
 | 
					        <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="sizeHint" stdset="0">
 | 
				
			||||||
 | 
					        <size>
 | 
				
			||||||
 | 
					         <width>40</width>
 | 
				
			||||||
 | 
					         <height>20</height>
 | 
				
			||||||
 | 
					        </size>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					      </spacer>
 | 
				
			||||||
 | 
					     </item>
 | 
				
			||||||
 | 
					     <item>
 | 
				
			||||||
 | 
					      <widget class="QPushButton" name="buttonRestoreDefaults">
 | 
				
			||||||
 | 
					       <property name="sizePolicy">
 | 
				
			||||||
 | 
					        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
 | 
				
			||||||
 | 
					         <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					         <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					        </sizepolicy>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="sizeIncrement">
 | 
				
			||||||
 | 
					        <size>
 | 
				
			||||||
 | 
					         <width>0</width>
 | 
				
			||||||
 | 
					         <height>0</height>
 | 
				
			||||||
 | 
					        </size>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="baseSize">
 | 
				
			||||||
 | 
					        <size>
 | 
				
			||||||
 | 
					         <width>0</width>
 | 
				
			||||||
 | 
					         <height>0</height>
 | 
				
			||||||
 | 
					        </size>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="layoutDirection">
 | 
				
			||||||
 | 
					        <enum>Qt::LeftToRight</enum>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <property name="text">
 | 
				
			||||||
 | 
					        <string>Restore Defaults</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					     </item>
 | 
				
			||||||
 | 
					    </layout>
 | 
				
			||||||
 | 
					   </item>
 | 
				
			||||||
 | 
					  </layout>
 | 
				
			||||||
 | 
					 </widget>
 | 
				
			||||||
 | 
					 <resources/>
 | 
				
			||||||
 | 
					 <connections/>
 | 
				
			||||||
 | 
					</ui>
 | 
				
			||||||
@@ -513,6 +513,7 @@ void GMainWindow::OnConfigure() {
 | 
				
			|||||||
    if (result == QDialog::Accepted)
 | 
					    if (result == QDialog::Accepted)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        configureDialog.applyConfiguration();
 | 
					        configureDialog.applyConfiguration();
 | 
				
			||||||
 | 
					        render_window->ReloadSetKeymaps();
 | 
				
			||||||
        config->Save();
 | 
					        config->Save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,7 +51,6 @@ static bool IsWithinTouchscreen(const EmuWindow::FramebufferLayout& layout, unsi
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::tuple<unsigned,unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) {
 | 
					std::tuple<unsigned,unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    new_x = std::max(new_x, framebuffer_layout.bottom_screen.left);
 | 
					    new_x = std::max(new_x, framebuffer_layout.bottom_screen.left);
 | 
				
			||||||
    new_x = std::min(new_x, framebuffer_layout.bottom_screen.right-1);
 | 
					    new_x = std::min(new_x, framebuffer_layout.bottom_screen.right-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -92,9 +91,9 @@ void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(unsigned width, unsigned height) {
 | 
					EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(unsigned width, unsigned height) {
 | 
				
			||||||
 | 
					    // When hiding the widget, the function receives a size of 0
 | 
				
			||||||
    ASSERT(width > 0);
 | 
					    if (width == 0) width = 1;
 | 
				
			||||||
    ASSERT(height > 0);
 | 
					    if (height == 0) height = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EmuWindow::FramebufferLayout res = { width, height, {}, {} };
 | 
					    EmuWindow::FramebufferLayout res = { width, height, {}, {} };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,8 @@
 | 
				
			|||||||
// Licensed under GPLv2 or any later version
 | 
					// Licensed under GPLv2 or any later version
 | 
				
			||||||
// Refer to the license.txt file included.
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// We can provide simple Thumb simulation by decoding the Thumb instruction into its corresponding
 | 
					// We can provide simple Thumb simulation by decoding the Thumb instruction into its corresponding
 | 
				
			||||||
// ARM instruction, and using the existing ARM simulator.
 | 
					// ARM instruction, and using the existing ARM simulator.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -293,15 +295,22 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
 | 
				
			|||||||
                    | (BIT(tinstr, 4) << 18); // enable bit
 | 
					                    | (BIT(tinstr, 4) << 18); // enable bit
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else if ((tinstr & 0x0F00) == 0x0a00) {
 | 
					        } else if ((tinstr & 0x0F00) == 0x0a00) {
 | 
				
			||||||
            static const u32 subset[3] = {
 | 
					            static const u32 subset[4] = {
 | 
				
			||||||
                0xE6BF0F30, // REV
 | 
					                0xE6BF0F30, // REV
 | 
				
			||||||
                0xE6BF0FB0, // REV16
 | 
					                0xE6BF0FB0, // REV16
 | 
				
			||||||
 | 
					                0,          // undefined
 | 
				
			||||||
                0xE6FF0FB0, // REVSH
 | 
					                0xE6FF0FB0, // REVSH
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            *ainstr = subset[BITS(tinstr, 6, 7)] // base
 | 
					            size_t subset_index = BITS(tinstr, 6, 7);
 | 
				
			||||||
                | (BITS(tinstr, 0, 2) << 12)     // Rd
 | 
					
 | 
				
			||||||
                | BITS(tinstr, 3, 5);            // Rm
 | 
					            if (subset_index == 2) {
 | 
				
			||||||
 | 
					                valid = ThumbDecodeStatus::UNDEFINED;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                *ainstr = subset[subset_index]       // base
 | 
				
			||||||
 | 
					                    | (BITS(tinstr, 0, 2) << 12)     // Rd
 | 
				
			||||||
 | 
					                    | BITS(tinstr, 3, 5);            // Rm
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            static const u32 subset[4] = {
 | 
					            static const u32 subset[4] = {
 | 
				
			||||||
                0xE92D0000, // STMDB sp!,{rlist}
 | 
					                0xE92D0000, // STMDB sp!,{rlist}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@
 | 
				
			|||||||
extern int g_clock_rate_arm11;
 | 
					extern int g_clock_rate_arm11;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline s64 msToCycles(int ms) {
 | 
					inline s64 msToCycles(int ms) {
 | 
				
			||||||
    return g_clock_rate_arm11 / 1000 * ms;
 | 
					    return (s64)g_clock_rate_arm11 / 1000 * ms;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline s64 msToCycles(float ms) {
 | 
					inline s64 msToCycles(float ms) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,8 @@ static u32 cpu_percent; ///< CPU time available to the running application
 | 
				
			|||||||
// APT::CheckNew3DSApp will check this unknown_ns_state_field to determine processing mode
 | 
					// APT::CheckNew3DSApp will check this unknown_ns_state_field to determine processing mode
 | 
				
			||||||
static u8 unknown_ns_state_field;
 | 
					static u8 unknown_ns_state_field;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ScreencapPostPermission screen_capture_post_permission;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Parameter data to be returned in the next call to Glance/ReceiveParameter
 | 
					/// Parameter data to be returned in the next call to Glance/ReceiveParameter
 | 
				
			||||||
static MessageParameter next_parameter;
 | 
					static MessageParameter next_parameter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -70,6 +72,13 @@ void Initialize(Service::Interface* self) {
 | 
				
			|||||||
void GetSharedFont(Service::Interface* self) {
 | 
					void GetSharedFont(Service::Interface* self) {
 | 
				
			||||||
    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
					    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!shared_font_mem) {
 | 
				
			||||||
 | 
					        LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds");
 | 
				
			||||||
 | 
					        cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
 | 
				
			||||||
 | 
					        cmd_buff[1] = -1;  // TODO: Find the right error code
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The shared font has to be relocated to the new address before being passed to the application.
 | 
					    // The shared font has to be relocated to the new address before being passed to the application.
 | 
				
			||||||
    VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address);
 | 
					    VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address);
 | 
				
			||||||
    // The shared font dumped by 3dsutils (https://github.com/citra-emu/3dsutils) uses this address as base,
 | 
					    // The shared font dumped by 3dsutils (https://github.com/citra-emu/3dsutils) uses this address as base,
 | 
				
			||||||
@@ -382,23 +391,23 @@ void StartLibraryApplet(Service::Interface* self) {
 | 
				
			|||||||
    cmd_buff[1] = applet->Start(parameter).raw;
 | 
					    cmd_buff[1] = applet->Start(parameter).raw;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SetNSStateField(Service::Interface* self) {
 | 
					void SetScreenCapPostPermission(Service::Interface* self) {
 | 
				
			||||||
    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
					    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unknown_ns_state_field = cmd_buff[1];
 | 
					    screen_capture_post_permission = static_cast<ScreencapPostPermission>(cmd_buff[1] & 0xF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0);
 | 
					    cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0);
 | 
				
			||||||
    cmd_buff[1] = RESULT_SUCCESS.raw;
 | 
					    cmd_buff[1] = RESULT_SUCCESS.raw;
 | 
				
			||||||
    LOG_WARNING(Service_APT, "(STUBBED) unknown_ns_state_field=%u", unknown_ns_state_field);
 | 
					    LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void GetNSStateField(Service::Interface* self) {
 | 
					void GetScreenCapPostPermission(Service::Interface* self) {
 | 
				
			||||||
    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
					    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0);
 | 
					    cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0);
 | 
				
			||||||
    cmd_buff[1] = RESULT_SUCCESS.raw;
 | 
					    cmd_buff[1] = RESULT_SUCCESS.raw;
 | 
				
			||||||
    cmd_buff[8] = unknown_ns_state_field;
 | 
					    cmd_buff[2] = static_cast<u32>(screen_capture_post_permission);
 | 
				
			||||||
    LOG_WARNING(Service_APT, "(STUBBED) unknown_ns_state_field=%u", unknown_ns_state_field);
 | 
					    LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void GetAppletInfo(Service::Interface* self) {
 | 
					void GetAppletInfo(Service::Interface* self) {
 | 
				
			||||||
@@ -493,6 +502,7 @@ void Init() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    cpu_percent = 0;
 | 
					    cpu_percent = 0;
 | 
				
			||||||
    unknown_ns_state_field = 0;
 | 
					    unknown_ns_state_field = 0;
 | 
				
			||||||
 | 
					    screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
 | 
					    // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
 | 
				
			||||||
    notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification");
 | 
					    notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,6 +94,13 @@ enum class StartupArgumentType : u32 {
 | 
				
			|||||||
    OtherMedia = 2,
 | 
					    OtherMedia = 2,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class ScreencapPostPermission : u32 {
 | 
				
			||||||
 | 
					    CleanThePermission                 = 0, //TODO(JamePeng): verify what "zero" means
 | 
				
			||||||
 | 
					    NoExplicitSetting                  = 1,
 | 
				
			||||||
 | 
					    EnableScreenshotPostingToMiiverse  = 2,
 | 
				
			||||||
 | 
					    DisableScreenshotPostingToMiiverse = 3
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Send a parameter to the currently-running application, which will read it via ReceiveParameter
 | 
					/// Send a parameter to the currently-running application, which will read it via ReceiveParameter
 | 
				
			||||||
void SendParameter(const MessageParameter& parameter);
 | 
					void SendParameter(const MessageParameter& parameter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -383,25 +390,24 @@ void StartLibraryApplet(Service::Interface* self);
 | 
				
			|||||||
void GetStartupArgument(Service::Interface* self);
 | 
					void GetStartupArgument(Service::Interface* self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * APT::SetNSStateField service function
 | 
					 * APT::SetScreenCapPostPermission service function
 | 
				
			||||||
 *  Inputs:
 | 
					 *  Inputs:
 | 
				
			||||||
 *      1 : u8 NS state field
 | 
					 *      0 : Header Code[0x00550040]
 | 
				
			||||||
 | 
					 *      1 : u8 The screenshot posting permission
 | 
				
			||||||
 *  Outputs:
 | 
					 *  Outputs:
 | 
				
			||||||
 *      1 : Result of function, 0 on success, otherwise error code
 | 
					 *      1 : Result of function, 0 on success, otherwise error code
 | 
				
			||||||
 *  Note:
 | 
					 | 
				
			||||||
 *      This writes the input u8 to a NS state field.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void SetNSStateField(Service::Interface* self);
 | 
					void SetScreenCapPostPermission(Service::Interface* self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * APT::GetNSStateField service function
 | 
					 * APT::GetScreenCapPostPermission service function
 | 
				
			||||||
 | 
					 *  Inputs:
 | 
				
			||||||
 | 
					 *      0 : Header Code[0x00560000]
 | 
				
			||||||
 *  Outputs:
 | 
					 *  Outputs:
 | 
				
			||||||
 *      1 : Result of function, 0 on success, otherwise error code
 | 
					 *      1 : Result of function, 0 on success, otherwise error code
 | 
				
			||||||
 *      8 : u8 NS state field
 | 
					 *      2 : u8 The screenshot posting permission
 | 
				
			||||||
 *  Note:
 | 
					 | 
				
			||||||
 *      This returns a u8 NS state field(which can be set by cmd 0x00550040), at cmdreply+8.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void GetNSStateField(Service::Interface* self);
 | 
					void GetScreenCapPostPermission(Service::Interface* self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * APT::CheckNew3DSApp service function
 | 
					 * APT::CheckNew3DSApp service function
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,8 +33,8 @@ const Interface::FunctionInfo FunctionTable[] = {
 | 
				
			|||||||
    {0x004F0080, SetAppCpuTimeLimit,           "SetAppCpuTimeLimit"},
 | 
					    {0x004F0080, SetAppCpuTimeLimit,           "SetAppCpuTimeLimit"},
 | 
				
			||||||
    {0x00500040, GetAppCpuTimeLimit,           "GetAppCpuTimeLimit"},
 | 
					    {0x00500040, GetAppCpuTimeLimit,           "GetAppCpuTimeLimit"},
 | 
				
			||||||
    {0x00510080, GetStartupArgument,           "GetStartupArgument"},
 | 
					    {0x00510080, GetStartupArgument,           "GetStartupArgument"},
 | 
				
			||||||
    {0x00550040, SetNSStateField,              "SetNSStateField?"},
 | 
					    {0x00550040, SetScreenCapPostPermission,   "SetScreenCapPostPermission"},
 | 
				
			||||||
    {0x00560000, GetNSStateField,              "GetNSStateField?"},
 | 
					    {0x00560000, GetScreenCapPostPermission,   "GetScreenCapPostPermission"},
 | 
				
			||||||
    {0x01010000, CheckNew3DSApp,               "CheckNew3DSApp"},
 | 
					    {0x01010000, CheckNew3DSApp,               "CheckNew3DSApp"},
 | 
				
			||||||
    {0x01020000, CheckNew3DS,                  "CheckNew3DS"}
 | 
					    {0x01020000, CheckNew3DS,                  "CheckNew3DS"}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,8 +92,8 @@ const Interface::FunctionInfo FunctionTable[] = {
 | 
				
			|||||||
    {0x00510080, GetStartupArgument,    "GetStartupArgument"},
 | 
					    {0x00510080, GetStartupArgument,    "GetStartupArgument"},
 | 
				
			||||||
    {0x00520104, nullptr,               "Wrap1"},
 | 
					    {0x00520104, nullptr,               "Wrap1"},
 | 
				
			||||||
    {0x00530104, nullptr,               "Unwrap1"},
 | 
					    {0x00530104, nullptr,               "Unwrap1"},
 | 
				
			||||||
    {0x00550040, SetNSStateField,       "SetNSStateField?" },
 | 
					    {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"},
 | 
				
			||||||
    {0x00560000, GetNSStateField,       "GetNSStateField?" },
 | 
					    {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
 | 
				
			||||||
    {0x00580002, nullptr,               "GetProgramID"},
 | 
					    {0x00580002, nullptr,               "GetProgramID"},
 | 
				
			||||||
    {0x01010000, CheckNew3DSApp,        "CheckNew3DSApp"},
 | 
					    {0x01010000, CheckNew3DSApp,        "CheckNew3DSApp"},
 | 
				
			||||||
    {0x01020000, CheckNew3DS,           "CheckNew3DS"}
 | 
					    {0x01020000, CheckNew3DS,           "CheckNew3DS"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,8 +92,8 @@ const Interface::FunctionInfo FunctionTable[] = {
 | 
				
			|||||||
    {0x00510080, GetStartupArgument,              "GetStartupArgument"},
 | 
					    {0x00510080, GetStartupArgument,              "GetStartupArgument"},
 | 
				
			||||||
    {0x00520104, nullptr,                         "Wrap1"},
 | 
					    {0x00520104, nullptr,                         "Wrap1"},
 | 
				
			||||||
    {0x00530104, nullptr,                         "Unwrap1"},
 | 
					    {0x00530104, nullptr,                         "Unwrap1"},
 | 
				
			||||||
    {0x00550040, SetNSStateField,                 "SetNSStateField?"},
 | 
					    {0x00550040, SetScreenCapPostPermission,      "SetScreenCapPostPermission"},
 | 
				
			||||||
    {0x00560000, GetNSStateField,                 "GetNSStateField?"},
 | 
					    {0x00560000, GetScreenCapPostPermission,      "GetScreenCapPostPermission"},
 | 
				
			||||||
    {0x00580002, nullptr,                         "GetProgramID"},
 | 
					    {0x00580002, nullptr,                         "GetProgramID"},
 | 
				
			||||||
    {0x01010000, CheckNew3DSApp,                  "CheckNew3DSApp"},
 | 
					    {0x01010000, CheckNew3DSApp,                  "CheckNew3DSApp"},
 | 
				
			||||||
    {0x01020000, CheckNew3DS,                     "CheckNew3DS"}
 | 
					    {0x01020000, CheckNew3DS,                     "CheckNew3DS"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,11 @@
 | 
				
			|||||||
// Licensed under GPLv2 or any later version
 | 
					// Licensed under GPLv2 or any later version
 | 
				
			||||||
// Refer to the license.txt file included.
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <chrono>
 | 
				
			||||||
#include <cstring>
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <ctime>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "core/core_timing.h"
 | 
				
			||||||
#include "core/hle/shared_page.h"
 | 
					#include "core/hle/shared_page.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
					////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
@@ -12,6 +15,57 @@ namespace SharedPage {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
SharedPageDef shared_page;
 | 
					SharedPageDef shared_page;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int update_time_event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond.
 | 
				
			||||||
 | 
					static u64 GetSystemTime() {
 | 
				
			||||||
 | 
					    auto now = std::chrono::system_clock::now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 3DS system does't allow user to set a time before Jan 1 2000,
 | 
				
			||||||
 | 
					    // so we use it as an auxiliary epoch to calculate the console time.
 | 
				
			||||||
 | 
					    std::tm epoch_tm;
 | 
				
			||||||
 | 
					    epoch_tm.tm_sec = 0;
 | 
				
			||||||
 | 
					    epoch_tm.tm_min = 0;
 | 
				
			||||||
 | 
					    epoch_tm.tm_hour = 0;
 | 
				
			||||||
 | 
					    epoch_tm.tm_mday = 1;
 | 
				
			||||||
 | 
					    epoch_tm.tm_mon = 0;
 | 
				
			||||||
 | 
					    epoch_tm.tm_year = 100;
 | 
				
			||||||
 | 
					    epoch_tm.tm_isdst = 0;
 | 
				
			||||||
 | 
					    auto epoch = std::chrono::system_clock::from_time_t(std::mktime(&epoch_tm));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 3DS console time uses Jan 1 1900 as internal epoch,
 | 
				
			||||||
 | 
					    // so we use the milliseconds between 1900 and 2000 as base console time
 | 
				
			||||||
 | 
					    u64 console_time = 3155673600000ULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Only when system time is after 2000, we set it as 3DS system time
 | 
				
			||||||
 | 
					    if (now > epoch) {
 | 
				
			||||||
 | 
					        console_time += std::chrono::duration_cast<std::chrono::milliseconds>(now - epoch).count();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If the system time is in daylight saving, we give an additional hour to console time
 | 
				
			||||||
 | 
					    std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
 | 
				
			||||||
 | 
					    std::tm* now_tm = std::localtime(&now_time_t);
 | 
				
			||||||
 | 
					    if (now_tm && now_tm->tm_isdst > 0)
 | 
				
			||||||
 | 
					        console_time += 60 * 60 * 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return console_time;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void UpdateTimeCallback(u64 userdata, int cycles_late) {
 | 
				
			||||||
 | 
					    DateTime& date_time = shared_page.date_time_counter % 2 ?
 | 
				
			||||||
 | 
					        shared_page.date_time_0 : shared_page.date_time_1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    date_time.date_time = GetSystemTime();
 | 
				
			||||||
 | 
					    date_time.update_tick = CoreTiming::GetTicks();
 | 
				
			||||||
 | 
					    date_time.tick_to_second_coefficient = g_clock_rate_arm11;
 | 
				
			||||||
 | 
					    date_time.tick_offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ++shared_page.date_time_counter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // system time is updated hourly
 | 
				
			||||||
 | 
					    CoreTiming::ScheduleEvent(msToCycles(60 * 60 * 1000) - cycles_late, update_time_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Init() {
 | 
					void Init() {
 | 
				
			||||||
    std::memset(&shared_page, 0, sizeof(shared_page));
 | 
					    std::memset(&shared_page, 0, sizeof(shared_page));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,6 +73,9 @@ void Init() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Some games wait until this value becomes 0x1, before asking running_hw
 | 
					    // Some games wait until this value becomes 0x1, before asking running_hw
 | 
				
			||||||
    shared_page.unknown_value = 0x1;
 | 
					    shared_page.unknown_value = 0x1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update_time_event = CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
 | 
				
			||||||
 | 
					    CoreTiming::ScheduleEvent(0, update_time_event);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace
 | 
					} // namespace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,13 +25,14 @@ namespace SharedPage {
 | 
				
			|||||||
struct DateTime {
 | 
					struct DateTime {
 | 
				
			||||||
    u64_le date_time;                  // 0
 | 
					    u64_le date_time;                  // 0
 | 
				
			||||||
    u64_le update_tick;                // 8
 | 
					    u64_le update_tick;                // 8
 | 
				
			||||||
    INSERT_PADDING_BYTES(0x20 - 0x10); // 10
 | 
					    u64_le tick_to_second_coefficient; // 10
 | 
				
			||||||
 | 
					    u64_le tick_offset;                // 18
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
 | 
					static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SharedPageDef {
 | 
					struct SharedPageDef {
 | 
				
			||||||
    // Most of these names are taken from the 3dbrew page linked above.
 | 
					    // Most of these names are taken from the 3dbrew page linked above.
 | 
				
			||||||
    u32_le   date_time_selector;         // 0
 | 
					    u32_le   date_time_counter;          // 0
 | 
				
			||||||
    u8       running_hw;                 // 4
 | 
					    u8       running_hw;                 // 4
 | 
				
			||||||
    /// "Microcontroller hardware info"
 | 
					    /// "Microcontroller hardware info"
 | 
				
			||||||
    u8       mcu_hw_info;                // 5
 | 
					    u8       mcu_hw_info;                // 5
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user