diff options
46 files changed, 1171 insertions, 606 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 302afe216..82b66be75 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md | |||
| @@ -24,6 +24,10 @@ Citra is a brand new project, so we have a great opportunity to keep things clea | |||
| 24 | ### Indentation/Whitespace Style | 24 | ### Indentation/Whitespace Style |
| 25 | Follow the indentation/whitespace style shown below. Do not use tabs, use 4-spaces instead. | 25 | Follow the indentation/whitespace style shown below. Do not use tabs, use 4-spaces instead. |
| 26 | 26 | ||
| 27 | ### Comments | ||
| 28 | * For regular comments, use C++ style (`//`) comments, even for multi-line ones. | ||
| 29 | * For doc-comments (Doxygen comments), use `/// ` if it's a single line, else use the `/**` `*/` style featured in the example. Start the text on the second line, not the first containing `/**`. | ||
| 30 | |||
| 27 | ```cpp | 31 | ```cpp |
| 28 | namespace Example { | 32 | namespace Example { |
| 29 | 33 | ||
| @@ -33,12 +37,17 @@ namespace Example { | |||
| 33 | int g_foo = 0; | 37 | int g_foo = 0; |
| 34 | char* g_some_pointer; // Notice the position of the * | 38 | char* g_some_pointer; // Notice the position of the * |
| 35 | 39 | ||
| 40 | /// A colorful enum. | ||
| 36 | enum SomeEnum { | 41 | enum SomeEnum { |
| 37 | COLOR_RED, | 42 | COLOR_RED, ///< The color of fire. |
| 38 | COLOR_GREEN, | 43 | COLOR_GREEN, ///< The color of grass. |
| 39 | COLOR_BLUE | 44 | COLOR_BLUE ///< Not actually the color of water. |
| 40 | }; | 45 | }; |
| 41 | 46 | ||
| 47 | /** | ||
| 48 | * Very important struct that does a lot of stuff. | ||
| 49 | * Note that the asterisks are indented by one space. | ||
| 50 | */ | ||
| 42 | struct Position { | 51 | struct Position { |
| 43 | int x, y; | 52 | int x, y; |
| 44 | }; | 53 | }; |
diff --git a/src/citra/config.cpp b/src/citra/config.cpp index f45d09fc2..1f8f5922b 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp | |||
| @@ -36,7 +36,8 @@ bool Config::LoadINI(INIReader* config, const char* location, const std::string& | |||
| 36 | return true; | 36 | return true; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | void Config::ReadControls() { | 39 | void Config::ReadValues() { |
| 40 | // Controls | ||
| 40 | Settings::values.pad_a_key = glfw_config->GetInteger("Controls", "pad_a", GLFW_KEY_A); | 41 | Settings::values.pad_a_key = glfw_config->GetInteger("Controls", "pad_a", GLFW_KEY_A); |
| 41 | Settings::values.pad_b_key = glfw_config->GetInteger("Controls", "pad_b", GLFW_KEY_S); | 42 | Settings::values.pad_b_key = glfw_config->GetInteger("Controls", "pad_b", GLFW_KEY_S); |
| 42 | Settings::values.pad_x_key = glfw_config->GetInteger("Controls", "pad_x", GLFW_KEY_Z); | 43 | Settings::values.pad_x_key = glfw_config->GetInteger("Controls", "pad_x", GLFW_KEY_Z); |
| @@ -54,27 +55,21 @@ void Config::ReadControls() { | |||
| 54 | Settings::values.pad_sdown_key = glfw_config->GetInteger("Controls", "pad_sdown", GLFW_KEY_DOWN); | 55 | Settings::values.pad_sdown_key = glfw_config->GetInteger("Controls", "pad_sdown", GLFW_KEY_DOWN); |
| 55 | Settings::values.pad_sleft_key = glfw_config->GetInteger("Controls", "pad_sleft", GLFW_KEY_LEFT); | 56 | Settings::values.pad_sleft_key = glfw_config->GetInteger("Controls", "pad_sleft", GLFW_KEY_LEFT); |
| 56 | Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); | 57 | Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); |
| 57 | } | ||
| 58 | 58 | ||
| 59 | void Config::ReadCore() { | 59 | // Core |
| 60 | Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter); | 60 | Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter); |
| 61 | Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 60); | 61 | Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 60); |
| 62 | } | ||
| 63 | 62 | ||
| 64 | void Config::ReadData() { | 63 | // Data Storage |
| 65 | Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true); | 64 | Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true); |
| 66 | } | ||
| 67 | 65 | ||
| 68 | void Config::ReadMiscellaneous() { | 66 | // Miscellaneous |
| 69 | Settings::values.enable_log = glfw_config->GetBoolean("Miscellaneous", "enable_log", true); | 67 | Settings::values.enable_log = glfw_config->GetBoolean("Miscellaneous", "enable_log", true); |
| 70 | } | 68 | } |
| 71 | 69 | ||
| 72 | void Config::Reload() { | 70 | void Config::Reload() { |
| 73 | LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file); | 71 | LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file); |
| 74 | ReadControls(); | 72 | ReadValues(); |
| 75 | ReadCore(); | ||
| 76 | ReadData(); | ||
| 77 | ReadMiscellaneous(); | ||
| 78 | } | 73 | } |
| 79 | 74 | ||
| 80 | Config::~Config() { | 75 | Config::~Config() { |
diff --git a/src/citra/config.h b/src/citra/config.h index 19bb83700..2b46fa8aa 100644 --- a/src/citra/config.h +++ b/src/citra/config.h | |||
| @@ -15,10 +15,7 @@ class Config { | |||
| 15 | std::string glfw_config_loc; | 15 | std::string glfw_config_loc; |
| 16 | 16 | ||
| 17 | bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true); | 17 | bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true); |
| 18 | void ReadControls(); | 18 | void ReadValues(); |
| 19 | void ReadCore(); | ||
| 20 | void ReadData(); | ||
| 21 | void ReadMiscellaneous(); | ||
| 22 | public: | 19 | public: |
| 23 | Config(); | 20 | Config(); |
| 24 | ~Config(); | 21 | ~Config(); |
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp index 8efb39e2e..697bf4693 100644 --- a/src/citra/emu_window/emu_window_glfw.cpp +++ b/src/citra/emu_window/emu_window_glfw.cpp | |||
| @@ -58,9 +58,13 @@ EmuWindow_GLFW::EmuWindow_GLFW() { | |||
| 58 | 58 | ||
| 59 | ReloadSetKeymaps(); | 59 | ReloadSetKeymaps(); |
| 60 | 60 | ||
| 61 | glfwSetErrorCallback([](int error, const char *desc){ | ||
| 62 | ERROR_LOG(GUI, "GLFW 0x%08x: %s", error, desc); | ||
| 63 | }); | ||
| 64 | |||
| 61 | // Initialize the window | 65 | // Initialize the window |
| 62 | if(glfwInit() != GL_TRUE) { | 66 | if(glfwInit() != GL_TRUE) { |
| 63 | printf("Failed to initialize GLFW! Exiting..."); | 67 | ERROR_LOG(GUI, "Failed to initialize GLFW! Exiting..."); |
| 64 | exit(1); | 68 | exit(1); |
| 65 | } | 69 | } |
| 66 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | 70 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); |
| @@ -75,7 +79,7 @@ EmuWindow_GLFW::EmuWindow_GLFW() { | |||
| 75 | window_title.c_str(), NULL, NULL); | 79 | window_title.c_str(), NULL, NULL); |
| 76 | 80 | ||
| 77 | if (m_render_window == NULL) { | 81 | if (m_render_window == NULL) { |
| 78 | printf("Failed to create GLFW window! Exiting..."); | 82 | ERROR_LOG(GUI, "Failed to create GLFW window! Exiting..."); |
| 79 | exit(1); | 83 | exit(1); |
| 80 | } | 84 | } |
| 81 | 85 | ||
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index 09fce4d6f..3209e5900 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp | |||
| @@ -21,7 +21,7 @@ Config::Config() { | |||
| 21 | Reload(); | 21 | Reload(); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | void Config::ReadControls() { | 24 | void Config::ReadValues() { |
| 25 | qt_config->beginGroup("Controls"); | 25 | qt_config->beginGroup("Controls"); |
| 26 | Settings::values.pad_a_key = qt_config->value("pad_a", Qt::Key_A).toInt(); | 26 | Settings::values.pad_a_key = qt_config->value("pad_a", Qt::Key_A).toInt(); |
| 27 | Settings::values.pad_b_key = qt_config->value("pad_b", Qt::Key_S).toInt(); | 27 | Settings::values.pad_b_key = qt_config->value("pad_b", Qt::Key_S).toInt(); |
| @@ -41,9 +41,22 @@ void Config::ReadControls() { | |||
| 41 | Settings::values.pad_sleft_key = qt_config->value("pad_sleft", Qt::Key_Left).toInt(); | 41 | Settings::values.pad_sleft_key = qt_config->value("pad_sleft", Qt::Key_Left).toInt(); |
| 42 | Settings::values.pad_sright_key = qt_config->value("pad_sright", Qt::Key_Right).toInt(); | 42 | Settings::values.pad_sright_key = qt_config->value("pad_sright", Qt::Key_Right).toInt(); |
| 43 | qt_config->endGroup(); | 43 | qt_config->endGroup(); |
| 44 | |||
| 45 | qt_config->beginGroup("Core"); | ||
| 46 | Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt(); | ||
| 47 | Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 60).toInt(); | ||
| 48 | qt_config->endGroup(); | ||
| 49 | |||
| 50 | qt_config->beginGroup("Data Storage"); | ||
| 51 | Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); | ||
| 52 | qt_config->endGroup(); | ||
| 53 | |||
| 54 | qt_config->beginGroup("Miscellaneous"); | ||
| 55 | Settings::values.enable_log = qt_config->value("enable_log", true).toBool(); | ||
| 56 | qt_config->endGroup(); | ||
| 44 | } | 57 | } |
| 45 | 58 | ||
| 46 | void Config::SaveControls() { | 59 | void Config::SaveValues() { |
| 47 | qt_config->beginGroup("Controls"); | 60 | qt_config->beginGroup("Controls"); |
| 48 | qt_config->setValue("pad_a", Settings::values.pad_a_key); | 61 | qt_config->setValue("pad_a", Settings::values.pad_a_key); |
| 49 | qt_config->setValue("pad_b", Settings::values.pad_b_key); | 62 | qt_config->setValue("pad_b", Settings::values.pad_b_key); |
| @@ -63,58 +76,27 @@ void Config::SaveControls() { | |||
| 63 | qt_config->setValue("pad_sleft", Settings::values.pad_sleft_key); | 76 | qt_config->setValue("pad_sleft", Settings::values.pad_sleft_key); |
| 64 | qt_config->setValue("pad_sright", Settings::values.pad_sright_key); | 77 | qt_config->setValue("pad_sright", Settings::values.pad_sright_key); |
| 65 | qt_config->endGroup(); | 78 | qt_config->endGroup(); |
| 66 | } | ||
| 67 | |||
| 68 | void Config::ReadCore() { | ||
| 69 | qt_config->beginGroup("Core"); | ||
| 70 | Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt(); | ||
| 71 | Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 60).toInt(); | ||
| 72 | qt_config->endGroup(); | ||
| 73 | } | ||
| 74 | 79 | ||
| 75 | void Config::SaveCore() { | ||
| 76 | qt_config->beginGroup("Core"); | 80 | qt_config->beginGroup("Core"); |
| 77 | qt_config->setValue("cpu_core", Settings::values.cpu_core); | 81 | qt_config->setValue("cpu_core", Settings::values.cpu_core); |
| 78 | qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate); | 82 | qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate); |
| 79 | qt_config->endGroup(); | 83 | qt_config->endGroup(); |
| 80 | } | ||
| 81 | |||
| 82 | void Config::ReadData() { | ||
| 83 | qt_config->beginGroup("Data Storage"); | ||
| 84 | Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); | ||
| 85 | qt_config->endGroup(); | ||
| 86 | } | ||
| 87 | 84 | ||
| 88 | void Config::SaveData() { | ||
| 89 | qt_config->beginGroup("Data Storage"); | 85 | qt_config->beginGroup("Data Storage"); |
| 90 | qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); | 86 | qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); |
| 91 | qt_config->endGroup(); | 87 | qt_config->endGroup(); |
| 92 | } | ||
| 93 | |||
| 94 | void Config::ReadMiscellaneous() { | ||
| 95 | qt_config->beginGroup("Miscellaneous"); | ||
| 96 | Settings::values.enable_log = qt_config->value("enable_log", true).toBool(); | ||
| 97 | qt_config->endGroup(); | ||
| 98 | } | ||
| 99 | 88 | ||
| 100 | void Config::SaveMiscellaneous() { | ||
| 101 | qt_config->beginGroup("Miscellaneous"); | 89 | qt_config->beginGroup("Miscellaneous"); |
| 102 | qt_config->setValue("enable_log", Settings::values.enable_log); | 90 | qt_config->setValue("enable_log", Settings::values.enable_log); |
| 103 | qt_config->endGroup(); | 91 | qt_config->endGroup(); |
| 104 | } | 92 | } |
| 105 | 93 | ||
| 106 | void Config::Reload() { | 94 | void Config::Reload() { |
| 107 | ReadControls(); | 95 | ReadValues(); |
| 108 | ReadCore(); | ||
| 109 | ReadData(); | ||
| 110 | ReadMiscellaneous(); | ||
| 111 | } | 96 | } |
| 112 | 97 | ||
| 113 | void Config::Save() { | 98 | void Config::Save() { |
| 114 | SaveControls(); | 99 | SaveValues(); |
| 115 | SaveCore(); | ||
| 116 | SaveData(); | ||
| 117 | SaveMiscellaneous(); | ||
| 118 | } | 100 | } |
| 119 | 101 | ||
| 120 | Config::~Config() { | 102 | Config::~Config() { |
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h index 8c6568cb2..4c95d0cb9 100644 --- a/src/citra_qt/config.h +++ b/src/citra_qt/config.h | |||
| @@ -12,15 +12,8 @@ class Config { | |||
| 12 | QSettings* qt_config; | 12 | QSettings* qt_config; |
| 13 | std::string qt_config_loc; | 13 | std::string qt_config_loc; |
| 14 | 14 | ||
| 15 | void ReadControls(); | 15 | void ReadValues(); |
| 16 | void SaveControls(); | 16 | void SaveValues(); |
| 17 | void ReadCore(); | ||
| 18 | void SaveCore(); | ||
| 19 | void ReadData(); | ||
| 20 | void SaveData(); | ||
| 21 | |||
| 22 | void ReadMiscellaneous(); | ||
| 23 | void SaveMiscellaneous(); | ||
| 24 | public: | 17 | public: |
| 25 | Config(); | 18 | Config(); |
| 26 | ~Config(); | 19 | ~Config(); |
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp index 38c681ee0..2ef7d98c0 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include "common/log_manager.h" | 7 | #include "common/log_manager.h" |
| 8 | #include "common/console_listener.h" | 8 | #include "common/console_listener.h" |
| 9 | #include "common/timer.h" | 9 | #include "common/timer.h" |
| 10 | #include "common/thread.h" | ||
| 11 | 10 | ||
| 12 | void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, | 11 | void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, |
| 13 | const char* function, const char* fmt, ...) | 12 | const char* function, const char* fmt, ...) |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b3bfbca9e..48241c3d4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -133,6 +133,7 @@ set(HEADERS | |||
| 133 | hle/service/srv.h | 133 | hle/service/srv.h |
| 134 | hle/service/ssl_c.h | 134 | hle/service/ssl_c.h |
| 135 | hle/config_mem.h | 135 | hle/config_mem.h |
| 136 | hle/result.h | ||
| 136 | hle/function_wrappers.h | 137 | hle/function_wrappers.h |
| 137 | hle/hle.h | 138 | hle/hle.h |
| 138 | hle/svc.h | 139 | hle/svc.h |
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index f899e2e8a..233cd3e3a 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | #define CITRA_IGNORE_EXIT(x) | 26 | #define CITRA_IGNORE_EXIT(x) |
| 27 | 27 | ||
| 28 | #include <algorithm> | 28 | #include <algorithm> |
| 29 | #include <map> | 29 | #include <unordered_map> |
| 30 | #include <stdio.h> | 30 | #include <stdio.h> |
| 31 | #include <assert.h> | 31 | #include <assert.h> |
| 32 | #include <cstdio> | 32 | #include <cstdio> |
| @@ -94,9 +94,8 @@ typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper); | |||
| 94 | 94 | ||
| 95 | /* exclusive memory access */ | 95 | /* exclusive memory access */ |
| 96 | static int exclusive_detect(ARMul_State* state, ARMword addr){ | 96 | static int exclusive_detect(ARMul_State* state, ARMword addr){ |
| 97 | int i; | ||
| 98 | #if 0 | 97 | #if 0 |
| 99 | for(i = 0; i < 128; i++){ | 98 | for(int i = 0; i < 128; i++){ |
| 100 | if(state->exclusive_tag_array[i] == addr) | 99 | if(state->exclusive_tag_array[i] == addr) |
| 101 | return 0; | 100 | return 0; |
| 102 | } | 101 | } |
| @@ -108,9 +107,8 @@ static int exclusive_detect(ARMul_State* state, ARMword addr){ | |||
| 108 | } | 107 | } |
| 109 | 108 | ||
| 110 | static void add_exclusive_addr(ARMul_State* state, ARMword addr){ | 109 | static void add_exclusive_addr(ARMul_State* state, ARMword addr){ |
| 111 | int i; | ||
| 112 | #if 0 | 110 | #if 0 |
| 113 | for(i = 0; i < 128; i++){ | 111 | for(int i = 0; i < 128; i++){ |
| 114 | if(state->exclusive_tag_array[i] == 0xffffffff){ | 112 | if(state->exclusive_tag_array[i] == 0xffffffff){ |
| 115 | state->exclusive_tag_array[i] = addr; | 113 | state->exclusive_tag_array[i] = addr; |
| 116 | //DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr); | 114 | //DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr); |
| @@ -3309,9 +3307,8 @@ const transop_fp_t arm_instruction_trans[] = { | |||
| 3309 | INTERPRETER_TRANSLATE(blx_1_thumb) | 3307 | INTERPRETER_TRANSLATE(blx_1_thumb) |
| 3310 | }; | 3308 | }; |
| 3311 | 3309 | ||
| 3312 | typedef map<unsigned int, int> bb_map; | 3310 | typedef std::unordered_map<u32, int> bb_map; |
| 3313 | bb_map CreamCache[65536]; | 3311 | bb_map CreamCache; |
| 3314 | bb_map ProfileCache[65536]; | ||
| 3315 | 3312 | ||
| 3316 | //#define USE_DUMMY_CACHE | 3313 | //#define USE_DUMMY_CACHE |
| 3317 | 3314 | ||
| @@ -3319,14 +3316,12 @@ bb_map ProfileCache[65536]; | |||
| 3319 | unsigned int DummyCache[0x100000]; | 3316 | unsigned int DummyCache[0x100000]; |
| 3320 | #endif | 3317 | #endif |
| 3321 | 3318 | ||
| 3322 | #define HASH(x) ((x + (x << 3) + (x >> 6)) % 65536) | ||
| 3323 | void insert_bb(unsigned int addr, int start) | 3319 | void insert_bb(unsigned int addr, int start) |
| 3324 | { | 3320 | { |
| 3325 | #ifdef USE_DUMMY_CACHE | 3321 | #ifdef USE_DUMMY_CACHE |
| 3326 | DummyCache[addr] = start; | 3322 | DummyCache[addr] = start; |
| 3327 | #else | 3323 | #else |
| 3328 | // CreamCache[addr] = start; | 3324 | CreamCache[addr] = start; |
| 3329 | CreamCache[HASH(addr)][addr] = start; | ||
| 3330 | #endif | 3325 | #endif |
| 3331 | } | 3326 | } |
| 3332 | 3327 | ||
| @@ -3341,8 +3336,8 @@ int find_bb(unsigned int addr, int &start) | |||
| 3341 | } else | 3336 | } else |
| 3342 | ret = -1; | 3337 | ret = -1; |
| 3343 | #else | 3338 | #else |
| 3344 | bb_map::const_iterator it = CreamCache[HASH(addr)].find(addr); | 3339 | bb_map::const_iterator it = CreamCache.find(addr); |
| 3345 | if (it != CreamCache[HASH(addr)].end()) { | 3340 | if (it != CreamCache.end()) { |
| 3346 | start = static_cast<int>(it->second); | 3341 | start = static_cast<int>(it->second); |
| 3347 | ret = 0; | 3342 | ret = 0; |
| 3348 | #if HYBRID_MODE | 3343 | #if HYBRID_MODE |
| @@ -3473,30 +3468,15 @@ void flush_bb(uint32_t addr) | |||
| 3473 | uint32_t start; | 3468 | uint32_t start; |
| 3474 | 3469 | ||
| 3475 | addr &= 0xfffff000; | 3470 | addr &= 0xfffff000; |
| 3476 | for (int i = 0; i < 65536; i ++) { | 3471 | for (it = CreamCache.begin(); it != CreamCache.end(); ) { |
| 3477 | for (it = CreamCache[i].begin(); it != CreamCache[i].end(); ) { | 3472 | start = static_cast<uint32_t>(it->first); |
| 3478 | start = static_cast<uint32_t>(it->first); | 3473 | //start = (start >> 12) << 12; |
| 3479 | //start = (start >> 12) << 12; | 3474 | start &= 0xfffff000; |
| 3480 | start &= 0xfffff000; | 3475 | if (start == addr) { |
| 3481 | if (start == addr) { | 3476 | //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first)); |
| 3482 | //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first)); | 3477 | CreamCache.erase(it++); |
| 3483 | CreamCache[i].erase(it ++); | 3478 | } else |
| 3484 | } else | 3479 | ++it; |
| 3485 | ++it; | ||
| 3486 | } | ||
| 3487 | } | ||
| 3488 | |||
| 3489 | for (int i = 0; i < 65536; i ++) { | ||
| 3490 | for (it = ProfileCache[i].begin(); it != ProfileCache[i].end(); ) { | ||
| 3491 | start = static_cast<uint32_t>(it->first); | ||
| 3492 | //start = (start >> 12) << 12; | ||
| 3493 | start &= 0xfffff000; | ||
| 3494 | if (start == addr) { | ||
| 3495 | //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first)); | ||
| 3496 | ProfileCache[i].erase(it ++); | ||
| 3497 | } else | ||
| 3498 | ++it; | ||
| 3499 | } | ||
| 3500 | } | 3480 | } |
| 3501 | 3481 | ||
| 3502 | //DEBUG_LOG(ARM11, "flush bb @ %x\n", addr); | 3482 | //DEBUG_LOG(ARM11, "flush bb @ %x\n", addr); |
diff --git a/src/core/arm/skyeye_common/armcpu.h b/src/core/arm/skyeye_common/armcpu.h index 3a029f0e7..2b756c5bc 100644 --- a/src/core/arm/skyeye_common/armcpu.h +++ b/src/core/arm/skyeye_common/armcpu.h | |||
| @@ -24,8 +24,6 @@ | |||
| 24 | #include <stddef.h> | 24 | #include <stddef.h> |
| 25 | #include <stdio.h> | 25 | #include <stdio.h> |
| 26 | 26 | ||
| 27 | #include "common/thread.h" | ||
| 28 | |||
| 29 | #include "core/arm/skyeye_common/armdefs.h" | 27 | #include "core/arm/skyeye_common/armdefs.h" |
| 30 | 28 | ||
| 31 | typedef struct ARM_CPU_State_s { | 29 | typedef struct ARM_CPU_State_s { |
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index 8e71948c6..8343aaa01 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h | |||
| @@ -799,22 +799,24 @@ pascal void SpinCursor (short increment); /* copied from CursorCtl.h */ | |||
| 799 | #include "list.h" | 799 | #include "list.h" |
| 800 | #include "tb.h" | 800 | #include "tb.h" |
| 801 | */ | 801 | */ |
| 802 | #define EQ 0 | 802 | enum ConditionCode { |
| 803 | #define NE 1 | 803 | EQ = 0, |
| 804 | #define CS 2 | 804 | NE = 1, |
| 805 | #define CC 3 | 805 | CS = 2, |
| 806 | #define MI 4 | 806 | CC = 3, |
| 807 | #define PL 5 | 807 | MI = 4, |
| 808 | #define VS 6 | 808 | PL = 5, |
| 809 | #define VC 7 | 809 | VS = 6, |
| 810 | #define HI 8 | 810 | VC = 7, |
| 811 | #define LS 9 | 811 | HI = 8, |
| 812 | #define GE 10 | 812 | LS = 9, |
| 813 | #define LT 11 | 813 | GE = 10, |
| 814 | #define GT 12 | 814 | LT = 11, |
| 815 | #define LE 13 | 815 | GT = 12, |
| 816 | #define AL 14 | 816 | LE = 13, |
| 817 | #define NV 15 | 817 | AL = 14, |
| 818 | NV = 15, | ||
| 819 | }; | ||
| 818 | 820 | ||
| 819 | #ifndef NFLAG | 821 | #ifndef NFLAG |
| 820 | #define NFLAG state->NFlag | 822 | #define NFLAG state->NFlag |
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h index c0f0270fe..075fc7e9e 100644 --- a/src/core/arm/skyeye_common/armemu.h +++ b/src/core/arm/skyeye_common/armemu.h | |||
| @@ -25,24 +25,6 @@ | |||
| 25 | 25 | ||
| 26 | #define DEBUG(...) DEBUG_LOG(ARM11, __VA_ARGS__) | 26 | #define DEBUG(...) DEBUG_LOG(ARM11, __VA_ARGS__) |
| 27 | 27 | ||
| 28 | /* Condition code values. */ | ||
| 29 | #define EQ 0 | ||
| 30 | #define NE 1 | ||
| 31 | #define CS 2 | ||
| 32 | #define CC 3 | ||
| 33 | #define MI 4 | ||
| 34 | #define PL 5 | ||
| 35 | #define VS 6 | ||
| 36 | #define VC 7 | ||
| 37 | #define HI 8 | ||
| 38 | #define LS 9 | ||
| 39 | #define GE 10 | ||
| 40 | #define LT 11 | ||
| 41 | #define GT 12 | ||
| 42 | #define LE 13 | ||
| 43 | #define AL 14 | ||
| 44 | #define NV 15 | ||
| 45 | |||
| 46 | /* Shift Opcodes. */ | 28 | /* Shift Opcodes. */ |
| 47 | #define LSL 0 | 29 | #define LSL 0 |
| 48 | #define LSR 1 | 30 | #define LSR 1 |
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h index 1135d8804..c2426a153 100644 --- a/src/core/file_sys/archive.h +++ b/src/core/file_sys/archive.h | |||
| @@ -67,6 +67,8 @@ public: | |||
| 67 | u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. | 67 | u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. |
| 68 | break; | 68 | break; |
| 69 | } | 69 | } |
| 70 | default: | ||
| 71 | break; | ||
| 70 | } | 72 | } |
| 71 | } | 73 | } |
| 72 | 74 | ||
| @@ -185,6 +187,20 @@ public: | |||
| 185 | virtual std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const = 0; | 187 | virtual std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const = 0; |
| 186 | 188 | ||
| 187 | /** | 189 | /** |
| 190 | * Delete a file specified by its path | ||
| 191 | * @param path Path relative to the archive | ||
| 192 | * @return Whether the file could be deleted | ||
| 193 | */ | ||
| 194 | virtual bool DeleteFile(const FileSys::Path& path) const = 0; | ||
| 195 | |||
| 196 | /** | ||
| 197 | * Delete a directory specified by its path | ||
| 198 | * @param path Path relative to the archive | ||
| 199 | * @return Whether the directory could be deleted | ||
| 200 | */ | ||
| 201 | virtual bool DeleteDirectory(const FileSys::Path& path) const = 0; | ||
| 202 | |||
| 203 | /** | ||
| 188 | * Create a directory specified by its path | 204 | * Create a directory specified by its path |
| 189 | * @param path Path relative to the archive | 205 | * @param path Path relative to the archive |
| 190 | * @return Whether the directory could be created | 206 | * @return Whether the directory could be created |
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index 551913a42..53dc57954 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -34,6 +34,26 @@ std::unique_ptr<File> Archive_RomFS::OpenFile(const Path& path, const Mode mode) | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | /** | 36 | /** |
| 37 | * Delete a file specified by its path | ||
| 38 | * @param path Path relative to the archive | ||
| 39 | * @return Whether the file could be deleted | ||
| 40 | */ | ||
| 41 | bool Archive_RomFS::DeleteFile(const FileSys::Path& path) const { | ||
| 42 | ERROR_LOG(FILESYS, "Attempted to delete a file from ROMFS."); | ||
| 43 | return false; | ||
| 44 | } | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Delete a directory specified by its path | ||
| 48 | * @param path Path relative to the archive | ||
| 49 | * @return Whether the directory could be deleted | ||
| 50 | */ | ||
| 51 | bool Archive_RomFS::DeleteDirectory(const FileSys::Path& path) const { | ||
| 52 | ERROR_LOG(FILESYS, "Attempted to delete a directory from ROMFS."); | ||
| 53 | return false; | ||
| 54 | } | ||
| 55 | |||
| 56 | /** | ||
| 37 | * Create a directory specified by its path | 57 | * Create a directory specified by its path |
| 38 | * @param path Path relative to the archive | 58 | * @param path Path relative to the archive |
| 39 | * @return Whether the directory could be created | 59 | * @return Whether the directory could be created |
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index f05327f51..0649dde99 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -37,6 +37,20 @@ public: | |||
| 37 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; | 37 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; |
| 38 | 38 | ||
| 39 | /** | 39 | /** |
| 40 | * Delete a file specified by its path | ||
| 41 | * @param path Path relative to the archive | ||
| 42 | * @return Whether the file could be deleted | ||
| 43 | */ | ||
| 44 | bool DeleteFile(const FileSys::Path& path) const override; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Delete a directory specified by its path | ||
| 48 | * @param path Path relative to the archive | ||
| 49 | * @return Whether the directory could be deleted | ||
| 50 | */ | ||
| 51 | bool DeleteDirectory(const FileSys::Path& path) const override; | ||
| 52 | |||
| 53 | /** | ||
| 40 | * Create a directory specified by its path | 54 | * Create a directory specified by its path |
| 41 | * @param path Path relative to the archive | 55 | * @param path Path relative to the archive |
| 42 | * @return Whether the directory could be created | 56 | * @return Whether the directory could be created |
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index ecdb7f211..789212b17 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -50,7 +50,7 @@ bool Archive_SDMC::Initialize() { | |||
| 50 | * @return Opened file, or nullptr | 50 | * @return Opened file, or nullptr |
| 51 | */ | 51 | */ |
| 52 | std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { | 52 | std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { |
| 53 | DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.DebugStr().c_str(), mode); | 53 | DEBUG_LOG(FILESYS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex); |
| 54 | File_SDMC* file = new File_SDMC(this, path, mode); | 54 | File_SDMC* file = new File_SDMC(this, path, mode); |
| 55 | if (!file->Open()) | 55 | if (!file->Open()) |
| 56 | return nullptr; | 56 | return nullptr; |
| @@ -58,6 +58,24 @@ std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | /** | 60 | /** |
| 61 | * Delete a file specified by its path | ||
| 62 | * @param path Path relative to the archive | ||
| 63 | * @return Whether the file could be deleted | ||
| 64 | */ | ||
| 65 | bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const { | ||
| 66 | return FileUtil::Delete(GetMountPoint() + path.AsString()); | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Delete a directory specified by its path | ||
| 71 | * @param path Path relative to the archive | ||
| 72 | * @return Whether the directory could be deleted | ||
| 73 | */ | ||
| 74 | bool Archive_SDMC::DeleteDirectory(const FileSys::Path& path) const { | ||
| 75 | return FileUtil::DeleteDir(GetMountPoint() + path.AsString()); | ||
| 76 | } | ||
| 77 | |||
| 78 | /** | ||
| 61 | * Create a directory specified by its path | 79 | * Create a directory specified by its path |
| 62 | * @param path Path relative to the archive | 80 | * @param path Path relative to the archive |
| 63 | * @return Whether the directory could be created | 81 | * @return Whether the directory could be created |
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 17b9209b4..74ce29c0d 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -41,6 +41,20 @@ public: | |||
| 41 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; | 41 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Delete a file specified by its path | ||
| 45 | * @param path Path relative to the archive | ||
| 46 | * @return Whether the file could be deleted | ||
| 47 | */ | ||
| 48 | bool DeleteFile(const FileSys::Path& path) const override; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Delete a directory specified by its path | ||
| 52 | * @param path Path relative to the archive | ||
| 53 | * @return Whether the directory could be deleted | ||
| 54 | */ | ||
| 55 | bool DeleteDirectory(const FileSys::Path& path) const override; | ||
| 56 | |||
| 57 | /** | ||
| 44 | * Create a directory specified by its path | 58 | * Create a directory specified by its path |
| 45 | * @param path Path relative to the archive | 59 | * @param path Path relative to the archive |
| 46 | * @return Whether the directory could be created | 60 | * @return Whether the directory could be created |
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 2b21657da..db571b895 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -25,22 +25,17 @@ public: | |||
| 25 | 25 | ||
| 26 | std::string name; ///< Name of address arbiter object (optional) | 26 | std::string name; ///< Name of address arbiter object (optional) |
| 27 | 27 | ||
| 28 | /** | 28 | ResultVal<bool> WaitSynchronization() override { |
| 29 | * Wait for kernel object to synchronize | ||
| 30 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 31 | * @return Result of operation, 0 on success, otherwise error code | ||
| 32 | */ | ||
| 33 | Result WaitSynchronization(bool* wait) override { | ||
| 34 | // TODO(bunnei): ImplementMe | 29 | // TODO(bunnei): ImplementMe |
| 35 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 30 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 36 | return 0; | 31 | return UnimplementedFunction(ErrorModule::OS); |
| 37 | } | 32 | } |
| 38 | }; | 33 | }; |
| 39 | 34 | ||
| 40 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 41 | 36 | ||
| 42 | /// Arbitrate an address | 37 | /// Arbitrate an address |
| 43 | Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { | 38 | ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { |
| 44 | switch (type) { | 39 | switch (type) { |
| 45 | 40 | ||
| 46 | // Signal thread(s) waiting for arbitrate address... | 41 | // Signal thread(s) waiting for arbitrate address... |
| @@ -65,9 +60,9 @@ Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 va | |||
| 65 | 60 | ||
| 66 | default: | 61 | default: |
| 67 | ERROR_LOG(KERNEL, "unknown type=%d", type); | 62 | ERROR_LOG(KERNEL, "unknown type=%d", type); |
| 68 | return -1; | 63 | return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage); |
| 69 | } | 64 | } |
| 70 | return 0; | 65 | return RESULT_SUCCESS; |
| 71 | } | 66 | } |
| 72 | 67 | ||
| 73 | /// Create an address arbiter | 68 | /// Create an address arbiter |
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 6886e479d..8a5fb10b4 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h | |||
| @@ -28,7 +28,7 @@ enum class ArbitrationType : u32 { | |||
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | /// Arbitrate an address | 30 | /// Arbitrate an address |
| 31 | Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value); | 31 | ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value); |
| 32 | 32 | ||
| 33 | /// Create an address arbiter | 33 | /// Create an address arbiter |
| 34 | Handle CreateAddressArbiter(const std::string& name = "Unknown"); | 34 | Handle CreateAddressArbiter(const std::string& name = "Unknown"); |
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index d9ee4682a..e273444c9 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp | |||
| @@ -9,8 +9,9 @@ | |||
| 9 | #include "core/file_sys/archive.h" | 9 | #include "core/file_sys/archive.h" |
| 10 | #include "core/file_sys/archive_sdmc.h" | 10 | #include "core/file_sys/archive_sdmc.h" |
| 11 | #include "core/file_sys/directory.h" | 11 | #include "core/file_sys/directory.h" |
| 12 | #include "core/hle/service/service.h" | ||
| 13 | #include "core/hle/kernel/archive.h" | 12 | #include "core/hle/kernel/archive.h" |
| 13 | #include "core/hle/result.h" | ||
| 14 | #include "core/hle/service/service.h" | ||
| 14 | 15 | ||
| 15 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 16 | // Kernel namespace | 17 | // Kernel namespace |
| @@ -51,12 +52,7 @@ public: | |||
| 51 | std::string name; ///< Name of archive (optional) | 52 | std::string name; ///< Name of archive (optional) |
| 52 | FileSys::Archive* backend; ///< Archive backend interface | 53 | FileSys::Archive* backend; ///< Archive backend interface |
| 53 | 54 | ||
| 54 | /** | 55 | ResultVal<bool> SyncRequest() override { |
| 55 | * Synchronize kernel object | ||
| 56 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 57 | * @return Result of operation, 0 on success, otherwise error code | ||
| 58 | */ | ||
| 59 | Result SyncRequest(bool* wait) override { | ||
| 60 | u32* cmd_buff = Service::GetCommandBuffer(); | 56 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 61 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | 57 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 62 | 58 | ||
| @@ -106,22 +102,17 @@ public: | |||
| 106 | default: | 102 | default: |
| 107 | { | 103 | { |
| 108 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 104 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 109 | return -1; | 105 | return UnimplementedFunction(ErrorModule::FS); |
| 110 | } | 106 | } |
| 111 | } | 107 | } |
| 112 | cmd_buff[1] = 0; // No error | 108 | cmd_buff[1] = 0; // No error |
| 113 | return 0; | 109 | return MakeResult<bool>(false); |
| 114 | } | 110 | } |
| 115 | 111 | ||
| 116 | /** | 112 | ResultVal<bool> WaitSynchronization() override { |
| 117 | * Wait for kernel object to synchronize | ||
| 118 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 119 | * @return Result of operation, 0 on success, otherwise error code | ||
| 120 | */ | ||
| 121 | Result WaitSynchronization(bool* wait) override { | ||
| 122 | // TODO(bunnei): ImplementMe | 113 | // TODO(bunnei): ImplementMe |
| 123 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 114 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 124 | return 0; | 115 | return UnimplementedFunction(ErrorModule::FS); |
| 125 | } | 116 | } |
| 126 | }; | 117 | }; |
| 127 | 118 | ||
| @@ -136,12 +127,7 @@ public: | |||
| 136 | FileSys::Path path; ///< Path of the file | 127 | FileSys::Path path; ///< Path of the file |
| 137 | std::unique_ptr<FileSys::File> backend; ///< File backend interface | 128 | std::unique_ptr<FileSys::File> backend; ///< File backend interface |
| 138 | 129 | ||
| 139 | /** | 130 | ResultVal<bool> SyncRequest() override { |
| 140 | * Synchronize kernel object | ||
| 141 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 142 | * @return Result of operation, 0 on success, otherwise error code | ||
| 143 | */ | ||
| 144 | Result SyncRequest(bool* wait) override { | ||
| 145 | u32* cmd_buff = Service::GetCommandBuffer(); | 131 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 146 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | 132 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 147 | switch (cmd) { | 133 | switch (cmd) { |
| @@ -183,7 +169,8 @@ public: | |||
| 183 | case FileCommand::SetSize: | 169 | case FileCommand::SetSize: |
| 184 | { | 170 | { |
| 185 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | 171 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); |
| 186 | DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(), size); | 172 | DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", |
| 173 | GetTypeName().c_str(), GetName().c_str(), size); | ||
| 187 | backend->SetSize(size); | 174 | backend->SetSize(size); |
| 188 | break; | 175 | break; |
| 189 | } | 176 | } |
| @@ -198,22 +185,18 @@ public: | |||
| 198 | // Unknown command... | 185 | // Unknown command... |
| 199 | default: | 186 | default: |
| 200 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 187 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 201 | cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. | 188 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 202 | return -1; | 189 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 190 | return error; | ||
| 203 | } | 191 | } |
| 204 | cmd_buff[1] = 0; // No error | 192 | cmd_buff[1] = 0; // No error |
| 205 | return 0; | 193 | return MakeResult<bool>(false); |
| 206 | } | 194 | } |
| 207 | 195 | ||
| 208 | /** | 196 | ResultVal<bool> WaitSynchronization() override { |
| 209 | * Wait for kernel object to synchronize | ||
| 210 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 211 | * @return Result of operation, 0 on success, otherwise error code | ||
| 212 | */ | ||
| 213 | Result WaitSynchronization(bool* wait) override { | ||
| 214 | // TODO(bunnei): ImplementMe | 197 | // TODO(bunnei): ImplementMe |
| 215 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 198 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 216 | return 0; | 199 | return UnimplementedFunction(ErrorModule::FS); |
| 217 | } | 200 | } |
| 218 | }; | 201 | }; |
| 219 | 202 | ||
| @@ -228,12 +211,7 @@ public: | |||
| 228 | FileSys::Path path; ///< Path of the directory | 211 | FileSys::Path path; ///< Path of the directory |
| 229 | std::unique_ptr<FileSys::Directory> backend; ///< File backend interface | 212 | std::unique_ptr<FileSys::Directory> backend; ///< File backend interface |
| 230 | 213 | ||
| 231 | /** | 214 | ResultVal<bool> SyncRequest() override { |
| 232 | * Synchronize kernel object | ||
| 233 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 234 | * @return Result of operation, 0 on success, otherwise error code | ||
| 235 | */ | ||
| 236 | Result SyncRequest(bool* wait) override { | ||
| 237 | u32* cmd_buff = Service::GetCommandBuffer(); | 215 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 238 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | 216 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); |
| 239 | switch (cmd) { | 217 | switch (cmd) { |
| @@ -243,8 +221,9 @@ public: | |||
| 243 | { | 221 | { |
| 244 | u32 count = cmd_buff[1]; | 222 | u32 count = cmd_buff[1]; |
| 245 | u32 address = cmd_buff[3]; | 223 | u32 address = cmd_buff[3]; |
| 246 | FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); | 224 | auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); |
| 247 | DEBUG_LOG(KERNEL, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), count); | 225 | DEBUG_LOG(KERNEL, "Read %s %s: count=%d", |
| 226 | GetTypeName().c_str(), GetName().c_str(), count); | ||
| 248 | 227 | ||
| 249 | // Number of entries actually read | 228 | // Number of entries actually read |
| 250 | cmd_buff[2] = backend->Read(count, entries); | 229 | cmd_buff[2] = backend->Read(count, entries); |
| @@ -261,22 +240,18 @@ public: | |||
| 261 | // Unknown command... | 240 | // Unknown command... |
| 262 | default: | 241 | default: |
| 263 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 242 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 264 | cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. | 243 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 265 | return -1; | 244 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 245 | return error; | ||
| 266 | } | 246 | } |
| 267 | cmd_buff[1] = 0; // No error | 247 | cmd_buff[1] = 0; // No error |
| 268 | return 0; | 248 | return MakeResult<bool>(false); |
| 269 | } | 249 | } |
| 270 | 250 | ||
| 271 | /** | 251 | ResultVal<bool> WaitSynchronization() override { |
| 272 | * Wait for kernel object to synchronize | ||
| 273 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 274 | * @return Result of operation, 0 on success, otherwise error code | ||
| 275 | */ | ||
| 276 | Result WaitSynchronization(bool* wait) override { | ||
| 277 | // TODO(bunnei): ImplementMe | 252 | // TODO(bunnei): ImplementMe |
| 278 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 253 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 279 | return 0; | 254 | return UnimplementedFunction(ErrorModule::FS); |
| 280 | } | 255 | } |
| 281 | }; | 256 | }; |
| 282 | 257 | ||
| @@ -284,89 +259,58 @@ public: | |||
| 284 | 259 | ||
| 285 | std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode | 260 | std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode |
| 286 | 261 | ||
| 287 | /** | 262 | ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) { |
| 288 | * Opens an archive | ||
| 289 | * @param id_code IdCode of the archive to open | ||
| 290 | * @return Handle to archive if it exists, otherwise a null handle (0) | ||
| 291 | */ | ||
| 292 | Handle OpenArchive(FileSys::Archive::IdCode id_code) { | ||
| 293 | auto itr = g_archive_map.find(id_code); | 263 | auto itr = g_archive_map.find(id_code); |
| 294 | if (itr == g_archive_map.end()) { | 264 | if (itr == g_archive_map.end()) { |
| 295 | return 0; | 265 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 266 | ErrorSummary::NotFound, ErrorLevel::Permanent); | ||
| 296 | } | 267 | } |
| 297 | return itr->second; | 268 | |
| 269 | return MakeResult<Handle>(itr->second); | ||
| 298 | } | 270 | } |
| 299 | 271 | ||
| 300 | /** | 272 | ResultCode CloseArchive(FileSys::Archive::IdCode id_code) { |
| 301 | * Closes an archive | ||
| 302 | * @param id_code IdCode of the archive to open | ||
| 303 | * @return Result of operation, 0 on success, otherwise error code | ||
| 304 | */ | ||
| 305 | Result CloseArchive(FileSys::Archive::IdCode id_code) { | ||
| 306 | auto itr = g_archive_map.find(id_code); | 273 | auto itr = g_archive_map.find(id_code); |
| 307 | if (itr == g_archive_map.end()) { | 274 | if (itr == g_archive_map.end()) { |
| 308 | ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); | 275 | ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); |
| 309 | return -1; | 276 | return InvalidHandle(ErrorModule::FS); |
| 310 | } | 277 | } |
| 311 | 278 | ||
| 312 | INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); | 279 | INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); |
| 313 | return 0; | 280 | return RESULT_SUCCESS; |
| 314 | } | 281 | } |
| 315 | 282 | ||
| 316 | /** | 283 | /** |
| 317 | * Mounts an archive | 284 | * Mounts an archive |
| 318 | * @param archive Pointer to the archive to mount | 285 | * @param archive Pointer to the archive to mount |
| 319 | * @return Result of operation, 0 on success, otherwise error code | ||
| 320 | */ | 286 | */ |
| 321 | Result MountArchive(Archive* archive) { | 287 | ResultCode MountArchive(Archive* archive) { |
| 322 | FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); | 288 | FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); |
| 323 | if (0 != OpenArchive(id_code)) { | 289 | ResultVal<Handle> archive_handle = OpenArchive(id_code); |
| 290 | if (archive_handle.Succeeded()) { | ||
| 324 | ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); | 291 | ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); |
| 325 | return -1; | 292 | return archive_handle.Code(); |
| 326 | } | 293 | } |
| 327 | g_archive_map[id_code] = archive->GetHandle(); | 294 | g_archive_map[id_code] = archive->GetHandle(); |
| 328 | INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str()); | 295 | INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str()); |
| 329 | return 0; | 296 | return RESULT_SUCCESS; |
| 330 | } | 297 | } |
| 331 | 298 | ||
| 332 | /** | 299 | ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name) { |
| 333 | * Creates an Archive | ||
| 334 | * @param handle Handle to newly created archive object | ||
| 335 | * @param backend File system backend interface to the archive | ||
| 336 | * @param name Optional name of Archive | ||
| 337 | * @return Newly created Archive object | ||
| 338 | */ | ||
| 339 | Archive* CreateArchive(Handle& handle, FileSys::Archive* backend, const std::string& name) { | ||
| 340 | Archive* archive = new Archive; | 300 | Archive* archive = new Archive; |
| 341 | handle = Kernel::g_object_pool.Create(archive); | 301 | Handle handle = Kernel::g_object_pool.Create(archive); |
| 342 | archive->name = name; | 302 | archive->name = name; |
| 343 | archive->backend = backend; | 303 | archive->backend = backend; |
| 344 | 304 | ||
| 345 | MountArchive(archive); | 305 | ResultCode result = MountArchive(archive); |
| 346 | 306 | if (result.IsError()) { | |
| 347 | return archive; | 307 | return result; |
| 348 | } | 308 | } |
| 349 | 309 | ||
| 350 | /** | 310 | return RESULT_SUCCESS; |
| 351 | * Creates an Archive | ||
| 352 | * @param backend File system backend interface to the archive | ||
| 353 | * @param name Optional name of Archive | ||
| 354 | * @return Handle to newly created Archive object | ||
| 355 | */ | ||
| 356 | Handle CreateArchive(FileSys::Archive* backend, const std::string& name) { | ||
| 357 | Handle handle; | ||
| 358 | CreateArchive(handle, backend, name); | ||
| 359 | return handle; | ||
| 360 | } | 311 | } |
| 361 | 312 | ||
| 362 | /** | 313 | ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { |
| 363 | * Open a File from an Archive | ||
| 364 | * @param archive_handle Handle to an open Archive object | ||
| 365 | * @param path Path to the File inside of the Archive | ||
| 366 | * @param mode Mode under which to open the File | ||
| 367 | * @return Opened File object | ||
| 368 | */ | ||
| 369 | Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { | ||
| 370 | // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create | 314 | // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create |
| 371 | // the archive file handles at app loading, and then keep them persistent throughout execution. | 315 | // the archive file handles at app loading, and then keep them persistent throughout execution. |
| 372 | // Archives file handles are just reused and not actually freed until emulation shut down. | 316 | // Archives file handles are just reused and not actually freed until emulation shut down. |
| @@ -376,26 +320,61 @@ Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, con | |||
| 376 | // design. While the functionally of this is OK, our implementation decision to separate | 320 | // design. While the functionally of this is OK, our implementation decision to separate |
| 377 | // normal files from archive file pointers is very likely wrong. | 321 | // normal files from archive file pointers is very likely wrong. |
| 378 | // See https://github.com/citra-emu/citra/issues/205 | 322 | // See https://github.com/citra-emu/citra/issues/205 |
| 379 | return archive_handle; | 323 | return MakeResult<Handle>(archive_handle); |
| 380 | 324 | ||
| 381 | File* file = new File; | 325 | File* file = new File; |
| 382 | Handle handle = Kernel::g_object_pool.Create(file); | 326 | Handle handle = Kernel::g_object_pool.Create(file); |
| 383 | 327 | ||
| 384 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 328 | Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); |
| 329 | if (archive == nullptr) { | ||
| 330 | return InvalidHandle(ErrorModule::FS); | ||
| 331 | } | ||
| 385 | file->path = path; | 332 | file->path = path; |
| 386 | file->backend = archive->backend->OpenFile(path, mode); | 333 | file->backend = archive->backend->OpenFile(path, mode); |
| 387 | 334 | ||
| 388 | if (!file->backend) | 335 | if (!file->backend) { |
| 336 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | ||
| 337 | ErrorSummary::NotFound, ErrorLevel::Permanent); | ||
| 338 | } | ||
| 339 | |||
| 340 | return MakeResult<Handle>(handle); | ||
| 341 | } | ||
| 342 | |||
| 343 | /** | ||
| 344 | * Delete a File from an Archive | ||
| 345 | * @param archive_handle Handle to an open Archive object | ||
| 346 | * @param path Path to the File inside of the Archive | ||
| 347 | * @return Whether deletion succeeded | ||
| 348 | */ | ||
| 349 | Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) { | ||
| 350 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | ||
| 351 | if (archive == nullptr) | ||
| 352 | return -1; | ||
| 353 | if (archive->backend->DeleteFile(path)) | ||
| 389 | return 0; | 354 | return 0; |
| 355 | return -1; | ||
| 356 | } | ||
| 390 | 357 | ||
| 391 | return handle; | 358 | /** |
| 359 | * Delete a Directory from an Archive | ||
| 360 | * @param archive_handle Handle to an open Archive object | ||
| 361 | * @param path Path to the Directory inside of the Archive | ||
| 362 | * @return Whether deletion succeeded | ||
| 363 | */ | ||
| 364 | Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | ||
| 365 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | ||
| 366 | if (archive == nullptr) | ||
| 367 | return -1; | ||
| 368 | if (archive->backend->DeleteDirectory(path)) | ||
| 369 | return 0; | ||
| 370 | return -1; | ||
| 392 | } | 371 | } |
| 393 | 372 | ||
| 394 | /** | 373 | /** |
| 395 | * Create a Directory from an Archive | 374 | * Create a Directory from an Archive |
| 396 | * @param archive_handle Handle to an open Archive object | 375 | * @param archive_handle Handle to an open Archive object |
| 397 | * @param path Path to the Directory inside of the Archive | 376 | * @param path Path to the Directory inside of the Archive |
| 398 | * @return Opened Directory object | 377 | * @return Whether creation succeeded |
| 399 | */ | 378 | */ |
| 400 | Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | 379 | Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { |
| 401 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 380 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); |
| @@ -412,15 +391,18 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa | |||
| 412 | * @param path Path to the Directory inside of the Archive | 391 | * @param path Path to the Directory inside of the Archive |
| 413 | * @return Opened Directory object | 392 | * @return Opened Directory object |
| 414 | */ | 393 | */ |
| 415 | Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | 394 | ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { |
| 416 | Directory* directory = new Directory; | 395 | Directory* directory = new Directory; |
| 417 | Handle handle = Kernel::g_object_pool.Create(directory); | 396 | Handle handle = Kernel::g_object_pool.Create(directory); |
| 418 | 397 | ||
| 419 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 398 | Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); |
| 399 | if (archive == nullptr) { | ||
| 400 | return InvalidHandle(ErrorModule::FS); | ||
| 401 | } | ||
| 420 | directory->path = path; | 402 | directory->path = path; |
| 421 | directory->backend = archive->backend->OpenDirectory(path); | 403 | directory->backend = archive->backend->OpenDirectory(path); |
| 422 | 404 | ||
| 423 | return handle; | 405 | return MakeResult<Handle>(handle); |
| 424 | } | 406 | } |
| 425 | 407 | ||
| 426 | /// Initialize archives | 408 | /// Initialize archives |
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h index 9c6015506..6fc4f0f25 100644 --- a/src/core/hle/kernel/archive.h +++ b/src/core/hle/kernel/archive.h | |||
| @@ -6,8 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/hle/kernel/kernel.h" | ||
| 10 | #include "core/file_sys/archive.h" | 9 | #include "core/file_sys/archive.h" |
| 10 | #include "core/hle/kernel/kernel.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 11 | 12 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 13 | // Kernel namespace | 14 | // Kernel namespace |
| @@ -17,33 +18,47 @@ namespace Kernel { | |||
| 17 | /** | 18 | /** |
| 18 | * Opens an archive | 19 | * Opens an archive |
| 19 | * @param id_code IdCode of the archive to open | 20 | * @param id_code IdCode of the archive to open |
| 20 | * @return Handle to archive if it exists, otherwise a null handle (0) | 21 | * @return Handle to the opened archive |
| 21 | */ | 22 | */ |
| 22 | Handle OpenArchive(FileSys::Archive::IdCode id_code); | 23 | ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code); |
| 23 | 24 | ||
| 24 | /** | 25 | /** |
| 25 | * Closes an archive | 26 | * Closes an archive |
| 26 | * @param id_code IdCode of the archive to open | 27 | * @param id_code IdCode of the archive to open |
| 27 | * @return true if it worked fine | ||
| 28 | */ | 28 | */ |
| 29 | Result CloseArchive(FileSys::Archive::IdCode id_code); | 29 | ResultCode CloseArchive(FileSys::Archive::IdCode id_code); |
| 30 | 30 | ||
| 31 | /** | 31 | /** |
| 32 | * Creates an Archive | 32 | * Creates an Archive |
| 33 | * @param backend File system backend interface to the archive | 33 | * @param backend File system backend interface to the archive |
| 34 | * @param name Optional name of Archive | 34 | * @param name Name of Archive |
| 35 | * @return Handle to newly created Archive object | ||
| 36 | */ | 35 | */ |
| 37 | Handle CreateArchive(FileSys::Archive* backend, const std::string& name); | 36 | ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name); |
| 38 | 37 | ||
| 39 | /** | 38 | /** |
| 40 | * Open a File from an Archive | 39 | * Open a File from an Archive |
| 41 | * @param archive_handle Handle to an open Archive object | 40 | * @param archive_handle Handle to an open Archive object |
| 42 | * @param path Path to the File inside of the Archive | 41 | * @param path Path to the File inside of the Archive |
| 43 | * @param mode Mode under which to open the File | 42 | * @param mode Mode under which to open the File |
| 44 | * @return Opened File object | 43 | * @return Handle to the opened File object |
| 44 | */ | ||
| 45 | ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Delete a File from an Archive | ||
| 49 | * @param archive_handle Handle to an open Archive object | ||
| 50 | * @param path Path to the File inside of the Archive | ||
| 51 | * @return Whether deletion succeeded | ||
| 52 | */ | ||
| 53 | Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path); | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Delete a Directory from an Archive | ||
| 57 | * @param archive_handle Handle to an open Archive object | ||
| 58 | * @param path Path to the Directory inside of the Archive | ||
| 59 | * @return Whether deletion succeeded | ||
| 45 | */ | 60 | */ |
| 46 | Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); | 61 | Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); |
| 47 | 62 | ||
| 48 | /** | 63 | /** |
| 49 | * Create a Directory from an Archive | 64 | * Create a Directory from an Archive |
| @@ -57,9 +72,9 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa | |||
| 57 | * Open a Directory from an Archive | 72 | * Open a Directory from an Archive |
| 58 | * @param archive_handle Handle to an open Archive object | 73 | * @param archive_handle Handle to an open Archive object |
| 59 | * @param path Path to the Directory inside of the Archive | 74 | * @param path Path to the Directory inside of the Archive |
| 60 | * @return Opened Directory object | 75 | * @return Handle to the opened File object |
| 61 | */ | 76 | */ |
| 62 | Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); | 77 | ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); |
| 63 | 78 | ||
| 64 | /// Initialize archives | 79 | /// Initialize archives |
| 65 | void ArchiveInit(); | 80 | void ArchiveInit(); |
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e0117c0bc..288080209 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp | |||
| @@ -30,13 +30,8 @@ public: | |||
| 30 | std::vector<Handle> waiting_threads; ///< Threads that are waiting for the event | 30 | std::vector<Handle> waiting_threads; ///< Threads that are waiting for the event |
| 31 | std::string name; ///< Name of event (optional) | 31 | std::string name; ///< Name of event (optional) |
| 32 | 32 | ||
| 33 | /** | 33 | ResultVal<bool> WaitSynchronization() override { |
| 34 | * Wait for kernel object to synchronize | 34 | bool wait = locked; |
| 35 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 36 | * @return Result of operation, 0 on success, otherwise error code | ||
| 37 | */ | ||
| 38 | Result WaitSynchronization(bool* wait) override { | ||
| 39 | *wait = locked; | ||
| 40 | if (locked) { | 35 | if (locked) { |
| 41 | Handle thread = GetCurrentThreadHandle(); | 36 | Handle thread = GetCurrentThreadHandle(); |
| 42 | if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { | 37 | if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { |
| @@ -47,7 +42,7 @@ public: | |||
| 47 | if (reset_type != RESETTYPE_STICKY && !permanent_locked) { | 42 | if (reset_type != RESETTYPE_STICKY && !permanent_locked) { |
| 48 | locked = true; | 43 | locked = true; |
| 49 | } | 44 | } |
| 50 | return 0; | 45 | return MakeResult<bool>(wait); |
| 51 | } | 46 | } |
| 52 | }; | 47 | }; |
| 53 | 48 | ||
| @@ -57,12 +52,12 @@ public: | |||
| 57 | * @param permanent_locked Boolean permanent locked value to set event | 52 | * @param permanent_locked Boolean permanent locked value to set event |
| 58 | * @return Result of operation, 0 on success, otherwise error code | 53 | * @return Result of operation, 0 on success, otherwise error code |
| 59 | */ | 54 | */ |
| 60 | Result SetPermanentLock(Handle handle, const bool permanent_locked) { | 55 | ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { |
| 61 | Event* evt = g_object_pool.GetFast<Event>(handle); | 56 | Event* evt = g_object_pool.Get<Event>(handle); |
| 62 | _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); | 57 | if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 63 | 58 | ||
| 64 | evt->permanent_locked = permanent_locked; | 59 | evt->permanent_locked = permanent_locked; |
| 65 | return 0; | 60 | return RESULT_SUCCESS; |
| 66 | } | 61 | } |
| 67 | 62 | ||
| 68 | /** | 63 | /** |
| @@ -71,14 +66,14 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) { | |||
| 71 | * @param locked Boolean locked value to set event | 66 | * @param locked Boolean locked value to set event |
| 72 | * @return Result of operation, 0 on success, otherwise error code | 67 | * @return Result of operation, 0 on success, otherwise error code |
| 73 | */ | 68 | */ |
| 74 | Result SetEventLocked(const Handle handle, const bool locked) { | 69 | ResultCode SetEventLocked(const Handle handle, const bool locked) { |
| 75 | Event* evt = g_object_pool.GetFast<Event>(handle); | 70 | Event* evt = g_object_pool.Get<Event>(handle); |
| 76 | _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); | 71 | if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 77 | 72 | ||
| 78 | if (!evt->permanent_locked) { | 73 | if (!evt->permanent_locked) { |
| 79 | evt->locked = locked; | 74 | evt->locked = locked; |
| 80 | } | 75 | } |
| 81 | return 0; | 76 | return RESULT_SUCCESS; |
| 82 | } | 77 | } |
| 83 | 78 | ||
| 84 | /** | 79 | /** |
| @@ -86,9 +81,9 @@ Result SetEventLocked(const Handle handle, const bool locked) { | |||
| 86 | * @param handle Handle to event to signal | 81 | * @param handle Handle to event to signal |
| 87 | * @return Result of operation, 0 on success, otherwise error code | 82 | * @return Result of operation, 0 on success, otherwise error code |
| 88 | */ | 83 | */ |
| 89 | Result SignalEvent(const Handle handle) { | 84 | ResultCode SignalEvent(const Handle handle) { |
| 90 | Event* evt = g_object_pool.GetFast<Event>(handle); | 85 | Event* evt = g_object_pool.Get<Event>(handle); |
| 91 | _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); | 86 | if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 92 | 87 | ||
| 93 | // Resume threads waiting for event to signal | 88 | // Resume threads waiting for event to signal |
| 94 | bool event_caught = false; | 89 | bool event_caught = false; |
| @@ -106,7 +101,7 @@ Result SignalEvent(const Handle handle) { | |||
| 106 | if (!evt->permanent_locked) { | 101 | if (!evt->permanent_locked) { |
| 107 | evt->locked = event_caught; | 102 | evt->locked = event_caught; |
| 108 | } | 103 | } |
| 109 | return 0; | 104 | return RESULT_SUCCESS; |
| 110 | } | 105 | } |
| 111 | 106 | ||
| 112 | /** | 107 | /** |
| @@ -114,14 +109,14 @@ Result SignalEvent(const Handle handle) { | |||
| 114 | * @param handle Handle to event to clear | 109 | * @param handle Handle to event to clear |
| 115 | * @return Result of operation, 0 on success, otherwise error code | 110 | * @return Result of operation, 0 on success, otherwise error code |
| 116 | */ | 111 | */ |
| 117 | Result ClearEvent(Handle handle) { | 112 | ResultCode ClearEvent(Handle handle) { |
| 118 | Event* evt = g_object_pool.GetFast<Event>(handle); | 113 | Event* evt = g_object_pool.Get<Event>(handle); |
| 119 | _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); | 114 | if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 120 | 115 | ||
| 121 | if (!evt->permanent_locked) { | 116 | if (!evt->permanent_locked) { |
| 122 | evt->locked = true; | 117 | evt->locked = true; |
| 123 | } | 118 | } |
| 124 | return 0; | 119 | return RESULT_SUCCESS; |
| 125 | } | 120 | } |
| 126 | 121 | ||
| 127 | /** | 122 | /** |
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 6add72897..73aec4e79 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h | |||
| @@ -15,31 +15,27 @@ namespace Kernel { | |||
| 15 | * Changes whether an event is locked or not | 15 | * Changes whether an event is locked or not |
| 16 | * @param handle Handle to event to change | 16 | * @param handle Handle to event to change |
| 17 | * @param locked Boolean locked value to set event | 17 | * @param locked Boolean locked value to set event |
| 18 | * @return Result of operation, 0 on success, otherwise error code | ||
| 19 | */ | 18 | */ |
| 20 | Result SetEventLocked(const Handle handle, const bool locked); | 19 | ResultCode SetEventLocked(const Handle handle, const bool locked); |
| 21 | 20 | ||
| 22 | /** | 21 | /** |
| 23 | * Hackish function to set an events permanent lock state, used to pass through synch blocks | 22 | * Hackish function to set an events permanent lock state, used to pass through synch blocks |
| 24 | * @param handle Handle to event to change | 23 | * @param handle Handle to event to change |
| 25 | * @param permanent_locked Boolean permanent locked value to set event | 24 | * @param permanent_locked Boolean permanent locked value to set event |
| 26 | * @return Result of operation, 0 on success, otherwise error code | ||
| 27 | */ | 25 | */ |
| 28 | Result SetPermanentLock(Handle handle, const bool permanent_locked); | 26 | ResultCode SetPermanentLock(Handle handle, const bool permanent_locked); |
| 29 | 27 | ||
| 30 | /** | 28 | /** |
| 31 | * Signals an event | 29 | * Signals an event |
| 32 | * @param handle Handle to event to signal | 30 | * @param handle Handle to event to signal |
| 33 | * @return Result of operation, 0 on success, otherwise error code | ||
| 34 | */ | 31 | */ |
| 35 | Result SignalEvent(const Handle handle); | 32 | ResultCode SignalEvent(const Handle handle); |
| 36 | 33 | ||
| 37 | /** | 34 | /** |
| 38 | * Clears an event | 35 | * Clears an event |
| 39 | * @param handle Handle to event to clear | 36 | * @param handle Handle to event to clear |
| 40 | * @return Result of operation, 0 on success, otherwise error code | ||
| 41 | */ | 37 | */ |
| 42 | Result ClearEvent(Handle handle); | 38 | ResultCode ClearEvent(Handle handle); |
| 43 | 39 | ||
| 44 | /** | 40 | /** |
| 45 | * Creates an event | 41 | * Creates an event |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index e0c94f186..8d3937ce8 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include "common/common.h" | 9 | #include "common/common.h" |
| 10 | #include "core/hle/result.h" | ||
| 10 | 11 | ||
| 11 | typedef u32 Handle; | 12 | typedef u32 Handle; |
| 12 | typedef s32 Result; | 13 | typedef s32 Result; |
| @@ -52,21 +53,19 @@ public: | |||
| 52 | virtual Kernel::HandleType GetHandleType() const = 0; | 53 | virtual Kernel::HandleType GetHandleType() const = 0; |
| 53 | 54 | ||
| 54 | /** | 55 | /** |
| 55 | * Synchronize kernel object | 56 | * Synchronize kernel object. |
| 56 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | 57 | * @return True if the current thread should wait as a result of the sync |
| 57 | * @return Result of operation, 0 on success, otherwise error code | ||
| 58 | */ | 58 | */ |
| 59 | virtual Result SyncRequest(bool* wait) { | 59 | virtual ResultVal<bool> SyncRequest() { |
| 60 | ERROR_LOG(KERNEL, "(UNIMPLEMENTED)"); | 60 | ERROR_LOG(KERNEL, "(UNIMPLEMENTED)"); |
| 61 | return -1; | 61 | return UnimplementedFunction(ErrorModule::Kernel); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | /** | 64 | /** |
| 65 | * Wait for kernel object to synchronize | 65 | * Wait for kernel object to synchronize. |
| 66 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | 66 | * @return True if the current thread should wait as a result of the wait |
| 67 | * @return Result of operation, 0 on success, otherwise error code | ||
| 68 | */ | 67 | */ |
| 69 | virtual Result WaitSynchronization(bool* wait) = 0; | 68 | virtual ResultVal<bool> WaitSynchronization() = 0; |
| 70 | }; | 69 | }; |
| 71 | 70 | ||
| 72 | class ObjectPool : NonCopyable { | 71 | class ObjectPool : NonCopyable { |
| @@ -80,38 +79,29 @@ public: | |||
| 80 | static Object* CreateByIDType(int type); | 79 | static Object* CreateByIDType(int type); |
| 81 | 80 | ||
| 82 | template <class T> | 81 | template <class T> |
| 83 | u32 Destroy(Handle handle) { | 82 | void Destroy(Handle handle) { |
| 84 | u32 error; | 83 | if (Get<T>(handle)) { |
| 85 | if (Get<T>(handle, error)) { | ||
| 86 | occupied[handle - HANDLE_OFFSET] = false; | 84 | occupied[handle - HANDLE_OFFSET] = false; |
| 87 | delete pool[handle - HANDLE_OFFSET]; | 85 | delete pool[handle - HANDLE_OFFSET]; |
| 88 | } | 86 | } |
| 89 | return error; | ||
| 90 | } | 87 | } |
| 91 | 88 | ||
| 92 | bool IsValid(Handle handle); | 89 | bool IsValid(Handle handle); |
| 93 | 90 | ||
| 94 | template <class T> | 91 | template <class T> |
| 95 | T* Get(Handle handle, u32& outError) { | 92 | T* Get(Handle handle) { |
| 96 | if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { | 93 | if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { |
| 97 | // Tekken 6 spams 0x80020001 gets wrong with no ill effects, also on the real PSP | 94 | if (handle != 0) { |
| 98 | if (handle != 0 && (u32)handle != 0x80020001) { | ||
| 99 | WARN_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); | 95 | WARN_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); |
| 100 | } | 96 | } |
| 101 | outError = 0;//T::GetMissingErrorCode(); | 97 | return nullptr; |
| 102 | return 0; | ||
| 103 | } else { | 98 | } else { |
| 104 | // Previously we had a dynamic_cast here, but since RTTI was disabled traditionally, | 99 | Object* t = pool[handle - HANDLE_OFFSET]; |
| 105 | // it just acted as a static case and everything worked. This means that we will never | 100 | if (t->GetHandleType() != T::GetStaticHandleType()) { |
| 106 | // see the Wrong type object error below, but we'll just have to live with that danger. | ||
| 107 | T* t = static_cast<T*>(pool[handle - HANDLE_OFFSET]); | ||
| 108 | if (t == 0 || t->GetHandleType() != T::GetStaticHandleType()) { | ||
| 109 | WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle); | 101 | WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle); |
| 110 | outError = 0;//T::GetMissingErrorCode(); | 102 | return nullptr; |
| 111 | return 0; | ||
| 112 | } | 103 | } |
| 113 | outError = 0;//SCE_KERNEL_ERROR_OK; | 104 | return static_cast<T*>(t); |
| 114 | return t; | ||
| 115 | } | 105 | } |
| 116 | } | 106 | } |
| 117 | 107 | ||
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 31129fd86..d07e9761b 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -27,31 +27,20 @@ public: | |||
| 27 | std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex | 27 | std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex |
| 28 | std::string name; ///< Name of mutex (optional) | 28 | std::string name; ///< Name of mutex (optional) |
| 29 | 29 | ||
| 30 | /** | 30 | ResultVal<bool> SyncRequest() override { |
| 31 | * Synchronize kernel object | ||
| 32 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 33 | * @return Result of operation, 0 on success, otherwise error code | ||
| 34 | */ | ||
| 35 | Result SyncRequest(bool* wait) override { | ||
| 36 | // TODO(bunnei): ImplementMe | 31 | // TODO(bunnei): ImplementMe |
| 37 | locked = true; | 32 | locked = true; |
| 38 | return 0; | 33 | return MakeResult<bool>(false); |
| 39 | } | 34 | } |
| 40 | 35 | ||
| 41 | /** | 36 | ResultVal<bool> WaitSynchronization() override { |
| 42 | * Wait for kernel object to synchronize | ||
| 43 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 44 | * @return Result of operation, 0 on success, otherwise error code | ||
| 45 | */ | ||
| 46 | Result WaitSynchronization(bool* wait) override { | ||
| 47 | // TODO(bunnei): ImplementMe | 37 | // TODO(bunnei): ImplementMe |
| 48 | *wait = locked; | 38 | bool wait = locked; |
| 49 | |||
| 50 | if (locked) { | 39 | if (locked) { |
| 51 | Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); | 40 | Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); |
| 52 | } | 41 | } |
| 53 | 42 | ||
| 54 | return 0; | 43 | return MakeResult<bool>(wait); |
| 55 | } | 44 | } |
| 56 | }; | 45 | }; |
| 57 | 46 | ||
| @@ -99,35 +88,36 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { | |||
| 99 | 88 | ||
| 100 | bool ReleaseMutex(Mutex* mutex) { | 89 | bool ReleaseMutex(Mutex* mutex) { |
| 101 | MutexEraseLock(mutex); | 90 | MutexEraseLock(mutex); |
| 102 | bool woke_threads = false; | ||
| 103 | 91 | ||
| 104 | // Find the next waiting thread for the mutex... | 92 | // Find the next waiting thread for the mutex... |
| 105 | while (!woke_threads && !mutex->waiting_threads.empty()) { | 93 | while (!mutex->waiting_threads.empty()) { |
| 106 | std::vector<Handle>::iterator iter = mutex->waiting_threads.begin(); | 94 | std::vector<Handle>::iterator iter = mutex->waiting_threads.begin(); |
| 107 | woke_threads |= ReleaseMutexForThread(mutex, *iter); | 95 | ReleaseMutexForThread(mutex, *iter); |
| 108 | mutex->waiting_threads.erase(iter); | 96 | mutex->waiting_threads.erase(iter); |
| 109 | } | 97 | } |
| 98 | |||
| 110 | // Reset mutex lock thread handle, nothing is waiting | 99 | // Reset mutex lock thread handle, nothing is waiting |
| 111 | if (!woke_threads) { | 100 | mutex->locked = false; |
| 112 | mutex->locked = false; | 101 | mutex->lock_thread = -1; |
| 113 | mutex->lock_thread = -1; | 102 | |
| 114 | } | 103 | return true; |
| 115 | return woke_threads; | ||
| 116 | } | 104 | } |
| 117 | 105 | ||
| 118 | /** | 106 | /** |
| 119 | * Releases a mutex | 107 | * Releases a mutex |
| 120 | * @param handle Handle to mutex to release | 108 | * @param handle Handle to mutex to release |
| 121 | */ | 109 | */ |
| 122 | Result ReleaseMutex(Handle handle) { | 110 | ResultCode ReleaseMutex(Handle handle) { |
| 123 | Mutex* mutex = Kernel::g_object_pool.GetFast<Mutex>(handle); | 111 | Mutex* mutex = Kernel::g_object_pool.Get<Mutex>(handle); |
| 124 | 112 | if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); | |
| 125 | _assert_msg_(KERNEL, (mutex != nullptr), "ReleaseMutex tried to release a nullptr mutex!"); | ||
| 126 | 113 | ||
| 127 | if (!ReleaseMutex(mutex)) { | 114 | if (!ReleaseMutex(mutex)) { |
| 128 | return -1; | 115 | // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure |
| 116 | // what error condition this is supposed to be signaling. | ||
| 117 | return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel, | ||
| 118 | ErrorSummary::NothingHappened, ErrorLevel::Temporary); | ||
| 129 | } | 119 | } |
| 130 | return 0; | 120 | return RESULT_SUCCESS; |
| 131 | } | 121 | } |
| 132 | 122 | ||
| 133 | /** | 123 | /** |
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 313ba6fee..155449f95 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h | |||
| @@ -13,9 +13,8 @@ namespace Kernel { | |||
| 13 | /** | 13 | /** |
| 14 | * Releases a mutex | 14 | * Releases a mutex |
| 15 | * @param handle Handle to mutex to release | 15 | * @param handle Handle to mutex to release |
| 16 | * @return Result of operation, 0 on success, otherwise error code | ||
| 17 | */ | 16 | */ |
| 18 | Result ReleaseMutex(Handle handle); | 17 | ResultCode ReleaseMutex(Handle handle); |
| 19 | 18 | ||
| 20 | /** | 19 | /** |
| 21 | * Creates a mutex | 20 | * Creates a mutex |
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 7ef3e54cc..cfcc0e0b7 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp | |||
| @@ -16,15 +16,10 @@ public: | |||
| 16 | static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; } | 16 | static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; } |
| 17 | Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; } | 17 | Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; } |
| 18 | 18 | ||
| 19 | /** | 19 | ResultVal<bool> WaitSynchronization() override { |
| 20 | * Wait for kernel object to synchronize | ||
| 21 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 22 | * @return Result of operation, 0 on success, otherwise error code | ||
| 23 | */ | ||
| 24 | Result WaitSynchronization(bool* wait) override { | ||
| 25 | // TODO(bunnei): ImplementMe | 20 | // TODO(bunnei): ImplementMe |
| 26 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 21 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 27 | return 0; | 22 | return UnimplementedFunction(ErrorModule::OS); |
| 28 | } | 23 | } |
| 29 | 24 | ||
| 30 | u32 base_address; ///< Address of shared memory block in RAM | 25 | u32 base_address; ///< Address of shared memory block in RAM |
| @@ -48,11 +43,6 @@ SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) { | |||
| 48 | return shared_memory; | 43 | return shared_memory; |
| 49 | } | 44 | } |
| 50 | 45 | ||
| 51 | /** | ||
| 52 | * Creates a shared memory object | ||
| 53 | * @param name Optional name of shared memory object | ||
| 54 | * @return Handle of newly created shared memory object | ||
| 55 | */ | ||
| 56 | Handle CreateSharedMemory(const std::string& name) { | 46 | Handle CreateSharedMemory(const std::string& name) { |
| 57 | Handle handle; | 47 | Handle handle; |
| 58 | CreateSharedMemory(handle, name); | 48 | CreateSharedMemory(handle, name); |
| @@ -67,39 +57,36 @@ Handle CreateSharedMemory(const std::string& name) { | |||
| 67 | * @param other_permissions Memory block map other permissions (specified by SVC field) | 57 | * @param other_permissions Memory block map other permissions (specified by SVC field) |
| 68 | * @return Result of operation, 0 on success, otherwise error code | 58 | * @return Result of operation, 0 on success, otherwise error code |
| 69 | */ | 59 | */ |
| 70 | Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, | 60 | ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, |
| 71 | MemoryPermission other_permissions) { | 61 | MemoryPermission other_permissions) { |
| 72 | 62 | ||
| 73 | if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { | 63 | if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { |
| 74 | ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", | 64 | ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", |
| 75 | handle, address); | 65 | handle, address); |
| 76 | return -1; | 66 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, |
| 67 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||
| 77 | } | 68 | } |
| 78 | SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle); | 69 | SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle); |
| 79 | _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle); | 70 | if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 80 | 71 | ||
| 81 | shared_memory->base_address = address; | 72 | shared_memory->base_address = address; |
| 82 | shared_memory->permissions = permissions; | 73 | shared_memory->permissions = permissions; |
| 83 | shared_memory->other_permissions = other_permissions; | 74 | shared_memory->other_permissions = other_permissions; |
| 84 | 75 | ||
| 85 | return 0; | 76 | return RESULT_SUCCESS; |
| 86 | } | 77 | } |
| 87 | 78 | ||
| 88 | /** | 79 | ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { |
| 89 | * Gets a pointer to the shared memory block | 80 | SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle); |
| 90 | * @param handle Shared memory block handle | 81 | if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 91 | * @param offset Offset from the start of the shared memory block to get pointer | ||
| 92 | * @return Pointer to the shared memory block from the specified offset | ||
| 93 | */ | ||
| 94 | u8* GetSharedMemoryPointer(Handle handle, u32 offset) { | ||
| 95 | SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle); | ||
| 96 | _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle); | ||
| 97 | 82 | ||
| 98 | if (0 != shared_memory->base_address) | 83 | if (0 != shared_memory->base_address) |
| 99 | return Memory::GetPointer(shared_memory->base_address + offset); | 84 | return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset)); |
| 100 | 85 | ||
| 101 | ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle); | 86 | ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle); |
| 102 | return nullptr; | 87 | // TODO(yuriks): Verify error code. |
| 88 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | ||
| 89 | ErrorSummary::InvalidState, ErrorLevel::Permanent); | ||
| 103 | } | 90 | } |
| 104 | 91 | ||
| 105 | } // namespace | 92 | } // namespace |
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index 0aec03538..304cf5b67 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h | |||
| @@ -32,9 +32,8 @@ Handle CreateSharedMemory(const std::string& name="Unknown"); | |||
| 32 | * @param address Address in system memory to map shared memory block to | 32 | * @param address Address in system memory to map shared memory block to |
| 33 | * @param permissions Memory block map permissions (specified by SVC field) | 33 | * @param permissions Memory block map permissions (specified by SVC field) |
| 34 | * @param other_permissions Memory block map other permissions (specified by SVC field) | 34 | * @param other_permissions Memory block map other permissions (specified by SVC field) |
| 35 | * @return Result of operation, 0 on success, otherwise error code | ||
| 36 | */ | 35 | */ |
| 37 | Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, | 36 | ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions, |
| 38 | MemoryPermission other_permissions); | 37 | MemoryPermission other_permissions); |
| 39 | 38 | ||
| 40 | /** | 39 | /** |
| @@ -43,6 +42,6 @@ Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, | |||
| 43 | * @param offset Offset from the start of the shared memory block to get pointer | 42 | * @param offset Offset from the start of the shared memory block to get pointer |
| 44 | * @return Pointer to the shared memory block from the specified offset | 43 | * @return Pointer to the shared memory block from the specified offset |
| 45 | */ | 44 | */ |
| 46 | u8* GetSharedMemoryPointer(Handle handle, u32 offset); | 45 | ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset); |
| 47 | 46 | ||
| 48 | } // namespace | 47 | } // namespace |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index cc70cbca7..f59795901 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -11,10 +11,11 @@ | |||
| 11 | #include "common/thread_queue_list.h" | 11 | #include "common/thread_queue_list.h" |
| 12 | 12 | ||
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/mem_map.h" | ||
| 15 | #include "core/hle/hle.h" | 14 | #include "core/hle/hle.h" |
| 16 | #include "core/hle/kernel/kernel.h" | 15 | #include "core/hle/kernel/kernel.h" |
| 17 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 17 | #include "core/hle/result.h" | ||
| 18 | #include "core/mem_map.h" | ||
| 18 | 19 | ||
| 19 | namespace Kernel { | 20 | namespace Kernel { |
| 20 | 21 | ||
| @@ -33,21 +34,17 @@ public: | |||
| 33 | inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } | 34 | inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } |
| 34 | inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } | 35 | inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } |
| 35 | 36 | ||
| 36 | /** | 37 | ResultVal<bool> WaitSynchronization() override { |
| 37 | * Wait for kernel object to synchronize | 38 | const bool wait = status != THREADSTATUS_DORMANT; |
| 38 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | 39 | if (wait) { |
| 39 | * @return Result of operation, 0 on success, otherwise error code | ||
| 40 | */ | ||
| 41 | Result WaitSynchronization(bool* wait) override { | ||
| 42 | if (status != THREADSTATUS_DORMANT) { | ||
| 43 | Handle thread = GetCurrentThreadHandle(); | 40 | Handle thread = GetCurrentThreadHandle(); |
| 44 | if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { | 41 | if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { |
| 45 | waiting_threads.push_back(thread); | 42 | waiting_threads.push_back(thread); |
| 46 | } | 43 | } |
| 47 | WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); | 44 | WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); |
| 48 | *wait = true; | ||
| 49 | } | 45 | } |
| 50 | return 0; | 46 | |
| 47 | return MakeResult<bool>(wait); | ||
| 51 | } | 48 | } |
| 52 | 49 | ||
| 53 | ThreadContext context; | 50 | ThreadContext context; |
| @@ -144,27 +141,22 @@ void ChangeReadyState(Thread* t, bool ready) { | |||
| 144 | } | 141 | } |
| 145 | 142 | ||
| 146 | /// Verify that a thread has not been released from waiting | 143 | /// Verify that a thread has not been released from waiting |
| 147 | inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) { | 144 | inline bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) { |
| 148 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 145 | _dbg_assert_(KERNEL, thread != nullptr); |
| 149 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 146 | return (type == thread->wait_type) && (wait_handle == thread->wait_handle) && (thread->IsWaiting()); |
| 150 | |||
| 151 | if (type != thread->wait_type || wait_handle != thread->wait_handle) | ||
| 152 | return false; | ||
| 153 | |||
| 154 | return true; | ||
| 155 | } | 147 | } |
| 156 | 148 | ||
| 157 | /// Stops the current thread | 149 | /// Stops the current thread |
| 158 | void StopThread(Handle handle, const char* reason) { | 150 | ResultCode StopThread(Handle handle, const char* reason) { |
| 159 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 151 | Thread* thread = g_object_pool.Get<Thread>(handle); |
| 160 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 152 | if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 161 | 153 | ||
| 162 | ChangeReadyState(thread, false); | 154 | ChangeReadyState(thread, false); |
| 163 | thread->status = THREADSTATUS_DORMANT; | 155 | thread->status = THREADSTATUS_DORMANT; |
| 164 | for (size_t i = 0; i < thread->waiting_threads.size(); ++i) { | 156 | for (Handle waiting_handle : thread->waiting_threads) { |
| 165 | const Handle waiting_thread = thread->waiting_threads[i]; | 157 | Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle); |
| 166 | if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { | 158 | if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { |
| 167 | ResumeThreadFromWait(waiting_thread); | 159 | ResumeThreadFromWait(waiting_handle); |
| 168 | } | 160 | } |
| 169 | } | 161 | } |
| 170 | thread->waiting_threads.clear(); | 162 | thread->waiting_threads.clear(); |
| @@ -172,6 +164,8 @@ void StopThread(Handle handle, const char* reason) { | |||
| 172 | // Stopped threads are never waiting. | 164 | // Stopped threads are never waiting. |
| 173 | thread->wait_type = WAITTYPE_NONE; | 165 | thread->wait_type = WAITTYPE_NONE; |
| 174 | thread->wait_handle = 0; | 166 | thread->wait_handle = 0; |
| 167 | |||
| 168 | return RESULT_SUCCESS; | ||
| 175 | } | 169 | } |
| 176 | 170 | ||
| 177 | /// Changes a threads state | 171 | /// Changes a threads state |
| @@ -195,13 +189,15 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { | |||
| 195 | s32 priority = THREADPRIO_LOWEST; | 189 | s32 priority = THREADPRIO_LOWEST; |
| 196 | 190 | ||
| 197 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 191 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 198 | for (const auto& handle : thread_queue) { | 192 | for (Handle handle : thread_queue) { |
| 193 | Thread* thread = g_object_pool.Get<Thread>(handle); | ||
| 199 | 194 | ||
| 200 | // TODO(bunnei): Verify arbiter address... | 195 | // TODO(bunnei): Verify arbiter address... |
| 201 | if (!VerifyWait(handle, WAITTYPE_ARB, arbiter)) | 196 | if (!VerifyWait(thread, WAITTYPE_ARB, arbiter)) |
| 202 | continue; | 197 | continue; |
| 203 | 198 | ||
| 204 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 199 | if (thread == nullptr) |
| 200 | continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. | ||
| 205 | if(thread->current_priority <= priority) { | 201 | if(thread->current_priority <= priority) { |
| 206 | highest_priority_thread = handle; | 202 | highest_priority_thread = handle; |
| 207 | priority = thread->current_priority; | 203 | priority = thread->current_priority; |
| @@ -218,10 +214,11 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { | |||
| 218 | void ArbitrateAllThreads(u32 arbiter, u32 address) { | 214 | void ArbitrateAllThreads(u32 arbiter, u32 address) { |
| 219 | 215 | ||
| 220 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 216 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 221 | for (const auto& handle : thread_queue) { | 217 | for (Handle handle : thread_queue) { |
| 218 | Thread* thread = g_object_pool.Get<Thread>(handle); | ||
| 222 | 219 | ||
| 223 | // TODO(bunnei): Verify arbiter address... | 220 | // TODO(bunnei): Verify arbiter address... |
| 224 | if (VerifyWait(handle, WAITTYPE_ARB, arbiter)) | 221 | if (VerifyWait(thread, WAITTYPE_ARB, arbiter)) |
| 225 | ResumeThreadFromWait(handle); | 222 | ResumeThreadFromWait(handle); |
| 226 | } | 223 | } |
| 227 | } | 224 | } |
| @@ -272,7 +269,7 @@ Thread* NextThread() { | |||
| 272 | if (next == 0) { | 269 | if (next == 0) { |
| 273 | return nullptr; | 270 | return nullptr; |
| 274 | } | 271 | } |
| 275 | return Kernel::g_object_pool.GetFast<Thread>(next); | 272 | return Kernel::g_object_pool.Get<Thread>(next); |
| 276 | } | 273 | } |
| 277 | 274 | ||
| 278 | /** | 275 | /** |
| @@ -289,8 +286,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { | |||
| 289 | 286 | ||
| 290 | /// Resumes a thread from waiting by marking it as "ready" | 287 | /// Resumes a thread from waiting by marking it as "ready" |
| 291 | void ResumeThreadFromWait(Handle handle) { | 288 | void ResumeThreadFromWait(Handle handle) { |
| 292 | u32 error; | 289 | Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); |
| 293 | Thread* thread = Kernel::g_object_pool.Get<Thread>(handle, error); | ||
| 294 | if (thread) { | 290 | if (thread) { |
| 295 | thread->status &= ~THREADSTATUS_WAIT; | 291 | thread->status &= ~THREADSTATUS_WAIT; |
| 296 | if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | 292 | if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { |
| @@ -378,19 +374,23 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 | |||
| 378 | } | 374 | } |
| 379 | 375 | ||
| 380 | /// Get the priority of the thread specified by handle | 376 | /// Get the priority of the thread specified by handle |
| 381 | u32 GetThreadPriority(const Handle handle) { | 377 | ResultVal<u32> GetThreadPriority(const Handle handle) { |
| 382 | Thread* thread = g_object_pool.GetFast<Thread>(handle); | 378 | Thread* thread = g_object_pool.Get<Thread>(handle); |
| 383 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 379 | if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); |
| 384 | return thread->current_priority; | 380 | |
| 381 | return MakeResult<u32>(thread->current_priority); | ||
| 385 | } | 382 | } |
| 386 | 383 | ||
| 387 | /// Set the priority of the thread specified by handle | 384 | /// Set the priority of the thread specified by handle |
| 388 | Result SetThreadPriority(Handle handle, s32 priority) { | 385 | ResultCode SetThreadPriority(Handle handle, s32 priority) { |
| 389 | Thread* thread = nullptr; | 386 | Thread* thread = nullptr; |
| 390 | if (!handle) { | 387 | if (!handle) { |
| 391 | thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? | 388 | thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? |
| 392 | } else { | 389 | } else { |
| 393 | thread = g_object_pool.GetFast<Thread>(handle); | 390 | thread = g_object_pool.Get<Thread>(handle); |
| 391 | if (thread == nullptr) { | ||
| 392 | return InvalidHandle(ErrorModule::Kernel); | ||
| 393 | } | ||
| 394 | } | 394 | } |
| 395 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); | 395 | _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); |
| 396 | 396 | ||
| @@ -417,7 +417,7 @@ Result SetThreadPriority(Handle handle, s32 priority) { | |||
| 417 | thread_ready_queue.push_back(thread->current_priority, handle); | 417 | thread_ready_queue.push_back(thread->current_priority, handle); |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | return 0; | 420 | return RESULT_SUCCESS; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | /// Sets up the primary application thread | 423 | /// Sets up the primary application thread |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 2a43797ee..ce63a70d3 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "core/hle/kernel/kernel.h" | 8 | #include "core/hle/kernel/kernel.h" |
| 9 | #include "core/hle/result.h" | ||
| 9 | 10 | ||
| 10 | enum ThreadPriority { | 11 | enum ThreadPriority { |
| 11 | THREADPRIO_HIGHEST = 0, ///< Highest thread priority | 12 | THREADPRIO_HIGHEST = 0, ///< Highest thread priority |
| @@ -55,7 +56,7 @@ Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); | |||
| 55 | void Reschedule(); | 56 | void Reschedule(); |
| 56 | 57 | ||
| 57 | /// Stops the current thread | 58 | /// Stops the current thread |
| 58 | void StopThread(Handle thread, const char* reason); | 59 | ResultCode StopThread(Handle thread, const char* reason); |
| 59 | 60 | ||
| 60 | /// Resumes a thread from waiting by marking it as "ready" | 61 | /// Resumes a thread from waiting by marking it as "ready" |
| 61 | void ResumeThreadFromWait(Handle handle); | 62 | void ResumeThreadFromWait(Handle handle); |
| @@ -80,10 +81,10 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHa | |||
| 80 | void WaitThread_Synchronization(); | 81 | void WaitThread_Synchronization(); |
| 81 | 82 | ||
| 82 | /// Get the priority of the thread specified by handle | 83 | /// Get the priority of the thread specified by handle |
| 83 | u32 GetThreadPriority(const Handle handle); | 84 | ResultVal<u32> GetThreadPriority(const Handle handle); |
| 84 | 85 | ||
| 85 | /// Set the priority of the thread specified by handle | 86 | /// Set the priority of the thread specified by handle |
| 86 | Result SetThreadPriority(Handle handle, s32 priority); | 87 | ResultCode SetThreadPriority(Handle handle, s32 priority); |
| 87 | 88 | ||
| 88 | /// Initialize threading | 89 | /// Initialize threading |
| 89 | void ThreadingInit(); | 90 | void ThreadingInit(); |
diff --git a/src/core/hle/result.h b/src/core/hle/result.h new file mode 100644 index 000000000..15c4a2677 --- /dev/null +++ b/src/core/hle/result.h | |||
| @@ -0,0 +1,400 @@ | |||
| 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 <cassert> | ||
| 8 | #include <cstddef> | ||
| 9 | #include <type_traits> | ||
| 10 | #include <utility> | ||
| 11 | |||
| 12 | #include "common/common_types.h" | ||
| 13 | #include "common/bit_field.h" | ||
| 14 | |||
| 15 | // All the constants in this file come from http://3dbrew.org/wiki/Error_codes | ||
| 16 | |||
| 17 | /// Detailed description of the error. This listing is likely incomplete. | ||
| 18 | enum class ErrorDescription : u32 { | ||
| 19 | Success = 0, | ||
| 20 | InvalidSection = 1000, | ||
| 21 | TooLarge = 1001, | ||
| 22 | NotAuthorized = 1002, | ||
| 23 | AlreadyDone = 1003, | ||
| 24 | InvalidSize = 1004, | ||
| 25 | InvalidEnumValue = 1005, | ||
| 26 | InvalidCombination = 1006, | ||
| 27 | NoData = 1007, | ||
| 28 | Busy = 1008, | ||
| 29 | MisalignedAddress = 1009, | ||
| 30 | MisalignedSize = 1010, | ||
| 31 | OutOfMemory = 1011, | ||
| 32 | NotImplemented = 1012, | ||
| 33 | InvalidAddress = 1013, | ||
| 34 | InvalidPointer = 1014, | ||
| 35 | InvalidHandle = 1015, | ||
| 36 | NotInitialized = 1016, | ||
| 37 | AlreadyInitialized = 1017, | ||
| 38 | NotFound = 1018, | ||
| 39 | CancelRequested = 1019, | ||
| 40 | AlreadyExists = 1020, | ||
| 41 | OutOfRange = 1021, | ||
| 42 | Timeout = 1022, | ||
| 43 | InvalidResultValue = 1023, | ||
| 44 | }; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Identifies the module which caused the error. Error codes can be propagated through a call | ||
| 48 | * chain, meaning that this doesn't always correspond to the module where the API call made is | ||
| 49 | * contained. | ||
| 50 | */ | ||
| 51 | enum class ErrorModule : u32 { | ||
| 52 | Common = 0, | ||
| 53 | Kernel = 1, | ||
| 54 | Util = 2, | ||
| 55 | FileServer = 3, | ||
| 56 | LoaderServer = 4, | ||
| 57 | TCB = 5, | ||
| 58 | OS = 6, | ||
| 59 | DBG = 7, | ||
| 60 | DMNT = 8, | ||
| 61 | PDN = 9, | ||
| 62 | GX = 10, | ||
| 63 | I2C = 11, | ||
| 64 | GPIO = 12, | ||
| 65 | DD = 13, | ||
| 66 | CODEC = 14, | ||
| 67 | SPI = 15, | ||
| 68 | PXI = 16, | ||
| 69 | FS = 17, | ||
| 70 | DI = 18, | ||
| 71 | HID = 19, | ||
| 72 | CAM = 20, | ||
| 73 | PI = 21, | ||
| 74 | PM = 22, | ||
| 75 | PM_LOW = 23, | ||
| 76 | FSI = 24, | ||
| 77 | SRV = 25, | ||
| 78 | NDM = 26, | ||
| 79 | NWM = 27, | ||
| 80 | SOC = 28, | ||
| 81 | LDR = 29, | ||
| 82 | ACC = 30, | ||
| 83 | RomFS = 31, | ||
| 84 | AM = 32, | ||
| 85 | HIO = 33, | ||
| 86 | Updater = 34, | ||
| 87 | MIC = 35, | ||
| 88 | FND = 36, | ||
| 89 | MP = 37, | ||
| 90 | MPWL = 38, | ||
| 91 | AC = 39, | ||
| 92 | HTTP = 40, | ||
| 93 | DSP = 41, | ||
| 94 | SND = 42, | ||
| 95 | DLP = 43, | ||
| 96 | HIO_LOW = 44, | ||
| 97 | CSND = 45, | ||
| 98 | SSL = 46, | ||
| 99 | AM_LOW = 47, | ||
| 100 | NEX = 48, | ||
| 101 | Friends = 49, | ||
| 102 | RDT = 50, | ||
| 103 | Applet = 51, | ||
| 104 | NIM = 52, | ||
| 105 | PTM = 53, | ||
| 106 | MIDI = 54, | ||
| 107 | MC = 55, | ||
| 108 | SWC = 56, | ||
| 109 | FatFS = 57, | ||
| 110 | NGC = 58, | ||
| 111 | CARD = 59, | ||
| 112 | CARDNOR = 60, | ||
| 113 | SDMC = 61, | ||
| 114 | BOSS = 62, | ||
| 115 | DBM = 63, | ||
| 116 | Config = 64, | ||
| 117 | PS = 65, | ||
| 118 | CEC = 66, | ||
| 119 | IR = 67, | ||
| 120 | UDS = 68, | ||
| 121 | PL = 69, | ||
| 122 | CUP = 70, | ||
| 123 | Gyroscope = 71, | ||
| 124 | MCU = 72, | ||
| 125 | NS = 73, | ||
| 126 | News = 74, | ||
| 127 | RO_1 = 75, | ||
| 128 | GD = 76, | ||
| 129 | CardSPI = 77, | ||
| 130 | EC = 78, | ||
| 131 | RO_2 = 79, | ||
| 132 | WebBrowser = 80, | ||
| 133 | Test = 81, | ||
| 134 | ENC = 82, | ||
| 135 | PIA = 83, | ||
| 136 | |||
| 137 | Application = 254, | ||
| 138 | InvalidResult = 255 | ||
| 139 | }; | ||
| 140 | |||
| 141 | /// A less specific error cause. | ||
| 142 | enum class ErrorSummary : u32 { | ||
| 143 | Success = 0, | ||
| 144 | NothingHappened = 1, | ||
| 145 | WouldBlock = 2, | ||
| 146 | OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to | ||
| 147 | ///< execute the operation. | ||
| 148 | NotFound = 4, ///< A file or resource was not found. | ||
| 149 | InvalidState = 5, | ||
| 150 | NotSupported = 6, ///< The operation is not supported or not implemented. | ||
| 151 | InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime | ||
| 152 | ///< context. (Invalid handle, out-of-bounds pointer or size, etc.) | ||
| 153 | WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use | ||
| 154 | ///< with the function. (E.g. Invalid enum value) | ||
| 155 | Canceled = 9, | ||
| 156 | StatusChanged = 10, | ||
| 157 | Internal = 11, | ||
| 158 | |||
| 159 | InvalidResult = 63 | ||
| 160 | }; | ||
| 161 | |||
| 162 | /// The severity of the error. | ||
| 163 | enum class ErrorLevel : u32 { | ||
| 164 | Success = 0, | ||
| 165 | Info = 1, | ||
| 166 | |||
| 167 | Status = 25, | ||
| 168 | Temporary = 26, | ||
| 169 | Permanent = 27, | ||
| 170 | Usage = 28, | ||
| 171 | Reinitialize = 29, | ||
| 172 | Reset = 30, | ||
| 173 | Fatal = 31 | ||
| 174 | }; | ||
| 175 | |||
| 176 | /// Encapsulates a CTR-OS error code, allowing it to be separated into its constituent fields. | ||
| 177 | union ResultCode { | ||
| 178 | u32 raw; | ||
| 179 | |||
| 180 | BitField<0, 10, ErrorDescription> description; | ||
| 181 | BitField<10, 8, ErrorModule> module; | ||
| 182 | |||
| 183 | BitField<21, 6, ErrorSummary> summary; | ||
| 184 | BitField<27, 5, ErrorLevel> level; | ||
| 185 | |||
| 186 | // The last bit of `level` is checked by apps and the kernel to determine if a result code is an error | ||
| 187 | BitField<31, 1, u32> is_error; | ||
| 188 | |||
| 189 | explicit ResultCode(u32 raw) : raw(raw) {} | ||
| 190 | ResultCode(ErrorDescription description_, ErrorModule module_, | ||
| 191 | ErrorSummary summary_, ErrorLevel level_) : raw(0) { | ||
| 192 | description = description_; | ||
| 193 | module = module_; | ||
| 194 | summary = summary_; | ||
| 195 | level = level_; | ||
| 196 | } | ||
| 197 | |||
| 198 | ResultCode& operator=(const ResultCode& o) { raw = o.raw; return *this; } | ||
| 199 | |||
| 200 | bool IsSuccess() const { | ||
| 201 | return is_error == 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | bool IsError() const { | ||
| 205 | return is_error == 1; | ||
| 206 | } | ||
| 207 | }; | ||
| 208 | |||
| 209 | inline bool operator==(const ResultCode a, const ResultCode b) { | ||
| 210 | return a.raw == b.raw; | ||
| 211 | } | ||
| 212 | |||
| 213 | inline bool operator!=(const ResultCode a, const ResultCode b) { | ||
| 214 | return a.raw != b.raw; | ||
| 215 | } | ||
| 216 | |||
| 217 | // Convenience functions for creating some common kinds of errors: | ||
| 218 | |||
| 219 | /// The default success `ResultCode`. | ||
| 220 | const ResultCode RESULT_SUCCESS(0); | ||
| 221 | |||
| 222 | /// Might be returned instead of a dummy success for unimplemented APIs. | ||
| 223 | inline ResultCode UnimplementedFunction(ErrorModule module) { | ||
| 224 | return ResultCode(ErrorDescription::NotImplemented, module, | ||
| 225 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | ||
| 226 | } | ||
| 227 | /// Returned when a function is passed an invalid handle. | ||
| 228 | inline ResultCode InvalidHandle(ErrorModule module) { | ||
| 229 | return ResultCode(ErrorDescription::InvalidHandle, module, | ||
| 230 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||
| 231 | } | ||
| 232 | |||
| 233 | /** | ||
| 234 | * This is an optional value type. It holds a `ResultCode` and, if that code is a success code, | ||
| 235 | * also holds a result of type `T`. If the code is an error code then trying to access the inner | ||
| 236 | * value fails, thus ensuring that the ResultCode of functions is always checked properly before | ||
| 237 | * their return value is used. It is similar in concept to the `std::optional` type | ||
| 238 | * (http://en.cppreference.com/w/cpp/experimental/optional) originally proposed for inclusion in | ||
| 239 | * C++14, or the `Result` type in Rust (http://doc.rust-lang.org/std/result/index.html). | ||
| 240 | * | ||
| 241 | * An example of how it could be used: | ||
| 242 | * \code | ||
| 243 | * ResultVal<int> Frobnicate(float strength) { | ||
| 244 | * if (strength < 0.f || strength > 1.0f) { | ||
| 245 | * // Can't frobnicate too weakly or too strongly | ||
| 246 | * return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Common, | ||
| 247 | * ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||
| 248 | * } else { | ||
| 249 | * // Frobnicated! Give caller a cookie | ||
| 250 | * return MakeResult<int>(42); | ||
| 251 | * } | ||
| 252 | * } | ||
| 253 | * \endcode | ||
| 254 | * | ||
| 255 | * \code | ||
| 256 | * ResultVal<int> frob_result = Frobnicate(0.75f); | ||
| 257 | * if (frob_result) { | ||
| 258 | * // Frobbed ok | ||
| 259 | * printf("My cookie is %d\n", *frob_result); | ||
| 260 | * } else { | ||
| 261 | * printf("Guess I overdid it. :( Error code: %ux\n", frob_result.code().hex); | ||
| 262 | * } | ||
| 263 | * \endcode | ||
| 264 | */ | ||
| 265 | template <typename T> | ||
| 266 | class ResultVal { | ||
| 267 | public: | ||
| 268 | /// Constructs an empty `ResultVal` with the given error code. The code must not be a success code. | ||
| 269 | ResultVal(ResultCode error_code = ResultCode(-1)) | ||
| 270 | : result_code(error_code) | ||
| 271 | { | ||
| 272 | assert(error_code.IsError()); | ||
| 273 | UpdateDebugPtr(); | ||
| 274 | } | ||
| 275 | |||
| 276 | /** | ||
| 277 | * Similar to the non-member function `MakeResult`, with the exception that you can manually | ||
| 278 | * specify the success code. `success_code` must not be an error code. | ||
| 279 | */ | ||
| 280 | template <typename... Args> | ||
| 281 | static ResultVal WithCode(ResultCode success_code, Args&&... args) { | ||
| 282 | ResultVal<T> result; | ||
| 283 | result.emplace(success_code, std::forward<Args>(args)...); | ||
| 284 | return result; | ||
| 285 | } | ||
| 286 | |||
| 287 | ResultVal(const ResultVal& o) | ||
| 288 | : result_code(o.result_code) | ||
| 289 | { | ||
| 290 | if (!o.empty()) { | ||
| 291 | new (&storage) T(*o.GetPointer()); | ||
| 292 | } | ||
| 293 | UpdateDebugPtr(); | ||
| 294 | } | ||
| 295 | |||
| 296 | ResultVal(ResultVal&& o) | ||
| 297 | : result_code(o.result_code) | ||
| 298 | { | ||
| 299 | if (!o.empty()) { | ||
| 300 | new (&storage) T(std::move(*o.GetPointer())); | ||
| 301 | } | ||
| 302 | UpdateDebugPtr(); | ||
| 303 | } | ||
| 304 | |||
| 305 | ~ResultVal() { | ||
| 306 | if (!empty()) { | ||
| 307 | GetPointer()->~T(); | ||
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | ResultVal& operator=(const ResultVal& o) { | ||
| 312 | if (*this) { | ||
| 313 | if (o) { | ||
| 314 | *GetPointer() = *o.GetPointer(); | ||
| 315 | } else { | ||
| 316 | GetPointer()->~T(); | ||
| 317 | } | ||
| 318 | } else { | ||
| 319 | if (o) { | ||
| 320 | new (&storage) T(*o.GetPointer()); | ||
| 321 | } | ||
| 322 | } | ||
| 323 | result_code = o.result_code; | ||
| 324 | UpdateDebugPtr(); | ||
| 325 | |||
| 326 | return *this; | ||
| 327 | } | ||
| 328 | |||
| 329 | /** | ||
| 330 | * Replaces the current result with a new constructed result value in-place. The code must not | ||
| 331 | * be an error code. | ||
| 332 | */ | ||
| 333 | template <typename... Args> | ||
| 334 | void emplace(ResultCode success_code, Args&&... args) { | ||
| 335 | assert(success_code.IsSuccess()); | ||
| 336 | if (!empty()) { | ||
| 337 | GetPointer()->~T(); | ||
| 338 | } | ||
| 339 | new (&storage) T(std::forward<Args>(args)...); | ||
| 340 | result_code = success_code; | ||
| 341 | UpdateDebugPtr(); | ||
| 342 | } | ||
| 343 | |||
| 344 | /// Returns true if the `ResultVal` contains an error code and no value. | ||
| 345 | bool empty() const { return result_code.IsError(); } | ||
| 346 | |||
| 347 | /// Returns true if the `ResultVal` contains a return value. | ||
| 348 | bool Succeeded() const { return result_code.IsSuccess(); } | ||
| 349 | /// Returns true if the `ResultVal` contains an error code and no value. | ||
| 350 | bool Failed() const { return empty(); } | ||
| 351 | |||
| 352 | ResultCode Code() const { return result_code; } | ||
| 353 | |||
| 354 | const T& operator* () const { return *GetPointer(); } | ||
| 355 | T& operator* () { return *GetPointer(); } | ||
| 356 | const T* operator->() const { return GetPointer(); } | ||
| 357 | T* operator->() { return GetPointer(); } | ||
| 358 | |||
| 359 | /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing. | ||
| 360 | template <typename U> | ||
| 361 | T ValueOr(U&& value) const { | ||
| 362 | return !empty() ? *GetPointer() : std::move(value); | ||
| 363 | } | ||
| 364 | |||
| 365 | private: | ||
| 366 | typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType; | ||
| 367 | |||
| 368 | StorageType storage; | ||
| 369 | ResultCode result_code; | ||
| 370 | #if _DEBUG | ||
| 371 | // The purpose of this pointer is to aid inspecting the type with a debugger, eliminating the | ||
| 372 | // need to cast `storage` to a pointer or pay attention to `result_code`. | ||
| 373 | const T* debug_ptr; | ||
| 374 | #endif | ||
| 375 | |||
| 376 | void UpdateDebugPtr() { | ||
| 377 | #if _DEBUG | ||
| 378 | debug_ptr = empty() ? nullptr : static_cast<const T*>(static_cast<const void*>(&storage)); | ||
| 379 | #endif | ||
| 380 | } | ||
| 381 | |||
| 382 | const T* GetPointer() const { | ||
| 383 | assert(!empty()); | ||
| 384 | return static_cast<const T*>(static_cast<const void*>(&storage)); | ||
| 385 | } | ||
| 386 | |||
| 387 | T* GetPointer() { | ||
| 388 | assert(!empty()); | ||
| 389 | return static_cast<T*>(static_cast<void*>(&storage)); | ||
| 390 | } | ||
| 391 | }; | ||
| 392 | |||
| 393 | /** | ||
| 394 | * This function is a helper used to construct `ResultVal`s. It receives the arguments to construct | ||
| 395 | * `T` with and creates a success `ResultVal` contained the constructed value. | ||
| 396 | */ | ||
| 397 | template <typename T, typename... Args> | ||
| 398 | ResultVal<T> MakeResult(Args&&... args) { | ||
| 399 | return ResultVal<T>::WithCode(RESULT_SUCCESS, std::forward<Args>(args)...); | ||
| 400 | } | ||
diff --git a/src/core/hle/service/cfg_u.cpp b/src/core/hle/service/cfg_u.cpp index 822b0e2b8..d6b586ea0 100644 --- a/src/core/hle/service/cfg_u.cpp +++ b/src/core/hle/service/cfg_u.cpp | |||
| @@ -11,6 +11,90 @@ | |||
| 11 | 11 | ||
| 12 | namespace CFG_U { | 12 | namespace CFG_U { |
| 13 | 13 | ||
| 14 | static const std::array<const char*, 187> country_codes = { | ||
| 15 | nullptr, "JP", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 0-7 | ||
| 16 | "AI", "AG", "AR", "AW", "BS", "BB", "BZ", "BO", // 8-15 | ||
| 17 | "BR", "VG", "CA", "KY", "CL", "CO", "CR", "DM", // 16-23 | ||
| 18 | "DO", "EC", "SV", "GF", "GD", "GP", "GT", "GY", // 24-31 | ||
| 19 | "HT", "HN", "JM", "MQ", "MX", "MS", "AN", "NI", // 32-39 | ||
| 20 | "PA", "PY", "PE", "KN", "LC", "VC", "SR", "TT", // 40-47 | ||
| 21 | "TC", "US", "UY", "VI", "VE", nullptr, nullptr, nullptr, // 48-55 | ||
| 22 | nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 56-63 | ||
| 23 | "AL", "AU", "AT", "BE", "BA", "BW", "BG", "HR", // 64-71 | ||
| 24 | "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", // 72-79 | ||
| 25 | "HU", "IS", "IE", "IT", "LV", "LS", "LI", "LT", // 80-87 | ||
| 26 | "LU", "MK", "MT", "ME", "MZ", "NA", "NL", "NZ", // 88-95 | ||
| 27 | "NO", "PL", "PT", "RO", "RU", "RS", "SK", "SI", // 96-103 | ||
| 28 | "ZA", "ES", "SZ", "SE", "CH", "TR", "GB", "ZM", // 104-111 | ||
| 29 | "ZW", "AZ", "MR", "ML", "NE", "TD", "SD", "ER", // 112-119 | ||
| 30 | "DJ", "SO", "AD", "GI", "GG", "IM", "JE", "MC", // 120-127 | ||
| 31 | "TW", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 128-135 | ||
| 32 | "KR", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 136-143 | ||
| 33 | "HK", "MO", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 144-151 | ||
| 34 | "ID", "SG", "TH", "PH", "MY", nullptr, nullptr, nullptr, // 152-159 | ||
| 35 | "CN", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 160-167 | ||
| 36 | "AE", "IN", "EG", "OM", "QA", "KW", "SA", "SY", // 168-175 | ||
| 37 | "BH", "JO", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 176-183 | ||
| 38 | "SM", "VA", "BM", // 184-186 | ||
| 39 | }; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * CFG_User::GetCountryCodeString service function | ||
| 43 | * Inputs: | ||
| 44 | * 1 : Country Code ID | ||
| 45 | * Outputs: | ||
| 46 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 47 | * 2 : Country's 2-char string | ||
| 48 | */ | ||
| 49 | static void GetCountryCodeString(Service::Interface* self) { | ||
| 50 | u32* cmd_buffer = Service::GetCommandBuffer(); | ||
| 51 | u32 country_code_id = cmd_buffer[1]; | ||
| 52 | |||
| 53 | if (country_code_id >= country_codes.size()) { | ||
| 54 | ERROR_LOG(KERNEL, "requested country code id=%d is invalid", country_code_id); | ||
| 55 | cmd_buffer[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; | ||
| 56 | return; | ||
| 57 | } | ||
| 58 | |||
| 59 | const char* code = country_codes[country_code_id]; | ||
| 60 | if (code != nullptr) { | ||
| 61 | cmd_buffer[1] = 0; | ||
| 62 | cmd_buffer[2] = code[0] | (code[1] << 8); | ||
| 63 | } else { | ||
| 64 | cmd_buffer[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; | ||
| 65 | DEBUG_LOG(KERNEL, "requested country code id=%d is not set", country_code_id); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * CFG_User::GetCountryCodeID service function | ||
| 71 | * Inputs: | ||
| 72 | * 1 : Country Code 2-char string | ||
| 73 | * Outputs: | ||
| 74 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 75 | * 2 : Country Code ID | ||
| 76 | */ | ||
| 77 | static void GetCountryCodeID(Service::Interface* self) { | ||
| 78 | u32* cmd_buffer = Service::GetCommandBuffer(); | ||
| 79 | u16 country_code = cmd_buffer[1]; | ||
| 80 | u16 country_code_id = -1; | ||
| 81 | |||
| 82 | for (u32 i = 0; i < country_codes.size(); ++i) { | ||
| 83 | const char* code_string = country_codes[i]; | ||
| 84 | |||
| 85 | if (code_string != nullptr) { | ||
| 86 | u16 code = code_string[0] | (code_string[1] << 8); | ||
| 87 | if (code == country_code) { | ||
| 88 | country_code_id = i; | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | cmd_buffer[1] = 0; | ||
| 95 | cmd_buffer[2] = country_code_id; | ||
| 96 | } | ||
| 97 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | 98 | const Interface::FunctionInfo FunctionTable[] = { |
| 15 | {0x00010082, nullptr, "GetConfigInfoBlk2"}, | 99 | {0x00010082, nullptr, "GetConfigInfoBlk2"}, |
| 16 | {0x00020000, nullptr, "SecureInfoGetRegion"}, | 100 | {0x00020000, nullptr, "SecureInfoGetRegion"}, |
| @@ -20,8 +104,8 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 20 | {0x00060000, nullptr, "GetModelNintendo2DS"}, | 104 | {0x00060000, nullptr, "GetModelNintendo2DS"}, |
| 21 | {0x00070040, nullptr, "unknown"}, | 105 | {0x00070040, nullptr, "unknown"}, |
| 22 | {0x00080080, nullptr, "unknown"}, | 106 | {0x00080080, nullptr, "unknown"}, |
| 23 | {0x00090080, nullptr, "GetCountryCodeString"}, | 107 | {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, |
| 24 | {0x000A0040, nullptr, "GetCountryCodeID"}, | 108 | {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, |
| 25 | }; | 109 | }; |
| 26 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 110 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 27 | // Interface class | 111 | // Interface class |
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index bbcf26f61..a2b68cac8 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/log.h" | 5 | #include "common/log.h" |
| 6 | #include "core/hle/hle.h" | 6 | #include "core/hle/hle.h" |
| 7 | #include "core/hle/kernel/event.h" | ||
| 7 | #include "core/hle/service/dsp_dsp.h" | 8 | #include "core/hle/service/dsp_dsp.h" |
| 8 | 9 | ||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 10 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -11,38 +12,118 @@ | |||
| 11 | 12 | ||
| 12 | namespace DSP_DSP { | 13 | namespace DSP_DSP { |
| 13 | 14 | ||
| 15 | static Handle semaphore_event; | ||
| 16 | static Handle interrupt_event; | ||
| 17 | |||
| 18 | /** | ||
| 19 | * DSP_DSP::LoadComponent service function | ||
| 20 | * Inputs: | ||
| 21 | * 1 : Size | ||
| 22 | * 2 : Unknown (observed only half word used) | ||
| 23 | * 3 : Unknown (observed only half word used) | ||
| 24 | * 4 : (size << 4) | 0xA | ||
| 25 | * 5 : Buffer address | ||
| 26 | * Outputs: | ||
| 27 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 28 | * 2 : Component loaded, 0 on not loaded, 1 on loaded | ||
| 29 | */ | ||
| 30 | void LoadComponent(Service::Interface* self) { | ||
| 31 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 32 | |||
| 33 | cmd_buff[1] = 0; // No error | ||
| 34 | cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware | ||
| 35 | |||
| 36 | // TODO(bunnei): Implement real DSP firmware loading | ||
| 37 | |||
| 38 | DEBUG_LOG(KERNEL, "(STUBBED) called"); | ||
| 39 | } | ||
| 40 | |||
| 41 | /** | ||
| 42 | * DSP_DSP::GetSemaphoreEventHandle service function | ||
| 43 | * Outputs: | ||
| 44 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 45 | * 3 : Semaphore event handle | ||
| 46 | */ | ||
| 47 | void GetSemaphoreEventHandle(Service::Interface* self) { | ||
| 48 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 49 | |||
| 50 | cmd_buff[1] = 0; // No error | ||
| 51 | cmd_buff[3] = semaphore_event; // Event handle | ||
| 52 | |||
| 53 | DEBUG_LOG(KERNEL, "(STUBBED) called"); | ||
| 54 | } | ||
| 55 | |||
| 56 | /** | ||
| 57 | * DSP_DSP::RegisterInterruptEvents service function | ||
| 58 | * Inputs: | ||
| 59 | * 1 : Parameter 0 (purpose unknown) | ||
| 60 | * 2 : Parameter 1 (purpose unknown) | ||
| 61 | * 4 : Interrupt event handle | ||
| 62 | * Outputs: | ||
| 63 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 64 | */ | ||
| 65 | void RegisterInterruptEvents(Service::Interface* self) { | ||
| 66 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 67 | |||
| 68 | interrupt_event = static_cast<Handle>(cmd_buff[4]); | ||
| 69 | |||
| 70 | cmd_buff[1] = 0; // No error | ||
| 71 | |||
| 72 | DEBUG_LOG(KERNEL, "(STUBBED) called"); | ||
| 73 | } | ||
| 74 | |||
| 75 | /** | ||
| 76 | * DSP_DSP::WriteReg0x10 service function | ||
| 77 | * Inputs: | ||
| 78 | * 1 : Unknown (observed only half word used) | ||
| 79 | * Outputs: | ||
| 80 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 81 | */ | ||
| 82 | void WriteReg0x10(Service::Interface* self) { | ||
| 83 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 84 | |||
| 85 | Kernel::SignalEvent(interrupt_event); | ||
| 86 | |||
| 87 | cmd_buff[1] = 0; // No error | ||
| 88 | |||
| 89 | DEBUG_LOG(KERNEL, "(STUBBED) called"); | ||
| 90 | } | ||
| 91 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | 92 | const Interface::FunctionInfo FunctionTable[] = { |
| 15 | {0x00010040, nullptr, "RecvData"}, | 93 | {0x00010040, nullptr, "RecvData"}, |
| 16 | {0x00020040, nullptr, "RecvDataIsReady"}, | 94 | {0x00020040, nullptr, "RecvDataIsReady"}, |
| 17 | {0x00030080, nullptr, "SendData"}, | 95 | {0x00030080, nullptr, "SendData"}, |
| 18 | {0x00040040, nullptr, "SendDataIsEmpty"}, | 96 | {0x00040040, nullptr, "SendDataIsEmpty"}, |
| 19 | {0x00070040, nullptr, "WriteReg0x10"}, | 97 | {0x00070040, WriteReg0x10, "WriteReg0x10"}, |
| 20 | {0x00080000, nullptr, "GetSemaphore"}, | 98 | {0x00080000, nullptr, "GetSemaphore"}, |
| 21 | {0x00090040, nullptr, "ClearSemaphore"}, | 99 | {0x00090040, nullptr, "ClearSemaphore"}, |
| 22 | {0x000B0000, nullptr, "CheckSemaphoreRequest"}, | 100 | {0x000B0000, nullptr, "CheckSemaphoreRequest"}, |
| 23 | {0x000C0040, nullptr, "ConvertProcessAddressFromDspDram"}, | 101 | {0x000C0040, nullptr, "ConvertProcessAddressFromDspDram"}, |
| 24 | {0x000D0082, nullptr, "WriteProcessPipe"}, | 102 | {0x000D0082, nullptr, "WriteProcessPipe"}, |
| 25 | {0x001000C0, nullptr, "ReadPipeIfPossible"}, | 103 | {0x001000C0, nullptr, "ReadPipeIfPossible"}, |
| 26 | {0x001100C2, nullptr, "LoadComponent"}, | 104 | {0x001100C2, LoadComponent, "LoadComponent"}, |
| 27 | {0x00120000, nullptr, "UnloadComponent"}, | 105 | {0x00120000, nullptr, "UnloadComponent"}, |
| 28 | {0x00130082, nullptr, "FlushDataCache"}, | 106 | {0x00130082, nullptr, "FlushDataCache"}, |
| 29 | {0x00140082, nullptr, "InvalidateDCache"}, | 107 | {0x00140082, nullptr, "InvalidateDCache"}, |
| 30 | {0x00150082, nullptr, "RegisterInterruptEvents"}, | 108 | {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"}, |
| 31 | {0x00160000, nullptr, "GetSemaphoreEventHandle"}, | 109 | {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"}, |
| 32 | {0x00170040, nullptr, "SetSemaphoreMask"}, | 110 | {0x00170040, nullptr, "SetSemaphoreMask"}, |
| 33 | {0x00180040, nullptr, "GetPhysicalAddress"}, | 111 | {0x00180040, nullptr, "GetPhysicalAddress"}, |
| 34 | {0x00190040, nullptr, "GetVirtualAddress"}, | 112 | {0x00190040, nullptr, "GetVirtualAddress"}, |
| 35 | {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, | 113 | {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, |
| 36 | {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, | 114 | {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, |
| 37 | {0x001C0082, nullptr, "SetIirFilterEQ"}, | 115 | {0x001C0082, nullptr, "SetIirFilterEQ"}, |
| 38 | {0x001F0000, nullptr, "GetHeadphoneStatus"}, | 116 | {0x001F0000, nullptr, "GetHeadphoneStatus"}, |
| 39 | {0x00210000, nullptr, "GetIsDspOccupied"}, | 117 | {0x00210000, nullptr, "GetIsDspOccupied"}, |
| 40 | }; | 118 | }; |
| 41 | 119 | ||
| 42 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 120 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 43 | // Interface class | 121 | // Interface class |
| 44 | 122 | ||
| 45 | Interface::Interface() { | 123 | Interface::Interface() { |
| 124 | semaphore_event = Kernel::CreateEvent(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event"); | ||
| 125 | interrupt_event = 0; | ||
| 126 | |||
| 46 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | 127 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); |
| 47 | } | 128 | } |
| 48 | 129 | ||
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h index c4ce44245..9431b62f6 100644 --- a/src/core/hle/service/dsp_dsp.h +++ b/src/core/hle/service/dsp_dsp.h | |||
| @@ -20,7 +20,7 @@ public: | |||
| 20 | * @return Port name of service | 20 | * @return Port name of service |
| 21 | */ | 21 | */ |
| 22 | std::string GetPortName() const override { | 22 | std::string GetPortName() const override { |
| 23 | return "dsp:DSP"; | 23 | return "dsp::DSP"; |
| 24 | } | 24 | } |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
diff --git a/src/core/hle/service/fs_user.cpp b/src/core/hle/service/fs_user.cpp index dadc89ef8..34af78cb9 100644 --- a/src/core/hle/service/fs_user.cpp +++ b/src/core/hle/service/fs_user.cpp | |||
| @@ -4,26 +4,24 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/common.h" | 5 | #include "common/common.h" |
| 6 | 6 | ||
| 7 | #include "fs_user.h" | ||
| 8 | #include "common/string_util.h" | 7 | #include "common/string_util.h" |
| 9 | #include "core/settings.h" | ||
| 10 | #include "core/hle/kernel/archive.h" | 8 | #include "core/hle/kernel/archive.h" |
| 9 | #include "core/hle/kernel/archive.h" | ||
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "core/hle/service/fs_user.h" | ||
| 12 | #include "core/settings.h" | ||
| 11 | 13 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 13 | // Namespace FS_User | 15 | // Namespace FS_User |
| 14 | 16 | ||
| 15 | namespace FS_User { | 17 | namespace FS_User { |
| 16 | 18 | ||
| 17 | // We currently return 0 for success and -1 for failure in cmd_buff[1]. -1 was chosen because it | ||
| 18 | // puts all the sections of the http://3dbrew.org/wiki/Error_codes to something non-zero, to make | ||
| 19 | // sure we don't mislead the application into thinking something worked. | ||
| 20 | |||
| 21 | static void Initialize(Service::Interface* self) { | 19 | static void Initialize(Service::Interface* self) { |
| 22 | u32* cmd_buff = Service::GetCommandBuffer(); | 20 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 23 | 21 | ||
| 24 | // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per | 22 | // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per |
| 25 | // http://3dbrew.org/wiki/FS:Initialize#Request | 23 | // http://3dbrew.org/wiki/FS:Initialize#Request |
| 26 | cmd_buff[1] = 0; | 24 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 27 | 25 | ||
| 28 | DEBUG_LOG(KERNEL, "called"); | 26 | DEBUG_LOG(KERNEL, "called"); |
| 29 | } | 27 | } |
| @@ -57,16 +55,14 @@ static void OpenFile(Service::Interface* self) { | |||
| 57 | u32 filename_ptr = cmd_buff[9]; | 55 | u32 filename_ptr = cmd_buff[9]; |
| 58 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | 56 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); |
| 59 | 57 | ||
| 60 | DEBUG_LOG(KERNEL, "path=%s, mode=%d attrs=%d", file_path.DebugStr().c_str(), mode, attributes); | 58 | DEBUG_LOG(KERNEL, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); |
| 61 | 59 | ||
| 62 | Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode); | 60 | ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode); |
| 63 | if (handle) { | 61 | cmd_buff[1] = handle.Code().raw; |
| 64 | cmd_buff[1] = 0; | 62 | if (handle.Succeeded()) { |
| 65 | cmd_buff[3] = handle; | 63 | cmd_buff[3] = *handle; |
| 66 | } else { | 64 | } else { |
| 67 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str()); | 65 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |
| 68 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 69 | cmd_buff[1] = -1; | ||
| 70 | } | 66 | } |
| 71 | 67 | ||
| 72 | DEBUG_LOG(KERNEL, "called"); | 68 | DEBUG_LOG(KERNEL, "called"); |
| @@ -106,38 +102,100 @@ static void OpenFileDirectly(Service::Interface* self) { | |||
| 106 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); | 102 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); |
| 107 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | 103 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); |
| 108 | 104 | ||
| 109 | DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%d attributes=%d", | 105 | DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%u attributes=%d", |
| 110 | archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode, attributes); | 106 | archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); |
| 111 | 107 | ||
| 112 | if (archive_path.GetType() != FileSys::Empty) { | 108 | if (archive_path.GetType() != FileSys::Empty) { |
| 113 | ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); | 109 | ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); |
| 114 | cmd_buff[1] = -1; | 110 | cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; |
| 115 | return; | 111 | return; |
| 116 | } | 112 | } |
| 117 | 113 | ||
| 118 | // TODO(Link Mauve): Check if we should even get a handle for the archive, and don't leak it | 114 | // TODO(Link Mauve): Check if we should even get a handle for the archive, and don't leak it |
| 119 | Handle archive_handle = Kernel::OpenArchive(archive_id); | 115 | // TODO(yuriks): Why is there all this duplicate (and seemingly useless) code up here? |
| 120 | if (!archive_handle) { | 116 | ResultVal<Handle> archive_handle = Kernel::OpenArchive(archive_id); |
| 117 | cmd_buff[1] = archive_handle.Code().raw; | ||
| 118 | if (archive_handle.Failed()) { | ||
| 121 | ERROR_LOG(KERNEL, "failed to get a handle for archive"); | 119 | ERROR_LOG(KERNEL, "failed to get a handle for archive"); |
| 122 | // TODO(Link Mauve): Check for the actual error values, this one was just chosen arbitrarily | ||
| 123 | cmd_buff[1] = -1; | ||
| 124 | return; | 120 | return; |
| 125 | } | 121 | } |
| 122 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | ||
| 123 | cmd_buff[3] = *archive_handle; | ||
| 126 | 124 | ||
| 127 | Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode); | 125 | ResultVal<Handle> handle = Kernel::OpenFileFromArchive(*archive_handle, file_path, mode); |
| 128 | if (handle) { | 126 | cmd_buff[1] = handle.Code().raw; |
| 129 | cmd_buff[1] = 0; | 127 | if (handle.Succeeded()) { |
| 130 | cmd_buff[3] = handle; | 128 | cmd_buff[3] = *handle; |
| 131 | } else { | 129 | } else { |
| 132 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str()); | 130 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |
| 133 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 134 | cmd_buff[1] = -1; | ||
| 135 | } | 131 | } |
| 136 | 132 | ||
| 137 | DEBUG_LOG(KERNEL, "called"); | 133 | DEBUG_LOG(KERNEL, "called"); |
| 138 | } | 134 | } |
| 139 | 135 | ||
| 140 | /* | 136 | /* |
| 137 | * FS_User::DeleteFile service function | ||
| 138 | * Inputs: | ||
| 139 | * 2 : Archive handle lower word | ||
| 140 | * 3 : Archive handle upper word | ||
| 141 | * 4 : File path string type | ||
| 142 | * 5 : File path string size | ||
| 143 | * 7 : File path string data | ||
| 144 | * Outputs: | ||
| 145 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 146 | */ | ||
| 147 | void DeleteFile(Service::Interface* self) { | ||
| 148 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 149 | |||
| 150 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | ||
| 151 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 152 | Handle archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 153 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | ||
| 154 | u32 filename_size = cmd_buff[5]; | ||
| 155 | u32 filename_ptr = cmd_buff[7]; | ||
| 156 | |||
| 157 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | ||
| 158 | |||
| 159 | DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", | ||
| 160 | filename_type, filename_size, file_path.DebugStr().c_str()); | ||
| 161 | |||
| 162 | cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path); | ||
| 163 | |||
| 164 | DEBUG_LOG(KERNEL, "called"); | ||
| 165 | } | ||
| 166 | |||
| 167 | /* | ||
| 168 | * FS_User::DeleteDirectory service function | ||
| 169 | * Inputs: | ||
| 170 | * 2 : Archive handle lower word | ||
| 171 | * 3 : Archive handle upper word | ||
| 172 | * 4 : Directory path string type | ||
| 173 | * 5 : Directory path string size | ||
| 174 | * 7 : Directory path string data | ||
| 175 | * Outputs: | ||
| 176 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 177 | */ | ||
| 178 | void DeleteDirectory(Service::Interface* self) { | ||
| 179 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 180 | |||
| 181 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | ||
| 182 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 183 | Handle archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 184 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | ||
| 185 | u32 dirname_size = cmd_buff[5]; | ||
| 186 | u32 dirname_ptr = cmd_buff[7]; | ||
| 187 | |||
| 188 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); | ||
| 189 | |||
| 190 | DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", | ||
| 191 | dirname_type, dirname_size, dir_path.DebugStr().c_str()); | ||
| 192 | |||
| 193 | cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path); | ||
| 194 | |||
| 195 | DEBUG_LOG(KERNEL, "called"); | ||
| 196 | } | ||
| 197 | |||
| 198 | /* | ||
| 141 | * FS_User::CreateDirectory service function | 199 | * FS_User::CreateDirectory service function |
| 142 | * Inputs: | 200 | * Inputs: |
| 143 | * 2 : Archive handle lower word | 201 | * 2 : Archive handle lower word |
| @@ -159,18 +217,8 @@ static void CreateDirectory(Service::Interface* self) { | |||
| 159 | u32 dirname_ptr = cmd_buff[8]; | 217 | u32 dirname_ptr = cmd_buff[8]; |
| 160 | 218 | ||
| 161 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); | 219 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); |
| 162 | std::string dir_string; | ||
| 163 | switch (dir_path.GetType()) { | ||
| 164 | case FileSys::Char: | ||
| 165 | case FileSys::Wchar: | ||
| 166 | dir_string = dir_path.AsString(); | ||
| 167 | break; | ||
| 168 | default: | ||
| 169 | cmd_buff[1] = -1; | ||
| 170 | return; | ||
| 171 | } | ||
| 172 | 220 | ||
| 173 | DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_string.c_str()); | 221 | DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); |
| 174 | 222 | ||
| 175 | cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path); | 223 | cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path); |
| 176 | 224 | ||
| @@ -188,27 +236,15 @@ static void OpenDirectory(Service::Interface* self) { | |||
| 188 | u32 dirname_ptr = cmd_buff[6]; | 236 | u32 dirname_ptr = cmd_buff[6]; |
| 189 | 237 | ||
| 190 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); | 238 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); |
| 191 | std::string dir_string; | ||
| 192 | switch (dir_path.GetType()) { | ||
| 193 | case FileSys::Char: | ||
| 194 | case FileSys::Wchar: | ||
| 195 | dir_string = dir_path.AsString(); | ||
| 196 | break; | ||
| 197 | default: | ||
| 198 | cmd_buff[1] = -1; | ||
| 199 | return; | ||
| 200 | } | ||
| 201 | 239 | ||
| 202 | DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_string.c_str()); | 240 | DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); |
| 203 | 241 | ||
| 204 | Handle handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_path); | 242 | ResultVal<Handle> handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_path); |
| 205 | if (handle) { | 243 | cmd_buff[1] = handle.Code().raw; |
| 206 | cmd_buff[1] = 0; | 244 | if (handle.Succeeded()) { |
| 207 | cmd_buff[3] = handle; | 245 | cmd_buff[3] = *handle; |
| 208 | } else { | 246 | } else { |
| 209 | ERROR_LOG(KERNEL, "failed to get a handle for directory %s", dir_string.c_str()); | 247 | ERROR_LOG(KERNEL, "failed to get a handle for directory"); |
| 210 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 211 | cmd_buff[1] = -1; | ||
| 212 | } | 248 | } |
| 213 | 249 | ||
| 214 | DEBUG_LOG(KERNEL, "called"); | 250 | DEBUG_LOG(KERNEL, "called"); |
| @@ -240,19 +276,17 @@ static void OpenArchive(Service::Interface* self) { | |||
| 240 | 276 | ||
| 241 | if (archive_path.GetType() != FileSys::Empty) { | 277 | if (archive_path.GetType() != FileSys::Empty) { |
| 242 | ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); | 278 | ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); |
| 243 | cmd_buff[1] = -1; | 279 | cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; |
| 244 | return; | 280 | return; |
| 245 | } | 281 | } |
| 246 | 282 | ||
| 247 | Handle handle = Kernel::OpenArchive(archive_id); | 283 | ResultVal<Handle> handle = Kernel::OpenArchive(archive_id); |
| 248 | if (handle) { | 284 | cmd_buff[1] = handle.Code().raw; |
| 249 | cmd_buff[1] = 0; | 285 | if (handle.Succeeded()) { |
| 250 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | 286 | // cmd_buff[2] isn't used according to 3dmoo's implementation. |
| 251 | cmd_buff[3] = handle; | 287 | cmd_buff[3] = *handle; |
| 252 | } else { | 288 | } else { |
| 253 | ERROR_LOG(KERNEL, "failed to get a handle for archive"); | 289 | ERROR_LOG(KERNEL, "failed to get a handle for archive"); |
| 254 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 255 | cmd_buff[1] = -1; | ||
| 256 | } | 290 | } |
| 257 | 291 | ||
| 258 | DEBUG_LOG(KERNEL, "called"); | 292 | DEBUG_LOG(KERNEL, "called"); |
| @@ -279,9 +313,9 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 279 | {0x08010002, Initialize, "Initialize"}, | 313 | {0x08010002, Initialize, "Initialize"}, |
| 280 | {0x080201C2, OpenFile, "OpenFile"}, | 314 | {0x080201C2, OpenFile, "OpenFile"}, |
| 281 | {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, | 315 | {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, |
| 282 | {0x08040142, nullptr, "DeleteFile"}, | 316 | {0x08040142, DeleteFile, "DeleteFile"}, |
| 283 | {0x08050244, nullptr, "RenameFile"}, | 317 | {0x08050244, nullptr, "RenameFile"}, |
| 284 | {0x08060142, nullptr, "DeleteDirectory"}, | 318 | {0x08060142, DeleteDirectory, "DeleteDirectory"}, |
| 285 | {0x08070142, nullptr, "DeleteDirectoryRecursively"}, | 319 | {0x08070142, nullptr, "DeleteDirectoryRecursively"}, |
| 286 | {0x08080202, nullptr, "CreateFile"}, | 320 | {0x08080202, nullptr, "CreateFile"}, |
| 287 | {0x08090182, CreateDirectory, "CreateDirectory"}, | 321 | {0x08090182, CreateDirectory, "CreateDirectory"}, |
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 66daded94..de1bd3f61 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp | |||
| @@ -28,28 +28,23 @@ u32 g_thread_id = 1; ///< Thread index into interrupt relay queue, 1 | |||
| 28 | 28 | ||
| 29 | /// Gets a pointer to a thread command buffer in GSP shared memory | 29 | /// Gets a pointer to a thread command buffer in GSP shared memory |
| 30 | static inline u8* GetCommandBuffer(u32 thread_id) { | 30 | static inline u8* GetCommandBuffer(u32 thread_id) { |
| 31 | if (0 == g_shared_memory) | 31 | ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * sizeof(CommandBuffer))); |
| 32 | return nullptr; | 32 | return ptr.ValueOr(nullptr); |
| 33 | |||
| 34 | return Kernel::GetSharedMemoryPointer(g_shared_memory, | ||
| 35 | 0x800 + (thread_id * sizeof(CommandBuffer))); | ||
| 36 | } | 33 | } |
| 37 | 34 | ||
| 38 | static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) { | 35 | static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) { |
| 39 | if (0 == g_shared_memory) | ||
| 40 | return nullptr; | ||
| 41 | |||
| 42 | _dbg_assert_msg_(GSP, screen_index < 2, "Invalid screen index"); | 36 | _dbg_assert_msg_(GSP, screen_index < 2, "Invalid screen index"); |
| 43 | 37 | ||
| 44 | // For each thread there are two FrameBufferUpdate fields | 38 | // For each thread there are two FrameBufferUpdate fields |
| 45 | u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate); | 39 | u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate); |
| 46 | return (FrameBufferUpdate*)Kernel::GetSharedMemoryPointer(g_shared_memory, offset); | 40 | ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, offset); |
| 41 | return reinterpret_cast<FrameBufferUpdate*>(ptr.ValueOr(nullptr)); | ||
| 47 | } | 42 | } |
| 48 | 43 | ||
| 49 | /// Gets a pointer to the interrupt relay queue for a given thread index | 44 | /// Gets a pointer to the interrupt relay queue for a given thread index |
| 50 | static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { | 45 | static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { |
| 51 | return (InterruptRelayQueue*)Kernel::GetSharedMemoryPointer(g_shared_memory, | 46 | ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, sizeof(InterruptRelayQueue) * thread_id); |
| 52 | sizeof(InterruptRelayQueue) * thread_id); | 47 | return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr)); |
| 53 | } | 48 | } |
| 54 | 49 | ||
| 55 | static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { | 50 | static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { |
diff --git a/src/core/hle/service/hid_user.cpp b/src/core/hle/service/hid_user.cpp index 5f6bf1eff..d29de1a52 100644 --- a/src/core/hle/service/hid_user.cpp +++ b/src/core/hle/service/hid_user.cpp | |||
| @@ -34,10 +34,7 @@ static s16 next_circle_y = 0; | |||
| 34 | * Gets a pointer to the PadData structure inside HID shared memory | 34 | * Gets a pointer to the PadData structure inside HID shared memory |
| 35 | */ | 35 | */ |
| 36 | static inline PadData* GetPadData() { | 36 | static inline PadData* GetPadData() { |
| 37 | if (0 == shared_mem) | 37 | return reinterpret_cast<PadData*>(Kernel::GetSharedMemoryPointer(shared_mem, 0).ValueOr(nullptr)); |
| 38 | return nullptr; | ||
| 39 | |||
| 40 | return reinterpret_cast<PadData*>(Kernel::GetSharedMemoryPointer(shared_mem, 0)); | ||
| 41 | } | 38 | } |
| 42 | 39 | ||
| 43 | /** | 40 | /** |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index abc8d5edb..fed2268a0 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -62,7 +62,7 @@ void Manager::DeleteService(const std::string& port_name) { | |||
| 62 | 62 | ||
| 63 | /// Get a Service Interface from its Handle | 63 | /// Get a Service Interface from its Handle |
| 64 | Interface* Manager::FetchFromHandle(Handle handle) { | 64 | Interface* Manager::FetchFromHandle(Handle handle) { |
| 65 | return Kernel::g_object_pool.GetFast<Interface>(handle); | 65 | return Kernel::g_object_pool.Get<Interface>(handle); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /// Get a Service Interface from its port | 68 | /// Get a Service Interface from its port |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 55aa84e83..20e7fb4d3 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -75,12 +75,7 @@ public: | |||
| 75 | m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); | 75 | m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | /** | 78 | ResultVal<bool> SyncRequest() override { |
| 79 | * Synchronize kernel object | ||
| 80 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 81 | * @return Result of operation, 0 on success, otherwise error code | ||
| 82 | */ | ||
| 83 | Result SyncRequest(bool* wait) override { | ||
| 84 | u32* cmd_buff = GetCommandBuffer(); | 79 | u32* cmd_buff = GetCommandBuffer(); |
| 85 | auto itr = m_functions.find(cmd_buff[0]); | 80 | auto itr = m_functions.find(cmd_buff[0]); |
| 86 | 81 | ||
| @@ -91,7 +86,7 @@ public: | |||
| 91 | // TODO(bunnei): Hack - ignore error | 86 | // TODO(bunnei): Hack - ignore error |
| 92 | u32* cmd_buff = Service::GetCommandBuffer(); | 87 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 93 | cmd_buff[1] = 0; | 88 | cmd_buff[1] = 0; |
| 94 | return 0; | 89 | return MakeResult<bool>(false); |
| 95 | } | 90 | } |
| 96 | if (itr->second.func == nullptr) { | 91 | if (itr->second.func == nullptr) { |
| 97 | ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s", | 92 | ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s", |
| @@ -100,23 +95,18 @@ public: | |||
| 100 | // TODO(bunnei): Hack - ignore error | 95 | // TODO(bunnei): Hack - ignore error |
| 101 | u32* cmd_buff = Service::GetCommandBuffer(); | 96 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 102 | cmd_buff[1] = 0; | 97 | cmd_buff[1] = 0; |
| 103 | return 0; | 98 | return MakeResult<bool>(false); |
| 104 | } | 99 | } |
| 105 | 100 | ||
| 106 | itr->second.func(this); | 101 | itr->second.func(this); |
| 107 | 102 | ||
| 108 | return 0; // TODO: Implement return from actual function | 103 | return MakeResult<bool>(false); // TODO: Implement return from actual function |
| 109 | } | 104 | } |
| 110 | 105 | ||
| 111 | /** | 106 | ResultVal<bool> WaitSynchronization() override { |
| 112 | * Wait for kernel object to synchronize | ||
| 113 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 114 | * @return Result of operation, 0 on success, otherwise error code | ||
| 115 | */ | ||
| 116 | Result WaitSynchronization(bool* wait) override { | ||
| 117 | // TODO(bunnei): ImplementMe | 107 | // TODO(bunnei): ImplementMe |
| 118 | ERROR_LOG(OSHLE, "unimplemented function"); | 108 | ERROR_LOG(OSHLE, "unimplemented function"); |
| 119 | return 0; | 109 | return UnimplementedFunction(ErrorModule::OS); |
| 120 | } | 110 | } |
| 121 | 111 | ||
| 122 | protected: | 112 | protected: |
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index df38bd93c..0e7fa9e3b 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp | |||
| @@ -35,7 +35,7 @@ static void GetProcSemaphore(Service::Interface* self) { | |||
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | static void GetServiceHandle(Service::Interface* self) { | 37 | static void GetServiceHandle(Service::Interface* self) { |
| 38 | Result res = 0; | 38 | ResultCode res = RESULT_SUCCESS; |
| 39 | u32* cmd_buff = Service::GetCommandBuffer(); | 39 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 40 | 40 | ||
| 41 | std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); | 41 | std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); |
| @@ -46,9 +46,9 @@ static void GetServiceHandle(Service::Interface* self) { | |||
| 46 | DEBUG_LOG(OSHLE, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); | 46 | DEBUG_LOG(OSHLE, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); |
| 47 | } else { | 47 | } else { |
| 48 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); | 48 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); |
| 49 | res = -1; | 49 | res = UnimplementedFunction(ErrorModule::SRV); |
| 50 | } | 50 | } |
| 51 | cmd_buff[1] = res; | 51 | cmd_buff[1] = res.raw; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | const Interface::FunctionInfo FunctionTable[] = { | 54 | const Interface::FunctionInfo FunctionTable[] = { |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 3a06d6765..43a3cbe03 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 17 | 17 | ||
| 18 | #include "core/hle/function_wrappers.h" | 18 | #include "core/hle/function_wrappers.h" |
| 19 | #include "core/hle/result.h" | ||
| 19 | #include "core/hle/service/service.h" | 20 | #include "core/hle/service/service.h" |
| 20 | 21 | ||
| 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 22 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -86,18 +87,22 @@ static Result ConnectToPort(Handle* out, const char* port_name) { | |||
| 86 | 87 | ||
| 87 | /// Synchronize to an OS service | 88 | /// Synchronize to an OS service |
| 88 | static Result SendSyncRequest(Handle handle) { | 89 | static Result SendSyncRequest(Handle handle) { |
| 90 | // TODO(yuriks): ObjectPool::Get tries to check the Object type, which fails since this is a generic base Object, | ||
| 91 | // so we are forced to use GetFast and manually verify the handle. | ||
| 92 | if (!Kernel::g_object_pool.IsValid(handle)) { | ||
| 93 | return InvalidHandle(ErrorModule::Kernel).raw; | ||
| 94 | } | ||
| 89 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); | 95 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); |
| 90 | 96 | ||
| 91 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); | 97 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); |
| 92 | DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str()); | 98 | DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str()); |
| 93 | 99 | ||
| 94 | bool wait = false; | 100 | ResultVal<bool> wait = object->SyncRequest(); |
| 95 | Result res = object->SyncRequest(&wait); | 101 | if (wait.Succeeded() && *wait) { |
| 96 | if (wait) { | ||
| 97 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? | 102 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? |
| 98 | } | 103 | } |
| 99 | 104 | ||
| 100 | return res; | 105 | return wait.Code().raw; |
| 101 | } | 106 | } |
| 102 | 107 | ||
| 103 | /// Close a handle | 108 | /// Close a handle |
| @@ -110,25 +115,25 @@ static Result CloseHandle(Handle handle) { | |||
| 110 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds | 115 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds |
| 111 | static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { | 116 | static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { |
| 112 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this | 117 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this |
| 113 | bool wait = false; | ||
| 114 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated | 118 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated |
| 115 | 119 | ||
| 120 | if (!Kernel::g_object_pool.IsValid(handle)) { | ||
| 121 | return InvalidHandle(ErrorModule::Kernel).raw; | ||
| 122 | } | ||
| 116 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); | 123 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); |
| 124 | _dbg_assert_(KERNEL, object != nullptr); | ||
| 117 | 125 | ||
| 118 | DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), | 126 | DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), |
| 119 | object->GetName().c_str(), nano_seconds); | 127 | object->GetName().c_str(), nano_seconds); |
| 120 | 128 | ||
| 121 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); | 129 | ResultVal<bool> wait = object->WaitSynchronization(); |
| 122 | |||
| 123 | Result res = object->WaitSynchronization(&wait); | ||
| 124 | 130 | ||
| 125 | // Check for next thread to schedule | 131 | // Check for next thread to schedule |
| 126 | if (wait) { | 132 | if (wait.Succeeded() && *wait) { |
| 127 | HLE::Reschedule(__func__); | 133 | HLE::Reschedule(__func__); |
| 128 | return 0; | ||
| 129 | } | 134 | } |
| 130 | 135 | ||
| 131 | return res; | 136 | return wait.Code().raw; |
| 132 | } | 137 | } |
| 133 | 138 | ||
| 134 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 139 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| @@ -143,20 +148,21 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 143 | 148 | ||
| 144 | // Iterate through each handle, synchronize kernel object | 149 | // Iterate through each handle, synchronize kernel object |
| 145 | for (s32 i = 0; i < handle_count; i++) { | 150 | for (s32 i = 0; i < handle_count; i++) { |
| 146 | bool wait = false; | 151 | if (!Kernel::g_object_pool.IsValid(handles[i])) { |
| 152 | return InvalidHandle(ErrorModule::Kernel).raw; | ||
| 153 | } | ||
| 147 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]); | 154 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]); |
| 148 | 155 | ||
| 149 | _assert_msg_(KERNEL, (object != nullptr), "called handle=0x%08X, but kernel object " | ||
| 150 | "is nullptr!", handles[i]); | ||
| 151 | |||
| 152 | DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), | 156 | DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), |
| 153 | object->GetName().c_str()); | 157 | object->GetName().c_str()); |
| 154 | 158 | ||
| 155 | Result res = object->WaitSynchronization(&wait); | 159 | // TODO(yuriks): Verify how the real function behaves when an error happens here |
| 160 | ResultVal<bool> wait_result = object->WaitSynchronization(); | ||
| 161 | bool wait = wait_result.Succeeded() && *wait_result; | ||
| 156 | 162 | ||
| 157 | if (!wait && !wait_all) { | 163 | if (!wait && !wait_all) { |
| 158 | *out = i; | 164 | *out = i; |
| 159 | return 0; | 165 | return RESULT_SUCCESS.raw; |
| 160 | } else { | 166 | } else { |
| 161 | unlock_all = false; | 167 | unlock_all = false; |
| 162 | } | 168 | } |
| @@ -164,13 +170,13 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 164 | 170 | ||
| 165 | if (wait_all && unlock_all) { | 171 | if (wait_all && unlock_all) { |
| 166 | *out = handle_count; | 172 | *out = handle_count; |
| 167 | return 0; | 173 | return RESULT_SUCCESS.raw; |
| 168 | } | 174 | } |
| 169 | 175 | ||
| 170 | // Check for next thread to schedule | 176 | // Check for next thread to schedule |
| 171 | HLE::Reschedule(__func__); | 177 | HLE::Reschedule(__func__); |
| 172 | 178 | ||
| 173 | return 0; | 179 | return RESULT_SUCCESS.raw; |
| 174 | } | 180 | } |
| 175 | 181 | ||
| 176 | /// Create an address arbiter (to allocate access to shared resources) | 182 | /// Create an address arbiter (to allocate access to shared resources) |
| @@ -183,8 +189,10 @@ static Result CreateAddressArbiter(u32* arbiter) { | |||
| 183 | 189 | ||
| 184 | /// Arbitrate address | 190 | /// Arbitrate address |
| 185 | static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { | 191 | static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { |
| 186 | return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), address, | 192 | DEBUG_LOG(SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter, |
| 187 | value); | 193 | address, type, value); |
| 194 | return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), | ||
| 195 | address, value).raw; | ||
| 188 | } | 196 | } |
| 189 | 197 | ||
| 190 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 198 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| @@ -246,13 +254,16 @@ static u32 ExitThread() { | |||
| 246 | 254 | ||
| 247 | /// Gets the priority for the specified thread | 255 | /// Gets the priority for the specified thread |
| 248 | static Result GetThreadPriority(s32* priority, Handle handle) { | 256 | static Result GetThreadPriority(s32* priority, Handle handle) { |
| 249 | *priority = Kernel::GetThreadPriority(handle); | 257 | ResultVal<u32> priority_result = Kernel::GetThreadPriority(handle); |
| 250 | return 0; | 258 | if (priority_result.Succeeded()) { |
| 259 | *priority = *priority_result; | ||
| 260 | } | ||
| 261 | return priority_result.Code().raw; | ||
| 251 | } | 262 | } |
| 252 | 263 | ||
| 253 | /// Sets the priority for the specified thread | 264 | /// Sets the priority for the specified thread |
| 254 | static Result SetThreadPriority(Handle handle, s32 priority) { | 265 | static Result SetThreadPriority(Handle handle, s32 priority) { |
| 255 | return Kernel::SetThreadPriority(handle, priority); | 266 | return Kernel::SetThreadPriority(handle, priority).raw; |
| 256 | } | 267 | } |
| 257 | 268 | ||
| 258 | /// Create a mutex | 269 | /// Create a mutex |
| @@ -266,9 +277,8 @@ static Result CreateMutex(Handle* mutex, u32 initial_locked) { | |||
| 266 | /// Release a mutex | 277 | /// Release a mutex |
| 267 | static Result ReleaseMutex(Handle handle) { | 278 | static Result ReleaseMutex(Handle handle) { |
| 268 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); | 279 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); |
| 269 | _assert_msg_(KERNEL, (handle != 0), "called, but handle is nullptr!"); | 280 | ResultCode res = Kernel::ReleaseMutex(handle); |
| 270 | Kernel::ReleaseMutex(handle); | 281 | return res.raw; |
| 271 | return 0; | ||
| 272 | } | 282 | } |
| 273 | 283 | ||
| 274 | /// Get current thread ID | 284 | /// Get current thread ID |
| @@ -310,21 +320,22 @@ static Result DuplicateHandle(Handle* out, Handle handle) { | |||
| 310 | 320 | ||
| 311 | /// Signals an event | 321 | /// Signals an event |
| 312 | static Result SignalEvent(Handle evt) { | 322 | static Result SignalEvent(Handle evt) { |
| 313 | Result res = Kernel::SignalEvent(evt); | ||
| 314 | DEBUG_LOG(SVC, "called event=0x%08X", evt); | 323 | DEBUG_LOG(SVC, "called event=0x%08X", evt); |
| 315 | return res; | 324 | return Kernel::SignalEvent(evt).raw; |
| 316 | } | 325 | } |
| 317 | 326 | ||
| 318 | /// Clears an event | 327 | /// Clears an event |
| 319 | static Result ClearEvent(Handle evt) { | 328 | static Result ClearEvent(Handle evt) { |
| 320 | Result res = Kernel::ClearEvent(evt); | ||
| 321 | DEBUG_LOG(SVC, "called event=0x%08X", evt); | 329 | DEBUG_LOG(SVC, "called event=0x%08X", evt); |
| 322 | return res; | 330 | return Kernel::ClearEvent(evt).raw; |
| 323 | } | 331 | } |
| 324 | 332 | ||
| 325 | /// Sleep the current thread | 333 | /// Sleep the current thread |
| 326 | static void SleepThread(s64 nanoseconds) { | 334 | static void SleepThread(s64 nanoseconds) { |
| 327 | DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds); | 335 | DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds); |
| 336 | |||
| 337 | // Check for next thread to schedule | ||
| 338 | HLE::Reschedule(__func__); | ||
| 328 | } | 339 | } |
| 329 | 340 | ||
| 330 | /// This returns the total CPU ticks elapsed since the CPU was powered-on | 341 | /// This returns the total CPU ticks elapsed since the CPU was powered-on |
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 3ad801c63..af5e1b39b 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -49,7 +49,7 @@ inline void Write(u32 addr, const T data) { | |||
| 49 | 49 | ||
| 50 | // Writes other than u32 are untested, so I'd rather have them abort than silently fail | 50 | // Writes other than u32 are untested, so I'd rather have them abort than silently fail |
| 51 | if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { | 51 | if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { |
| 52 | ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); | 52 | ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); |
| 53 | return; | 53 | return; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| @@ -140,8 +140,8 @@ inline void Write(u32 addr, const T data) { | |||
| 140 | 140 | ||
| 141 | DEBUG_LOG(GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x", | 141 | DEBUG_LOG(GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x", |
| 142 | config.output_height * config.output_width * 4, | 142 | config.output_height * config.output_width * 4, |
| 143 | config.GetPhysicalInputAddress(), config.input_width, config.input_height, | 143 | config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height, |
| 144 | config.GetPhysicalOutputAddress(), config.output_width, config.output_height, | 144 | config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height, |
| 145 | config.output_format.Value()); | 145 | config.output_format.Value()); |
| 146 | } | 146 | } |
| 147 | break; | 147 | break; |
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp index 4d0719263..ea001673a 100644 --- a/src/core/hw/hw.cpp +++ b/src/core/hw/hw.cpp | |||
| @@ -68,7 +68,7 @@ inline void Write(u32 addr, const T data) { | |||
| 68 | break; | 68 | break; |
| 69 | 69 | ||
| 70 | default: | 70 | default: |
| 71 | ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); | 71 | ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); |
| 72 | } | 72 | } |
| 73 | } | 73 | } |
| 74 | 74 | ||
diff --git a/src/core/hw/ndma.cpp b/src/core/hw/ndma.cpp index e29a773f1..593e5de30 100644 --- a/src/core/hw/ndma.cpp +++ b/src/core/hw/ndma.cpp | |||
| @@ -15,7 +15,7 @@ inline void Read(T &var, const u32 addr) { | |||
| 15 | 15 | ||
| 16 | template <typename T> | 16 | template <typename T> |
| 17 | inline void Write(u32 addr, const T data) { | 17 | inline void Write(u32 addr, const T data) { |
| 18 | ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); | 18 | ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | // Explicitly instantiate template functions because we aren't defining this in the header: | 21 | // Explicitly instantiate template functions because we aren't defining this in the header: |
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp index 443d5ad7e..e8747840c 100644 --- a/src/core/mem_map_funcs.cpp +++ b/src/core/mem_map_funcs.cpp | |||
| @@ -92,7 +92,7 @@ inline void Read(T &var, const VAddr vaddr) { | |||
| 92 | var = *((const T*)&g_vram[vaddr & VRAM_MASK]); | 92 | var = *((const T*)&g_vram[vaddr & VRAM_MASK]); |
| 93 | 93 | ||
| 94 | } else { | 94 | } else { |
| 95 | ERROR_LOG(MEMMAP, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr); | 95 | ERROR_LOG(MEMMAP, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, vaddr); |
| 96 | } | 96 | } |
| 97 | } | 97 | } |
| 98 | 98 | ||
| @@ -141,7 +141,7 @@ inline void Write(const VAddr vaddr, const T data) { | |||
| 141 | 141 | ||
| 142 | // Error out... | 142 | // Error out... |
| 143 | } else { | 143 | } else { |
| 144 | ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr); | 144 | ERROR_LOG(MEMMAP, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, vaddr); |
| 145 | } | 145 | } |
| 146 | } | 146 | } |
| 147 | 147 | ||
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index abbb4c2cb..fd44c3f68 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -240,14 +240,14 @@ MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() { | |||
| 240 | MathUtil::Rectangle<unsigned> viewport_extent; | 240 | MathUtil::Rectangle<unsigned> viewport_extent; |
| 241 | if (window_aspect_ratio > emulation_aspect_ratio) { | 241 | if (window_aspect_ratio > emulation_aspect_ratio) { |
| 242 | // Window is narrower than the emulation content => apply borders to the top and bottom | 242 | // Window is narrower than the emulation content => apply borders to the top and bottom |
| 243 | unsigned viewport_height = emulation_aspect_ratio * framebuffer_width; | 243 | unsigned viewport_height = std::round(emulation_aspect_ratio * framebuffer_width); |
| 244 | viewport_extent.left = 0; | 244 | viewport_extent.left = 0; |
| 245 | viewport_extent.top = (framebuffer_height - viewport_height) / 2; | 245 | viewport_extent.top = (framebuffer_height - viewport_height) / 2; |
| 246 | viewport_extent.right = viewport_extent.left + framebuffer_width; | 246 | viewport_extent.right = viewport_extent.left + framebuffer_width; |
| 247 | viewport_extent.bottom = viewport_extent.top + viewport_height; | 247 | viewport_extent.bottom = viewport_extent.top + viewport_height; |
| 248 | } else { | 248 | } else { |
| 249 | // Otherwise, apply borders to the left and right sides of the window. | 249 | // Otherwise, apply borders to the left and right sides of the window. |
| 250 | unsigned viewport_width = framebuffer_height / emulation_aspect_ratio; | 250 | unsigned viewport_width = std::round(framebuffer_height / emulation_aspect_ratio); |
| 251 | viewport_extent.left = (framebuffer_width - viewport_width) / 2; | 251 | viewport_extent.left = (framebuffer_width - viewport_width) / 2; |
| 252 | viewport_extent.top = 0; | 252 | viewport_extent.top = 0; |
| 253 | viewport_extent.right = viewport_extent.left + viewport_width; | 253 | viewport_extent.right = viewport_extent.left + viewport_width; |