diff options
41 files changed, 692 insertions, 195 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..d7201387a --- /dev/null +++ b/.gitmodules | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | [submodule "externals/inih/inih"] | ||
| 2 | path = externals/inih/inih | ||
| 3 | url = https://github.com/svn2github/inih | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt index 83b0863f9..bbe9f76cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -68,7 +68,7 @@ if (ENABLE_GLFW) | |||
| 68 | if (NOT APPLE) | 68 | if (NOT APPLE) |
| 69 | find_package(X11 REQUIRED) | 69 | find_package(X11 REQUIRED) |
| 70 | endif() | 70 | endif() |
| 71 | 71 | ||
| 72 | find_package(PkgConfig REQUIRED) | 72 | find_package(PkgConfig REQUIRED) |
| 73 | pkg_search_module(GLFW REQUIRED glfw3) | 73 | pkg_search_module(GLFW REQUIRED glfw3) |
| 74 | endif() | 74 | endif() |
| @@ -127,6 +127,10 @@ get_git_head_revision(GIT_REF_SPEC GIT_REV) | |||
| 127 | git_describe(GIT_DESC --always --long --dirty) | 127 | git_describe(GIT_DESC --always --long --dirty) |
| 128 | git_branch_name(GIT_BRANCH) | 128 | git_branch_name(GIT_BRANCH) |
| 129 | 129 | ||
| 130 | set(INI_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/externals/inih") | ||
| 131 | include_directories(${INI_PREFIX}) | ||
| 132 | add_subdirectory(${INI_PREFIX}) | ||
| 133 | |||
| 130 | # process subdirectories | 134 | # process subdirectories |
| 131 | if(ENABLE_QT) | 135 | if(ENABLE_QT) |
| 132 | include_directories(externals/qhexedit) | 136 | include_directories(externals/qhexedit) |
diff --git a/externals/inih/CMakeLists.txt b/externals/inih/CMakeLists.txt new file mode 100644 index 000000000..c87f78bfc --- /dev/null +++ b/externals/inih/CMakeLists.txt | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | set(SRCS | ||
| 2 | inih/ini.c | ||
| 3 | inih/cpp/INIReader.cpp | ||
| 4 | ) | ||
| 5 | set(HEADERS | ||
| 6 | inih/ini.h | ||
| 7 | inih/cpp/INIReader.h | ||
| 8 | ) | ||
| 9 | |||
| 10 | create_directory_groups(${SRCS} ${HEADERS}) | ||
| 11 | add_library(inih ${SRCS} ${HEADERS}) | ||
diff --git a/externals/inih/inih b/externals/inih/inih new file mode 160000 | |||
| Subproject 603729dec89aaca42d7bd08f08bc333165b7d5d | |||
diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt index f10f3e603..f2add394f 100644 --- a/src/citra/CMakeLists.txt +++ b/src/citra/CMakeLists.txt | |||
| @@ -1,9 +1,12 @@ | |||
| 1 | set(SRCS | 1 | set(SRCS |
| 2 | emu_window/emu_window_glfw.cpp | 2 | emu_window/emu_window_glfw.cpp |
| 3 | citra.cpp | 3 | citra.cpp |
| 4 | config.cpp | ||
| 4 | ) | 5 | ) |
| 5 | set(HEADERS | 6 | set(HEADERS |
| 6 | emu_window/emu_window_glfw.h | 7 | emu_window/emu_window_glfw.h |
| 8 | config.h | ||
| 9 | default_ini.h | ||
| 7 | resource.h | 10 | resource.h |
| 8 | ) | 11 | ) |
| 9 | 12 | ||
| @@ -16,7 +19,7 @@ endif() | |||
| 16 | 19 | ||
| 17 | add_executable(citra ${SRCS} ${HEADERS}) | 20 | add_executable(citra ${SRCS} ${HEADERS}) |
| 18 | target_link_libraries(citra core common video_core) | 21 | target_link_libraries(citra core common video_core) |
| 19 | target_link_libraries(citra ${OPENGL_gl_LIBRARY} ${GLFW_LIBRARIES}) | 22 | target_link_libraries(citra ${OPENGL_gl_LIBRARY} ${GLFW_LIBRARIES} inih) |
| 20 | 23 | ||
| 21 | if (APPLE) | 24 | if (APPLE) |
| 22 | target_link_libraries(citra iconv pthread ${COREFOUNDATION_LIBRARY}) | 25 | target_link_libraries(citra iconv pthread ${COREFOUNDATION_LIBRARY}) |
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index 7dc721dc3..46781defa 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp | |||
| @@ -4,12 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/common.h" | 5 | #include "common/common.h" |
| 6 | #include "common/log_manager.h" | 6 | #include "common/log_manager.h" |
| 7 | #include "common/file_util.h" | ||
| 8 | 7 | ||
| 9 | #include "core/system.h" | 8 | #include "core/system.h" |
| 10 | #include "core/core.h" | 9 | #include "core/core.h" |
| 11 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 12 | 11 | ||
| 12 | #include "citra/config.h" | ||
| 13 | #include "citra/emu_window/emu_window_glfw.h" | 13 | #include "citra/emu_window/emu_window_glfw.h" |
| 14 | 14 | ||
| 15 | /// Application entry point | 15 | /// Application entry point |
| @@ -21,13 +21,16 @@ int __cdecl main(int argc, char **argv) { | |||
| 21 | return -1; | 21 | return -1; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | Config config; | ||
| 25 | |||
| 24 | std::string boot_filename = argv[1]; | 26 | std::string boot_filename = argv[1]; |
| 25 | EmuWindow_GLFW* emu_window = new EmuWindow_GLFW; | 27 | EmuWindow_GLFW* emu_window = new EmuWindow_GLFW; |
| 26 | 28 | ||
| 27 | System::Init(emu_window); | 29 | System::Init(emu_window); |
| 28 | 30 | ||
| 29 | if (Loader::ResultStatus::Success != Loader::LoadFile(boot_filename)) { | 31 | Loader::ResultStatus load_result = Loader::LoadFile(boot_filename); |
| 30 | ERROR_LOG(BOOT, "Failed to load ROM!"); | 32 | if (Loader::ResultStatus::Success != load_result) { |
| 33 | ERROR_LOG(BOOT, "Failed to load ROM (Error %i)!", load_result); | ||
| 31 | return -1; | 34 | return -1; |
| 32 | } | 35 | } |
| 33 | 36 | ||
diff --git a/src/citra/config.cpp b/src/citra/config.cpp new file mode 100644 index 000000000..1d5e9c717 --- /dev/null +++ b/src/citra/config.cpp | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <GLFW/glfw3.h> | ||
| 6 | |||
| 7 | #include "citra/default_ini.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | #include "core/settings.h" | ||
| 10 | |||
| 11 | #include "config.h" | ||
| 12 | |||
| 13 | Config::Config() { | ||
| 14 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | ||
| 15 | glfw_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "glfw-config.ini"; | ||
| 16 | glfw_config = new INIReader(glfw_config_loc); | ||
| 17 | |||
| 18 | Reload(); | ||
| 19 | } | ||
| 20 | |||
| 21 | bool Config::LoadINI(INIReader* config, const char* location, const std::string& default_contents, bool retry) { | ||
| 22 | if (config->ParseError() < 0) { | ||
| 23 | if (retry) { | ||
| 24 | ERROR_LOG(CONFIG, "Failed to load %s. Creating file from defaults...", location); | ||
| 25 | FileUtil::CreateFullPath(location); | ||
| 26 | FileUtil::WriteStringToFile(true, default_contents, location); | ||
| 27 | *config = INIReader(location); // Reopen file | ||
| 28 | |||
| 29 | return LoadINI(config, location, default_contents, false); | ||
| 30 | } | ||
| 31 | ERROR_LOG(CONFIG, "Failed."); | ||
| 32 | return false; | ||
| 33 | } | ||
| 34 | INFO_LOG(CONFIG, "Successfully loaded %s", location); | ||
| 35 | return true; | ||
| 36 | } | ||
| 37 | |||
| 38 | void Config::ReadControls() { | ||
| 39 | Settings::values.pad_a_key = glfw_config->GetInteger("Controls", "pad_a", GLFW_KEY_A); | ||
| 40 | Settings::values.pad_b_key = glfw_config->GetInteger("Controls", "pad_b", GLFW_KEY_S); | ||
| 41 | Settings::values.pad_x_key = glfw_config->GetInteger("Controls", "pad_x", GLFW_KEY_Z); | ||
| 42 | Settings::values.pad_y_key = glfw_config->GetInteger("Controls", "pad_y", GLFW_KEY_X); | ||
| 43 | Settings::values.pad_l_key = glfw_config->GetInteger("Controls", "pad_l", GLFW_KEY_Q); | ||
| 44 | Settings::values.pad_r_key = glfw_config->GetInteger("Controls", "pad_r", GLFW_KEY_W); | ||
| 45 | Settings::values.pad_start_key = glfw_config->GetInteger("Controls", "pad_start", GLFW_KEY_M); | ||
| 46 | Settings::values.pad_select_key = glfw_config->GetInteger("Controls", "pad_select", GLFW_KEY_N); | ||
| 47 | Settings::values.pad_home_key = glfw_config->GetInteger("Controls", "pad_home", GLFW_KEY_B); | ||
| 48 | Settings::values.pad_dup_key = glfw_config->GetInteger("Controls", "pad_dup", GLFW_KEY_T); | ||
| 49 | Settings::values.pad_ddown_key = glfw_config->GetInteger("Controls", "pad_ddown", GLFW_KEY_G); | ||
| 50 | Settings::values.pad_dleft_key = glfw_config->GetInteger("Controls", "pad_dleft", GLFW_KEY_F); | ||
| 51 | Settings::values.pad_dright_key = glfw_config->GetInteger("Controls", "pad_dright", GLFW_KEY_H); | ||
| 52 | Settings::values.pad_sup_key = glfw_config->GetInteger("Controls", "pad_sup", GLFW_KEY_UP); | ||
| 53 | Settings::values.pad_sdown_key = glfw_config->GetInteger("Controls", "pad_sdown", GLFW_KEY_DOWN); | ||
| 54 | Settings::values.pad_sleft_key = glfw_config->GetInteger("Controls", "pad_sleft", GLFW_KEY_LEFT); | ||
| 55 | Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); | ||
| 56 | } | ||
| 57 | |||
| 58 | void Config::Reload() { | ||
| 59 | LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file); | ||
| 60 | ReadControls(); | ||
| 61 | } | ||
| 62 | |||
| 63 | Config::~Config() { | ||
| 64 | delete glfw_config; | ||
| 65 | } | ||
diff --git a/src/citra/config.h b/src/citra/config.h new file mode 100644 index 000000000..de0570b42 --- /dev/null +++ b/src/citra/config.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <map> | ||
| 8 | |||
| 9 | #include <inih/cpp/INIReader.h> | ||
| 10 | |||
| 11 | #include "common/common_types.h" | ||
| 12 | |||
| 13 | class Config { | ||
| 14 | INIReader* glfw_config; | ||
| 15 | std::string glfw_config_loc; | ||
| 16 | |||
| 17 | bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true); | ||
| 18 | void ReadControls(); | ||
| 19 | public: | ||
| 20 | Config(); | ||
| 21 | ~Config(); | ||
| 22 | |||
| 23 | void Reload(); | ||
| 24 | }; | ||
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h new file mode 100644 index 000000000..11b985e1b --- /dev/null +++ b/src/citra/default_ini.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace DefaultINI { | ||
| 8 | |||
| 9 | const char* glfw_config_file = R"( | ||
| 10 | [Controls] | ||
| 11 | pad_start = | ||
| 12 | pad_select = | ||
| 13 | pad_home = | ||
| 14 | pad_dup = | ||
| 15 | pad_ddown = | ||
| 16 | pad_dleft = | ||
| 17 | pad_dright = | ||
| 18 | pad_a = | ||
| 19 | pad_b = | ||
| 20 | pad_x = | ||
| 21 | pad_y = | ||
| 22 | pad_r = | ||
| 23 | pad_l = | ||
| 24 | pad_sup = | ||
| 25 | pad_sdown = | ||
| 26 | pad_sleft = | ||
| 27 | pad_sright = | ||
| 28 | )"; | ||
| 29 | |||
| 30 | } | ||
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp index b911e60c5..661521eb7 100644 --- a/src/citra/emu_window/emu_window_glfw.cpp +++ b/src/citra/emu_window/emu_window_glfw.cpp | |||
| @@ -6,26 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #include "video_core/video_core.h" | 7 | #include "video_core/video_core.h" |
| 8 | 8 | ||
| 9 | #include "citra/emu_window/emu_window_glfw.h" | 9 | #include "core/settings.h" |
| 10 | 10 | ||
| 11 | static const std::pair<int, HID_User::PadState> default_key_map[] = { | 11 | #include "citra/emu_window/emu_window_glfw.h" |
| 12 | { GLFW_KEY_A, HID_User::PAD_A }, | ||
| 13 | { GLFW_KEY_B, HID_User::PAD_B }, | ||
| 14 | { GLFW_KEY_BACKSLASH, HID_User::PAD_SELECT }, | ||
| 15 | { GLFW_KEY_ENTER, HID_User::PAD_START }, | ||
| 16 | { GLFW_KEY_RIGHT, HID_User::PAD_RIGHT }, | ||
| 17 | { GLFW_KEY_LEFT, HID_User::PAD_LEFT }, | ||
| 18 | { GLFW_KEY_UP, HID_User::PAD_UP }, | ||
| 19 | { GLFW_KEY_DOWN, HID_User::PAD_DOWN }, | ||
| 20 | { GLFW_KEY_R, HID_User::PAD_R }, | ||
| 21 | { GLFW_KEY_L, HID_User::PAD_L }, | ||
| 22 | { GLFW_KEY_X, HID_User::PAD_X }, | ||
| 23 | { GLFW_KEY_Y, HID_User::PAD_Y }, | ||
| 24 | { GLFW_KEY_H, HID_User::PAD_CIRCLE_RIGHT }, | ||
| 25 | { GLFW_KEY_F, HID_User::PAD_CIRCLE_LEFT }, | ||
| 26 | { GLFW_KEY_T, HID_User::PAD_CIRCLE_UP }, | ||
| 27 | { GLFW_KEY_G, HID_User::PAD_CIRCLE_DOWN }, | ||
| 28 | }; | ||
| 29 | 12 | ||
| 30 | /// Called by GLFW when a key event occurs | 13 | /// Called by GLFW when a key event occurs |
| 31 | void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) { | 14 | void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) { |
| @@ -48,14 +31,9 @@ void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int acti | |||
| 48 | 31 | ||
| 49 | /// EmuWindow_GLFW constructor | 32 | /// EmuWindow_GLFW constructor |
| 50 | EmuWindow_GLFW::EmuWindow_GLFW() { | 33 | EmuWindow_GLFW::EmuWindow_GLFW() { |
| 51 | |||
| 52 | // Register a new ID for the default keyboard | ||
| 53 | keyboard_id = KeyMap::NewDeviceId(); | 34 | keyboard_id = KeyMap::NewDeviceId(); |
| 54 | 35 | ||
| 55 | // Set default key mappings for keyboard | 36 | ReloadSetKeymaps(); |
| 56 | for (auto mapping : default_key_map) { | ||
| 57 | KeyMap::SetKeyMapping({mapping.first, keyboard_id}, mapping.second); | ||
| 58 | } | ||
| 59 | 37 | ||
| 60 | // Initialize the window | 38 | // Initialize the window |
| 61 | if(glfwInit() != GL_TRUE) { | 39 | if(glfwInit() != GL_TRUE) { |
| @@ -111,3 +89,22 @@ void EmuWindow_GLFW::MakeCurrent() { | |||
| 111 | void EmuWindow_GLFW::DoneCurrent() { | 89 | void EmuWindow_GLFW::DoneCurrent() { |
| 112 | glfwMakeContextCurrent(NULL); | 90 | glfwMakeContextCurrent(NULL); |
| 113 | } | 91 | } |
| 92 | |||
| 93 | void EmuWindow_GLFW::ReloadSetKeymaps() { | ||
| 94 | KeyMap::SetKeyMapping({Settings::values.pad_a_key, keyboard_id}, HID_User::PAD_A); | ||
| 95 | KeyMap::SetKeyMapping({Settings::values.pad_b_key, keyboard_id}, HID_User::PAD_B); | ||
| 96 | KeyMap::SetKeyMapping({Settings::values.pad_select_key, keyboard_id}, HID_User::PAD_SELECT); | ||
| 97 | KeyMap::SetKeyMapping({Settings::values.pad_start_key, keyboard_id}, HID_User::PAD_START); | ||
| 98 | KeyMap::SetKeyMapping({Settings::values.pad_dright_key, keyboard_id}, HID_User::PAD_RIGHT); | ||
| 99 | KeyMap::SetKeyMapping({Settings::values.pad_dleft_key, keyboard_id}, HID_User::PAD_LEFT); | ||
| 100 | KeyMap::SetKeyMapping({Settings::values.pad_dup_key, keyboard_id}, HID_User::PAD_UP); | ||
| 101 | KeyMap::SetKeyMapping({Settings::values.pad_ddown_key, keyboard_id}, HID_User::PAD_DOWN); | ||
| 102 | KeyMap::SetKeyMapping({Settings::values.pad_r_key, keyboard_id}, HID_User::PAD_R); | ||
| 103 | KeyMap::SetKeyMapping({Settings::values.pad_l_key, keyboard_id}, HID_User::PAD_L); | ||
| 104 | KeyMap::SetKeyMapping({Settings::values.pad_x_key, keyboard_id}, HID_User::PAD_X); | ||
| 105 | KeyMap::SetKeyMapping({Settings::values.pad_y_key, keyboard_id}, HID_User::PAD_Y); | ||
| 106 | KeyMap::SetKeyMapping({Settings::values.pad_sright_key, keyboard_id}, HID_User::PAD_CIRCLE_RIGHT); | ||
| 107 | KeyMap::SetKeyMapping({Settings::values.pad_sleft_key, keyboard_id}, HID_User::PAD_CIRCLE_LEFT); | ||
| 108 | KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, HID_User::PAD_CIRCLE_UP); | ||
| 109 | KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, HID_User::PAD_CIRCLE_DOWN); | ||
| 110 | } | ||
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h index 29325bb75..d38a11c2c 100644 --- a/src/citra/emu_window/emu_window_glfw.h +++ b/src/citra/emu_window/emu_window_glfw.h | |||
| @@ -27,7 +27,11 @@ public: | |||
| 27 | 27 | ||
| 28 | static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods); | 28 | static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods); |
| 29 | 29 | ||
| 30 | void ReloadSetKeymaps() override; | ||
| 31 | |||
| 30 | private: | 32 | private: |
| 31 | GLFWwindow* m_render_window; ///< Internal GLFW render window | 33 | GLFWwindow* m_render_window; ///< Internal GLFW render window |
| 32 | int keyboard_id; ///< Device id of keyboard for use with KeyMap | 34 | |
| 35 | /// Device id of keyboard for use with KeyMap | ||
| 36 | int keyboard_id; | ||
| 33 | }; | 37 | }; |
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 426e4ef99..98a48a69a 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt | |||
| @@ -4,6 +4,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) | |||
| 4 | set(SRCS | 4 | set(SRCS |
| 5 | config/controller_config.cpp | 5 | config/controller_config.cpp |
| 6 | config/controller_config_util.cpp | 6 | config/controller_config_util.cpp |
| 7 | config.cpp | ||
| 7 | debugger/callstack.cpp | 8 | debugger/callstack.cpp |
| 8 | debugger/disassembler.cpp | 9 | debugger/disassembler.cpp |
| 9 | debugger/graphics.cpp | 10 | debugger/graphics.cpp |
| @@ -18,6 +19,7 @@ set(SRCS | |||
| 18 | set(HEADERS | 19 | set(HEADERS |
| 19 | config/controller_config.hxx | 20 | config/controller_config.hxx |
| 20 | config/controller_config_util.hxx | 21 | config/controller_config_util.hxx |
| 22 | config.h | ||
| 21 | debugger/callstack.hxx | 23 | debugger/callstack.hxx |
| 22 | debugger/disassembler.hxx | 24 | debugger/disassembler.hxx |
| 23 | debugger/graphics.hxx | 25 | debugger/graphics.hxx |
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index cf4d8b32b..5dce9e570 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp | |||
| @@ -6,12 +6,11 @@ | |||
| 6 | #include "bootmanager.hxx" | 6 | #include "bootmanager.hxx" |
| 7 | 7 | ||
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/loader/loader.h" | 9 | #include "core/settings.h" |
| 10 | #include "core/hw/hw.h" | ||
| 11 | 10 | ||
| 12 | #include "video_core/video_core.h" | 11 | #include "video_core/video_core.h" |
| 13 | 12 | ||
| 14 | #include "version.h" | 13 | #include "citra_qt/version.h" |
| 15 | 14 | ||
| 16 | #define APP_NAME "citra" | 15 | #define APP_NAME "citra" |
| 17 | #define APP_VERSION "0.1-" VERSION | 16 | #define APP_VERSION "0.1-" VERSION |
| @@ -102,40 +101,15 @@ private: | |||
| 102 | GRenderWindow* parent_; | 101 | GRenderWindow* parent_; |
| 103 | }; | 102 | }; |
| 104 | 103 | ||
| 105 | |||
| 106 | EmuThread& GRenderWindow::GetEmuThread() | 104 | EmuThread& GRenderWindow::GetEmuThread() |
| 107 | { | 105 | { |
| 108 | return emu_thread; | 106 | return emu_thread; |
| 109 | } | 107 | } |
| 110 | 108 | ||
| 111 | static const std::pair<int, HID_User::PadState> default_key_map[] = { | 109 | GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this), keyboard_id(0) |
| 112 | { Qt::Key_A, HID_User::PAD_A }, | ||
| 113 | { Qt::Key_B, HID_User::PAD_B }, | ||
| 114 | { Qt::Key_Backslash, HID_User::PAD_SELECT }, | ||
| 115 | { Qt::Key_Enter, HID_User::PAD_START }, | ||
| 116 | { Qt::Key_Right, HID_User::PAD_RIGHT }, | ||
| 117 | { Qt::Key_Left, HID_User::PAD_LEFT }, | ||
| 118 | { Qt::Key_Up, HID_User::PAD_UP }, | ||
| 119 | { Qt::Key_Down, HID_User::PAD_DOWN }, | ||
| 120 | { Qt::Key_R, HID_User::PAD_R }, | ||
| 121 | { Qt::Key_L, HID_User::PAD_L }, | ||
| 122 | { Qt::Key_X, HID_User::PAD_X }, | ||
| 123 | { Qt::Key_Y, HID_User::PAD_Y }, | ||
| 124 | { Qt::Key_H, HID_User::PAD_CIRCLE_RIGHT }, | ||
| 125 | { Qt::Key_F, HID_User::PAD_CIRCLE_LEFT }, | ||
| 126 | { Qt::Key_T, HID_User::PAD_CIRCLE_UP }, | ||
| 127 | { Qt::Key_G, HID_User::PAD_CIRCLE_DOWN }, | ||
| 128 | }; | ||
| 129 | |||
| 130 | GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this) | ||
| 131 | { | 110 | { |
| 132 | // Register a new ID for the default keyboard | ||
| 133 | keyboard_id = KeyMap::NewDeviceId(); | 111 | keyboard_id = KeyMap::NewDeviceId(); |
| 134 | 112 | ReloadSetKeymaps(); | |
| 135 | // Set default key mappings for keyboard | ||
| 136 | for (auto mapping : default_key_map) { | ||
| 137 | KeyMap::SetKeyMapping({mapping.first, keyboard_id}, mapping.second); | ||
| 138 | } | ||
| 139 | 113 | ||
| 140 | // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose | 114 | // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose |
| 141 | QGLFormat fmt; | 115 | QGLFormat fmt; |
| @@ -245,3 +219,23 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) | |||
| 245 | HID_User::PadUpdateComplete(); | 219 | HID_User::PadUpdateComplete(); |
| 246 | } | 220 | } |
| 247 | 221 | ||
| 222 | void GRenderWindow::ReloadSetKeymaps() | ||
| 223 | { | ||
| 224 | KeyMap::SetKeyMapping({Settings::values.pad_a_key, keyboard_id}, HID_User::PAD_A); | ||
| 225 | KeyMap::SetKeyMapping({Settings::values.pad_b_key, keyboard_id}, HID_User::PAD_B); | ||
| 226 | KeyMap::SetKeyMapping({Settings::values.pad_select_key, keyboard_id}, HID_User::PAD_SELECT); | ||
| 227 | KeyMap::SetKeyMapping({Settings::values.pad_start_key, keyboard_id}, HID_User::PAD_START); | ||
| 228 | KeyMap::SetKeyMapping({Settings::values.pad_dright_key, keyboard_id}, HID_User::PAD_RIGHT); | ||
| 229 | KeyMap::SetKeyMapping({Settings::values.pad_dleft_key, keyboard_id}, HID_User::PAD_LEFT); | ||
| 230 | KeyMap::SetKeyMapping({Settings::values.pad_dup_key, keyboard_id}, HID_User::PAD_UP); | ||
| 231 | KeyMap::SetKeyMapping({Settings::values.pad_ddown_key, keyboard_id}, HID_User::PAD_DOWN); | ||
| 232 | KeyMap::SetKeyMapping({Settings::values.pad_r_key, keyboard_id}, HID_User::PAD_R); | ||
| 233 | KeyMap::SetKeyMapping({Settings::values.pad_l_key, keyboard_id}, HID_User::PAD_L); | ||
| 234 | KeyMap::SetKeyMapping({Settings::values.pad_x_key, keyboard_id}, HID_User::PAD_X); | ||
| 235 | KeyMap::SetKeyMapping({Settings::values.pad_y_key, keyboard_id}, HID_User::PAD_Y); | ||
| 236 | KeyMap::SetKeyMapping({Settings::values.pad_sright_key, keyboard_id}, HID_User::PAD_CIRCLE_RIGHT); | ||
| 237 | KeyMap::SetKeyMapping({Settings::values.pad_sleft_key, keyboard_id}, HID_User::PAD_CIRCLE_LEFT); | ||
| 238 | KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, HID_User::PAD_CIRCLE_UP); | ||
| 239 | KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, HID_User::PAD_CIRCLE_DOWN); | ||
| 240 | } | ||
| 241 | |||
diff --git a/src/citra_qt/bootmanager.hxx b/src/citra_qt/bootmanager.hxx index eedf19471..816ffed2e 100644 --- a/src/citra_qt/bootmanager.hxx +++ b/src/citra_qt/bootmanager.hxx | |||
| @@ -107,6 +107,8 @@ public: | |||
| 107 | void keyPressEvent(QKeyEvent* event); | 107 | void keyPressEvent(QKeyEvent* event); |
| 108 | void keyReleaseEvent(QKeyEvent* event); | 108 | void keyReleaseEvent(QKeyEvent* event); |
| 109 | 109 | ||
| 110 | void ReloadSetKeymaps() override; | ||
| 111 | |||
| 110 | public slots: | 112 | public slots: |
| 111 | void moveContext(); | 113 | void moveContext(); |
| 112 | 114 | ||
| @@ -117,5 +119,6 @@ private: | |||
| 117 | 119 | ||
| 118 | QByteArray geometry; | 120 | QByteArray geometry; |
| 119 | 121 | ||
| 122 | /// Device id of keyboard for use with KeyMap | ||
| 120 | int keyboard_id; | 123 | int keyboard_id; |
| 121 | }; | 124 | }; |
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp new file mode 100644 index 000000000..1b116edc5 --- /dev/null +++ b/src/citra_qt/config.cpp | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <QString> | ||
| 6 | #include <QStringList> | ||
| 7 | |||
| 8 | #include "core/settings.h" | ||
| 9 | #include "common/file_util.h" | ||
| 10 | |||
| 11 | #include "config.h" | ||
| 12 | |||
| 13 | Config::Config() { | ||
| 14 | |||
| 15 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | ||
| 16 | qt_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "qt-config.ini"; | ||
| 17 | FileUtil::CreateFullPath(qt_config_loc); | ||
| 18 | qt_config = new QSettings(QString::fromStdString(qt_config_loc), QSettings::IniFormat); | ||
| 19 | |||
| 20 | Reload(); | ||
| 21 | } | ||
| 22 | |||
| 23 | void Config::ReadControls() { | ||
| 24 | qt_config->beginGroup("Controls"); | ||
| 25 | Settings::values.pad_a_key = qt_config->value("pad_a", Qt::Key_A).toInt(); | ||
| 26 | Settings::values.pad_b_key = qt_config->value("pad_b", Qt::Key_S).toInt(); | ||
| 27 | Settings::values.pad_x_key = qt_config->value("pad_x", Qt::Key_Z).toInt(); | ||
| 28 | Settings::values.pad_y_key = qt_config->value("pad_y", Qt::Key_X).toInt(); | ||
| 29 | Settings::values.pad_l_key = qt_config->value("pad_l", Qt::Key_Q).toInt(); | ||
| 30 | Settings::values.pad_r_key = qt_config->value("pad_r", Qt::Key_W).toInt(); | ||
| 31 | Settings::values.pad_start_key = qt_config->value("pad_start", Qt::Key_M).toInt(); | ||
| 32 | Settings::values.pad_select_key = qt_config->value("pad_select", Qt::Key_N).toInt(); | ||
| 33 | Settings::values.pad_home_key = qt_config->value("pad_home", Qt::Key_B).toInt(); | ||
| 34 | Settings::values.pad_dup_key = qt_config->value("pad_dup", Qt::Key_T).toInt(); | ||
| 35 | Settings::values.pad_ddown_key = qt_config->value("pad_ddown", Qt::Key_G).toInt(); | ||
| 36 | Settings::values.pad_dleft_key = qt_config->value("pad_dleft", Qt::Key_F).toInt(); | ||
| 37 | Settings::values.pad_dright_key = qt_config->value("pad_dright", Qt::Key_H).toInt(); | ||
| 38 | Settings::values.pad_sup_key = qt_config->value("pad_sup", Qt::Key_Up).toInt(); | ||
| 39 | Settings::values.pad_sdown_key = qt_config->value("pad_sdown", Qt::Key_Down).toInt(); | ||
| 40 | Settings::values.pad_sleft_key = qt_config->value("pad_sleft", Qt::Key_Left).toInt(); | ||
| 41 | Settings::values.pad_sright_key = qt_config->value("pad_sright", Qt::Key_Right).toInt(); | ||
| 42 | qt_config->endGroup(); | ||
| 43 | } | ||
| 44 | |||
| 45 | void Config::SaveControls() { | ||
| 46 | qt_config->beginGroup("Controls"); | ||
| 47 | qt_config->setValue("pad_a", Settings::values.pad_a_key); | ||
| 48 | qt_config->setValue("pad_b", Settings::values.pad_b_key); | ||
| 49 | qt_config->setValue("pad_x", Settings::values.pad_x_key); | ||
| 50 | qt_config->setValue("pad_y", Settings::values.pad_y_key); | ||
| 51 | qt_config->setValue("pad_l", Settings::values.pad_l_key); | ||
| 52 | qt_config->setValue("pad_r", Settings::values.pad_r_key); | ||
| 53 | qt_config->setValue("pad_start", Settings::values.pad_start_key); | ||
| 54 | qt_config->setValue("pad_select", Settings::values.pad_select_key); | ||
| 55 | qt_config->setValue("pad_home", Settings::values.pad_home_key); | ||
| 56 | qt_config->setValue("pad_dup", Settings::values.pad_dup_key); | ||
| 57 | qt_config->setValue("pad_ddown", Settings::values.pad_ddown_key); | ||
| 58 | qt_config->setValue("pad_dleft", Settings::values.pad_dleft_key); | ||
| 59 | qt_config->setValue("pad_dright", Settings::values.pad_dright_key); | ||
| 60 | qt_config->setValue("pad_sup", Settings::values.pad_sup_key); | ||
| 61 | qt_config->setValue("pad_sdown", Settings::values.pad_sdown_key); | ||
| 62 | qt_config->setValue("pad_sleft", Settings::values.pad_sleft_key); | ||
| 63 | qt_config->setValue("pad_sright", Settings::values.pad_sright_key); | ||
| 64 | qt_config->endGroup(); | ||
| 65 | } | ||
| 66 | |||
| 67 | void Config::Reload() { | ||
| 68 | ReadControls(); | ||
| 69 | } | ||
| 70 | |||
| 71 | void Config::Save() { | ||
| 72 | SaveControls(); | ||
| 73 | } | ||
| 74 | |||
| 75 | Config::~Config() { | ||
| 76 | Save(); | ||
| 77 | |||
| 78 | delete qt_config; | ||
| 79 | } | ||
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h new file mode 100644 index 000000000..ae390be6b --- /dev/null +++ b/src/citra_qt/config.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <QSettings> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | class Config { | ||
| 12 | QSettings* qt_config; | ||
| 13 | std::string qt_config_loc; | ||
| 14 | |||
| 15 | void ReadControls(); | ||
| 16 | void SaveControls(); | ||
| 17 | public: | ||
| 18 | Config(); | ||
| 19 | ~Config(); | ||
| 20 | |||
| 21 | void Reload(); | ||
| 22 | void Save(); | ||
| 23 | }; | ||
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 1bf9bc53c..bac6a6bb8 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp | |||
| @@ -26,12 +26,16 @@ | |||
| 26 | #include "core/core.h" | 26 | #include "core/core.h" |
| 27 | #include "core/loader/loader.h" | 27 | #include "core/loader/loader.h" |
| 28 | #include "core/arm/disassembler/load_symbol_map.h" | 28 | #include "core/arm/disassembler/load_symbol_map.h" |
| 29 | #include "citra_qt/config.h" | ||
| 29 | 30 | ||
| 30 | #include "version.h" | 31 | #include "version.h" |
| 31 | 32 | ||
| 32 | 33 | ||
| 33 | GMainWindow::GMainWindow() | 34 | GMainWindow::GMainWindow() |
| 34 | { | 35 | { |
| 36 | LogManager::Init(); | ||
| 37 | Config config; | ||
| 38 | |||
| 35 | ui.setupUi(this); | 39 | ui.setupUi(this); |
| 36 | statusBar()->hide(); | 40 | statusBar()->hide(); |
| 37 | 41 | ||
| @@ -112,7 +116,6 @@ GMainWindow::GMainWindow() | |||
| 112 | 116 | ||
| 113 | show(); | 117 | show(); |
| 114 | 118 | ||
| 115 | LogManager::Init(); | ||
| 116 | System::Init(render_window); | 119 | System::Init(render_window); |
| 117 | } | 120 | } |
| 118 | 121 | ||
diff --git a/src/common/common_paths.h b/src/common/common_paths.h index 7cd5b1f35..ae08d082a 100644 --- a/src/common/common_paths.h +++ b/src/common/common_paths.h | |||
| @@ -7,25 +7,25 @@ | |||
| 7 | // Make sure we pick up USER_DIR if set in config.h | 7 | // Make sure we pick up USER_DIR if set in config.h |
| 8 | #include "common/common.h" | 8 | #include "common/common.h" |
| 9 | 9 | ||
| 10 | // Directory seperators, do we need this? | 10 | // Directory separators, do we need this? |
| 11 | #define DIR_SEP "/" | 11 | #define DIR_SEP "/" |
| 12 | #define DIR_SEP_CHR '/' | 12 | #define DIR_SEP_CHR '/' |
| 13 | 13 | ||
| 14 | #ifndef MAX_PATH | 14 | #ifndef MAX_PATH |
| 15 | #define MAX_PATH 260 | 15 | #define MAX_PATH 260 |
| 16 | #endif | 16 | #endif |
| 17 | 17 | ||
| 18 | // The user data dir | 18 | // The user data dir |
| 19 | #define ROOT_DIR "." | 19 | #define ROOT_DIR "." |
| 20 | #ifdef _WIN32 | 20 | #ifdef _WIN32 |
| 21 | #define USERDATA_DIR "user" | 21 | #define USERDATA_DIR "user" |
| 22 | #define EMU_DATA_DIR "emu" | 22 | #define EMU_DATA_DIR "Citra Emulator" |
| 23 | #else | 23 | #else |
| 24 | #define USERDATA_DIR "user" | 24 | #define USERDATA_DIR "user" |
| 25 | #ifdef USER_DIR | 25 | #ifdef USER_DIR |
| 26 | #define EMU_DATA_DIR USER_DIR | 26 | #define EMU_DATA_DIR USER_DIR |
| 27 | #else | 27 | #else |
| 28 | #define EMU_DATA_DIR ".emu" | 28 | #define EMU_DATA_DIR ".citra-emu" |
| 29 | #endif | 29 | #endif |
| 30 | #endif | 30 | #endif |
| 31 | 31 | ||
| @@ -48,30 +48,30 @@ | |||
| 48 | #define JAP_DIR "JAP" | 48 | #define JAP_DIR "JAP" |
| 49 | 49 | ||
| 50 | // Subdirs in the User dir returned by GetUserPath(D_USER_IDX) | 50 | // Subdirs in the User dir returned by GetUserPath(D_USER_IDX) |
| 51 | #define CONFIG_DIR "config" | 51 | #define CONFIG_DIR "config" |
| 52 | #define GAMECONFIG_DIR "game_config" | 52 | #define GAMECONFIG_DIR "game_config" |
| 53 | #define MAPS_DIR "maps" | 53 | #define MAPS_DIR "maps" |
| 54 | #define CACHE_DIR "cache" | 54 | #define CACHE_DIR "cache" |
| 55 | #define SDMC_DIR "sdmc" | 55 | #define SDMC_DIR "sdmc" |
| 56 | #define SHADERCACHE_DIR "shader_cache" | 56 | #define SHADERCACHE_DIR "shader_cache" |
| 57 | #define STATESAVES_DIR "state_saves" | 57 | #define STATESAVES_DIR "state_saves" |
| 58 | #define SCREENSHOTS_DIR "screenShots" | 58 | #define SCREENSHOTS_DIR "screenShots" |
| 59 | #define DUMP_DIR "dump" | 59 | #define DUMP_DIR "dump" |
| 60 | #define DUMP_TEXTURES_DIR "textures" | 60 | #define DUMP_TEXTURES_DIR "textures" |
| 61 | #define DUMP_FRAMES_DIR "frames" | 61 | #define DUMP_FRAMES_DIR "frames" |
| 62 | #define DUMP_AUDIO_DIR "audio" | 62 | #define DUMP_AUDIO_DIR "audio" |
| 63 | #define LOGS_DIR "logs" | 63 | #define LOGS_DIR "logs" |
| 64 | #define SHADERS_DIR "shaders" | 64 | #define SHADERS_DIR "shaders" |
| 65 | #define SYSCONF_DIR "sysconf" | 65 | #define SYSCONF_DIR "sysconf" |
| 66 | 66 | ||
| 67 | // Filenames | 67 | // Filenames |
| 68 | // Files in the directory returned by GetUserPath(D_CONFIG_IDX) | 68 | // Files in the directory returned by GetUserPath(D_CONFIG_IDX) |
| 69 | #define EMU_CONFIG "emu.ini" | 69 | #define EMU_CONFIG "emu.ini" |
| 70 | #define DEBUGGER_CONFIG "debugger.ini" | 70 | #define DEBUGGER_CONFIG "debugger.ini" |
| 71 | #define LOGGER_CONFIG "logger.ini" | 71 | #define LOGGER_CONFIG "logger.ini" |
| 72 | 72 | ||
| 73 | // Files in the directory returned by GetUserPath(D_LOGS_IDX) | 73 | // Files in the directory returned by GetUserPath(D_LOGS_IDX) |
| 74 | #define MAIN_LOG "emu.log" | 74 | #define MAIN_LOG "emu.log" |
| 75 | 75 | ||
| 76 | // Files in the directory returned by GetUserPath(D_SYSCONF_IDX) | 76 | // Files in the directory returned by GetUserPath(D_SYSCONF_IDX) |
| 77 | #define SYSCONF "SYSCONF" | 77 | #define SYSCONF "SYSCONF" |
diff --git a/src/common/console_listener.cpp b/src/common/console_listener.cpp index 40122224c..53f20d754 100644 --- a/src/common/console_listener.cpp +++ b/src/common/console_listener.cpp | |||
| @@ -241,16 +241,6 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool | |||
| 241 | void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) | 241 | void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) |
| 242 | { | 242 | { |
| 243 | #if defined(_WIN32) | 243 | #if defined(_WIN32) |
| 244 | /* | ||
| 245 | const int MAX_BYTES = 1024*10; | ||
| 246 | char Str[MAX_BYTES]; | ||
| 247 | va_list ArgPtr; | ||
| 248 | int Cnt; | ||
| 249 | va_start(ArgPtr, Text); | ||
| 250 | Cnt = vsnprintf(Str, MAX_BYTES, Text, ArgPtr); | ||
| 251 | va_end(ArgPtr); | ||
| 252 | */ | ||
| 253 | DWORD cCharsWritten; | ||
| 254 | WORD Color; | 244 | WORD Color; |
| 255 | 245 | ||
| 256 | switch (Level) | 246 | switch (Level) |
diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 23f178fdf..34cecb40b 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h | |||
| @@ -16,7 +16,7 @@ class EmuWindow | |||
| 16 | 16 | ||
| 17 | public: | 17 | public: |
| 18 | /// Data structure to store an emuwindow configuration | 18 | /// Data structure to store an emuwindow configuration |
| 19 | struct Config{ | 19 | struct WindowConfig { |
| 20 | bool fullscreen; | 20 | bool fullscreen; |
| 21 | int res_width; | 21 | int res_width; |
| 22 | int res_height; | 22 | int res_height; |
| @@ -34,17 +34,19 @@ public: | |||
| 34 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread | 34 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread |
| 35 | virtual void DoneCurrent() = 0; | 35 | virtual void DoneCurrent() = 0; |
| 36 | 36 | ||
| 37 | virtual void ReloadSetKeymaps() = 0; | ||
| 38 | |||
| 37 | /// Signals a key press action to the HID module | 39 | /// Signals a key press action to the HID module |
| 38 | static void KeyPressed(KeyMap::HostDeviceKey key); | 40 | static void KeyPressed(KeyMap::HostDeviceKey key); |
| 39 | 41 | ||
| 40 | /// Signals a key release action to the HID module | 42 | /// Signals a key release action to the HID module |
| 41 | static void KeyReleased(KeyMap::HostDeviceKey key); | 43 | static void KeyReleased(KeyMap::HostDeviceKey key); |
| 42 | 44 | ||
| 43 | Config GetConfig() const { | 45 | WindowConfig GetConfig() const { |
| 44 | return m_config; | 46 | return m_config; |
| 45 | } | 47 | } |
| 46 | 48 | ||
| 47 | void SetConfig(const Config& val) { | 49 | void SetConfig(const WindowConfig& val) { |
| 48 | m_config = val; | 50 | m_config = val; |
| 49 | } | 51 | } |
| 50 | 52 | ||
| @@ -86,6 +88,6 @@ protected: | |||
| 86 | int m_client_area_height; ///< Current client height, should be set by window impl. | 88 | int m_client_area_height; ///< Current client height, should be set by window impl. |
| 87 | 89 | ||
| 88 | private: | 90 | private: |
| 89 | Config m_config; ///< Internal configuration | 91 | WindowConfig m_config; ///< Internal configuration |
| 90 | 92 | ||
| 91 | }; | 93 | }; |
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 40cd32d96..78a642599 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -648,7 +648,7 @@ std::string GetSysDirectory() | |||
| 648 | return sysDir; | 648 | return sysDir; |
| 649 | } | 649 | } |
| 650 | 650 | ||
| 651 | // Returns a string with a Dolphin data dir or file in the user's home | 651 | // Returns a string with a Citra data dir or file in the user's home |
| 652 | // directory. To be used in "multi-user" mode (that is, installed). | 652 | // directory. To be used in "multi-user" mode (that is, installed). |
| 653 | const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath) | 653 | const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath) |
| 654 | { | 654 | { |
| @@ -668,22 +668,22 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 668 | getenv("PWD") : "") + DIR_SEP EMU_DATA_DIR DIR_SEP; | 668 | getenv("PWD") : "") + DIR_SEP EMU_DATA_DIR DIR_SEP; |
| 669 | #endif | 669 | #endif |
| 670 | 670 | ||
| 671 | paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; | 671 | paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; |
| 672 | paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP; | 672 | paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP; |
| 673 | paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; | 673 | paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; |
| 674 | paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; | 674 | paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; |
| 675 | paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; | 675 | paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; |
| 676 | paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; | 676 | paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; |
| 677 | paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; | 677 | paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; |
| 678 | paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; | 678 | paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; |
| 679 | paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP; | 679 | paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP; |
| 680 | paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP; | 680 | paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP; |
| 681 | paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; | 681 | paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; |
| 682 | paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; | 682 | paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; |
| 683 | paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; | 683 | paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; |
| 684 | paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP; | 684 | paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP; |
| 685 | paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; | 685 | paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; |
| 686 | paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; | 686 | paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; |
| 687 | paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; | 687 | paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; |
| 688 | } | 688 | } |
| 689 | 689 | ||
| @@ -702,44 +702,44 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 702 | switch (DirIDX) | 702 | switch (DirIDX) |
| 703 | { | 703 | { |
| 704 | case D_ROOT_IDX: | 704 | case D_ROOT_IDX: |
| 705 | paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; | 705 | paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; |
| 706 | paths[D_SYSCONF_IDX] = paths[D_USER_IDX] + SYSCONF_DIR + DIR_SEP; | 706 | paths[D_SYSCONF_IDX] = paths[D_USER_IDX] + SYSCONF_DIR + DIR_SEP; |
| 707 | paths[F_SYSCONF_IDX] = paths[D_SYSCONF_IDX] + SYSCONF; | 707 | paths[F_SYSCONF_IDX] = paths[D_SYSCONF_IDX] + SYSCONF; |
| 708 | break; | 708 | break; |
| 709 | 709 | ||
| 710 | case D_USER_IDX: | 710 | case D_USER_IDX: |
| 711 | paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; | 711 | paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; |
| 712 | paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; | 712 | paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; |
| 713 | paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP; | 713 | paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP; |
| 714 | paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; | 714 | paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; |
| 715 | paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; | 715 | paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; |
| 716 | paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; | 716 | paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; |
| 717 | paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; | 717 | paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; |
| 718 | paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; | 718 | paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; |
| 719 | paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; | 719 | paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; |
| 720 | paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP; | 720 | paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP; |
| 721 | paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP; | 721 | paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP; |
| 722 | paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; | 722 | paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; |
| 723 | paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; | 723 | paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; |
| 724 | paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; | 724 | paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; |
| 725 | paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP; | 725 | paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP; |
| 726 | paths[D_SYSCONF_IDX] = paths[D_USER_IDX] + SYSCONF_DIR DIR_SEP; | 726 | paths[D_SYSCONF_IDX] = paths[D_USER_IDX] + SYSCONF_DIR DIR_SEP; |
| 727 | paths[F_EMUCONFIG_IDX] = paths[D_CONFIG_IDX] + EMU_CONFIG; | 727 | paths[F_EMUCONFIG_IDX] = paths[D_CONFIG_IDX] + EMU_CONFIG; |
| 728 | paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; | 728 | paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; |
| 729 | paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; | 729 | paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; |
| 730 | paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; | 730 | paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; |
| 731 | break; | 731 | break; |
| 732 | 732 | ||
| 733 | case D_CONFIG_IDX: | 733 | case D_CONFIG_IDX: |
| 734 | paths[F_EMUCONFIG_IDX] = paths[D_CONFIG_IDX] + EMU_CONFIG; | 734 | paths[F_EMUCONFIG_IDX] = paths[D_CONFIG_IDX] + EMU_CONFIG; |
| 735 | paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; | 735 | paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; |
| 736 | paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; | 736 | paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; |
| 737 | break; | 737 | break; |
| 738 | 738 | ||
| 739 | case D_DUMP_IDX: | 739 | case D_DUMP_IDX: |
| 740 | paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; | 740 | paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; |
| 741 | paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; | 741 | paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; |
| 742 | paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; | 742 | paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; |
| 743 | break; | 743 | break; |
| 744 | 744 | ||
| 745 | case D_LOGS_IDX: | 745 | case D_LOGS_IDX: |
| @@ -763,12 +763,12 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 763 | // return dir; | 763 | // return dir; |
| 764 | //} | 764 | //} |
| 765 | 765 | ||
| 766 | bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) | 766 | size_t WriteStringToFile(bool text_file, const std::string &str, const char *filename) |
| 767 | { | 767 | { |
| 768 | return FileUtil::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); | 768 | return FileUtil::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); |
| 769 | } | 769 | } |
| 770 | 770 | ||
| 771 | bool ReadFileToString(bool text_file, const char *filename, std::string &str) | 771 | size_t ReadFileToString(bool text_file, const char *filename, std::string &str) |
| 772 | { | 772 | { |
| 773 | FileUtil::IOFile file(filename, text_file ? "r" : "rb"); | 773 | FileUtil::IOFile file(filename, text_file ? "r" : "rb"); |
| 774 | auto const f = file.GetHandle(); | 774 | auto const f = file.GetHandle(); |
| @@ -780,6 +780,48 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str) | |||
| 780 | return file.ReadArray(&str[0], str.size()); | 780 | return file.ReadArray(&str[0], str.size()); |
| 781 | } | 781 | } |
| 782 | 782 | ||
| 783 | /** | ||
| 784 | * Splits the filename into 8.3 format | ||
| 785 | * Loosely implemented following https://en.wikipedia.org/wiki/8.3_filename | ||
| 786 | * @param filename The normal filename to use | ||
| 787 | * @param short_name A 9-char array in which the short name will be written | ||
| 788 | * @param extension A 4-char array in which the extension will be written | ||
| 789 | */ | ||
| 790 | void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, | ||
| 791 | std::array<char, 4>& extension) { | ||
| 792 | const std::string forbidden_characters = ".\"/\\[]:;=, "; | ||
| 793 | |||
| 794 | // On a FAT32 partition, 8.3 names are stored as a 11 bytes array, filled with spaces. | ||
| 795 | short_name = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\0'}; | ||
| 796 | extension = {' ', ' ', ' ', '\0'}; | ||
| 797 | |||
| 798 | std::string::size_type point = filename.rfind('.'); | ||
| 799 | if (point == filename.size() - 1) | ||
| 800 | point = filename.rfind('.', point); | ||
| 801 | |||
| 802 | // Get short name. | ||
| 803 | int j = 0; | ||
| 804 | for (char letter : filename.substr(0, point)) { | ||
| 805 | if (forbidden_characters.find(letter, 0) != std::string::npos) | ||
| 806 | continue; | ||
| 807 | if (j == 8) { | ||
| 808 | // TODO(Link Mauve): also do that for filenames containing a space. | ||
| 809 | // TODO(Link Mauve): handle multiple files having the same short name. | ||
| 810 | short_name[6] = '~'; | ||
| 811 | short_name[7] = '1'; | ||
| 812 | break; | ||
| 813 | } | ||
| 814 | short_name[j++] = toupper(letter); | ||
| 815 | } | ||
| 816 | |||
| 817 | // Get extension. | ||
| 818 | if (point != std::string::npos) { | ||
| 819 | j = 0; | ||
| 820 | for (char letter : filename.substr(point + 1, 3)) | ||
| 821 | extension[j++] = toupper(letter); | ||
| 822 | } | ||
| 823 | } | ||
| 824 | |||
| 783 | IOFile::IOFile() | 825 | IOFile::IOFile() |
| 784 | : m_file(NULL), m_good(true) | 826 | : m_file(NULL), m_good(true) |
| 785 | {} | 827 | {} |
diff --git a/src/common/file_util.h b/src/common/file_util.h index cddcd1951..173ce6623 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -4,11 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 7 | #include <fstream> | 8 | #include <fstream> |
| 8 | #include <cstdio> | 9 | #include <cstdio> |
| 10 | #include <cstring> | ||
| 9 | #include <string> | 11 | #include <string> |
| 10 | #include <vector> | 12 | #include <vector> |
| 11 | #include <string.h> | ||
| 12 | 13 | ||
| 13 | #include "common/common.h" | 14 | #include "common/common.h" |
| 14 | #include "common/string_util.h" | 15 | #include "common/string_util.h" |
| @@ -47,7 +48,7 @@ enum { | |||
| 47 | namespace FileUtil | 48 | namespace FileUtil |
| 48 | { | 49 | { |
| 49 | 50 | ||
| 50 | // FileSystem tree node/ | 51 | // FileSystem tree node/ |
| 51 | struct FSTEntry | 52 | struct FSTEntry |
| 52 | { | 53 | { |
| 53 | bool isDirectory; | 54 | bool isDirectory; |
| @@ -85,13 +86,13 @@ bool Delete(const std::string &filename); | |||
| 85 | // Deletes a directory filename, returns true on success | 86 | // Deletes a directory filename, returns true on success |
| 86 | bool DeleteDir(const std::string &filename); | 87 | bool DeleteDir(const std::string &filename); |
| 87 | 88 | ||
| 88 | // renames file srcFilename to destFilename, returns true on success | 89 | // renames file srcFilename to destFilename, returns true on success |
| 89 | bool Rename(const std::string &srcFilename, const std::string &destFilename); | 90 | bool Rename(const std::string &srcFilename, const std::string &destFilename); |
| 90 | 91 | ||
| 91 | // copies file srcFilename to destFilename, returns true on success | 92 | // copies file srcFilename to destFilename, returns true on success |
| 92 | bool Copy(const std::string &srcFilename, const std::string &destFilename); | 93 | bool Copy(const std::string &srcFilename, const std::string &destFilename); |
| 93 | 94 | ||
| 94 | // creates an empty file filename, returns true on success | 95 | // creates an empty file filename, returns true on success |
| 95 | bool CreateEmptyFile(const std::string &filename); | 96 | bool CreateEmptyFile(const std::string &filename); |
| 96 | 97 | ||
| 97 | // Scans the directory tree gets, starting from _Directory and adds the | 98 | // Scans the directory tree gets, starting from _Directory and adds the |
| @@ -110,7 +111,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path); | |||
| 110 | // Set the current directory to given directory | 111 | // Set the current directory to given directory |
| 111 | bool SetCurrentDir(const std::string &directory); | 112 | bool SetCurrentDir(const std::string &directory); |
| 112 | 113 | ||
| 113 | // Returns a pointer to a string with a Dolphin data dir in the user's home | 114 | // Returns a pointer to a string with a Citra data dir in the user's home |
| 114 | // directory. To be used in "multi-user" mode (that is, installed). | 115 | // directory. To be used in "multi-user" mode (that is, installed). |
| 115 | const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath=""); | 116 | const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath=""); |
| 116 | 117 | ||
| @@ -128,8 +129,18 @@ std::string GetBundleDirectory(); | |||
| 128 | std::string &GetExeDirectory(); | 129 | std::string &GetExeDirectory(); |
| 129 | #endif | 130 | #endif |
| 130 | 131 | ||
| 131 | bool WriteStringToFile(bool text_file, const std::string &str, const char *filename); | 132 | size_t WriteStringToFile(bool text_file, const std::string &str, const char *filename); |
| 132 | bool ReadFileToString(bool text_file, const char *filename, std::string &str); | 133 | size_t ReadFileToString(bool text_file, const char *filename, std::string &str); |
| 134 | |||
| 135 | /** | ||
| 136 | * Splits the filename into 8.3 format | ||
| 137 | * Loosely implemented following https://en.wikipedia.org/wiki/8.3_filename | ||
| 138 | * @param filename The normal filename to use | ||
| 139 | * @param short_name A 9-char array in which the short name will be written | ||
| 140 | * @param extension A 4-char array in which the extension will be written | ||
| 141 | */ | ||
| 142 | void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, | ||
| 143 | std::array<char, 4>& extension); | ||
| 133 | 144 | ||
| 134 | // simple wrapper for cstdlib file functions to | 145 | // simple wrapper for cstdlib file functions to |
| 135 | // hopefully will make error checking easier | 146 | // hopefully will make error checking easier |
| @@ -142,10 +153,10 @@ public: | |||
| 142 | IOFile(const std::string& filename, const char openmode[]); | 153 | IOFile(const std::string& filename, const char openmode[]); |
| 143 | 154 | ||
| 144 | ~IOFile(); | 155 | ~IOFile(); |
| 145 | 156 | ||
| 146 | IOFile(IOFile&& other); | 157 | IOFile(IOFile&& other); |
| 147 | IOFile& operator=(IOFile&& other); | 158 | IOFile& operator=(IOFile&& other); |
| 148 | 159 | ||
| 149 | void Swap(IOFile& other); | 160 | void Swap(IOFile& other); |
| 150 | 161 | ||
| 151 | bool Open(const std::string& filename, const char openmode[]); | 162 | bool Open(const std::string& filename, const char openmode[]); |
diff --git a/src/common/log.h b/src/common/log.h index 291534c67..bfd73f8a5 100644 --- a/src/common/log.h +++ b/src/common/log.h | |||
| @@ -28,6 +28,7 @@ enum LOG_TYPE { | |||
| 28 | COMMANDPROCESSOR, | 28 | COMMANDPROCESSOR, |
| 29 | COMMON, | 29 | COMMON, |
| 30 | CONSOLE, | 30 | CONSOLE, |
| 31 | CONFIG, | ||
| 31 | DISCIO, | 32 | DISCIO, |
| 32 | FILEMON, | 33 | FILEMON, |
| 33 | DSPHLE, | 34 | DSPHLE, |
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp index 28b72fa20..4d590d98f 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp | |||
| @@ -30,6 +30,7 @@ LogManager::LogManager() | |||
| 30 | m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log"); | 30 | m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log"); |
| 31 | m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot"); | 31 | m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot"); |
| 32 | m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common"); | 32 | m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common"); |
| 33 | m_Log[LogTypes::CONFIG] = new LogContainer("CONFIG", "Configuration"); | ||
| 33 | m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO"); | 34 | m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO"); |
| 34 | m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor"); | 35 | m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor"); |
| 35 | m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad"); | 36 | m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad"); |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2b26292fd..06df9a677 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -56,6 +56,7 @@ set(SRCS | |||
| 56 | core_timing.cpp | 56 | core_timing.cpp |
| 57 | mem_map.cpp | 57 | mem_map.cpp |
| 58 | mem_map_funcs.cpp | 58 | mem_map_funcs.cpp |
| 59 | settings.cpp | ||
| 59 | system.cpp | 60 | system.cpp |
| 60 | ) | 61 | ) |
| 61 | 62 | ||
| @@ -117,6 +118,7 @@ set(HEADERS | |||
| 117 | core.h | 118 | core.h |
| 118 | core_timing.h | 119 | core_timing.h |
| 119 | mem_map.h | 120 | mem_map.h |
| 121 | settings.h | ||
| 120 | system.h | 122 | system.h |
| 121 | ) | 123 | ) |
| 122 | 124 | ||
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 30d33be5f..213923c02 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -24,6 +24,10 @@ Archive_SDMC::Archive_SDMC(const std::string& mount_point) { | |||
| 24 | Archive_SDMC::~Archive_SDMC() { | 24 | Archive_SDMC::~Archive_SDMC() { |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | /** | ||
| 28 | * Initialize the archive. | ||
| 29 | * @return true if it initialized successfully | ||
| 30 | */ | ||
| 27 | bool Archive_SDMC::Initialize() { | 31 | bool Archive_SDMC::Initialize() { |
| 28 | if (!FileUtil::IsDirectory(mount_point)) { | 32 | if (!FileUtil::IsDirectory(mount_point)) { |
| 29 | WARN_LOG(FILESYS, "Directory %s not found, disabling SDMC.", mount_point.c_str()); | 33 | WARN_LOG(FILESYS, "Directory %s not found, disabling SDMC.", mount_point.c_str()); |
| @@ -42,6 +46,8 @@ bool Archive_SDMC::Initialize() { | |||
| 42 | std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const Mode mode) const { | 46 | std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const Mode mode) const { |
| 43 | DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.c_str(), mode); | 47 | DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.c_str(), mode); |
| 44 | File_SDMC* file = new File_SDMC(this, path, mode); | 48 | File_SDMC* file = new File_SDMC(this, path, mode); |
| 49 | if (!file->Open()) | ||
| 50 | return nullptr; | ||
| 45 | return std::unique_ptr<File>(file); | 51 | return std::unique_ptr<File>(file); |
| 46 | } | 52 | } |
| 47 | 53 | ||
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 946f8b957..f68648e6f 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -20,6 +20,10 @@ public: | |||
| 20 | Archive_SDMC(const std::string& mount_point); | 20 | Archive_SDMC(const std::string& mount_point); |
| 21 | ~Archive_SDMC() override; | 21 | ~Archive_SDMC() override; |
| 22 | 22 | ||
| 23 | /** | ||
| 24 | * Initialize the archive. | ||
| 25 | * @return true if it initialized successfully | ||
| 26 | */ | ||
| 23 | bool Initialize(); | 27 | bool Initialize(); |
| 24 | 28 | ||
| 25 | /** | 29 | /** |
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h index cf9a2010b..e10431337 100644 --- a/src/core/file_sys/directory.h +++ b/src/core/file_sys/directory.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstddef> | ||
| 8 | |||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 8 | 10 | ||
| 9 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| @@ -17,9 +19,9 @@ namespace FileSys { | |||
| 17 | const size_t FILENAME_LENGTH = 0x20C / 2; | 19 | const size_t FILENAME_LENGTH = 0x20C / 2; |
| 18 | struct Entry { | 20 | struct Entry { |
| 19 | char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) | 21 | char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) |
| 20 | char short_name[8]; // 8.3 file name ('longfilename' -> 'LONGFI~1') | 22 | std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) |
| 21 | char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) | 23 | char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) |
| 22 | char extension[3]; // 8.3 file extension (set to spaces for directories) | 24 | std::array<char, 4> extension; // 8.3 file extension (set to spaces for directories, null-terminated) |
| 23 | char unknown2; // unknown (always 0x01) | 25 | char unknown2; // unknown (always 0x01) |
| 24 | char unknown3; // unknown (0x00 or 0x08) | 26 | char unknown3; // unknown (0x00 or 0x08) |
| 25 | char is_directory; // directory flag | 27 | char is_directory; // directory flag |
| @@ -29,6 +31,10 @@ struct Entry { | |||
| 29 | u64 file_size; // file size (for files only) | 31 | u64 file_size; // file size (for files only) |
| 30 | }; | 32 | }; |
| 31 | static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); | 33 | static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); |
| 34 | static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); | ||
| 35 | static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension in Entry."); | ||
| 36 | static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); | ||
| 37 | static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); | ||
| 32 | 38 | ||
| 33 | class Directory : NonCopyable { | 39 | class Directory : NonCopyable { |
| 34 | public: | 40 | public: |
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp index 11e867857..36951564d 100644 --- a/src/core/file_sys/directory_sdmc.cpp +++ b/src/core/file_sys/directory_sdmc.cpp | |||
| @@ -20,8 +20,8 @@ Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const std::string& p | |||
| 20 | // the root directory we set while opening the archive. | 20 | // the root directory we set while opening the archive. |
| 21 | // For example, opening /../../usr/bin can give the emulated program your installed programs. | 21 | // For example, opening /../../usr/bin can give the emulated program your installed programs. |
| 22 | std::string absolute_path = archive->GetMountPoint() + path; | 22 | std::string absolute_path = archive->GetMountPoint() + path; |
| 23 | entry_count = FileUtil::ScanDirectoryTree(absolute_path, entry); | 23 | FileUtil::ScanDirectoryTree(absolute_path, directory); |
| 24 | current_entry = 0; | 24 | children_iterator = directory.children.begin(); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | Directory_SDMC::~Directory_SDMC() { | 27 | Directory_SDMC::~Directory_SDMC() { |
| @@ -35,44 +35,39 @@ Directory_SDMC::~Directory_SDMC() { | |||
| 35 | * @return Number of entries listed | 35 | * @return Number of entries listed |
| 36 | */ | 36 | */ |
| 37 | u32 Directory_SDMC::Read(const u32 count, Entry* entries) { | 37 | u32 Directory_SDMC::Read(const u32 count, Entry* entries) { |
| 38 | u32 i; | 38 | u32 entries_read = 0; |
| 39 | for (i = 0; i < count && current_entry < entry_count; ++i) { | 39 | |
| 40 | FileUtil::FSTEntry file = entry.children[current_entry]; | 40 | while (entries_read < count && children_iterator != directory.children.cend()) { |
| 41 | std::string filename = file.virtualName; | 41 | const FileUtil::FSTEntry& file = *children_iterator; |
| 42 | WARN_LOG(FILESYS, "File %s: size=%d dir=%d", filename.c_str(), file.size, file.isDirectory); | 42 | const std::string& filename = file.virtualName; |
| 43 | Entry& entry = entries[entries_read]; | ||
| 43 | 44 | ||
| 44 | Entry* entry = &entries[i]; | 45 | WARN_LOG(FILESYS, "File %s: size=%d dir=%d", filename.c_str(), file.size, file.isDirectory); |
| 45 | 46 | ||
| 46 | // TODO(Link Mauve): use a proper conversion to UTF-16. | 47 | // TODO(Link Mauve): use a proper conversion to UTF-16. |
| 47 | for (int j = 0; j < FILENAME_LENGTH; ++j) { | 48 | for (int j = 0; j < FILENAME_LENGTH; ++j) { |
| 48 | entry->filename[j] = filename[j]; | 49 | entry.filename[j] = filename[j]; |
| 49 | if (!filename[j]) | 50 | if (!filename[j]) |
| 50 | break; | 51 | break; |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | // Split the filename into 8.3 format. | 54 | FileUtil::SplitFilename83(filename, entry.short_name, entry.extension); |
| 54 | // TODO(Link Mauve): move that to common, I guess, and make it more robust to long filenames. | ||
| 55 | std::string::size_type n = filename.rfind('.'); | ||
| 56 | if (n == std::string::npos) { | ||
| 57 | strncpy(entry->short_name, filename.c_str(), 8); | ||
| 58 | memset(entry->extension, '\0', 3); | ||
| 59 | } else { | ||
| 60 | strncpy(entry->short_name, filename.substr(0, n).c_str(), 8); | ||
| 61 | strncpy(entry->extension, filename.substr(n + 1).c_str(), 8); | ||
| 62 | } | ||
| 63 | 55 | ||
| 64 | entry->is_directory = file.isDirectory; | 56 | entry.is_directory = file.isDirectory; |
| 65 | entry->file_size = file.size; | 57 | entry.is_hidden = (filename[0] == '.'); |
| 58 | entry.is_read_only = 0; | ||
| 59 | entry.file_size = file.size; | ||
| 66 | 60 | ||
| 67 | // We emulate a SD card where the archive bit has never been cleared, as it would be on | 61 | // We emulate a SD card where the archive bit has never been cleared, as it would be on |
| 68 | // most user SD cards. | 62 | // most user SD cards. |
| 69 | // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a | 63 | // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a |
| 70 | // file bit. | 64 | // file bit. |
| 71 | entry->is_archive = !file.isDirectory; | 65 | entry.is_archive = !file.isDirectory; |
| 72 | 66 | ||
| 73 | ++current_entry; | 67 | ++entries_read; |
| 68 | ++children_iterator; | ||
| 74 | } | 69 | } |
| 75 | return i; | 70 | return entries_read; |
| 76 | } | 71 | } |
| 77 | 72 | ||
| 78 | /** | 73 | /** |
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h index 0bc6c9eff..cb8d32fda 100644 --- a/src/core/file_sys/directory_sdmc.h +++ b/src/core/file_sys/directory_sdmc.h | |||
| @@ -37,9 +37,12 @@ public: | |||
| 37 | bool Close() const override; | 37 | bool Close() const override; |
| 38 | 38 | ||
| 39 | private: | 39 | private: |
| 40 | u32 entry_count; | 40 | u32 total_entries_in_directory; |
| 41 | u32 current_entry; | 41 | FileUtil::FSTEntry directory; |
| 42 | FileUtil::FSTEntry entry; | 42 | |
| 43 | // We need to remember the last entry we returned, so a subsequent call to Read will continue | ||
| 44 | // from the next one. This iterator will always point to the next unread entry. | ||
| 45 | std::vector<FileUtil::FSTEntry>::iterator children_iterator; | ||
| 43 | }; | 46 | }; |
| 44 | 47 | ||
| 45 | } // namespace FileSys | 48 | } // namespace FileSys |
diff --git a/src/core/file_sys/file.h b/src/core/file_sys/file.h index f7b009f5a..4013b6c3e 100644 --- a/src/core/file_sys/file.h +++ b/src/core/file_sys/file.h | |||
| @@ -19,6 +19,12 @@ public: | |||
| 19 | virtual ~File() { } | 19 | virtual ~File() { } |
| 20 | 20 | ||
| 21 | /** | 21 | /** |
| 22 | * Open the file | ||
| 23 | * @return true if the file opened correctly | ||
| 24 | */ | ||
| 25 | virtual bool Open() = 0; | ||
| 26 | |||
| 27 | /** | ||
| 22 | * Read data from the file | 28 | * Read data from the file |
| 23 | * @param offset Offset in bytes to start reading data from | 29 | * @param offset Offset in bytes to start reading data from |
| 24 | * @param length Length in bytes of data to read from file | 30 | * @param length Length in bytes of data to read from file |
| @@ -31,8 +37,8 @@ public: | |||
| 31 | * Write data to the file | 37 | * Write data to the file |
| 32 | * @param offset Offset in bytes to start writing data to | 38 | * @param offset Offset in bytes to start writing data to |
| 33 | * @param length Length in bytes of data to write to file | 39 | * @param length Length in bytes of data to write to file |
| 34 | * @param buffer Buffer to write data from | ||
| 35 | * @param flush The flush parameters (0 == do not flush) | 40 | * @param flush The flush parameters (0 == do not flush) |
| 41 | * @param buffer Buffer to read data from | ||
| 36 | * @return Number of bytes written | 42 | * @return Number of bytes written |
| 37 | */ | 43 | */ |
| 38 | virtual size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const = 0; | 44 | virtual size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const = 0; |
| @@ -44,6 +50,13 @@ public: | |||
| 44 | virtual size_t GetSize() const = 0; | 50 | virtual size_t GetSize() const = 0; |
| 45 | 51 | ||
| 46 | /** | 52 | /** |
| 53 | * Set the size of the file in bytes | ||
| 54 | * @param size New size of the file | ||
| 55 | * @return true if successful | ||
| 56 | */ | ||
| 57 | virtual bool SetSize(const u64 size) const = 0; | ||
| 58 | |||
| 59 | /** | ||
| 47 | * Close the file | 60 | * Close the file |
| 48 | * @return true if the file closed correctly | 61 | * @return true if the file closed correctly |
| 49 | */ | 62 | */ |
diff --git a/src/core/file_sys/file_romfs.cpp b/src/core/file_sys/file_romfs.cpp index 00f3c2ea8..b55708df4 100644 --- a/src/core/file_sys/file_romfs.cpp +++ b/src/core/file_sys/file_romfs.cpp | |||
| @@ -18,6 +18,14 @@ File_RomFS::~File_RomFS() { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | * Open the file | ||
| 22 | * @return true if the file opened correctly | ||
| 23 | */ | ||
| 24 | bool File_RomFS::Open() { | ||
| 25 | return false; | ||
| 26 | } | ||
| 27 | |||
| 28 | /** | ||
| 21 | * Read data from the file | 29 | * Read data from the file |
| 22 | * @param offset Offset in bytes to start reading data from | 30 | * @param offset Offset in bytes to start reading data from |
| 23 | * @param length Length in bytes of data to read from file | 31 | * @param length Length in bytes of data to read from file |
| @@ -32,8 +40,8 @@ size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | |||
| 32 | * Write data to the file | 40 | * Write data to the file |
| 33 | * @param offset Offset in bytes to start writing data to | 41 | * @param offset Offset in bytes to start writing data to |
| 34 | * @param length Length in bytes of data to write to file | 42 | * @param length Length in bytes of data to write to file |
| 35 | * @param buffer Buffer to write data from | ||
| 36 | * @param flush The flush parameters (0 == do not flush) | 43 | * @param flush The flush parameters (0 == do not flush) |
| 44 | * @param buffer Buffer to read data from | ||
| 37 | * @return Number of bytes written | 45 | * @return Number of bytes written |
| 38 | */ | 46 | */ |
| 39 | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | 47 | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { |
| @@ -49,6 +57,15 @@ size_t File_RomFS::GetSize() const { | |||
| 49 | } | 57 | } |
| 50 | 58 | ||
| 51 | /** | 59 | /** |
| 60 | * Set the size of the file in bytes | ||
| 61 | * @param size New size of the file | ||
| 62 | * @return true if successful | ||
| 63 | */ | ||
| 64 | bool File_RomFS::SetSize(const u64 size) const { | ||
| 65 | return false; | ||
| 66 | } | ||
| 67 | |||
| 68 | /** | ||
| 52 | * Close the file | 69 | * Close the file |
| 53 | * @return true if the file closed correctly | 70 | * @return true if the file closed correctly |
| 54 | */ | 71 | */ |
diff --git a/src/core/file_sys/file_romfs.h b/src/core/file_sys/file_romfs.h index 5db43d4a0..5196701d3 100644 --- a/src/core/file_sys/file_romfs.h +++ b/src/core/file_sys/file_romfs.h | |||
| @@ -20,6 +20,12 @@ public: | |||
| 20 | ~File_RomFS() override; | 20 | ~File_RomFS() override; |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * Open the file | ||
| 24 | * @return true if the file opened correctly | ||
| 25 | */ | ||
| 26 | bool Open() override; | ||
| 27 | |||
| 28 | /** | ||
| 23 | * Read data from the file | 29 | * Read data from the file |
| 24 | * @param offset Offset in bytes to start reading data from | 30 | * @param offset Offset in bytes to start reading data from |
| 25 | * @param length Length in bytes of data to read from file | 31 | * @param length Length in bytes of data to read from file |
| @@ -32,8 +38,8 @@ public: | |||
| 32 | * Write data to the file | 38 | * Write data to the file |
| 33 | * @param offset Offset in bytes to start writing data to | 39 | * @param offset Offset in bytes to start writing data to |
| 34 | * @param length Length in bytes of data to write to file | 40 | * @param length Length in bytes of data to write to file |
| 35 | * @param buffer Buffer to write data from | ||
| 36 | * @param flush The flush parameters (0 == do not flush) | 41 | * @param flush The flush parameters (0 == do not flush) |
| 42 | * @param buffer Buffer to read data from | ||
| 37 | * @return Number of bytes written | 43 | * @return Number of bytes written |
| 38 | */ | 44 | */ |
| 39 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | 45 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; |
| @@ -45,6 +51,13 @@ public: | |||
| 45 | size_t GetSize() const override; | 51 | size_t GetSize() const override; |
| 46 | 52 | ||
| 47 | /** | 53 | /** |
| 54 | * Set the size of the file in bytes | ||
| 55 | * @param size New size of the file | ||
| 56 | * @return true if successful | ||
| 57 | */ | ||
| 58 | bool SetSize(const u64 size) const override; | ||
| 59 | |||
| 60 | /** | ||
| 48 | * Close the file | 61 | * Close the file |
| 49 | * @return true if the file closed correctly | 62 | * @return true if the file closed correctly |
| 50 | */ | 63 | */ |
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp index 76adc6403..26204392c 100644 --- a/src/core/file_sys/file_sdmc.cpp +++ b/src/core/file_sys/file_sdmc.cpp | |||
| @@ -19,31 +19,56 @@ File_SDMC::File_SDMC(const Archive_SDMC* archive, const std::string& path, const | |||
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass |
| 20 | // the root directory we set while opening the archive. | 20 | // the root directory we set while opening the archive. |
| 21 | // For example, opening /../../etc/passwd can give the emulated program your users list. | 21 | // For example, opening /../../etc/passwd can give the emulated program your users list. |
| 22 | std::string real_path = archive->GetMountPoint() + path; | 22 | this->path = archive->GetMountPoint() + path; |
| 23 | this->mode.hex = mode.hex; | ||
| 24 | } | ||
| 25 | |||
| 26 | File_SDMC::~File_SDMC() { | ||
| 27 | Close(); | ||
| 28 | } | ||
| 23 | 29 | ||
| 24 | if (!mode.create_flag && !FileUtil::Exists(real_path)) { | 30 | /** |
| 25 | file = nullptr; | 31 | * Open the file |
| 26 | return; | 32 | * @return true if the file opened correctly |
| 33 | */ | ||
| 34 | bool File_SDMC::Open() { | ||
| 35 | if (!mode.create_flag && !FileUtil::Exists(path)) { | ||
| 36 | ERROR_LOG(FILESYS, "Non-existing file %s can’t be open without mode create.", path.c_str()); | ||
| 37 | return false; | ||
| 27 | } | 38 | } |
| 28 | 39 | ||
| 29 | std::string mode_string; | 40 | std::string mode_string; |
| 30 | if (mode.read_flag) | 41 | if (mode.read_flag && mode.write_flag) |
| 31 | mode_string += "r"; | 42 | mode_string = "w+"; |
| 32 | if (mode.write_flag) | 43 | else if (mode.read_flag) |
| 33 | mode_string += "w"; | 44 | mode_string = "r"; |
| 45 | else if (mode.write_flag) | ||
| 46 | mode_string = "w"; | ||
| 34 | 47 | ||
| 35 | file = new FileUtil::IOFile(real_path, mode_string.c_str()); | 48 | file = new FileUtil::IOFile(path, mode_string.c_str()); |
| 36 | } | 49 | return true; |
| 37 | |||
| 38 | File_SDMC::~File_SDMC() { | ||
| 39 | Close(); | ||
| 40 | } | 50 | } |
| 41 | 51 | ||
| 52 | /** | ||
| 53 | * Read data from the file | ||
| 54 | * @param offset Offset in bytes to start reading data from | ||
| 55 | * @param length Length in bytes of data to read from file | ||
| 56 | * @param buffer Buffer to read data into | ||
| 57 | * @return Number of bytes read | ||
| 58 | */ | ||
| 42 | size_t File_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | 59 | size_t File_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { |
| 43 | file->Seek(offset, SEEK_SET); | 60 | file->Seek(offset, SEEK_SET); |
| 44 | return file->ReadBytes(buffer, length); | 61 | return file->ReadBytes(buffer, length); |
| 45 | } | 62 | } |
| 46 | 63 | ||
| 64 | /** | ||
| 65 | * Write data to the file | ||
| 66 | * @param offset Offset in bytes to start writing data to | ||
| 67 | * @param length Length in bytes of data to write to file | ||
| 68 | * @param flush The flush parameters (0 == do not flush) | ||
| 69 | * @param buffer Buffer to read data from | ||
| 70 | * @return Number of bytes written | ||
| 71 | */ | ||
| 47 | size_t File_SDMC::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | 72 | size_t File_SDMC::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { |
| 48 | file->Seek(offset, SEEK_SET); | 73 | file->Seek(offset, SEEK_SET); |
| 49 | size_t written = file->WriteBytes(buffer, length); | 74 | size_t written = file->WriteBytes(buffer, length); |
| @@ -52,10 +77,29 @@ size_t File_SDMC::Write(const u64 offset, const u32 length, const u32 flush, con | |||
| 52 | return written; | 77 | return written; |
| 53 | } | 78 | } |
| 54 | 79 | ||
| 80 | /** | ||
| 81 | * Get the size of the file in bytes | ||
| 82 | * @return Size of the file in bytes | ||
| 83 | */ | ||
| 55 | size_t File_SDMC::GetSize() const { | 84 | size_t File_SDMC::GetSize() const { |
| 56 | return file->GetSize(); | 85 | return static_cast<size_t>(file->GetSize()); |
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Set the size of the file in bytes | ||
| 90 | * @param size New size of the file | ||
| 91 | * @return true if successful | ||
| 92 | */ | ||
| 93 | bool File_SDMC::SetSize(const u64 size) const { | ||
| 94 | file->Resize(size); | ||
| 95 | file->Flush(); | ||
| 96 | return true; | ||
| 57 | } | 97 | } |
| 58 | 98 | ||
| 99 | /** | ||
| 100 | * Close the file | ||
| 101 | * @return true if the file closed correctly | ||
| 102 | */ | ||
| 59 | bool File_SDMC::Close() const { | 103 | bool File_SDMC::Close() const { |
| 60 | return file->Close(); | 104 | return file->Close(); |
| 61 | } | 105 | } |
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h index b2e46f449..df032f7c0 100644 --- a/src/core/file_sys/file_sdmc.h +++ b/src/core/file_sys/file_sdmc.h | |||
| @@ -23,6 +23,12 @@ public: | |||
| 23 | ~File_SDMC() override; | 23 | ~File_SDMC() override; |
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| 26 | * Open the file | ||
| 27 | * @return true if the file opened correctly | ||
| 28 | */ | ||
| 29 | bool Open() override; | ||
| 30 | |||
| 31 | /** | ||
| 26 | * Read data from the file | 32 | * Read data from the file |
| 27 | * @param offset Offset in bytes to start reading data from | 33 | * @param offset Offset in bytes to start reading data from |
| 28 | * @param length Length in bytes of data to read from file | 34 | * @param length Length in bytes of data to read from file |
| @@ -35,8 +41,8 @@ public: | |||
| 35 | * Write data to the file | 41 | * Write data to the file |
| 36 | * @param offset Offset in bytes to start writing data to | 42 | * @param offset Offset in bytes to start writing data to |
| 37 | * @param length Length in bytes of data to write to file | 43 | * @param length Length in bytes of data to write to file |
| 38 | * @param buffer Buffer to write data from | ||
| 39 | * @param flush The flush parameters (0 == do not flush) | 44 | * @param flush The flush parameters (0 == do not flush) |
| 45 | * @param buffer Buffer to read data from | ||
| 40 | * @return Number of bytes written | 46 | * @return Number of bytes written |
| 41 | */ | 47 | */ |
| 42 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | 48 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; |
| @@ -48,12 +54,21 @@ public: | |||
| 48 | size_t GetSize() const override; | 54 | size_t GetSize() const override; |
| 49 | 55 | ||
| 50 | /** | 56 | /** |
| 57 | * Set the size of the file in bytes | ||
| 58 | * @param size New size of the file | ||
| 59 | * @return true if successful | ||
| 60 | */ | ||
| 61 | bool SetSize(const u64 size) const override; | ||
| 62 | |||
| 63 | /** | ||
| 51 | * Close the file | 64 | * Close the file |
| 52 | * @return true if the file closed correctly | 65 | * @return true if the file closed correctly |
| 53 | */ | 66 | */ |
| 54 | bool Close() const override; | 67 | bool Close() const override; |
| 55 | 68 | ||
| 56 | private: | 69 | private: |
| 70 | std::string path; | ||
| 71 | Mode mode; | ||
| 57 | FileUtil::IOFile* file; | 72 | FileUtil::IOFile* file; |
| 58 | }; | 73 | }; |
| 59 | 74 | ||
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index fa4972994..86aba7489 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp | |||
| @@ -181,6 +181,14 @@ public: | |||
| 181 | break; | 181 | break; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | case FileCommand::SetSize: | ||
| 185 | { | ||
| 186 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | ||
| 187 | DEBUG_LOG(KERNEL, "SetSize %s %s size=%d", GetTypeName().c_str(), GetName().c_str(), size); | ||
| 188 | backend->SetSize(size); | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | |||
| 184 | case FileCommand::Close: | 192 | case FileCommand::Close: |
| 185 | { | 193 | { |
| 186 | DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); | 194 | DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); |
| @@ -366,6 +374,9 @@ Handle OpenFileFromArchive(Handle archive_handle, const std::string& path, const | |||
| 366 | file->path = path; | 374 | file->path = path; |
| 367 | file->backend = archive->backend->OpenFile(path, mode); | 375 | file->backend = archive->backend->OpenFile(path, mode); |
| 368 | 376 | ||
| 377 | if (!file->backend) | ||
| 378 | return 0; | ||
| 379 | |||
| 369 | return handle; | 380 | return handle; |
| 370 | } | 381 | } |
| 371 | 382 | ||
diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index e97e7dbf7..3753f1107 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp | |||
| @@ -73,6 +73,36 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 73 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | 73 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | /** | ||
| 77 | * APT_U::GlanceParameter service function | ||
| 78 | * Inputs: | ||
| 79 | * 1 : AppID | ||
| 80 | * 2 : Parameter buffer size, max size is 0x1000 | ||
| 81 | * Outputs: | ||
| 82 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 83 | * 2 : Unknown, for now assume AppID of the process which sent these parameters | ||
| 84 | * 3 : Unknown, for now assume Signal type | ||
| 85 | * 4 : Actual parameter buffer size, this is <= to the the input size | ||
| 86 | * 5 : Value | ||
| 87 | * 6 : Handle from the source process which set the parameters, likely used for shared memory | ||
| 88 | * 7 : Size | ||
| 89 | * 8 : Output parameter buffer ptr | ||
| 90 | */ | ||
| 91 | void GlanceParameter(Service::Interface* self) { | ||
| 92 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 93 | u32 app_id = cmd_buff[1]; | ||
| 94 | u32 buffer_size = cmd_buff[2]; | ||
| 95 | cmd_buff[1] = 0; // No error | ||
| 96 | cmd_buff[2] = 0; | ||
| 97 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type | ||
| 98 | cmd_buff[4] = 0; | ||
| 99 | cmd_buff[5] = 0; | ||
| 100 | cmd_buff[6] = 0; | ||
| 101 | cmd_buff[7] = 0; | ||
| 102 | cmd_buff[8] = 0; | ||
| 103 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | ||
| 104 | } | ||
| 105 | |||
| 76 | const Interface::FunctionInfo FunctionTable[] = { | 106 | const Interface::FunctionInfo FunctionTable[] = { |
| 77 | {0x00010040, GetLockHandle, "GetLockHandle"}, | 107 | {0x00010040, GetLockHandle, "GetLockHandle"}, |
| 78 | {0x00020080, Initialize, "Initialize"}, | 108 | {0x00020080, Initialize, "Initialize"}, |
| @@ -87,7 +117,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 87 | {0x000B0040, InquireNotification, "InquireNotification"}, | 117 | {0x000B0040, InquireNotification, "InquireNotification"}, |
| 88 | {0x000C0104, nullptr, "SendParameter"}, | 118 | {0x000C0104, nullptr, "SendParameter"}, |
| 89 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, | 119 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, |
| 90 | {0x000E0080, nullptr, "GlanceParameter"}, | 120 | {0x000E0080, GlanceParameter, "GlanceParameter"}, |
| 91 | {0x000F0100, nullptr, "CancelParameter"}, | 121 | {0x000F0100, nullptr, "CancelParameter"}, |
| 92 | {0x001000C2, nullptr, "DebugFunc"}, | 122 | {0x001000C2, nullptr, "DebugFunc"}, |
| 93 | {0x001100C0, nullptr, "MapProgramIdForDebug"}, | 123 | {0x001100C0, nullptr, "MapProgramIdForDebug"}, |
| @@ -152,6 +182,8 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 152 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, | 182 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, |
| 153 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, | 183 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, |
| 154 | {0x004E0000, nullptr, "HardwareResetAsync"}, | 184 | {0x004E0000, nullptr, "HardwareResetAsync"}, |
| 185 | {0x004F0080, nullptr, "SetApplicationCpuTimeLimit"}, | ||
| 186 | {0x00500040, nullptr, "GetApplicationCpuTimeLimit"}, | ||
| 155 | }; | 187 | }; |
| 156 | 188 | ||
| 157 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 189 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index accbe84e3..614d9584d 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp | |||
| @@ -358,6 +358,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 358 | {0x001C0040, nullptr, "SetLedForceOff"}, | 358 | {0x001C0040, nullptr, "SetLedForceOff"}, |
| 359 | {0x001D0040, nullptr, "SetTestCommand"}, | 359 | {0x001D0040, nullptr, "SetTestCommand"}, |
| 360 | {0x001E0080, nullptr, "SetInternalPriorities"}, | 360 | {0x001E0080, nullptr, "SetInternalPriorities"}, |
| 361 | {0x001F0082, nullptr, "StoreDataCache"}, | ||
| 361 | }; | 362 | }; |
| 362 | 363 | ||
| 363 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 364 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp index f510df835..90951812b 100644 --- a/src/core/mem_map_funcs.cpp +++ b/src/core/mem_map_funcs.cpp | |||
| @@ -287,7 +287,7 @@ void Write64(const VAddr addr, const u64 data) { | |||
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | void WriteBlock(const VAddr addr, const u8* data, const size_t size) { | 289 | void WriteBlock(const VAddr addr, const u8* data, const size_t size) { |
| 290 | int offset = 0; | 290 | u32 offset = 0; |
| 291 | while (offset < (size & ~3)) { | 291 | while (offset < (size & ~3)) { |
| 292 | Write32(addr + offset, *(u32*)&data[offset]); | 292 | Write32(addr + offset, *(u32*)&data[offset]); |
| 293 | offset += 4; | 293 | offset += 4; |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp new file mode 100644 index 000000000..c486f6274 --- /dev/null +++ b/src/core/settings.cpp | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "settings.h" | ||
| 6 | |||
| 7 | namespace Settings { | ||
| 8 | |||
| 9 | Values values = {}; | ||
| 10 | |||
| 11 | } | ||
diff --git a/src/core/settings.h b/src/core/settings.h new file mode 100644 index 000000000..a84c3d4b6 --- /dev/null +++ b/src/core/settings.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Settings { | ||
| 8 | |||
| 9 | struct Values { | ||
| 10 | int pad_a_key; | ||
| 11 | int pad_b_key; | ||
| 12 | int pad_x_key; | ||
| 13 | int pad_y_key; | ||
| 14 | int pad_l_key; | ||
| 15 | int pad_r_key; | ||
| 16 | int pad_start_key; | ||
| 17 | int pad_select_key; | ||
| 18 | int pad_home_key; | ||
| 19 | int pad_dup_key; | ||
| 20 | int pad_ddown_key; | ||
| 21 | int pad_dleft_key; | ||
| 22 | int pad_dright_key; | ||
| 23 | int pad_sup_key; | ||
| 24 | int pad_sdown_key; | ||
| 25 | int pad_sleft_key; | ||
| 26 | int pad_sright_key; | ||
| 27 | } extern values; | ||
| 28 | |||
| 29 | } | ||