diff options
Diffstat (limited to 'src')
138 files changed, 2434 insertions, 1242 deletions
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index 41b62ac16..f2aeb510e 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp | |||
| @@ -23,7 +23,7 @@ int __cdecl main(int argc, char **argv) { | |||
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | Config config; | 25 | Config config; |
| 26 | 26 | ||
| 27 | if (!Settings::values.enable_log) | 27 | if (!Settings::values.enable_log) |
| 28 | LogManager::Shutdown(); | 28 | LogManager::Shutdown(); |
| 29 | 29 | ||
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp index 0c774bbc5..697bf4693 100644 --- a/src/citra/emu_window/emu_window_glfw.cpp +++ b/src/citra/emu_window/emu_window_glfw.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <GLFW/glfw3.h> | ||
| 6 | |||
| 5 | #include "common/common.h" | 7 | #include "common/common.h" |
| 6 | 8 | ||
| 7 | #include "video_core/video_core.h" | 9 | #include "video_core/video_core.h" |
| @@ -10,22 +12,21 @@ | |||
| 10 | 12 | ||
| 11 | #include "citra/emu_window/emu_window_glfw.h" | 13 | #include "citra/emu_window/emu_window_glfw.h" |
| 12 | 14 | ||
| 15 | EmuWindow_GLFW* EmuWindow_GLFW::GetEmuWindow(GLFWwindow* win) { | ||
| 16 | return static_cast<EmuWindow_GLFW*>(glfwGetWindowUserPointer(win)); | ||
| 17 | } | ||
| 18 | |||
| 13 | /// Called by GLFW when a key event occurs | 19 | /// Called by GLFW when a key event occurs |
| 14 | void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) { | 20 | void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) { |
| 15 | 21 | ||
| 16 | if (!VideoCore::g_emu_window) { | 22 | int keyboard_id = GetEmuWindow(win)->keyboard_id; |
| 17 | return; | ||
| 18 | } | ||
| 19 | |||
| 20 | int keyboard_id = ((EmuWindow_GLFW*)VideoCore::g_emu_window)->keyboard_id; | ||
| 21 | 23 | ||
| 22 | if (action == GLFW_PRESS) { | 24 | if (action == GLFW_PRESS) { |
| 23 | EmuWindow::KeyPressed({key, keyboard_id}); | 25 | EmuWindow::KeyPressed({key, keyboard_id}); |
| 24 | } | 26 | } else if (action == GLFW_RELEASE) { |
| 25 | |||
| 26 | if (action == GLFW_RELEASE) { | ||
| 27 | EmuWindow::KeyReleased({key, keyboard_id}); | 27 | EmuWindow::KeyReleased({key, keyboard_id}); |
| 28 | } | 28 | } |
| 29 | |||
| 29 | HID_User::PadUpdateComplete(); | 30 | HID_User::PadUpdateComplete(); |
| 30 | } | 31 | } |
| 31 | 32 | ||
| @@ -34,15 +35,36 @@ const bool EmuWindow_GLFW::IsOpen() { | |||
| 34 | return glfwWindowShouldClose(m_render_window) == 0; | 35 | return glfwWindowShouldClose(m_render_window) == 0; |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 38 | void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) { | ||
| 39 | _dbg_assert_(GUI, width > 0); | ||
| 40 | _dbg_assert_(GUI, height > 0); | ||
| 41 | |||
| 42 | GetEmuWindow(win)->NotifyFramebufferSizeChanged(std::pair<unsigned,unsigned>(width, height)); | ||
| 43 | } | ||
| 44 | |||
| 45 | void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) { | ||
| 46 | _dbg_assert_(GUI, width > 0); | ||
| 47 | _dbg_assert_(GUI, height > 0); | ||
| 48 | |||
| 49 | // NOTE: GLFW provides no proper way to set a minimal window size. | ||
| 50 | // Hence, we just ignore the corresponding EmuWindow hint. | ||
| 51 | |||
| 52 | GetEmuWindow(win)->NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(width, height)); | ||
| 53 | } | ||
| 54 | |||
| 37 | /// EmuWindow_GLFW constructor | 55 | /// EmuWindow_GLFW constructor |
| 38 | EmuWindow_GLFW::EmuWindow_GLFW() { | 56 | EmuWindow_GLFW::EmuWindow_GLFW() { |
| 39 | keyboard_id = KeyMap::NewDeviceId(); | 57 | keyboard_id = KeyMap::NewDeviceId(); |
| 40 | 58 | ||
| 41 | ReloadSetKeymaps(); | 59 | ReloadSetKeymaps(); |
| 42 | 60 | ||
| 61 | glfwSetErrorCallback([](int error, const char *desc){ | ||
| 62 | ERROR_LOG(GUI, "GLFW 0x%08x: %s", error, desc); | ||
| 63 | }); | ||
| 64 | |||
| 43 | // Initialize the window | 65 | // Initialize the window |
| 44 | if(glfwInit() != GL_TRUE) { | 66 | if(glfwInit() != GL_TRUE) { |
| 45 | printf("Failed to initialize GLFW! Exiting..."); | 67 | ERROR_LOG(GUI, "Failed to initialize GLFW! Exiting..."); |
| 46 | exit(1); | 68 | exit(1); |
| 47 | } | 69 | } |
| 48 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | 70 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); |
| @@ -50,19 +72,31 @@ EmuWindow_GLFW::EmuWindow_GLFW() { | |||
| 50 | // GLFW on OSX requires these window hints to be set to create a 3.2+ GL context. | 72 | // GLFW on OSX requires these window hints to be set to create a 3.2+ GL context. |
| 51 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); | 73 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); |
| 52 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | 74 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); |
| 53 | 75 | ||
| 54 | m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth, | 76 | std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); |
| 55 | (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight), | 77 | m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth, |
| 56 | m_window_title.c_str(), NULL, NULL); | 78 | (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight), |
| 79 | window_title.c_str(), NULL, NULL); | ||
| 57 | 80 | ||
| 58 | if (m_render_window == NULL) { | 81 | if (m_render_window == NULL) { |
| 59 | printf("Failed to create GLFW window! Exiting..."); | 82 | ERROR_LOG(GUI, "Failed to create GLFW window! Exiting..."); |
| 60 | exit(1); | 83 | exit(1); |
| 61 | } | 84 | } |
| 62 | 85 | ||
| 63 | // Setup callbacks | ||
| 64 | glfwSetWindowUserPointer(m_render_window, this); | 86 | glfwSetWindowUserPointer(m_render_window, this); |
| 87 | |||
| 88 | // Notify base interface about window state | ||
| 89 | int width, height; | ||
| 90 | glfwGetFramebufferSize(m_render_window, &width, &height); | ||
| 91 | OnFramebufferResizeEvent(m_render_window, width, height); | ||
| 92 | |||
| 93 | glfwGetWindowSize(m_render_window, &width, &height); | ||
| 94 | OnClientAreaResizeEvent(m_render_window, width, height); | ||
| 95 | |||
| 96 | // Setup callbacks | ||
| 65 | glfwSetKeyCallback(m_render_window, OnKeyEvent); | 97 | glfwSetKeyCallback(m_render_window, OnKeyEvent); |
| 98 | glfwSetFramebufferSizeCallback(m_render_window, OnFramebufferResizeEvent); | ||
| 99 | glfwSetWindowSizeCallback(m_render_window, OnClientAreaResizeEvent); | ||
| 66 | 100 | ||
| 67 | DoneCurrent(); | 101 | DoneCurrent(); |
| 68 | } | 102 | } |
| @@ -110,3 +144,15 @@ void EmuWindow_GLFW::ReloadSetKeymaps() { | |||
| 110 | KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, HID_User::PAD_CIRCLE_UP); | 144 | KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, HID_User::PAD_CIRCLE_UP); |
| 111 | KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, HID_User::PAD_CIRCLE_DOWN); | 145 | KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, HID_User::PAD_CIRCLE_DOWN); |
| 112 | } | 146 | } |
| 147 | |||
| 148 | void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { | ||
| 149 | std::pair<int,int> current_size; | ||
| 150 | glfwGetWindowSize(m_render_window, ¤t_size.first, ¤t_size.second); | ||
| 151 | |||
| 152 | _dbg_assert_(GUI, (int)minimal_size.first > 0 && (int)minimal_size.second > 0); | ||
| 153 | int new_width = std::max(current_size.first, (int)minimal_size.first); | ||
| 154 | int new_height = std::max(current_size.second, (int)minimal_size.second); | ||
| 155 | |||
| 156 | if (current_size != std::make_pair(new_width, new_height)) | ||
| 157 | glfwSetWindowSize(m_render_window, new_width, new_height); | ||
| 158 | } | ||
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h index 7c3072145..5b04e87bb 100644 --- a/src/citra/emu_window/emu_window_glfw.h +++ b/src/citra/emu_window/emu_window_glfw.h | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <GLFW/glfw3.h> | ||
| 8 | |||
| 9 | #include "common/emu_window.h" | 7 | #include "common/emu_window.h" |
| 10 | 8 | ||
| 9 | struct GLFWwindow; | ||
| 10 | |||
| 11 | class EmuWindow_GLFW : public EmuWindow { | 11 | class EmuWindow_GLFW : public EmuWindow { |
| 12 | public: | 12 | public: |
| 13 | EmuWindow_GLFW(); | 13 | EmuWindow_GLFW(); |
| @@ -16,12 +16,12 @@ public: | |||
| 16 | /// Swap buffers to display the next frame | 16 | /// Swap buffers to display the next frame |
| 17 | void SwapBuffers() override; | 17 | void SwapBuffers() override; |
| 18 | 18 | ||
| 19 | /// Polls window events | 19 | /// Polls window events |
| 20 | void PollEvents() override; | 20 | void PollEvents() override; |
| 21 | 21 | ||
| 22 | /// Makes the graphics context current for the caller thread | 22 | /// Makes the graphics context current for the caller thread |
| 23 | void MakeCurrent() override; | 23 | void MakeCurrent() override; |
| 24 | 24 | ||
| 25 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread | 25 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread |
| 26 | void DoneCurrent() override; | 26 | void DoneCurrent() override; |
| 27 | 27 | ||
| @@ -30,9 +30,17 @@ public: | |||
| 30 | /// Whether the window is still open, and a close request hasn't yet been sent | 30 | /// Whether the window is still open, and a close request hasn't yet been sent |
| 31 | const bool IsOpen(); | 31 | const bool IsOpen(); |
| 32 | 32 | ||
| 33 | static void OnClientAreaResizeEvent(GLFWwindow* win, int width, int height); | ||
| 34 | |||
| 35 | static void OnFramebufferResizeEvent(GLFWwindow* win, int width, int height); | ||
| 36 | |||
| 33 | void ReloadSetKeymaps() override; | 37 | void ReloadSetKeymaps() override; |
| 34 | 38 | ||
| 35 | private: | 39 | private: |
| 40 | void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override; | ||
| 41 | |||
| 42 | static EmuWindow_GLFW* GetEmuWindow(GLFWwindow* win); | ||
| 43 | |||
| 36 | GLFWwindow* m_render_window; ///< Internal GLFW render window | 44 | GLFWwindow* m_render_window; ///< Internal GLFW render window |
| 37 | 45 | ||
| 38 | /// Device id of keyboard for use with KeyMap | 46 | /// Device id of keyboard for use with KeyMap |
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 20824692d..9bf079919 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp | |||
| @@ -2,6 +2,12 @@ | |||
| 2 | #include <QKeyEvent> | 2 | #include <QKeyEvent> |
| 3 | #include <QApplication> | 3 | #include <QApplication> |
| 4 | 4 | ||
| 5 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||
| 6 | // Required for screen DPI information | ||
| 7 | #include <QScreen> | ||
| 8 | #include <QWindow> | ||
| 9 | #endif | ||
| 10 | |||
| 5 | #include "common/common.h" | 11 | #include "common/common.h" |
| 6 | #include "bootmanager.hxx" | 12 | #include "bootmanager.hxx" |
| 7 | 13 | ||
| @@ -17,7 +23,7 @@ | |||
| 17 | #define APP_TITLE APP_NAME " " APP_VERSION | 23 | #define APP_TITLE APP_NAME " " APP_VERSION |
| 18 | #define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" | 24 | #define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" |
| 19 | 25 | ||
| 20 | EmuThread::EmuThread(GRenderWindow* render_window) : | 26 | EmuThread::EmuThread(GRenderWindow* render_window) : |
| 21 | filename(""), exec_cpu_step(false), cpu_running(false), | 27 | filename(""), exec_cpu_step(false), cpu_running(false), |
| 22 | stop_run(false), render_window(render_window) | 28 | stop_run(false), render_window(render_window) |
| 23 | { | 29 | { |
| @@ -36,7 +42,7 @@ void EmuThread::run() | |||
| 36 | if (cpu_running) | 42 | if (cpu_running) |
| 37 | { | 43 | { |
| 38 | Core::RunLoop(); | 44 | Core::RunLoop(); |
| 39 | } | 45 | } |
| 40 | else if (exec_cpu_step) | 46 | else if (exec_cpu_step) |
| 41 | { | 47 | { |
| 42 | exec_cpu_step = false; | 48 | exec_cpu_step = false; |
| @@ -82,20 +88,20 @@ void EmuThread::Stop() | |||
| 82 | class GGLWidgetInternal : public QGLWidget | 88 | class GGLWidgetInternal : public QGLWidget |
| 83 | { | 89 | { |
| 84 | public: | 90 | public: |
| 85 | GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) : QGLWidget(fmt, parent) | 91 | GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) |
| 86 | { | 92 | : QGLWidget(fmt, parent), parent(parent) { |
| 87 | parent_ = parent; | ||
| 88 | } | 93 | } |
| 89 | 94 | ||
| 90 | void paintEvent(QPaintEvent* ev) override | 95 | void paintEvent(QPaintEvent* ev) override { |
| 91 | { | ||
| 92 | } | 96 | } |
| 97 | |||
| 93 | void resizeEvent(QResizeEvent* ev) override { | 98 | void resizeEvent(QResizeEvent* ev) override { |
| 94 | parent_->SetClientAreaWidth(size().width()); | 99 | parent->OnClientAreaResized(ev->size().width(), ev->size().height()); |
| 95 | parent_->SetClientAreaHeight(size().height()); | 100 | parent->OnFramebufferSizeChanged(); |
| 96 | } | 101 | } |
| 102 | |||
| 97 | private: | 103 | private: |
| 98 | GRenderWindow* parent_; | 104 | GRenderWindow* parent; |
| 99 | }; | 105 | }; |
| 100 | 106 | ||
| 101 | EmuThread& GRenderWindow::GetEmuThread() | 107 | EmuThread& GRenderWindow::GetEmuThread() |
| @@ -105,6 +111,9 @@ EmuThread& GRenderWindow::GetEmuThread() | |||
| 105 | 111 | ||
| 106 | GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this), keyboard_id(0) | 112 | GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this), keyboard_id(0) |
| 107 | { | 113 | { |
| 114 | std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||
| 115 | setWindowTitle(QString::fromStdString(window_title)); | ||
| 116 | |||
| 108 | keyboard_id = KeyMap::NewDeviceId(); | 117 | keyboard_id = KeyMap::NewDeviceId(); |
| 109 | ReloadSetKeymaps(); | 118 | ReloadSetKeymaps(); |
| 110 | 119 | ||
| @@ -114,16 +123,25 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this | |||
| 114 | fmt.setProfile(QGLFormat::CoreProfile); | 123 | fmt.setProfile(QGLFormat::CoreProfile); |
| 115 | // Requests a forward-compatible context, which is required to get a 3.2+ context on OS X | 124 | // Requests a forward-compatible context, which is required to get a 3.2+ context on OS X |
| 116 | fmt.setOption(QGL::NoDeprecatedFunctions); | 125 | fmt.setOption(QGL::NoDeprecatedFunctions); |
| 117 | 126 | ||
| 118 | child = new GGLWidgetInternal(fmt, this); | 127 | child = new GGLWidgetInternal(fmt, this); |
| 119 | QBoxLayout* layout = new QHBoxLayout(this); | 128 | QBoxLayout* layout = new QHBoxLayout(this); |
| 120 | resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); | 129 | resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); |
| 121 | layout->addWidget(child); | 130 | layout->addWidget(child); |
| 122 | layout->setMargin(0); | 131 | layout->setMargin(0); |
| 123 | setLayout(layout); | 132 | setLayout(layout); |
| 124 | QObject::connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext())); | 133 | connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext())); |
| 134 | |||
| 135 | OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); | ||
| 136 | |||
| 137 | OnFramebufferSizeChanged(); | ||
| 138 | NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(child->width(), child->height())); | ||
| 125 | 139 | ||
| 126 | BackupGeometry(); | 140 | BackupGeometry(); |
| 141 | |||
| 142 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||
| 143 | connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, SLOT(OnFramebufferSizeChanged())); | ||
| 144 | #endif | ||
| 127 | } | 145 | } |
| 128 | 146 | ||
| 129 | void GRenderWindow::moveContext() | 147 | void GRenderWindow::moveContext() |
| @@ -166,14 +184,28 @@ void GRenderWindow::DoneCurrent() | |||
| 166 | } | 184 | } |
| 167 | 185 | ||
| 168 | void GRenderWindow::PollEvents() { | 186 | void GRenderWindow::PollEvents() { |
| 169 | // TODO(ShizZy): Does this belong here? This is a reasonable place to update the window title | 187 | } |
| 170 | // from the main thread, but this should probably be in an event handler... | 188 | |
| 171 | /* | 189 | // On Qt 5.0+, this correctly gets the size of the framebuffer (pixels). |
| 172 | static char title[128]; | 190 | // |
| 173 | sprintf(title, "%s (FPS: %02.02f)", window_title_.c_str(), | 191 | // Older versions get the window size (density independent pixels), |
| 174 | video_core::g_renderer->current_fps()); | 192 | // and hence, do not support DPI scaling ("retina" displays). |
| 175 | setWindowTitle(title); | 193 | // The result will be a viewport that is smaller than the extent of the window. |
| 176 | */ | 194 | void GRenderWindow::OnFramebufferSizeChanged() |
| 195 | { | ||
| 196 | // Screen changes potentially incur a change in screen DPI, hence we should update the framebuffer size | ||
| 197 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||
| 198 | // windowHandle() might not be accessible until the window is displayed to screen. | ||
| 199 | auto pixel_ratio = windowHandle() ? (windowHandle()->screen()->devicePixelRatio()) : 1.0; | ||
| 200 | |||
| 201 | unsigned width = child->QPaintDevice::width() * pixel_ratio; | ||
| 202 | unsigned height = child->QPaintDevice::height() * pixel_ratio; | ||
| 203 | #else | ||
| 204 | unsigned width = child->QPaintDevice::width(); | ||
| 205 | unsigned height = child->QPaintDevice::height(); | ||
| 206 | #endif | ||
| 207 | |||
| 208 | NotifyFramebufferSizeChanged(std::make_pair(width, height)); | ||
| 177 | } | 209 | } |
| 178 | 210 | ||
| 179 | void GRenderWindow::BackupGeometry() | 211 | void GRenderWindow::BackupGeometry() |
| @@ -236,3 +268,11 @@ void GRenderWindow::ReloadSetKeymaps() | |||
| 236 | KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, HID_User::PAD_CIRCLE_DOWN); | 268 | KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, HID_User::PAD_CIRCLE_DOWN); |
| 237 | } | 269 | } |
| 238 | 270 | ||
| 271 | void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) | ||
| 272 | { | ||
| 273 | NotifyClientAreaSizeChanged(std::make_pair(width, height)); | ||
| 274 | } | ||
| 275 | |||
| 276 | void GRenderWindow::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { | ||
| 277 | setMinimumSize(minimal_size.first, minimal_size.second); | ||
| 278 | } | ||
diff --git a/src/citra_qt/bootmanager.hxx b/src/citra_qt/bootmanager.hxx index f8afc403e..5f69f15ea 100644 --- a/src/citra_qt/bootmanager.hxx +++ b/src/citra_qt/bootmanager.hxx | |||
| @@ -1,12 +1,16 @@ | |||
| 1 | #include <atomic> | ||
| 2 | |||
| 1 | #include <QThread> | 3 | #include <QThread> |
| 2 | #include <QGLWidget> | 4 | #include <QGLWidget> |
| 3 | #include <atomic> | 5 | |
| 4 | #include "common/common.h" | 6 | #include "common/common.h" |
| 5 | #include "common/emu_window.h" | 7 | #include "common/emu_window.h" |
| 6 | 8 | ||
| 7 | class GRenderWindow; | 9 | class QScreen; |
| 8 | class QKeyEvent; | 10 | class QKeyEvent; |
| 9 | 11 | ||
| 12 | class GRenderWindow; | ||
| 13 | |||
| 10 | class EmuThread : public QThread | 14 | class EmuThread : public QThread |
| 11 | { | 15 | { |
| 12 | Q_OBJECT | 16 | Q_OBJECT |
| @@ -14,7 +18,7 @@ class EmuThread : public QThread | |||
| 14 | public: | 18 | public: |
| 15 | /** | 19 | /** |
| 16 | * Set image filename | 20 | * Set image filename |
| 17 | * | 21 | * |
| 18 | * @param filename | 22 | * @param filename |
| 19 | * @warning Only call when not running! | 23 | * @warning Only call when not running! |
| 20 | */ | 24 | */ |
| @@ -74,7 +78,7 @@ private: | |||
| 74 | signals: | 78 | signals: |
| 75 | /** | 79 | /** |
| 76 | * Emitted when CPU when we've finished processing a single Gekko instruction | 80 | * Emitted when CPU when we've finished processing a single Gekko instruction |
| 77 | * | 81 | * |
| 78 | * @warning This will only be emitted when the CPU is not running (SetCpuRunning(false)) | 82 | * @warning This will only be emitted when the CPU is not running (SetCpuRunning(false)) |
| 79 | * @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns) | 83 | * @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns) |
| 80 | */ | 84 | */ |
| @@ -100,7 +104,7 @@ public: | |||
| 100 | void BackupGeometry(); | 104 | void BackupGeometry(); |
| 101 | void RestoreGeometry(); | 105 | void RestoreGeometry(); |
| 102 | void restoreGeometry(const QByteArray& geometry); // overridden | 106 | void restoreGeometry(const QByteArray& geometry); // overridden |
| 103 | QByteArray saveGeometry(); // overridden | 107 | QByteArray saveGeometry(); // overridden |
| 104 | 108 | ||
| 105 | EmuThread& GetEmuThread(); | 109 | EmuThread& GetEmuThread(); |
| 106 | 110 | ||
| @@ -109,10 +113,16 @@ public: | |||
| 109 | 113 | ||
| 110 | void ReloadSetKeymaps() override; | 114 | void ReloadSetKeymaps() override; |
| 111 | 115 | ||
| 116 | void OnClientAreaResized(unsigned width, unsigned height); | ||
| 117 | |||
| 118 | void OnFramebufferSizeChanged(); | ||
| 119 | |||
| 112 | public slots: | 120 | public slots: |
| 113 | void moveContext(); | 121 | void moveContext(); // overridden |
| 114 | 122 | ||
| 115 | private: | 123 | private: |
| 124 | void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override; | ||
| 125 | |||
| 116 | QGLWidget* child; | 126 | QGLWidget* child; |
| 117 | 127 | ||
| 118 | EmuThread emu_thread; | 128 | EmuThread emu_thread; |
diff --git a/src/citra_qt/config/controller_config_util.cpp b/src/citra_qt/config/controller_config_util.cpp index c5426570b..aee3f8616 100644 --- a/src/citra_qt/config/controller_config_util.cpp +++ b/src/citra_qt/config/controller_config_util.cpp | |||
| @@ -48,7 +48,7 @@ void GKeyConfigButton::OnActivePortChanged(const common::Config::ControllerPort& | |||
| 48 | else if (config.keys.key_code[id] == Qt::Key_Control) text = tr("Control"); | 48 | else if (config.keys.key_code[id] == Qt::Key_Control) text = tr("Control"); |
| 49 | else if (config.keys.key_code[id] == Qt::Key_Alt) text = tr("Alt"); | 49 | else if (config.keys.key_code[id] == Qt::Key_Alt) text = tr("Alt"); |
| 50 | else if (config.keys.key_code[id] == Qt::Key_Meta) text = tr("Meta"); | 50 | else if (config.keys.key_code[id] == Qt::Key_Meta) text = tr("Meta"); |
| 51 | setText(text); | 51 | setText(text); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | void GKeyConfigButton::OnClicked() | 54 | void GKeyConfigButton::OnClicked() |
| @@ -118,4 +118,4 @@ GButtonConfigGroup::GButtonConfigGroup(const QString& name, common::Config::Cont | |||
| 118 | setLayout(layout); | 118 | setLayout(layout); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | */ \ No newline at end of file | 121 | */ |
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 77fb0c9ed..895851be3 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp | |||
| @@ -28,7 +28,7 @@ void CallstackWidget::OnCPUStepped() | |||
| 28 | 28 | ||
| 29 | u32 sp = app_core->GetReg(13); //stack pointer | 29 | u32 sp = app_core->GetReg(13); //stack pointer |
| 30 | u32 addr, ret_addr, call_addr, func_addr; | 30 | u32 addr, ret_addr, call_addr, func_addr; |
| 31 | 31 | ||
| 32 | int counter = 0; | 32 | int counter = 0; |
| 33 | for (int addr = 0x10000000; addr >= sp; addr -= 4) | 33 | for (int addr = 0x10000000; addr >= sp; addr -= 4) |
| 34 | { | 34 | { |
| @@ -55,7 +55,7 @@ void CallstackWidget::OnCPUStepped() | |||
| 55 | callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); | 55 | callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); |
| 56 | callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0')))); | 56 | callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0')))); |
| 57 | callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(call_addr, 8, 16, QLatin1Char('0')))); | 57 | callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(call_addr, 8, 16, QLatin1Char('0')))); |
| 58 | 58 | ||
| 59 | name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown"; | 59 | name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown"; |
| 60 | callstack_model->setItem(counter, 3, new QStandardItem(QString("%1_%2").arg(QString::fromStdString(name)) | 60 | callstack_model->setItem(counter, 3, new QStandardItem(QString("%1_%2").arg(QString::fromStdString(name)) |
| 61 | .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0'))))); | 61 | .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0'))))); |
| @@ -63,4 +63,4 @@ void CallstackWidget::OnCPUStepped() | |||
| 63 | counter++; | 63 | counter++; |
| 64 | } | 64 | } |
| 65 | } | 65 | } |
| 66 | } \ No newline at end of file | 66 | } |
diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp index 96ceed480..ed17ee4b4 100644 --- a/src/citra_qt/debugger/registers.cpp +++ b/src/citra_qt/debugger/registers.cpp | |||
| @@ -46,18 +46,18 @@ void RegistersWidget::OnCPUStepped() | |||
| 46 | 46 | ||
| 47 | CSPR->setText(1, QString("0x%1").arg(app_core->GetCPSR(), 8, 16, QLatin1Char('0'))); | 47 | CSPR->setText(1, QString("0x%1").arg(app_core->GetCPSR(), 8, 16, QLatin1Char('0'))); |
| 48 | CSPR->child(0)->setText(1, QString("b%1").arg(app_core->GetCPSR() & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode | 48 | CSPR->child(0)->setText(1, QString("b%1").arg(app_core->GetCPSR() & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode |
| 49 | CSPR->child(1)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 5) & 0x1)); // T - State | 49 | CSPR->child(1)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 5) & 0x1)); // T - State |
| 50 | CSPR->child(2)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 6) & 0x1)); // F - FIQ disable | 50 | CSPR->child(2)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 6) & 0x1)); // F - FIQ disable |
| 51 | CSPR->child(3)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 7) & 0x1)); // I - IRQ disable | 51 | CSPR->child(3)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 7) & 0x1)); // I - IRQ disable |
| 52 | CSPR->child(4)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 8) & 0x1)); // A - Imprecise abort | 52 | CSPR->child(4)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 8) & 0x1)); // A - Imprecise abort |
| 53 | CSPR->child(5)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 9) & 0x1)); // E - Data endianess | 53 | CSPR->child(5)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 9) & 0x1)); // E - Data endianess |
| 54 | CSPR->child(6)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 10) & 0x3F)); // IT - If-Then state (DNM) | 54 | CSPR->child(6)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 10) & 0x3F)); // IT - If-Then state (DNM) |
| 55 | CSPR->child(7)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 16) & 0xF)); // GE - Greater-than-or-Equal | 55 | CSPR->child(7)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 16) & 0xF)); // GE - Greater-than-or-Equal |
| 56 | CSPR->child(8)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 20) & 0xF)); // DNM - Do not modify | 56 | CSPR->child(8)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 20) & 0xF)); // DNM - Do not modify |
| 57 | CSPR->child(9)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 24) & 0x1)); // J - Java state | 57 | CSPR->child(9)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 24) & 0x1)); // J - Java state |
| 58 | CSPR->child(10)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 27) & 0x1)); // Q - Sticky overflow | 58 | CSPR->child(10)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 27) & 0x1)); // Q - Sticky overflow |
| 59 | CSPR->child(11)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 28) & 0x1)); // V - Overflow | 59 | CSPR->child(11)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 28) & 0x1)); // V - Overflow |
| 60 | CSPR->child(12)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 29) & 0x1)); // C - Carry/Borrow/Extend | 60 | CSPR->child(12)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 29) & 0x1)); // C - Carry/Borrow/Extend |
| 61 | CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero | 61 | CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero |
| 62 | CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than | 62 | CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than |
| 63 | } | 63 | } |
diff --git a/src/citra_qt/debugger/registers.hxx b/src/citra_qt/debugger/registers.hxx index 9645feb2a..4cca957ce 100644 --- a/src/citra_qt/debugger/registers.hxx +++ b/src/citra_qt/debugger/registers.hxx | |||
| @@ -16,10 +16,10 @@ public slots: | |||
| 16 | void OnCPUStepped(); | 16 | void OnCPUStepped(); |
| 17 | 17 | ||
| 18 | private: | 18 | private: |
| 19 | Ui::ARMRegisters cpu_regs_ui; | 19 | Ui::ARMRegisters cpu_regs_ui; |
| 20 | 20 | ||
| 21 | QTreeWidget* tree; | 21 | QTreeWidget* tree; |
| 22 | 22 | ||
| 23 | QTreeWidgetItem* registers; | 23 | QTreeWidgetItem* registers; |
| 24 | QTreeWidgetItem* CSPR; | 24 | QTreeWidgetItem* CSPR; |
| 25 | }; | 25 | }; |
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 9a4e36adf..d5554d917 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp | |||
| @@ -117,7 +117,8 @@ GMainWindow::GMainWindow() | |||
| 117 | connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile())); | 117 | connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile())); |
| 118 | connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); | 118 | connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); |
| 119 | 119 | ||
| 120 | setWindowTitle(render_window->GetWindowTitle().c_str()); | 120 | std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); |
| 121 | setWindowTitle(window_title.c_str()); | ||
| 121 | 122 | ||
| 122 | show(); | 123 | show(); |
| 123 | 124 | ||
diff --git a/src/common/chunk_file.h b/src/common/chunk_file.h index dc8ac1fd9..609784076 100644 --- a/src/common/chunk_file.h +++ b/src/common/chunk_file.h | |||
| @@ -51,7 +51,7 @@ public: | |||
| 51 | PointerWrapSection(PointerWrap &p, int ver, const char *title) : p_(p), ver_(ver), title_(title) { | 51 | PointerWrapSection(PointerWrap &p, int ver, const char *title) : p_(p), ver_(ver), title_(title) { |
| 52 | } | 52 | } |
| 53 | ~PointerWrapSection(); | 53 | ~PointerWrapSection(); |
| 54 | 54 | ||
| 55 | bool operator == (const int &v) const { return ver_ == v; } | 55 | bool operator == (const int &v) const { return ver_ == v; } |
| 56 | bool operator != (const int &v) const { return ver_ != v; } | 56 | bool operator != (const int &v) const { return ver_ != v; } |
| 57 | bool operator <= (const int &v) const { return ver_ <= v; } | 57 | bool operator <= (const int &v) const { return ver_ <= v; } |
| @@ -196,7 +196,7 @@ public: | |||
| 196 | } | 196 | } |
| 197 | (*ptr) += size; | 197 | (*ptr) += size; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | template<class K, class T> | 200 | template<class K, class T> |
| 201 | void Do(std::map<K, T *> &x) | 201 | void Do(std::map<K, T *> &x) |
| 202 | { | 202 | { |
| @@ -364,7 +364,7 @@ public: | |||
| 364 | if (vec_size > 0) | 364 | if (vec_size > 0) |
| 365 | DoArray(&x[0], vec_size); | 365 | DoArray(&x[0], vec_size); |
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | // Store deques. | 368 | // Store deques. |
| 369 | template<class T> | 369 | template<class T> |
| 370 | void Do(std::deque<T *> &x) | 370 | void Do(std::deque<T *> &x) |
| @@ -481,11 +481,11 @@ public: | |||
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | // Store strings. | 483 | // Store strings. |
| 484 | void Do(std::string &x) | 484 | void Do(std::string &x) |
| 485 | { | 485 | { |
| 486 | int stringLen = (int)x.length() + 1; | 486 | int stringLen = (int)x.length() + 1; |
| 487 | Do(stringLen); | 487 | Do(stringLen); |
| 488 | 488 | ||
| 489 | switch (mode) { | 489 | switch (mode) { |
| 490 | case MODE_READ: x = (char*)*ptr; break; | 490 | case MODE_READ: x = (char*)*ptr; break; |
| 491 | case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; | 491 | case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; |
| @@ -495,7 +495,7 @@ public: | |||
| 495 | (*ptr) += stringLen; | 495 | (*ptr) += stringLen; |
| 496 | } | 496 | } |
| 497 | 497 | ||
| 498 | void Do(std::wstring &x) | 498 | void Do(std::wstring &x) |
| 499 | { | 499 | { |
| 500 | int stringLen = sizeof(wchar_t)*((int)x.length() + 1); | 500 | int stringLen = sizeof(wchar_t)*((int)x.length() + 1); |
| 501 | Do(stringLen); | 501 | Do(stringLen); |
| @@ -534,7 +534,7 @@ public: | |||
| 534 | void Do(T &x) { | 534 | void Do(T &x) { |
| 535 | DoHelper<T>::Do(this, x); | 535 | DoHelper<T>::Do(this, x); |
| 536 | } | 536 | } |
| 537 | 537 | ||
| 538 | template<class T> | 538 | template<class T> |
| 539 | void DoPOD(T &x) { | 539 | void DoPOD(T &x) { |
| 540 | DoHelper<T>::Do(this, x); | 540 | DoHelper<T>::Do(this, x); |
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index c18afe119..d84ec4c42 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -17,7 +17,7 @@ template<> struct CompileTimeAssert<true> {}; | |||
| 17 | #define b2(x) ( (x) | ( (x) >> 1) ) | 17 | #define b2(x) ( (x) | ( (x) >> 1) ) |
| 18 | #define b4(x) ( b2(x) | ( b2(x) >> 2) ) | 18 | #define b4(x) ( b2(x) | ( b2(x) >> 2) ) |
| 19 | #define b8(x) ( b4(x) | ( b4(x) >> 4) ) | 19 | #define b8(x) ( b4(x) | ( b4(x) >> 4) ) |
| 20 | #define b16(x) ( b8(x) | ( b8(x) >> 8) ) | 20 | #define b16(x) ( b8(x) | ( b8(x) >> 8) ) |
| 21 | #define b32(x) (b16(x) | (b16(x) >>16) ) | 21 | #define b32(x) (b16(x) | (b16(x) >>16) ) |
| 22 | #define ROUND_UP_POW2(x) (b32(x - 1) + 1) | 22 | #define ROUND_UP_POW2(x) (b32(x - 1) + 1) |
| 23 | 23 | ||
| @@ -79,12 +79,12 @@ inline u64 _rotr64(u64 x, unsigned int shift){ | |||
| 79 | #define unlink _unlink | 79 | #define unlink _unlink |
| 80 | #define snprintf _snprintf | 80 | #define snprintf _snprintf |
| 81 | #define vscprintf _vscprintf | 81 | #define vscprintf _vscprintf |
| 82 | 82 | ||
| 83 | // Locale Cross-Compatibility | 83 | // Locale Cross-Compatibility |
| 84 | #define locale_t _locale_t | 84 | #define locale_t _locale_t |
| 85 | #define freelocale _free_locale | 85 | #define freelocale _free_locale |
| 86 | #define newlocale(mask, locale, base) _create_locale(mask, locale) | 86 | #define newlocale(mask, locale, base) _create_locale(mask, locale) |
| 87 | 87 | ||
| 88 | #define LC_GLOBAL_LOCALE ((locale_t)-1) | 88 | #define LC_GLOBAL_LOCALE ((locale_t)-1) |
| 89 | #define LC_ALL_MASK LC_ALL | 89 | #define LC_ALL_MASK LC_ALL |
| 90 | #define LC_COLLATE_MASK LC_COLLATE | 90 | #define LC_COLLATE_MASK LC_COLLATE |
| @@ -92,7 +92,7 @@ inline u64 _rotr64(u64 x, unsigned int shift){ | |||
| 92 | #define LC_MONETARY_MASK LC_MONETARY | 92 | #define LC_MONETARY_MASK LC_MONETARY |
| 93 | #define LC_NUMERIC_MASK LC_NUMERIC | 93 | #define LC_NUMERIC_MASK LC_NUMERIC |
| 94 | #define LC_TIME_MASK LC_TIME | 94 | #define LC_TIME_MASK LC_TIME |
| 95 | 95 | ||
| 96 | inline locale_t uselocale(locale_t new_locale) | 96 | inline locale_t uselocale(locale_t new_locale) |
| 97 | { | 97 | { |
| 98 | // Retrieve the current per thread locale setting | 98 | // Retrieve the current per thread locale setting |
| @@ -168,8 +168,8 @@ inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);} | |||
| 168 | inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);} | 168 | inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);} |
| 169 | inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);} | 169 | inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);} |
| 170 | #elif _M_ARM | 170 | #elif _M_ARM |
| 171 | inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;} | 171 | inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;} |
| 172 | inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} | 172 | inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} |
| 173 | inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);} | 173 | inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);} |
| 174 | #elif __linux__ | 174 | #elif __linux__ |
| 175 | inline u16 swap16(u16 _data) {return bswap_16(_data);} | 175 | inline u16 swap16(u16 _data) {return bswap_16(_data);} |
| @@ -226,7 +226,7 @@ template <typename T> | |||
| 226 | inline T FromBigEndian(T data) | 226 | inline T FromBigEndian(T data) |
| 227 | { | 227 | { |
| 228 | //static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types"); | 228 | //static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types"); |
| 229 | 229 | ||
| 230 | swap<sizeof(data)>(reinterpret_cast<u8*>(&data)); | 230 | swap<sizeof(data)>(reinterpret_cast<u8*>(&data)); |
| 231 | return data; | 231 | return data; |
| 232 | } | 232 | } |
diff --git a/src/common/common_types.h b/src/common/common_types.h index 7ce6b2240..fcc8b9a4e 100644 --- a/src/common/common_types.h +++ b/src/common/common_types.h | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | * http://code.google.com/p/gekko-gc-emu/ | 22 | * http://code.google.com/p/gekko-gc-emu/ |
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #pragma once | 25 | #pragma once |
| 26 | 26 | ||
| 27 | #include <cmath> | 27 | #include <cmath> |
| 28 | #include <cstdint> | 28 | #include <cstdint> |
| @@ -45,8 +45,8 @@ typedef double f64; ///< 64-bit floating point | |||
| 45 | 45 | ||
| 46 | /// Union for fast 16-bit type casting | 46 | /// Union for fast 16-bit type casting |
| 47 | union t16 { | 47 | union t16 { |
| 48 | u8 _u8[2]; ///< 8-bit unsigned char(s) | 48 | u8 _u8[2]; ///< 8-bit unsigned char(s) |
| 49 | u16 _u16; ///< 16-bit unsigned shorts(s) | 49 | u16 _u16; ///< 16-bit unsigned shorts(s) |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | /// Union for fast 32-bit type casting | 52 | /// Union for fast 32-bit type casting |
diff --git a/src/common/console_listener.cpp b/src/common/console_listener.cpp index 53f20d754..d7f27c358 100644 --- a/src/common/console_listener.cpp +++ b/src/common/console_listener.cpp | |||
| @@ -86,7 +86,7 @@ bool ConsoleListener::IsOpen() | |||
| 86 | 86 | ||
| 87 | /* | 87 | /* |
| 88 | LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are | 88 | LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are |
| 89 | dependent on each other, that's the reason for the additional checks. | 89 | dependent on each other, that's the reason for the additional checks. |
| 90 | */ | 90 | */ |
| 91 | void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst) | 91 | void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst) |
| 92 | { | 92 | { |
| @@ -225,7 +225,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool | |||
| 225 | 225 | ||
| 226 | BytesWritten += cAttrWritten; | 226 | BytesWritten += cAttrWritten; |
| 227 | coordScreen = GetCoordinates(BytesWritten, LBufWidth); | 227 | coordScreen = GetCoordinates(BytesWritten, LBufWidth); |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X; | 230 | const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X; |
| 231 | COORD Coo = GetCoordinates(OldCursor, LBufWidth); | 231 | COORD Coo = GetCoordinates(OldCursor, LBufWidth); |
| @@ -296,23 +296,23 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) | |||
| 296 | } | 296 | } |
| 297 | // Clear console screen | 297 | // Clear console screen |
| 298 | void ConsoleListener::ClearScreen(bool Cursor) | 298 | void ConsoleListener::ClearScreen(bool Cursor) |
| 299 | { | 299 | { |
| 300 | #if defined(_WIN32) | 300 | #if defined(_WIN32) |
| 301 | COORD coordScreen = { 0, 0 }; | 301 | COORD coordScreen = { 0, 0 }; |
| 302 | DWORD cCharsWritten; | 302 | DWORD cCharsWritten; |
| 303 | CONSOLE_SCREEN_BUFFER_INFO csbi; | 303 | CONSOLE_SCREEN_BUFFER_INFO csbi; |
| 304 | DWORD dwConSize; | 304 | DWORD dwConSize; |
| 305 | 305 | ||
| 306 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); | 306 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
| 307 | 307 | ||
| 308 | GetConsoleScreenBufferInfo(hConsole, &csbi); | 308 | GetConsoleScreenBufferInfo(hConsole, &csbi); |
| 309 | dwConSize = csbi.dwSize.X * csbi.dwSize.Y; | 309 | dwConSize = csbi.dwSize.X * csbi.dwSize.Y; |
| 310 | // Write space to the entire console | 310 | // Write space to the entire console |
| 311 | FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten); | 311 | FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten); |
| 312 | GetConsoleScreenBufferInfo(hConsole, &csbi); | 312 | GetConsoleScreenBufferInfo(hConsole, &csbi); |
| 313 | FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten); | 313 | FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten); |
| 314 | // Reset cursor | 314 | // Reset cursor |
| 315 | if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen); | 315 | if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen); |
| 316 | #endif | 316 | #endif |
| 317 | } | 317 | } |
| 318 | 318 | ||
diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 4d09acb8b..4cb94fed1 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h | |||
| @@ -9,17 +9,33 @@ | |||
| 9 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| 10 | #include "common/key_map.h" | 10 | #include "common/key_map.h" |
| 11 | 11 | ||
| 12 | // Abstraction class used to provide an interface between emulation code and the frontend (e.g. SDL, | 12 | /** |
| 13 | // QGLWidget, GLFW, etc...) | 13 | * Abstraction class used to provide an interface between emulation code and the frontend |
| 14 | * (e.g. SDL, QGLWidget, GLFW, etc...). | ||
| 15 | * | ||
| 16 | * Design notes on the interaction between EmuWindow and the emulation core: | ||
| 17 | * - Generally, decisions on anything visible to the user should be left up to the GUI. | ||
| 18 | * For example, the emulation core should not try to dictate some window title or size. | ||
| 19 | * This stuff is not the core's business and only causes problems with regards to thread-safety | ||
| 20 | * anyway. | ||
| 21 | * - Under certain circumstances, it may be desirable for the core to politely request the GUI | ||
| 22 | * to set e.g. a minimum window size. However, the GUI should always be free to ignore any | ||
| 23 | * such hints. | ||
| 24 | * - EmuWindow may expose some of its state as read-only to the emulation core, however care | ||
| 25 | * should be taken to make sure the provided information is self-consistent. This requires | ||
| 26 | * some sort of synchronization (most of this is still a TODO). | ||
| 27 | * - DO NOT TREAT THIS CLASS AS A GUI TOOLKIT ABSTRACTION LAYER. That's not what it is. Please | ||
| 28 | * re-read the upper points again and think about it if you don't see this. | ||
| 29 | */ | ||
| 14 | class EmuWindow | 30 | class EmuWindow |
| 15 | { | 31 | { |
| 16 | |||
| 17 | public: | 32 | public: |
| 18 | /// Data structure to store an emuwindow configuration | 33 | /// Data structure to store emuwindow configuration |
| 19 | struct WindowConfig { | 34 | struct WindowConfig { |
| 20 | bool fullscreen; | 35 | bool fullscreen; |
| 21 | int res_width; | 36 | int res_width; |
| 22 | int res_height; | 37 | int res_height; |
| 38 | std::pair<unsigned,unsigned> min_client_area_size; | ||
| 23 | }; | 39 | }; |
| 24 | 40 | ||
| 25 | /// Swap buffers to display the next frame | 41 | /// Swap buffers to display the next frame |
| @@ -42,52 +58,96 @@ public: | |||
| 42 | /// Signals a key release action to the HID module | 58 | /// Signals a key release action to the HID module |
| 43 | static void KeyReleased(KeyMap::HostDeviceKey key); | 59 | static void KeyReleased(KeyMap::HostDeviceKey key); |
| 44 | 60 | ||
| 45 | WindowConfig GetConfig() const { | 61 | /** |
| 46 | return m_config; | 62 | * Returns currently active configuration. |
| 63 | * @note Accesses to the returned object need not be consistent because it may be modified in another thread | ||
| 64 | */ | ||
| 65 | const WindowConfig& GetActiveConfig() const { | ||
| 66 | return active_config; | ||
| 47 | } | 67 | } |
| 48 | 68 | ||
| 69 | /** | ||
| 70 | * Requests the internal configuration to be replaced by the specified argument at some point in the future. | ||
| 71 | * @note This method is thread-safe, because it delays configuration changes to the GUI event loop. Hence there is no guarantee on when the requested configuration will be active. | ||
| 72 | */ | ||
| 49 | void SetConfig(const WindowConfig& val) { | 73 | void SetConfig(const WindowConfig& val) { |
| 50 | m_config = val; | 74 | config = val; |
| 51 | } | ||
| 52 | |||
| 53 | int GetClientAreaWidth() const { | ||
| 54 | return m_client_area_width; | ||
| 55 | } | 75 | } |
| 56 | 76 | ||
| 57 | void SetClientAreaWidth(const int val) { | 77 | /** |
| 58 | m_client_area_width = val; | 78 | * Gets the framebuffer size in pixels. |
| 79 | * @note This method is thread-safe | ||
| 80 | */ | ||
| 81 | const std::pair<unsigned,unsigned> GetFramebufferSize() const { | ||
| 82 | return framebuffer_size; | ||
| 59 | } | 83 | } |
| 60 | 84 | ||
| 61 | int GetClientAreaHeight() const { | 85 | /** |
| 62 | return m_client_area_height; | 86 | * Gets window client area width in logical coordinates. |
| 87 | * @note For high-DPI systems, this is smaller than the framebuffer size. | ||
| 88 | * @note This method is thread-safe | ||
| 89 | */ | ||
| 90 | std::pair<unsigned,unsigned> GetClientAreaSize() const { | ||
| 91 | return std::make_pair(client_area_width, client_area_height); | ||
| 63 | } | 92 | } |
| 64 | 93 | ||
| 65 | void SetClientAreaHeight(const int val) { | 94 | protected: |
| 66 | m_client_area_height = val; | 95 | EmuWindow() |
| 96 | { | ||
| 97 | // TODO: Find a better place to set this. | ||
| 98 | config.min_client_area_size = std::make_pair(400u, 480u); | ||
| 99 | active_config = config; | ||
| 67 | } | 100 | } |
| 101 | virtual ~EmuWindow() {} | ||
| 68 | 102 | ||
| 69 | std::string GetWindowTitle() const { | 103 | /** |
| 70 | return m_window_title; | 104 | * Processes any pending configuration changes from the last SetConfig call. |
| 105 | * This method invokes OnMinimalClientAreaChangeRequest if the corresponding configuration | ||
| 106 | * field changed. | ||
| 107 | * @note Implementations will usually want to call this from the GUI thread. | ||
| 108 | * @todo Actually call this in existing implementations. | ||
| 109 | */ | ||
| 110 | void ProcessConfigurationChanges() { | ||
| 111 | // TODO: For proper thread safety, we should eventually implement a proper | ||
| 112 | // multiple-writer/single-reader queue... | ||
| 113 | |||
| 114 | if (config.min_client_area_size != active_config.min_client_area_size) { | ||
| 115 | OnMinimalClientAreaChangeRequest(config.min_client_area_size); | ||
| 116 | config.min_client_area_size = active_config.min_client_area_size; | ||
| 117 | } | ||
| 71 | } | 118 | } |
| 72 | 119 | ||
| 73 | void SetWindowTitle(std::string val) { | 120 | /** |
| 74 | m_window_title = val; | 121 | * Update internal framebuffer size with the given parameter. |
| 122 | * @note EmuWindow implementations will usually use this in window resize event handlers. | ||
| 123 | */ | ||
| 124 | void NotifyFramebufferSizeChanged(const std::pair<unsigned,unsigned>& size) { | ||
| 125 | framebuffer_size = size; | ||
| 75 | } | 126 | } |
| 76 | 127 | ||
| 77 | protected: | 128 | /** |
| 78 | EmuWindow(): | 129 | * Update internal client area size with the given parameter. |
| 79 | m_client_area_width(640), | 130 | * @note EmuWindow implementations will usually use this in window resize event handlers. |
| 80 | m_client_area_height(480), | 131 | */ |
| 81 | m_window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc)) | 132 | void NotifyClientAreaSizeChanged(const std::pair<unsigned,unsigned>& size) { |
| 82 | {} | 133 | client_area_width = size.first; |
| 83 | virtual ~EmuWindow() {} | 134 | client_area_height = size.second; |
| 135 | } | ||
| 84 | 136 | ||
| 85 | std::string m_window_title; ///< Current window title, should be used by window impl. | 137 | private: |
| 138 | /** | ||
| 139 | * Handler called when the minimal client area was requested to be changed via SetConfig. | ||
| 140 | * For the request to be honored, EmuWindow implementations will usually reimplement this function. | ||
| 141 | */ | ||
| 142 | virtual void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { | ||
| 143 | // By default, ignore this request and do nothing. | ||
| 144 | } | ||
| 86 | 145 | ||
| 87 | int m_client_area_width; ///< Current client width, should be set by window impl. | 146 | std::pair<unsigned,unsigned> framebuffer_size; |
| 88 | int m_client_area_height; ///< Current client height, should be set by window impl. | ||
| 89 | 147 | ||
| 90 | private: | 148 | unsigned client_area_width; ///< Current client width, should be set by window impl. |
| 91 | WindowConfig m_config; ///< Internal configuration | 149 | unsigned client_area_height; ///< Current client height, should be set by window impl. |
| 92 | 150 | ||
| 151 | WindowConfig config; ///< Internal configuration (changes pending for being applied in ProcessConfigurationChanges) | ||
| 152 | WindowConfig active_config; ///< Internal active configuration | ||
| 93 | }; | 153 | }; |
diff --git a/src/common/extended_trace.cpp b/src/common/extended_trace.cpp index 9cd0398ed..bf61ac1d1 100644 --- a/src/common/extended_trace.cpp +++ b/src/common/extended_trace.cpp | |||
| @@ -29,7 +29,7 @@ using namespace std; | |||
| 29 | void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut ) | 29 | void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut ) |
| 30 | { | 30 | { |
| 31 | #if defined(UNICODE)||defined(_UNICODE) | 31 | #if defined(UNICODE)||defined(_UNICODE) |
| 32 | ULONG index = 0; | 32 | ULONG index = 0; |
| 33 | PCSTR lpAct = lpszIn; | 33 | PCSTR lpAct = lpszIn; |
| 34 | 34 | ||
| 35 | for( ; ; lpAct++ ) | 35 | for( ; ; lpAct++ ) |
| @@ -37,7 +37,7 @@ void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut ) | |||
| 37 | lpszOut[index++] = (TCHAR)(*lpAct); | 37 | lpszOut[index++] = (TCHAR)(*lpAct); |
| 38 | if ( *lpAct == 0 ) | 38 | if ( *lpAct == 0 ) |
| 39 | break; | 39 | break; |
| 40 | } | 40 | } |
| 41 | #else | 41 | #else |
| 42 | // This is trivial :) | 42 | // This is trivial :) |
| 43 | strcpy( lpszOut, lpszIn ); | 43 | strcpy( lpszOut, lpszIn ); |
| @@ -101,7 +101,7 @@ BOOL InitSymInfo( PCSTR lpszInitialSymbolPath ) | |||
| 101 | CHAR lpszSymbolPath[BUFFERSIZE]; | 101 | CHAR lpszSymbolPath[BUFFERSIZE]; |
| 102 | DWORD symOptions = SymGetOptions(); | 102 | DWORD symOptions = SymGetOptions(); |
| 103 | 103 | ||
| 104 | symOptions |= SYMOPT_LOAD_LINES; | 104 | symOptions |= SYMOPT_LOAD_LINES; |
| 105 | symOptions &= ~SYMOPT_UNDNAME; | 105 | symOptions &= ~SYMOPT_UNDNAME; |
| 106 | SymSetOptions( symOptions ); | 106 | SymSetOptions( symOptions ); |
| 107 | InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath ); | 107 | InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath ); |
| @@ -153,15 +153,15 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L | |||
| 153 | #ifndef _M_X64 | 153 | #ifndef _M_X64 |
| 154 | DWORD dwDisp = 0; | 154 | DWORD dwDisp = 0; |
| 155 | if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) ) | 155 | if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) ) |
| 156 | #else | 156 | #else |
| 157 | //makes it compile but hell im not sure if this works... | 157 | //makes it compile but hell im not sure if this works... |
| 158 | DWORD64 dwDisp = 0; | 158 | DWORD64 dwDisp = 0; |
| 159 | if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) ) | 159 | if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) ) |
| 160 | #endif | 160 | #endif |
| 161 | { | 161 | { |
| 162 | // Make the symbol readable for humans | 162 | // Make the symbol readable for humans |
| 163 | UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE, | 163 | UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE, |
| 164 | UNDNAME_COMPLETE | | 164 | UNDNAME_COMPLETE | |
| 165 | UNDNAME_NO_THISTYPE | | 165 | UNDNAME_NO_THISTYPE | |
| 166 | UNDNAME_NO_SPECIAL_SYMS | | 166 | UNDNAME_NO_SPECIAL_SYMS | |
| 167 | UNDNAME_NO_MEMBER_TYPE | | 167 | UNDNAME_NO_MEMBER_TYPE | |
| @@ -219,7 +219,7 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L | |||
| 219 | _tcscat( lpszSymbol, lpszParsed ); | 219 | _tcscat( lpszSymbol, lpszParsed ); |
| 220 | 220 | ||
| 221 | ret = TRUE; | 221 | ret = TRUE; |
| 222 | } | 222 | } |
| 223 | GlobalFree( pSym ); | 223 | GlobalFree( pSym ); |
| 224 | 224 | ||
| 225 | return ret; | 225 | return ret; |
| @@ -325,14 +325,14 @@ void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file ) | |||
| 325 | 325 | ||
| 326 | PrintFunctionAndSourceInfo(file, callStack); | 326 | PrintFunctionAndSourceInfo(file, callStack); |
| 327 | 327 | ||
| 328 | for( ULONG index = 0; ; index++ ) | 328 | for( ULONG index = 0; ; index++ ) |
| 329 | { | 329 | { |
| 330 | bResult = StackWalk( | 330 | bResult = StackWalk( |
| 331 | IMAGE_FILE_MACHINE_I386, | 331 | IMAGE_FILE_MACHINE_I386, |
| 332 | hProcess, | 332 | hProcess, |
| 333 | hThread, | 333 | hThread, |
| 334 | &callStack, | 334 | &callStack, |
| 335 | NULL, | 335 | NULL, |
| 336 | NULL, | 336 | NULL, |
| 337 | SymFunctionTableAccess, | 337 | SymFunctionTableAccess, |
| 338 | SymGetModuleBase, | 338 | SymGetModuleBase, |
| @@ -341,7 +341,7 @@ void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file ) | |||
| 341 | if ( index == 0 ) | 341 | if ( index == 0 ) |
| 342 | continue; | 342 | continue; |
| 343 | 343 | ||
| 344 | if( !bResult || callStack.AddrFrame.Offset == 0 ) | 344 | if( !bResult || callStack.AddrFrame.Offset == 0 ) |
| 345 | break; | 345 | break; |
| 346 | 346 | ||
| 347 | PrintFunctionAndSourceInfo(file, callStack); | 347 | PrintFunctionAndSourceInfo(file, callStack); |
| @@ -382,14 +382,14 @@ void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, | |||
| 382 | 382 | ||
| 383 | PrintFunctionAndSourceInfo(file, callStack); | 383 | PrintFunctionAndSourceInfo(file, callStack); |
| 384 | 384 | ||
| 385 | for( ULONG index = 0; ; index++ ) | 385 | for( ULONG index = 0; ; index++ ) |
| 386 | { | 386 | { |
| 387 | bResult = StackWalk( | 387 | bResult = StackWalk( |
| 388 | IMAGE_FILE_MACHINE_I386, | 388 | IMAGE_FILE_MACHINE_I386, |
| 389 | hProcess, | 389 | hProcess, |
| 390 | hThread, | 390 | hThread, |
| 391 | &callStack, | 391 | &callStack, |
| 392 | NULL, | 392 | NULL, |
| 393 | NULL, | 393 | NULL, |
| 394 | SymFunctionTableAccess, | 394 | SymFunctionTableAccess, |
| 395 | SymGetModuleBase, | 395 | SymGetModuleBase, |
| @@ -398,7 +398,7 @@ void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, | |||
| 398 | if ( index == 0 ) | 398 | if ( index == 0 ) |
| 399 | continue; | 399 | continue; |
| 400 | 400 | ||
| 401 | if( !bResult || callStack.AddrFrame.Offset == 0 ) | 401 | if( !bResult || callStack.AddrFrame.Offset == 0 ) |
| 402 | break; | 402 | break; |
| 403 | 403 | ||
| 404 | PrintFunctionAndSourceInfo(file, callStack); | 404 | PrintFunctionAndSourceInfo(file, callStack); |
diff --git a/src/common/fifo_queue.h b/src/common/fifo_queue.h index 78a8f561d..2c18285d4 100644 --- a/src/common/fifo_queue.h +++ b/src/common/fifo_queue.h | |||
| @@ -45,7 +45,7 @@ public: | |||
| 45 | // create the element, add it to the queue | 45 | // create the element, add it to the queue |
| 46 | m_write_ptr->current = new T(std::forward<Arg>(t)); | 46 | m_write_ptr->current = new T(std::forward<Arg>(t)); |
| 47 | // set the next pointer to a new element ptr | 47 | // set the next pointer to a new element ptr |
| 48 | // then advance the write pointer | 48 | // then advance the write pointer |
| 49 | m_write_ptr = m_write_ptr->next = new ElementPtr(); | 49 | m_write_ptr = m_write_ptr->next = new ElementPtr(); |
| 50 | Common::AtomicIncrement(m_size); | 50 | Common::AtomicIncrement(m_size); |
| 51 | } | 51 | } |
diff --git a/src/common/file_search.cpp b/src/common/file_search.cpp index 63580f688..bfb54ce72 100644 --- a/src/common/file_search.cpp +++ b/src/common/file_search.cpp | |||
| @@ -43,7 +43,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string& | |||
| 43 | bool bkeepLooping = true; | 43 | bool bkeepLooping = true; |
| 44 | 44 | ||
| 45 | while (bkeepLooping) | 45 | while (bkeepLooping) |
| 46 | { | 46 | { |
| 47 | if (findData.cFileName[0] != '.') | 47 | if (findData.cFileName[0] != '.') |
| 48 | { | 48 | { |
| 49 | std::string strFilename; | 49 | std::string strFilename; |
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 35da07306..b6dec838c 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -88,7 +88,7 @@ bool IsDirectory(const std::string &filename) | |||
| 88 | #endif | 88 | #endif |
| 89 | 89 | ||
| 90 | if (result < 0) { | 90 | if (result < 0) { |
| 91 | WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s", | 91 | WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s", |
| 92 | filename.c_str(), GetLastErrorMsg()); | 92 | filename.c_str(), GetLastErrorMsg()); |
| 93 | return false; | 93 | return false; |
| 94 | } | 94 | } |
| @@ -102,7 +102,7 @@ bool Delete(const std::string &filename) | |||
| 102 | { | 102 | { |
| 103 | INFO_LOG(COMMON, "Delete: file %s", filename.c_str()); | 103 | INFO_LOG(COMMON, "Delete: file %s", filename.c_str()); |
| 104 | 104 | ||
| 105 | // Return true because we care about the file no | 105 | // Return true because we care about the file no |
| 106 | // being there, not the actual delete. | 106 | // being there, not the actual delete. |
| 107 | if (!Exists(filename)) | 107 | if (!Exists(filename)) |
| 108 | { | 108 | { |
| @@ -120,13 +120,13 @@ bool Delete(const std::string &filename) | |||
| 120 | #ifdef _WIN32 | 120 | #ifdef _WIN32 |
| 121 | if (!DeleteFile(Common::UTF8ToTStr(filename).c_str())) | 121 | if (!DeleteFile(Common::UTF8ToTStr(filename).c_str())) |
| 122 | { | 122 | { |
| 123 | WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s", | 123 | WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s", |
| 124 | filename.c_str(), GetLastErrorMsg()); | 124 | filename.c_str(), GetLastErrorMsg()); |
| 125 | return false; | 125 | return false; |
| 126 | } | 126 | } |
| 127 | #else | 127 | #else |
| 128 | if (unlink(filename.c_str()) == -1) { | 128 | if (unlink(filename.c_str()) == -1) { |
| 129 | WARN_LOG(COMMON, "Delete: unlink failed on %s: %s", | 129 | WARN_LOG(COMMON, "Delete: unlink failed on %s: %s", |
| 130 | filename.c_str(), GetLastErrorMsg()); | 130 | filename.c_str(), GetLastErrorMsg()); |
| 131 | return false; | 131 | return false; |
| 132 | } | 132 | } |
| @@ -232,28 +232,28 @@ bool DeleteDir(const std::string &filename) | |||
| 232 | return false; | 232 | return false; |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | // renames file srcFilename to destFilename, returns true on success | 235 | // renames file srcFilename to destFilename, returns true on success |
| 236 | bool Rename(const std::string &srcFilename, const std::string &destFilename) | 236 | bool Rename(const std::string &srcFilename, const std::string &destFilename) |
| 237 | { | 237 | { |
| 238 | INFO_LOG(COMMON, "Rename: %s --> %s", | 238 | INFO_LOG(COMMON, "Rename: %s --> %s", |
| 239 | srcFilename.c_str(), destFilename.c_str()); | 239 | srcFilename.c_str(), destFilename.c_str()); |
| 240 | if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) | 240 | if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) |
| 241 | return true; | 241 | return true; |
| 242 | ERROR_LOG(COMMON, "Rename: failed %s --> %s: %s", | 242 | ERROR_LOG(COMMON, "Rename: failed %s --> %s: %s", |
| 243 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); | 243 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); |
| 244 | return false; | 244 | return false; |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | // copies file srcFilename to destFilename, returns true on success | 247 | // copies file srcFilename to destFilename, returns true on success |
| 248 | bool Copy(const std::string &srcFilename, const std::string &destFilename) | 248 | bool Copy(const std::string &srcFilename, const std::string &destFilename) |
| 249 | { | 249 | { |
| 250 | INFO_LOG(COMMON, "Copy: %s --> %s", | 250 | INFO_LOG(COMMON, "Copy: %s --> %s", |
| 251 | srcFilename.c_str(), destFilename.c_str()); | 251 | srcFilename.c_str(), destFilename.c_str()); |
| 252 | #ifdef _WIN32 | 252 | #ifdef _WIN32 |
| 253 | if (CopyFile(Common::UTF8ToTStr(srcFilename).c_str(), Common::UTF8ToTStr(destFilename).c_str(), FALSE)) | 253 | if (CopyFile(Common::UTF8ToTStr(srcFilename).c_str(), Common::UTF8ToTStr(destFilename).c_str(), FALSE)) |
| 254 | return true; | 254 | return true; |
| 255 | 255 | ||
| 256 | ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", | 256 | ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", |
| 257 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); | 257 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); |
| 258 | return false; | 258 | return false; |
| 259 | #else | 259 | #else |
| @@ -267,7 +267,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) | |||
| 267 | FILE *input = fopen(srcFilename.c_str(), "rb"); | 267 | FILE *input = fopen(srcFilename.c_str(), "rb"); |
| 268 | if (!input) | 268 | if (!input) |
| 269 | { | 269 | { |
| 270 | ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s", | 270 | ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s", |
| 271 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); | 271 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); |
| 272 | return false; | 272 | return false; |
| 273 | } | 273 | } |
| @@ -277,7 +277,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) | |||
| 277 | if (!output) | 277 | if (!output) |
| 278 | { | 278 | { |
| 279 | fclose(input); | 279 | fclose(input); |
| 280 | ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s", | 280 | ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s", |
| 281 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); | 281 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); |
| 282 | return false; | 282 | return false; |
| 283 | } | 283 | } |
| @@ -291,8 +291,8 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) | |||
| 291 | { | 291 | { |
| 292 | if (ferror(input) != 0) | 292 | if (ferror(input) != 0) |
| 293 | { | 293 | { |
| 294 | ERROR_LOG(COMMON, | 294 | ERROR_LOG(COMMON, |
| 295 | "Copy: failed reading from source, %s --> %s: %s", | 295 | "Copy: failed reading from source, %s --> %s: %s", |
| 296 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); | 296 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); |
| 297 | goto bail; | 297 | goto bail; |
| 298 | } | 298 | } |
| @@ -302,8 +302,8 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) | |||
| 302 | int wnum = fwrite(buffer, sizeof(char), rnum, output); | 302 | int wnum = fwrite(buffer, sizeof(char), rnum, output); |
| 303 | if (wnum != rnum) | 303 | if (wnum != rnum) |
| 304 | { | 304 | { |
| 305 | ERROR_LOG(COMMON, | 305 | ERROR_LOG(COMMON, |
| 306 | "Copy: failed writing to output, %s --> %s: %s", | 306 | "Copy: failed writing to output, %s --> %s: %s", |
| 307 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); | 307 | srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); |
| 308 | goto bail; | 308 | goto bail; |
| 309 | } | 309 | } |
| @@ -335,7 +335,7 @@ u64 GetSize(const std::string &filename) | |||
| 335 | WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str()); | 335 | WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str()); |
| 336 | return 0; | 336 | return 0; |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | struct stat64 buf; | 339 | struct stat64 buf; |
| 340 | #ifdef _WIN32 | 340 | #ifdef _WIN32 |
| 341 | if (_tstat64(Common::UTF8ToTStr(filename).c_str(), &buf) == 0) | 341 | if (_tstat64(Common::UTF8ToTStr(filename).c_str(), &buf) == 0) |
| @@ -384,10 +384,10 @@ u64 GetSize(FILE *f) | |||
| 384 | return size; | 384 | return size; |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | // creates an empty file filename, returns true on success | 387 | // creates an empty file filename, returns true on success |
| 388 | bool CreateEmptyFile(const std::string &filename) | 388 | bool CreateEmptyFile(const std::string &filename) |
| 389 | { | 389 | { |
| 390 | INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str()); | 390 | INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str()); |
| 391 | 391 | ||
| 392 | if (!FileUtil::IOFile(filename, "wb")) | 392 | if (!FileUtil::IOFile(filename, "wb")) |
| 393 | { | 393 | { |
| @@ -437,7 +437,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry) | |||
| 437 | #endif | 437 | #endif |
| 438 | // check for "." and ".." | 438 | // check for "." and ".." |
| 439 | if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || | 439 | if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || |
| 440 | ((virtualName[0] == '.') && (virtualName[1] == '.') && | 440 | ((virtualName[0] == '.') && (virtualName[1] == '.') && |
| 441 | (virtualName[2] == '\0'))) | 441 | (virtualName[2] == '\0'))) |
| 442 | continue; | 442 | continue; |
| 443 | entry.virtualName = virtualName; | 443 | entry.virtualName = virtualName; |
| @@ -452,14 +452,14 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry) | |||
| 452 | foundEntries += (u32)entry.size; | 452 | foundEntries += (u32)entry.size; |
| 453 | } | 453 | } |
| 454 | else | 454 | else |
| 455 | { // is a file | 455 | { // is a file |
| 456 | entry.isDirectory = false; | 456 | entry.isDirectory = false; |
| 457 | entry.size = GetSize(entry.physicalName.c_str()); | 457 | entry.size = GetSize(entry.physicalName.c_str()); |
| 458 | } | 458 | } |
| 459 | ++foundEntries; | 459 | ++foundEntries; |
| 460 | // Push into the tree | 460 | // Push into the tree |
| 461 | parentEntry.children.push_back(entry); | 461 | parentEntry.children.push_back(entry); |
| 462 | #ifdef _WIN32 | 462 | #ifdef _WIN32 |
| 463 | } while (FindNextFile(hFind, &ffd) != 0); | 463 | } while (FindNextFile(hFind, &ffd) != 0); |
| 464 | FindClose(hFind); | 464 | FindClose(hFind); |
| 465 | #else | 465 | #else |
| @@ -504,7 +504,7 @@ bool DeleteDirRecursively(const std::string &directory) | |||
| 504 | 504 | ||
| 505 | // check for "." and ".." | 505 | // check for "." and ".." |
| 506 | if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || | 506 | if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || |
| 507 | ((virtualName[0] == '.') && (virtualName[1] == '.') && | 507 | ((virtualName[0] == '.') && (virtualName[1] == '.') && |
| 508 | (virtualName[2] == '\0'))) | 508 | (virtualName[2] == '\0'))) |
| 509 | continue; | 509 | continue; |
| 510 | 510 | ||
| @@ -540,7 +540,7 @@ bool DeleteDirRecursively(const std::string &directory) | |||
| 540 | closedir(dirp); | 540 | closedir(dirp); |
| 541 | #endif | 541 | #endif |
| 542 | FileUtil::DeleteDir(directory); | 542 | FileUtil::DeleteDir(directory); |
| 543 | 543 | ||
| 544 | return true; | 544 | return true; |
| 545 | } | 545 | } |
| 546 | 546 | ||
| @@ -585,7 +585,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path) | |||
| 585 | std::string GetCurrentDir() | 585 | std::string GetCurrentDir() |
| 586 | { | 586 | { |
| 587 | char *dir; | 587 | char *dir; |
| 588 | // Get the current working directory (getcwd uses malloc) | 588 | // Get the current working directory (getcwd uses malloc) |
| 589 | if (!(dir = __getcwd(NULL, 0))) { | 589 | if (!(dir = __getcwd(NULL, 0))) { |
| 590 | 590 | ||
| 591 | ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s", | 591 | ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s", |
| @@ -604,7 +604,7 @@ bool SetCurrentDir(const std::string &directory) | |||
| 604 | } | 604 | } |
| 605 | 605 | ||
| 606 | #if defined(__APPLE__) | 606 | #if defined(__APPLE__) |
| 607 | std::string GetBundleDirectory() | 607 | std::string GetBundleDirectory() |
| 608 | { | 608 | { |
| 609 | CFURLRef BundleRef; | 609 | CFURLRef BundleRef; |
| 610 | char AppBundlePath[MAXPATHLEN]; | 610 | char AppBundlePath[MAXPATHLEN]; |
| @@ -666,8 +666,8 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 666 | if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) | 666 | if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) |
| 667 | paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; | 667 | paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; |
| 668 | else | 668 | else |
| 669 | paths[D_USER_IDX] = std::string(getenv("HOME") ? | 669 | paths[D_USER_IDX] = std::string(getenv("HOME") ? |
| 670 | getenv("HOME") : getenv("PWD") ? | 670 | getenv("HOME") : getenv("PWD") ? |
| 671 | getenv("PWD") : "") + DIR_SEP EMU_DATA_DIR DIR_SEP; | 671 | getenv("PWD") : "") + DIR_SEP EMU_DATA_DIR DIR_SEP; |
| 672 | #endif | 672 | #endif |
| 673 | 673 | ||
| @@ -749,7 +749,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 749 | paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; | 749 | paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; |
| 750 | } | 750 | } |
| 751 | } | 751 | } |
| 752 | 752 | ||
| 753 | return paths[DirIDX]; | 753 | return paths[DirIDX]; |
| 754 | } | 754 | } |
| 755 | 755 | ||
| @@ -762,7 +762,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 762 | // if (!FileUtil::Exists(dir)) | 762 | // if (!FileUtil::Exists(dir)) |
| 763 | // dir = SHARED_USER_DIR THEMES_DIR "/" + theme_name + "/"; | 763 | // dir = SHARED_USER_DIR THEMES_DIR "/" + theme_name + "/"; |
| 764 | //#endif | 764 | //#endif |
| 765 | // | 765 | // |
| 766 | // return dir; | 766 | // return dir; |
| 767 | //} | 767 | //} |
| 768 | 768 | ||
diff --git a/src/common/file_util.h b/src/common/file_util.h index 173ce6623..72b80be8a 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -16,33 +16,33 @@ | |||
| 16 | 16 | ||
| 17 | // User directory indices for GetUserPath | 17 | // User directory indices for GetUserPath |
| 18 | enum { | 18 | enum { |
| 19 | D_USER_IDX, | 19 | D_USER_IDX, |
| 20 | D_ROOT_IDX, | 20 | D_ROOT_IDX, |
| 21 | D_CONFIG_IDX, | 21 | D_CONFIG_IDX, |
| 22 | D_GAMECONFIG_IDX, | 22 | D_GAMECONFIG_IDX, |
| 23 | D_MAPS_IDX, | 23 | D_MAPS_IDX, |
| 24 | D_CACHE_IDX, | 24 | D_CACHE_IDX, |
| 25 | D_SHADERCACHE_IDX, | 25 | D_SHADERCACHE_IDX, |
| 26 | D_SHADERS_IDX, | 26 | D_SHADERS_IDX, |
| 27 | D_STATESAVES_IDX, | 27 | D_STATESAVES_IDX, |
| 28 | D_SCREENSHOTS_IDX, | 28 | D_SCREENSHOTS_IDX, |
| 29 | D_SDMC_IDX, | 29 | D_SDMC_IDX, |
| 30 | D_HIRESTEXTURES_IDX, | 30 | D_HIRESTEXTURES_IDX, |
| 31 | D_DUMP_IDX, | 31 | D_DUMP_IDX, |
| 32 | D_DUMPFRAMES_IDX, | 32 | D_DUMPFRAMES_IDX, |
| 33 | D_DUMPAUDIO_IDX, | 33 | D_DUMPAUDIO_IDX, |
| 34 | D_DUMPTEXTURES_IDX, | 34 | D_DUMPTEXTURES_IDX, |
| 35 | D_DUMPDSP_IDX, | 35 | D_DUMPDSP_IDX, |
| 36 | D_LOGS_IDX, | 36 | D_LOGS_IDX, |
| 37 | D_SYSCONF_IDX, | 37 | D_SYSCONF_IDX, |
| 38 | F_EMUCONFIG_IDX, | 38 | F_EMUCONFIG_IDX, |
| 39 | F_DEBUGGERCONFIG_IDX, | 39 | F_DEBUGGERCONFIG_IDX, |
| 40 | F_LOGGERCONFIG_IDX, | 40 | F_LOGGERCONFIG_IDX, |
| 41 | F_MAINLOG_IDX, | 41 | F_MAINLOG_IDX, |
| 42 | F_RAMDUMP_IDX, | 42 | F_RAMDUMP_IDX, |
| 43 | F_ARAMDUMP_IDX, | 43 | F_ARAMDUMP_IDX, |
| 44 | F_SYSCONF_IDX, | 44 | F_SYSCONF_IDX, |
| 45 | NUM_PATH_INDICES | 45 | NUM_PATH_INDICES |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | namespace FileUtil | 48 | namespace FileUtil |
| @@ -51,11 +51,11 @@ namespace FileUtil | |||
| 51 | // FileSystem tree node/ | 51 | // FileSystem tree node/ |
| 52 | struct FSTEntry | 52 | struct FSTEntry |
| 53 | { | 53 | { |
| 54 | bool isDirectory; | 54 | bool isDirectory; |
| 55 | u64 size; // file length or number of entries from children | 55 | u64 size; // file length or number of entries from children |
| 56 | std::string physicalName; // name on disk | 56 | std::string physicalName; // name on disk |
| 57 | std::string virtualName; // name in FST names table | 57 | std::string virtualName; // name in FST names table |
| 58 | std::vector<FSTEntry> children; | 58 | std::vector<FSTEntry> children; |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | // Returns true if file filename exists | 61 | // Returns true if file filename exists |
| @@ -148,86 +148,86 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam | |||
| 148 | class IOFile : public NonCopyable | 148 | class IOFile : public NonCopyable |
| 149 | { | 149 | { |
| 150 | public: | 150 | public: |
| 151 | IOFile(); | 151 | IOFile(); |
| 152 | IOFile(std::FILE* file); | 152 | IOFile(std::FILE* file); |
| 153 | IOFile(const std::string& filename, const char openmode[]); | 153 | IOFile(const std::string& filename, const char openmode[]); |
| 154 | 154 | ||
| 155 | ~IOFile(); | 155 | ~IOFile(); |
| 156 | 156 | ||
| 157 | IOFile(IOFile&& other); | 157 | IOFile(IOFile&& other); |
| 158 | IOFile& operator=(IOFile&& other); | 158 | IOFile& operator=(IOFile&& other); |
| 159 | 159 | ||
| 160 | void Swap(IOFile& other); | 160 | void Swap(IOFile& other); |
| 161 | 161 | ||
| 162 | bool Open(const std::string& filename, const char openmode[]); | 162 | bool Open(const std::string& filename, const char openmode[]); |
| 163 | bool Close(); | 163 | bool Close(); |
| 164 | 164 | ||
| 165 | template <typename T> | 165 | template <typename T> |
| 166 | size_t ReadArray(T* data, size_t length) | 166 | size_t ReadArray(T* data, size_t length) |
| 167 | { | 167 | { |
| 168 | if (!IsOpen()) { | 168 | if (!IsOpen()) { |
| 169 | m_good = false; | 169 | m_good = false; |
| 170 | return -1; | 170 | return -1; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | size_t items_read = std::fread(data, sizeof(T), length, m_file); | 173 | size_t items_read = std::fread(data, sizeof(T), length, m_file); |
| 174 | if (items_read != length) | 174 | if (items_read != length) |
| 175 | m_good = false; | 175 | m_good = false; |
| 176 | 176 | ||
| 177 | return items_read; | 177 | return items_read; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | template <typename T> | 180 | template <typename T> |
| 181 | size_t WriteArray(const T* data, size_t length) | 181 | size_t WriteArray(const T* data, size_t length) |
| 182 | { | 182 | { |
| 183 | if (!IsOpen()) { | 183 | if (!IsOpen()) { |
| 184 | m_good = false; | 184 | m_good = false; |
| 185 | return -1; | 185 | return -1; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | size_t items_written = std::fwrite(data, sizeof(T), length, m_file); | 188 | size_t items_written = std::fwrite(data, sizeof(T), length, m_file); |
| 189 | if (items_written != length) | 189 | if (items_written != length) |
| 190 | m_good = false; | 190 | m_good = false; |
| 191 | 191 | ||
| 192 | return items_written; | 192 | return items_written; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | size_t ReadBytes(void* data, size_t length) | 195 | size_t ReadBytes(void* data, size_t length) |
| 196 | { | 196 | { |
| 197 | return ReadArray(reinterpret_cast<char*>(data), length); | 197 | return ReadArray(reinterpret_cast<char*>(data), length); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | size_t WriteBytes(const void* data, size_t length) | 200 | size_t WriteBytes(const void* data, size_t length) |
| 201 | { | 201 | { |
| 202 | return WriteArray(reinterpret_cast<const char*>(data), length); | 202 | return WriteArray(reinterpret_cast<const char*>(data), length); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | bool IsOpen() { return NULL != m_file; } | 205 | bool IsOpen() { return NULL != m_file; } |
| 206 | 206 | ||
| 207 | // m_good is set to false when a read, write or other function fails | 207 | // m_good is set to false when a read, write or other function fails |
| 208 | bool IsGood() { return m_good; } | 208 | bool IsGood() { return m_good; } |
| 209 | operator void*() { return m_good ? m_file : NULL; } | 209 | operator void*() { return m_good ? m_file : NULL; } |
| 210 | 210 | ||
| 211 | std::FILE* ReleaseHandle(); | 211 | std::FILE* ReleaseHandle(); |
| 212 | 212 | ||
| 213 | std::FILE* GetHandle() { return m_file; } | 213 | std::FILE* GetHandle() { return m_file; } |
| 214 | 214 | ||
| 215 | void SetHandle(std::FILE* file); | 215 | void SetHandle(std::FILE* file); |
| 216 | 216 | ||
| 217 | bool Seek(s64 off, int origin); | 217 | bool Seek(s64 off, int origin); |
| 218 | u64 Tell(); | 218 | u64 Tell(); |
| 219 | u64 GetSize(); | 219 | u64 GetSize(); |
| 220 | bool Resize(u64 size); | 220 | bool Resize(u64 size); |
| 221 | bool Flush(); | 221 | bool Flush(); |
| 222 | 222 | ||
| 223 | // clear error state | 223 | // clear error state |
| 224 | void Clear() { m_good = true; std::clearerr(m_file); } | 224 | void Clear() { m_good = true; std::clearerr(m_file); } |
| 225 | 225 | ||
| 226 | std::FILE* m_file; | 226 | std::FILE* m_file; |
| 227 | bool m_good; | 227 | bool m_good; |
| 228 | private: | 228 | private: |
| 229 | IOFile(IOFile&); | 229 | IOFile(IOFile&); |
| 230 | IOFile& operator=(IOFile& other); | 230 | IOFile& operator=(IOFile& other); |
| 231 | }; | 231 | }; |
| 232 | 232 | ||
| 233 | } // namespace | 233 | } // namespace |
| @@ -237,8 +237,8 @@ template <typename T> | |||
| 237 | void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) | 237 | void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) |
| 238 | { | 238 | { |
| 239 | #ifdef _WIN32 | 239 | #ifdef _WIN32 |
| 240 | fstream.open(Common::UTF8ToTStr(filename).c_str(), openmode); | 240 | fstream.open(Common::UTF8ToTStr(filename).c_str(), openmode); |
| 241 | #else | 241 | #else |
| 242 | fstream.open(filename.c_str(), openmode); | 242 | fstream.open(filename.c_str(), openmode); |
| 243 | #endif | 243 | #endif |
| 244 | } | 244 | } |
diff --git a/src/common/hash.cpp b/src/common/hash.cpp index d2ebc7341..2ddcfe6b7 100644 --- a/src/common/hash.cpp +++ b/src/common/hash.cpp | |||
| @@ -115,15 +115,15 @@ inline u64 getblock(const u64 * p, int i) | |||
| 115 | 115 | ||
| 116 | inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2) | 116 | inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2) |
| 117 | { | 117 | { |
| 118 | k1 *= c1; | 118 | k1 *= c1; |
| 119 | k1 = _rotl64(k1,23); | 119 | k1 = _rotl64(k1,23); |
| 120 | k1 *= c2; | 120 | k1 *= c2; |
| 121 | h1 ^= k1; | 121 | h1 ^= k1; |
| 122 | h1 += h2; | 122 | h1 += h2; |
| 123 | 123 | ||
| 124 | h2 = _rotl64(h2,41); | 124 | h2 = _rotl64(h2,41); |
| 125 | 125 | ||
| 126 | k2 *= c2; | 126 | k2 *= c2; |
| 127 | k2 = _rotl64(k2,23); | 127 | k2 = _rotl64(k2,23); |
| 128 | k2 *= c1; | 128 | k2 *= c1; |
| 129 | h2 ^= k2; | 129 | h2 ^= k2; |
| @@ -250,7 +250,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) | |||
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | 252 | ||
| 253 | /* | 253 | /* |
| 254 | * NOTE: This hash function is used for custom texture loading/dumping, so | 254 | * NOTE: This hash function is used for custom texture loading/dumping, so |
| 255 | * it should not be changed, which would require all custom textures to be | 255 | * it should not be changed, which would require all custom textures to be |
| 256 | * recalculated for their new hash values. If the hashing function is | 256 | * recalculated for their new hash values. If the hashing function is |
| @@ -273,7 +273,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) | |||
| 273 | u64 k = data[0]; | 273 | u64 k = data[0]; |
| 274 | data+=Step; | 274 | data+=Step; |
| 275 | k *= m; | 275 | k *= m; |
| 276 | k ^= k >> r; | 276 | k ^= k >> r; |
| 277 | k *= m; | 277 | k *= m; |
| 278 | h ^= k; | 278 | h ^= k; |
| 279 | h *= m; | 279 | h *= m; |
| @@ -292,13 +292,13 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) | |||
| 292 | case 1: h ^= u64(data2[0]); | 292 | case 1: h ^= u64(data2[0]); |
| 293 | h *= m; | 293 | h *= m; |
| 294 | }; | 294 | }; |
| 295 | 295 | ||
| 296 | h ^= h >> r; | 296 | h ^= h >> r; |
| 297 | h *= m; | 297 | h *= m; |
| 298 | h ^= h >> r; | 298 | h ^= h >> r; |
| 299 | 299 | ||
| 300 | return h; | 300 | return h; |
| 301 | } | 301 | } |
| 302 | #else | 302 | #else |
| 303 | // CRC32 hash using the SSE4.2 instruction | 303 | // CRC32 hash using the SSE4.2 instruction |
| 304 | u64 GetCRC32(const u8 *src, int len, u32 samples) | 304 | u64 GetCRC32(const u8 *src, int len, u32 samples) |
| @@ -351,15 +351,15 @@ inline u32 fmix32(u32 h) | |||
| 351 | 351 | ||
| 352 | inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2) | 352 | inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2) |
| 353 | { | 353 | { |
| 354 | k1 *= c1; | 354 | k1 *= c1; |
| 355 | k1 = _rotl(k1,11); | 355 | k1 = _rotl(k1,11); |
| 356 | k1 *= c2; | 356 | k1 *= c2; |
| 357 | h1 ^= k1; | 357 | h1 ^= k1; |
| 358 | h1 += h2; | 358 | h1 += h2; |
| 359 | 359 | ||
| 360 | h2 = _rotl(h2,17); | 360 | h2 = _rotl(h2,17); |
| 361 | 361 | ||
| 362 | k2 *= c2; | 362 | k2 *= c2; |
| 363 | k2 = _rotl(k2,11); | 363 | k2 = _rotl(k2,11); |
| 364 | k2 *= c1; | 364 | k2 *= c1; |
| 365 | h2 ^= k2; | 365 | h2 ^= k2; |
| @@ -405,7 +405,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) | |||
| 405 | 405 | ||
| 406 | //---------- | 406 | //---------- |
| 407 | // tail | 407 | // tail |
| 408 | 408 | ||
| 409 | const u8 * tail = (const u8*)(data + nblocks*8); | 409 | const u8 * tail = (const u8*)(data + nblocks*8); |
| 410 | 410 | ||
| 411 | u32 k1 = 0; | 411 | u32 k1 = 0; |
| @@ -439,7 +439,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) | |||
| 439 | 439 | ||
| 440 | out[0] = h1; | 440 | out[0] = h1; |
| 441 | out[1] = h2; | 441 | out[1] = h2; |
| 442 | 442 | ||
| 443 | return *((u64 *)&out); | 443 | return *((u64 *)&out); |
| 444 | } | 444 | } |
| 445 | 445 | ||
| @@ -463,11 +463,11 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) | |||
| 463 | { | 463 | { |
| 464 | u64 k = data[0]; | 464 | u64 k = data[0]; |
| 465 | data+=Step; | 465 | data+=Step; |
| 466 | k *= m; | 466 | k *= m; |
| 467 | k ^= k >> r; | 467 | k ^= k >> r; |
| 468 | k *= m; | 468 | k *= m; |
| 469 | h ^= k; | 469 | h ^= k; |
| 470 | h *= m; | 470 | h *= m; |
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | const u8 * data2 = (const u8*)end; | 473 | const u8 * data2 = (const u8*)end; |
| @@ -483,7 +483,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) | |||
| 483 | case 1: h ^= u64(data2[0]); | 483 | case 1: h ^= u64(data2[0]); |
| 484 | h *= m; | 484 | h *= m; |
| 485 | }; | 485 | }; |
| 486 | 486 | ||
| 487 | h ^= h >> r; | 487 | h ^= h >> r; |
| 488 | h *= m; | 488 | h *= m; |
| 489 | h ^= h >> r; | 489 | h ^= h >> r; |
diff --git a/src/common/linear_disk_cache.h b/src/common/linear_disk_cache.h index 96dce3155..f4263f72a 100644 --- a/src/common/linear_disk_cache.h +++ b/src/common/linear_disk_cache.h | |||
| @@ -64,7 +64,7 @@ public: | |||
| 64 | m_file.seekg(0, std::ios::beg); | 64 | m_file.seekg(0, std::ios::beg); |
| 65 | std::fstream::pos_type start_pos = m_file.tellg(); | 65 | std::fstream::pos_type start_pos = m_file.tellg(); |
| 66 | std::streamoff file_size = end_pos - start_pos; | 66 | std::streamoff file_size = end_pos - start_pos; |
| 67 | 67 | ||
| 68 | if (m_file.is_open() && ValidateHeader()) | 68 | if (m_file.is_open() && ValidateHeader()) |
| 69 | { | 69 | { |
| 70 | // good header, read some key/value pairs | 70 | // good header, read some key/value pairs |
| @@ -87,7 +87,7 @@ public: | |||
| 87 | 87 | ||
| 88 | // read key/value and pass to reader | 88 | // read key/value and pass to reader |
| 89 | if (Read(&key) && | 89 | if (Read(&key) && |
| 90 | Read(value, value_size) && | 90 | Read(value, value_size) && |
| 91 | Read(&entry_number) && | 91 | Read(&entry_number) && |
| 92 | entry_number == m_num_entries+1) | 92 | entry_number == m_num_entries+1) |
| 93 | { | 93 | { |
| @@ -115,7 +115,7 @@ public: | |||
| 115 | WriteHeader(); | 115 | WriteHeader(); |
| 116 | return 0; | 116 | return 0; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | void Sync() | 119 | void Sync() |
| 120 | { | 120 | { |
| 121 | m_file.flush(); | 121 | m_file.flush(); |
diff --git a/src/common/log.h b/src/common/log.h index bfd73f8a5..14ad98c08 100644 --- a/src/common/log.h +++ b/src/common/log.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | enum { | 11 | enum { |
| 12 | OS_LEVEL, // Printed by the emulated operating system | 12 | OS_LEVEL, // Printed by the emulated operating system |
| 13 | NOTICE_LEVEL, // VERY important information that is NOT errors. Like startup and OSReports. | 13 | NOTICE_LEVEL, // VERY important information that is NOT errors. Like startup and OSReports. |
| 14 | ERROR_LEVEL, // Critical errors | 14 | ERROR_LEVEL, // Critical errors |
| 15 | WARNING_LEVEL, // Something is suspicious. | 15 | WARNING_LEVEL, // Something is suspicious. |
| 16 | INFO_LEVEL, // General information. | 16 | INFO_LEVEL, // General information. |
| 17 | DEBUG_LEVEL, // Detailed debugging - might make things slow. | 17 | DEBUG_LEVEL, // Detailed debugging - might make things slow. |
| @@ -46,7 +46,7 @@ enum LOG_TYPE { | |||
| 46 | MEMMAP, | 46 | MEMMAP, |
| 47 | MEMCARD_MANAGER, | 47 | MEMCARD_MANAGER, |
| 48 | OSREPORT, | 48 | OSREPORT, |
| 49 | PAD, | 49 | PAD, |
| 50 | PROCESSORINTERFACE, | 50 | PROCESSORINTERFACE, |
| 51 | PIXELENGINE, | 51 | PIXELENGINE, |
| 52 | SERIALINTERFACE, | 52 | SERIALINTERFACE, |
| @@ -69,6 +69,7 @@ enum LOG_TYPE { | |||
| 69 | HW, | 69 | HW, |
| 70 | TIME, | 70 | TIME, |
| 71 | NETPLAY, | 71 | NETPLAY, |
| 72 | GUI, | ||
| 72 | 73 | ||
| 73 | NUMBER_OF_LOGS // Must be last | 74 | NUMBER_OF_LOGS // Must be last |
| 74 | }; | 75 | }; |
| @@ -88,7 +89,7 @@ enum LOG_LEVELS { | |||
| 88 | 89 | ||
| 89 | } // namespace | 90 | } // namespace |
| 90 | 91 | ||
| 91 | void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int line, | 92 | void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int line, |
| 92 | const char* function, const char* fmt, ...) | 93 | const char* function, const char* fmt, ...) |
| 93 | #ifdef __GNUC__ | 94 | #ifdef __GNUC__ |
| 94 | __attribute__((format(printf, 6, 7))) | 95 | __attribute__((format(printf, 6, 7))) |
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp index 4d590d98f..2ef7d98c0 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp | |||
| @@ -7,9 +7,8 @@ | |||
| 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, ...) |
| 14 | { | 13 | { |
| 15 | va_list args; | 14 | va_list args; |
| @@ -75,6 +74,7 @@ LogManager::LogManager() | |||
| 75 | m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay"); | 74 | m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay"); |
| 76 | m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager"); | 75 | m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager"); |
| 77 | m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay"); | 76 | m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay"); |
| 77 | m_Log[LogTypes::GUI] = new LogContainer("GUI", "GUI"); | ||
| 78 | 78 | ||
| 79 | m_fileLog = new FileLogListener(FileUtil::GetUserPath(F_MAINLOG_IDX).c_str()); | 79 | m_fileLog = new FileLogListener(FileUtil::GetUserPath(F_MAINLOG_IDX).c_str()); |
| 80 | m_consoleLog = new ConsoleListener(); | 80 | m_consoleLog = new ConsoleListener(); |
| @@ -111,7 +111,7 @@ LogManager::~LogManager() | |||
| 111 | delete m_debuggerLog; | 111 | delete m_debuggerLog; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, | 114 | void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, |
| 115 | int line, const char* function, const char *fmt, va_list args) | 115 | int line, const char* function, const char *fmt, va_list args) |
| 116 | { | 116 | { |
| 117 | char temp[MAX_MSGLEN]; | 117 | char temp[MAX_MSGLEN]; |
| @@ -124,11 +124,11 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const | |||
| 124 | Common::CharArrayFromFormatV(temp, MAX_MSGLEN, fmt, args); | 124 | Common::CharArrayFromFormatV(temp, MAX_MSGLEN, fmt, args); |
| 125 | 125 | ||
| 126 | static const char level_to_char[7] = "ONEWID"; | 126 | static const char level_to_char[7] = "ONEWID"; |
| 127 | sprintf(msg, "%s %s:%u %c[%s] %s: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line, | 127 | sprintf(msg, "%s %s:%u %c[%s] %s: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line, |
| 128 | level_to_char[(int)level], log->GetShortName(), function, temp); | 128 | level_to_char[(int)level], log->GetShortName(), function, temp); |
| 129 | 129 | ||
| 130 | #ifdef ANDROID | 130 | #ifdef ANDROID |
| 131 | Host_SysMessage(msg); | 131 | Host_SysMessage(msg); |
| 132 | #endif | 132 | #endif |
| 133 | log->Trigger(level, msg); | 133 | log->Trigger(level, msg); |
| 134 | } | 134 | } |
diff --git a/src/common/log_manager.h b/src/common/log_manager.h index de1d16ee5..baefc4ba8 100644 --- a/src/common/log_manager.h +++ b/src/common/log_manager.h | |||
| @@ -54,7 +54,7 @@ class LogContainer | |||
| 54 | { | 54 | { |
| 55 | public: | 55 | public: |
| 56 | LogContainer(const char* shortName, const char* fullName, bool enable = false); | 56 | LogContainer(const char* shortName, const char* fullName, bool enable = false); |
| 57 | 57 | ||
| 58 | const char* GetShortName() const { return m_shortName; } | 58 | const char* GetShortName() const { return m_shortName; } |
| 59 | const char* GetFullName() const { return m_fullName; } | 59 | const char* GetFullName() const { return m_fullName; } |
| 60 | 60 | ||
| @@ -98,7 +98,7 @@ public: | |||
| 98 | 98 | ||
| 99 | static u32 GetMaxLevel() { return LogTypes::MAX_LOGLEVEL; } | 99 | static u32 GetMaxLevel() { return LogTypes::MAX_LOGLEVEL; } |
| 100 | 100 | ||
| 101 | void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, | 101 | void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, |
| 102 | const char* function, const char *fmt, va_list args); | 102 | const char* function, const char *fmt, va_list args); |
| 103 | 103 | ||
| 104 | void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level) | 104 | void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level) |
diff --git a/src/common/math_util.cpp b/src/common/math_util.cpp index ab0e6b75c..3613e82a6 100644 --- a/src/common/math_util.cpp +++ b/src/common/math_util.cpp | |||
| @@ -18,7 +18,7 @@ u32 ClassifyDouble(double dvalue) | |||
| 18 | value.d = dvalue; | 18 | value.d = dvalue; |
| 19 | u64 sign = value.i & DOUBLE_SIGN; | 19 | u64 sign = value.i & DOUBLE_SIGN; |
| 20 | u64 exp = value.i & DOUBLE_EXP; | 20 | u64 exp = value.i & DOUBLE_EXP; |
| 21 | if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP) | 21 | if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP) |
| 22 | { | 22 | { |
| 23 | // Nice normalized number. | 23 | // Nice normalized number. |
| 24 | return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; | 24 | return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; |
| @@ -58,7 +58,7 @@ u32 ClassifyFloat(float fvalue) | |||
| 58 | value.f = fvalue; | 58 | value.f = fvalue; |
| 59 | u32 sign = value.i & FLOAT_SIGN; | 59 | u32 sign = value.i & FLOAT_SIGN; |
| 60 | u32 exp = value.i & FLOAT_EXP; | 60 | u32 exp = value.i & FLOAT_EXP; |
| 61 | if (exp > FLOAT_ZERO && exp < FLOAT_EXP) | 61 | if (exp > FLOAT_ZERO && exp < FLOAT_EXP) |
| 62 | { | 62 | { |
| 63 | // Nice normalized number. | 63 | // Nice normalized number. |
| 64 | return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; | 64 | return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; |
| @@ -77,13 +77,13 @@ u32 ClassifyFloat(float fvalue) | |||
| 77 | // Denormalized number. | 77 | // Denormalized number. |
| 78 | return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD; | 78 | return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD; |
| 79 | } | 79 | } |
| 80 | } | 80 | } |
| 81 | else if (exp) | 81 | else if (exp) |
| 82 | { | 82 | { |
| 83 | // Infinite | 83 | // Infinite |
| 84 | return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF; | 84 | return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF; |
| 85 | } | 85 | } |
| 86 | else | 86 | else |
| 87 | { | 87 | { |
| 88 | //Zero | 88 | //Zero |
| 89 | return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ; | 89 | return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ; |
| @@ -143,7 +143,7 @@ void Matrix33::RotateY(Matrix33 &mtx, float rad) | |||
| 143 | mtx.data[0] = c; | 143 | mtx.data[0] = c; |
| 144 | mtx.data[2] = s; | 144 | mtx.data[2] = s; |
| 145 | mtx.data[4] = 1; | 145 | mtx.data[4] = 1; |
| 146 | mtx.data[6] = -s; | 146 | mtx.data[6] = -s; |
| 147 | mtx.data[8] = c; | 147 | mtx.data[8] = c; |
| 148 | } | 148 | } |
| 149 | 149 | ||
diff --git a/src/common/math_util.h b/src/common/math_util.h index b32e7bb14..b10a25c13 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "common/common.h" | 7 | #include "common/common.h" |
| 8 | 8 | ||
| 9 | #include <algorithm> | 9 | #include <algorithm> |
| 10 | #include <type_traits> | ||
| 10 | #include <vector> | 11 | #include <vector> |
| 11 | 12 | ||
| 12 | namespace MathUtil | 13 | namespace MathUtil |
| @@ -109,11 +110,11 @@ struct Rectangle | |||
| 109 | Rectangle(T theLeft, T theTop, T theRight, T theBottom) | 110 | Rectangle(T theLeft, T theTop, T theRight, T theBottom) |
| 110 | : left(theLeft), top(theTop), right(theRight), bottom(theBottom) | 111 | : left(theLeft), top(theTop), right(theRight), bottom(theBottom) |
| 111 | { } | 112 | { } |
| 112 | 113 | ||
| 113 | bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; } | 114 | bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; } |
| 114 | 115 | ||
| 115 | T GetWidth() const { return abs(right - left); } | 116 | T GetWidth() const { return std::abs(static_cast<typename std::make_signed<T>::type>(right - left)); } |
| 116 | T GetHeight() const { return abs(bottom - top); } | 117 | T GetHeight() const { return std::abs(static_cast<typename std::make_signed<T>::type>(bottom - top)); } |
| 117 | 118 | ||
| 118 | // If the rectangle is in a coordinate system with a lower-left origin, use | 119 | // If the rectangle is in a coordinate system with a lower-left origin, use |
| 119 | // this Clamp. | 120 | // this Clamp. |
| @@ -127,7 +128,7 @@ struct Rectangle | |||
| 127 | 128 | ||
| 128 | // If the rectangle is in a coordinate system with an upper-left origin, | 129 | // If the rectangle is in a coordinate system with an upper-left origin, |
| 129 | // use this Clamp. | 130 | // use this Clamp. |
| 130 | void ClampUL(T x1, T y1, T x2, T y2) | 131 | void ClampUL(T x1, T y1, T x2, T y2) |
| 131 | { | 132 | { |
| 132 | if (left < x1) left = x1; | 133 | if (left < x1) left = x1; |
| 133 | if (right > x2) right = x2; | 134 | if (right > x2) right = x2; |
diff --git a/src/common/mem_arena.cpp b/src/common/mem_arena.cpp index 40d9c03a2..67dbaf509 100644 --- a/src/common/mem_arena.cpp +++ b/src/common/mem_arena.cpp | |||
| @@ -38,7 +38,7 @@ void* globalbase = NULL; | |||
| 38 | // Hopefully this ABI will never change... | 38 | // Hopefully this ABI will never change... |
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | #define ASHMEM_DEVICE "/dev/ashmem" | 41 | #define ASHMEM_DEVICE "/dev/ashmem" |
| 42 | 42 | ||
| 43 | /* | 43 | /* |
| 44 | * ashmem_create_region - creates a new ashmem region and returns the file | 44 | * ashmem_create_region - creates a new ashmem region and returns the file |
| @@ -272,11 +272,11 @@ u8* MemArena::Find4GBBase() | |||
| 272 | 272 | ||
| 273 | 273 | ||
| 274 | // yeah, this could also be done in like two bitwise ops... | 274 | // yeah, this could also be done in like two bitwise ops... |
| 275 | #define SKIP(a_flags, b_flags) | 275 | #define SKIP(a_flags, b_flags) |
| 276 | // if (!(a_flags & MV_WII_ONLY) && (b_flags & MV_WII_ONLY)) | 276 | //if (!(a_flags & MV_WII_ONLY) && (b_flags & MV_WII_ONLY)) |
| 277 | // continue; | 277 | // continue; |
| 278 | // if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM)) | 278 | //if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM)) |
| 279 | // continue; | 279 | // continue; |
| 280 | 280 | ||
| 281 | static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) { | 281 | static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) { |
| 282 | // OK, we know where to find free space. Now grab it! | 282 | // OK, we know where to find free space. Now grab it! |
diff --git a/src/common/memory_util.cpp b/src/common/memory_util.cpp index bab7d9f7a..b6f66e4e1 100644 --- a/src/common/memory_util.cpp +++ b/src/common/memory_util.cpp | |||
| @@ -47,7 +47,7 @@ void* AllocateExecutableMemory(size_t size, bool low) | |||
| 47 | 47 | ||
| 48 | // printf("Mapped executable memory at %p (size %ld)\n", ptr, | 48 | // printf("Mapped executable memory at %p (size %ld)\n", ptr, |
| 49 | // (unsigned long)size); | 49 | // (unsigned long)size); |
| 50 | 50 | ||
| 51 | #ifdef _WIN32 | 51 | #ifdef _WIN32 |
| 52 | if (ptr == nullptr) | 52 | if (ptr == nullptr) |
| 53 | { | 53 | { |
| @@ -55,7 +55,7 @@ void* AllocateExecutableMemory(size_t size, bool low) | |||
| 55 | if (ptr == MAP_FAILED) | 55 | if (ptr == MAP_FAILED) |
| 56 | { | 56 | { |
| 57 | ptr = nullptr; | 57 | ptr = nullptr; |
| 58 | #endif | 58 | #endif |
| 59 | PanicAlert("Failed to allocate executable memory"); | 59 | PanicAlert("Failed to allocate executable memory"); |
| 60 | } | 60 | } |
| 61 | #if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT) | 61 | #if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT) |
| @@ -127,11 +127,11 @@ void FreeMemoryPages(void* ptr, size_t size) | |||
| 127 | if (ptr) | 127 | if (ptr) |
| 128 | { | 128 | { |
| 129 | #ifdef _WIN32 | 129 | #ifdef _WIN32 |
| 130 | 130 | ||
| 131 | if (!VirtualFree(ptr, 0, MEM_RELEASE)) | 131 | if (!VirtualFree(ptr, 0, MEM_RELEASE)) |
| 132 | PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg()); | 132 | PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg()); |
| 133 | ptr = NULL; // Is this our responsibility? | 133 | ptr = NULL; // Is this our responsibility? |
| 134 | 134 | ||
| 135 | #else | 135 | #else |
| 136 | munmap(ptr, size); | 136 | munmap(ptr, size); |
| 137 | #endif | 137 | #endif |
diff --git a/src/common/msg_handler.h b/src/common/msg_handler.h index 7c5319ec3..9bfdf950e 100644 --- a/src/common/msg_handler.h +++ b/src/common/msg_handler.h | |||
| @@ -15,7 +15,7 @@ enum MSG_TYPE | |||
| 15 | CRITICAL | 15 | CRITICAL |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | typedef bool (*MsgAlertHandler)(const char* caption, const char* text, | 18 | typedef bool (*MsgAlertHandler)(const char* caption, const char* text, |
| 19 | bool yes_no, int Style); | 19 | bool yes_no, int Style); |
| 20 | typedef std::string (*StringTranslator)(const char* text); | 20 | typedef std::string (*StringTranslator)(const char* text); |
| 21 | 21 | ||
| @@ -31,29 +31,29 @@ void SetEnableAlert(bool enable); | |||
| 31 | 31 | ||
| 32 | #ifndef GEKKO | 32 | #ifndef GEKKO |
| 33 | #ifdef _WIN32 | 33 | #ifdef _WIN32 |
| 34 | #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) | 34 | #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) |
| 35 | #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) | 35 | #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) |
| 36 | #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) | 36 | #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) |
| 37 | #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) | 37 | #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) |
| 38 | #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) | 38 | #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) |
| 39 | // Use these macros (that do the same thing) if the message should be translated. | 39 | // Use these macros (that do the same thing) if the message should be translated. |
| 40 | #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) | 40 | #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) |
| 41 | #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) | 41 | #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) |
| 42 | #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) | 42 | #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) |
| 43 | #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) | 43 | #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) |
| 44 | #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) | 44 | #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) |
| 45 | #else | 45 | #else |
| 46 | #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) | 46 | #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) |
| 47 | #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) | 47 | #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) |
| 48 | #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) | 48 | #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) |
| 49 | #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) | 49 | #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) |
| 50 | #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) | 50 | #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) |
| 51 | // Use these macros (that do the same thing) if the message should be translated. | 51 | // Use these macros (that do the same thing) if the message should be translated. |
| 52 | #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) | 52 | #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) |
| 53 | #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) | 53 | #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) |
| 54 | #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) | 54 | #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) |
| 55 | #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) | 55 | #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) |
| 56 | #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) | 56 | #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) |
| 57 | #endif | 57 | #endif |
| 58 | #else | 58 | #else |
| 59 | // GEKKO | 59 | // GEKKO |
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 54943d306..dcec9275f 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp | |||
| @@ -121,11 +121,11 @@ std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces) | |||
| 121 | { | 121 | { |
| 122 | std::ostringstream oss; | 122 | std::ostringstream oss; |
| 123 | oss << std::setfill('0') << std::hex; | 123 | oss << std::setfill('0') << std::hex; |
| 124 | 124 | ||
| 125 | for (int line = 0; size; ++data, --size) | 125 | for (int line = 0; size; ++data, --size) |
| 126 | { | 126 | { |
| 127 | oss << std::setw(2) << (int)*data; | 127 | oss << std::setw(2) << (int)*data; |
| 128 | 128 | ||
| 129 | if (line_len == ++line) | 129 | if (line_len == ++line) |
| 130 | { | 130 | { |
| 131 | oss << '\n'; | 131 | oss << '\n'; |
| @@ -168,7 +168,7 @@ bool TryParse(const std::string &str, u32 *const output) | |||
| 168 | errno = 0; | 168 | errno = 0; |
| 169 | 169 | ||
| 170 | unsigned long value = strtoul(str.c_str(), &endptr, 0); | 170 | unsigned long value = strtoul(str.c_str(), &endptr, 0); |
| 171 | 171 | ||
| 172 | if (!endptr || *endptr) | 172 | if (!endptr || *endptr) |
| 173 | return false; | 173 | return false; |
| 174 | 174 | ||
| @@ -294,7 +294,7 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st | |||
| 294 | //#include <string> | 294 | //#include <string> |
| 295 | //#include <assert.h> | 295 | //#include <assert.h> |
| 296 | 296 | ||
| 297 | const char HEX2DEC[256] = | 297 | const char HEX2DEC[256] = |
| 298 | { | 298 | { |
| 299 | /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ | 299 | /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ |
| 300 | /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, | 300 | /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, |
| @@ -327,7 +327,7 @@ std::string UriDecode(const std::string & sSrc) | |||
| 327 | const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); | 327 | const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); |
| 328 | const size_t SRC_LEN = sSrc.length(); | 328 | const size_t SRC_LEN = sSrc.length(); |
| 329 | const unsigned char * const SRC_END = pSrc + SRC_LEN; | 329 | const unsigned char * const SRC_END = pSrc + SRC_LEN; |
| 330 | const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%' | 330 | const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%' |
| 331 | 331 | ||
| 332 | char * const pStart = new char[SRC_LEN]; | 332 | char * const pStart = new char[SRC_LEN]; |
| 333 | char * pEnd = pStart; | 333 | char * pEnd = pStart; |
| @@ -394,7 +394,7 @@ std::string UriEncode(const std::string & sSrc) | |||
| 394 | 394 | ||
| 395 | for (; pSrc < SRC_END; ++pSrc) | 395 | for (; pSrc < SRC_END; ++pSrc) |
| 396 | { | 396 | { |
| 397 | if (SAFE[*pSrc]) | 397 | if (SAFE[*pSrc]) |
| 398 | *pEnd++ = *pSrc; | 398 | *pEnd++ = *pSrc; |
| 399 | else | 399 | else |
| 400 | { | 400 | { |
| @@ -518,9 +518,9 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& | |||
| 518 | 518 | ||
| 519 | out_buffer.resize(out_buffer_size - dst_bytes); | 519 | out_buffer.resize(out_buffer_size - dst_bytes); |
| 520 | out_buffer.swap(result); | 520 | out_buffer.swap(result); |
| 521 | 521 | ||
| 522 | iconv_close(conv_desc); | 522 | iconv_close(conv_desc); |
| 523 | 523 | ||
| 524 | return result; | 524 | return result; |
| 525 | } | 525 | } |
| 526 | 526 | ||
| @@ -576,7 +576,7 @@ std::u16string UTF8ToUTF16(const std::string& input) | |||
| 576 | out_buffer.swap(result); | 576 | out_buffer.swap(result); |
| 577 | 577 | ||
| 578 | iconv_close(conv_desc); | 578 | iconv_close(conv_desc); |
| 579 | 579 | ||
| 580 | return result; | 580 | return result; |
| 581 | } | 581 | } |
| 582 | 582 | ||
diff --git a/src/common/string_util.h b/src/common/string_util.h index 787a5663f..ae5bbadad 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h | |||
| @@ -63,7 +63,7 @@ template <typename N> | |||
| 63 | static bool TryParse(const std::string &str, N *const output) | 63 | static bool TryParse(const std::string &str, N *const output) |
| 64 | { | 64 | { |
| 65 | std::istringstream iss(str); | 65 | std::istringstream iss(str); |
| 66 | 66 | ||
| 67 | N tmp = 0; | 67 | N tmp = 0; |
| 68 | if (iss >> tmp) | 68 | if (iss >> tmp) |
| 69 | { | 69 | { |
diff --git a/src/common/symbols.cpp b/src/common/symbols.cpp index d61f4c0c6..63ad6218b 100644 --- a/src/common/symbols.cpp +++ b/src/common/symbols.cpp | |||
| @@ -31,7 +31,7 @@ namespace Symbols | |||
| 31 | { | 31 | { |
| 32 | TSymbolsMap::iterator foundSymbolItr; | 32 | TSymbolsMap::iterator foundSymbolItr; |
| 33 | TSymbol symbol; | 33 | TSymbol symbol; |
| 34 | 34 | ||
| 35 | foundSymbolItr = g_symbols.find(_address); | 35 | foundSymbolItr = g_symbols.find(_address); |
| 36 | if (foundSymbolItr != g_symbols.end()) | 36 | if (foundSymbolItr != g_symbols.end()) |
| 37 | { | 37 | { |
| @@ -44,7 +44,7 @@ namespace Symbols | |||
| 44 | { | 44 | { |
| 45 | return GetSymbol(_address).name; | 45 | return GetSymbol(_address).name; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | void Remove(u32 _address) | 48 | void Remove(u32 _address) |
| 49 | { | 49 | { |
| 50 | g_symbols.erase(_address); | 50 | g_symbols.erase(_address); |
diff --git a/src/common/symbols.h b/src/common/symbols.h index b13a8001a..4560f5240 100644 --- a/src/common/symbols.h +++ b/src/common/symbols.h | |||
| @@ -33,5 +33,5 @@ namespace Symbols | |||
| 33 | const std::string GetName(u32 _address); | 33 | const std::string GetName(u32 _address); |
| 34 | void Remove(u32 _address); | 34 | void Remove(u32 _address); |
| 35 | void Clear(); | 35 | void Clear(); |
| 36 | }; | 36 | } |
| 37 | 37 | ||
diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 60d8ed075..dc153ba71 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp | |||
| @@ -25,7 +25,7 @@ int CurrentThreadId() | |||
| 25 | return 0; | 25 | return 0; |
| 26 | #endif | 26 | #endif |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | #ifdef _WIN32 | 29 | #ifdef _WIN32 |
| 30 | 30 | ||
| 31 | void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) | 31 | void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) |
| @@ -52,7 +52,7 @@ void SwitchCurrentThread() | |||
| 52 | // Sets the debugger-visible name of the current thread. | 52 | // Sets the debugger-visible name of the current thread. |
| 53 | // Uses undocumented (actually, it is now documented) trick. | 53 | // Uses undocumented (actually, it is now documented) trick. |
| 54 | // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp | 54 | // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp |
| 55 | 55 | ||
| 56 | // This is implemented much nicer in upcoming msvc++, see: | 56 | // This is implemented much nicer in upcoming msvc++, see: |
| 57 | // http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx | 57 | // http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx |
| 58 | void SetCurrentThreadName(const char* szThreadName) | 58 | void SetCurrentThreadName(const char* szThreadName) |
| @@ -81,7 +81,7 @@ void SetCurrentThreadName(const char* szThreadName) | |||
| 81 | __except(EXCEPTION_CONTINUE_EXECUTION) | 81 | __except(EXCEPTION_CONTINUE_EXECUTION) |
| 82 | {} | 82 | {} |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | #else // !WIN32, so must be POSIX threads | 85 | #else // !WIN32, so must be POSIX threads |
| 86 | 86 | ||
| 87 | void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) | 87 | void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) |
diff --git a/src/common/thread.h b/src/common/thread.h index f7ace21b4..be9b5cbe2 100644 --- a/src/common/thread.h +++ b/src/common/thread.h | |||
| @@ -30,13 +30,13 @@ int CurrentThreadId(); | |||
| 30 | 30 | ||
| 31 | void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); | 31 | void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); |
| 32 | void SetCurrentThreadAffinity(u32 mask); | 32 | void SetCurrentThreadAffinity(u32 mask); |
| 33 | 33 | ||
| 34 | class Event | 34 | class Event |
| 35 | { | 35 | { |
| 36 | public: | 36 | public: |
| 37 | Event() | 37 | Event() |
| 38 | : is_set(false) | 38 | : is_set(false) |
| 39 | {}; | 39 | {} |
| 40 | 40 | ||
| 41 | void Set() | 41 | void Set() |
| 42 | { | 42 | { |
| @@ -135,7 +135,7 @@ private: | |||
| 135 | const size_t m_count; | 135 | const size_t m_count; |
| 136 | volatile size_t m_waiting; | 136 | volatile size_t m_waiting; |
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | void SleepCurrentThread(int ms); | 139 | void SleepCurrentThread(int ms); |
| 140 | void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms | 140 | void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms |
| 141 | 141 | ||
| @@ -146,7 +146,7 @@ inline void YieldCPU() | |||
| 146 | { | 146 | { |
| 147 | std::this_thread::yield(); | 147 | std::this_thread::yield(); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | void SetCurrentThreadName(const char *name); | 150 | void SetCurrentThreadName(const char *name); |
| 151 | 151 | ||
| 152 | } // namespace Common | 152 | } // namespace Common |
diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h index 4a89572f6..59efbce4c 100644 --- a/src/common/thread_queue_list.h +++ b/src/common/thread_queue_list.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project | 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| @@ -12,7 +12,7 @@ template<class IdType> | |||
| 12 | struct ThreadQueueList { | 12 | struct ThreadQueueList { |
| 13 | // Number of queues (number of priority levels starting at 0.) | 13 | // Number of queues (number of priority levels starting at 0.) |
| 14 | static const int NUM_QUEUES = 128; | 14 | static const int NUM_QUEUES = 128; |
| 15 | 15 | ||
| 16 | // Initial number of threads a single queue can handle. | 16 | // Initial number of threads a single queue can handle. |
| 17 | static const int INITIAL_CAPACITY = 32; | 17 | static const int INITIAL_CAPACITY = 32; |
| 18 | 18 | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f41d52e80..48241c3d4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -31,17 +31,24 @@ set(SRCS | |||
| 31 | hle/kernel/shared_memory.cpp | 31 | hle/kernel/shared_memory.cpp |
| 32 | hle/kernel/thread.cpp | 32 | hle/kernel/thread.cpp |
| 33 | hle/service/ac_u.cpp | 33 | hle/service/ac_u.cpp |
| 34 | hle/service/am_net.cpp | ||
| 34 | hle/service/apt_u.cpp | 35 | hle/service/apt_u.cpp |
| 36 | hle/service/boss_u.cpp | ||
| 37 | hle/service/cfg_i.cpp | ||
| 35 | hle/service/cfg_u.cpp | 38 | hle/service/cfg_u.cpp |
| 39 | hle/service/csnd_snd.cpp | ||
| 36 | hle/service/dsp_dsp.cpp | 40 | hle/service/dsp_dsp.cpp |
| 37 | hle/service/err_f.cpp | 41 | hle/service/err_f.cpp |
| 38 | hle/service/fs_user.cpp | 42 | hle/service/fs_user.cpp |
| 39 | hle/service/frd_u.cpp | 43 | hle/service/frd_u.cpp |
| 40 | hle/service/gsp_gpu.cpp | 44 | hle/service/gsp_gpu.cpp |
| 41 | hle/service/hid_user.cpp | 45 | hle/service/hid_user.cpp |
| 46 | hle/service/ir_rst.cpp | ||
| 47 | hle/service/ir_u.cpp | ||
| 42 | hle/service/mic_u.cpp | 48 | hle/service/mic_u.cpp |
| 43 | hle/service/ndm_u.cpp | 49 | hle/service/ndm_u.cpp |
| 44 | hle/service/nwm_uds.cpp | 50 | hle/service/nwm_uds.cpp |
| 51 | hle/service/pm_app.cpp | ||
| 45 | hle/service/ptm_u.cpp | 52 | hle/service/ptm_u.cpp |
| 46 | hle/service/service.cpp | 53 | hle/service/service.cpp |
| 47 | hle/service/soc_u.cpp | 54 | hle/service/soc_u.cpp |
| @@ -102,23 +109,31 @@ set(HEADERS | |||
| 102 | hle/kernel/shared_memory.h | 109 | hle/kernel/shared_memory.h |
| 103 | hle/kernel/thread.h | 110 | hle/kernel/thread.h |
| 104 | hle/service/ac_u.h | 111 | hle/service/ac_u.h |
| 112 | hle/service/am_net.h | ||
| 105 | hle/service/apt_u.h | 113 | hle/service/apt_u.h |
| 114 | hle/service/boss_u.h | ||
| 115 | hle/service/cfg_i.h | ||
| 106 | hle/service/cfg_u.h | 116 | hle/service/cfg_u.h |
| 117 | hle/service/csnd_snd.h | ||
| 107 | hle/service/dsp_dsp.h | 118 | hle/service/dsp_dsp.h |
| 108 | hle/service/err_f.h | 119 | hle/service/err_f.h |
| 109 | hle/service/fs_user.h | 120 | hle/service/fs_user.h |
| 110 | hle/service/frd_u.h | 121 | hle/service/frd_u.h |
| 111 | hle/service/gsp_gpu.h | 122 | hle/service/gsp_gpu.h |
| 112 | hle/service/hid_user.h | 123 | hle/service/hid_user.h |
| 124 | hle/service/ir_rst.h | ||
| 125 | hle/service/ir_u.h | ||
| 113 | hle/service/mic_u.h | 126 | hle/service/mic_u.h |
| 114 | hle/service/ndm_u.h | 127 | hle/service/ndm_u.h |
| 115 | hle/service/nwm_uds.h | 128 | hle/service/nwm_uds.h |
| 129 | hle/service/pm_app.h | ||
| 116 | hle/service/ptm_u.h | 130 | hle/service/ptm_u.h |
| 117 | hle/service/service.h | 131 | hle/service/service.h |
| 118 | hle/service/soc_u.h | 132 | hle/service/soc_u.h |
| 119 | hle/service/srv.h | 133 | hle/service/srv.h |
| 120 | hle/service/ssl_c.h | 134 | hle/service/ssl_c.h |
| 121 | hle/config_mem.h | 135 | hle/config_mem.h |
| 136 | hle/result.h | ||
| 122 | hle/function_wrappers.h | 137 | hle/function_wrappers.h |
| 123 | hle/hle.h | 138 | hle/hle.h |
| 124 | hle/svc.h | 139 | hle/svc.h |
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 4b93d3313..3ae528562 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| @@ -63,7 +63,7 @@ public: | |||
| 63 | * Get the current CPSR register | 63 | * Get the current CPSR register |
| 64 | * @return Returns the value of the CPSR register | 64 | * @return Returns the value of the CPSR register |
| 65 | */ | 65 | */ |
| 66 | virtual u32 GetCPSR() const = 0; | 66 | virtual u32 GetCPSR() const = 0; |
| 67 | 67 | ||
| 68 | /** | 68 | /** |
| 69 | * Set the current CPSR register | 69 | * Set the current CPSR register |
| @@ -98,7 +98,7 @@ public: | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | protected: | 100 | protected: |
| 101 | 101 | ||
| 102 | /** | 102 | /** |
| 103 | * Executes the given number of instructions | 103 | * Executes the given number of instructions |
| 104 | * @param num_instructions Number of instructions to executes | 104 | * @param num_instructions Number of instructions to executes |
diff --git a/src/core/arm/disassembler/load_symbol_map.cpp b/src/core/arm/disassembler/load_symbol_map.cpp index 0f384ad3e..55278474b 100644 --- a/src/core/arm/disassembler/load_symbol_map.cpp +++ b/src/core/arm/disassembler/load_symbol_map.cpp | |||
| @@ -22,8 +22,8 @@ void LoadSymbolMap(std::string filename) { | |||
| 22 | 22 | ||
| 23 | while (std::getline(infile, line)) { | 23 | while (std::getline(infile, line)) { |
| 24 | std::istringstream iss(line); | 24 | std::istringstream iss(line); |
| 25 | if (!(iss >> address_str >> size >> function_name)) { | 25 | if (!(iss >> address_str >> size >> function_name)) { |
| 26 | break; // Error parsing | 26 | break; // Error parsing |
| 27 | } | 27 | } |
| 28 | u32 address = std::stoul(address_str, nullptr, 16); | 28 | u32 address = std::stoul(address_str, nullptr, 16); |
| 29 | 29 | ||
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index a3ed3e31e..6c8ea211e 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/arm/skyeye_common/armcpu.h" | 5 | #include "core/arm/skyeye_common/armcpu.h" |
| 6 | #include "core/arm/skyeye_common/armemu.h" | 6 | #include "core/arm/skyeye_common/armemu.h" |
| @@ -113,7 +113,7 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) { | |||
| 113 | state->NumInstrsToExecute = num_instructions; | 113 | state->NumInstrsToExecute = num_instructions; |
| 114 | 114 | ||
| 115 | // Dyncom only breaks on instruction dispatch. This only happens on every instruction when | 115 | // Dyncom only breaks on instruction dispatch. This only happens on every instruction when |
| 116 | // executing one instruction at a time. Otherwise, if a block is being executed, more | 116 | // executing one instruction at a time. Otherwise, if a block is being executed, more |
| 117 | // instructions may actually be executed than specified. | 117 | // instructions may actually be executed than specified. |
| 118 | ticks += InterpreterMainLoop(state.get()); | 118 | ticks += InterpreterMainLoop(state.get()); |
| 119 | } | 119 | } |
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 1f8cd3a3a..51eea41ed 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | * Set the Program Counter to an address | 21 | * Set the Program Counter to an address |
| 22 | * @param addr Address to set PC to | 22 | * @param pc Address to set PC to |
| 23 | */ | 23 | */ |
| 24 | void SetPC(u32 pc) override; | 24 | void SetPC(u32 pc) override; |
| 25 | 25 | ||
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/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h index c65eb23f7..3a2462f55 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.h +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp index ed4415082..e2aa5ce92 100644 --- a/src/core/arm/interpreter/arm_interpreter.cpp +++ b/src/core/arm/interpreter/arm_interpreter.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/arm/interpreter/arm_interpreter.h" | 5 | #include "core/arm/interpreter/arm_interpreter.h" |
| 6 | 6 | ||
| @@ -24,7 +24,7 @@ ARM_Interpreter::ARM_Interpreter() { | |||
| 24 | state->lateabtSig = LOW; | 24 | state->lateabtSig = LOW; |
| 25 | 25 | ||
| 26 | // Reset the core to initial state | 26 | // Reset the core to initial state |
| 27 | ARMul_CoProInit(state); | 27 | ARMul_CoProInit(state); |
| 28 | ARMul_Reset(state); | 28 | ARMul_Reset(state); |
| 29 | state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext | 29 | state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext |
| 30 | state->Emulate = 3; | 30 | state->Emulate = 3; |
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h index ceb1be438..ed53d997c 100644 --- a/src/core/arm/interpreter/arm_interpreter.h +++ b/src/core/arm/interpreter/arm_interpreter.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| @@ -18,7 +18,7 @@ public: | |||
| 18 | 18 | ||
| 19 | /** | 19 | /** |
| 20 | * Set the Program Counter to an address | 20 | * Set the Program Counter to an address |
| 21 | * @param addr Address to set PC to | 21 | * @param pc Address to set PC to |
| 22 | */ | 22 | */ |
| 23 | void SetPC(u32 pc) override; | 23 | void SetPC(u32 pc) override; |
| 24 | 24 | ||
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/core.cpp b/src/core/core.cpp index 25c78d33c..865898b24 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -16,10 +16,10 @@ | |||
| 16 | 16 | ||
| 17 | namespace Core { | 17 | namespace Core { |
| 18 | 18 | ||
| 19 | u64 g_last_ticks = 0; ///< Last CPU ticks | 19 | static u64 last_ticks = 0; ///< Last CPU ticks |
| 20 | ARM_Disasm* g_disasm = nullptr; ///< ARM disassembler | 20 | static ARM_Disasm* disasm = nullptr; ///< ARM disassembler |
| 21 | ARM_Interface* g_app_core = nullptr; ///< ARM11 application core | 21 | ARM_Interface* g_app_core = nullptr; ///< ARM11 application core |
| 22 | ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core | 22 | ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core |
| 23 | 23 | ||
| 24 | /// Run the core CPU loop | 24 | /// Run the core CPU loop |
| 25 | void RunLoop(int tight_loop) { | 25 | void RunLoop(int tight_loop) { |
| @@ -49,7 +49,7 @@ void Stop() { | |||
| 49 | int Init() { | 49 | int Init() { |
| 50 | NOTICE_LOG(MASTER_LOG, "initialized OK"); | 50 | NOTICE_LOG(MASTER_LOG, "initialized OK"); |
| 51 | 51 | ||
| 52 | g_disasm = new ARM_Disasm(); | 52 | disasm = new ARM_Disasm(); |
| 53 | g_sys_core = new ARM_Interpreter(); | 53 | g_sys_core = new ARM_Interpreter(); |
| 54 | 54 | ||
| 55 | switch (Settings::values.cpu_core) { | 55 | switch (Settings::values.cpu_core) { |
| @@ -62,13 +62,13 @@ int Init() { | |||
| 62 | break; | 62 | break; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | g_last_ticks = Core::g_app_core->GetTicks(); | 65 | last_ticks = Core::g_app_core->GetTicks(); |
| 66 | 66 | ||
| 67 | return 0; | 67 | return 0; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | void Shutdown() { | 70 | void Shutdown() { |
| 71 | delete g_disasm; | 71 | delete disasm; |
| 72 | delete g_app_core; | 72 | delete g_app_core; |
| 73 | delete g_sys_core; | 73 | delete g_sys_core; |
| 74 | 74 | ||
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 0116cb376..558c6cbf7 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -41,7 +41,7 @@ struct BaseEvent | |||
| 41 | s64 time; | 41 | s64 time; |
| 42 | u64 userdata; | 42 | u64 userdata; |
| 43 | int type; | 43 | int type; |
| 44 | // Event *next; | 44 | // Event *next; |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | typedef LinkedListItem<BaseEvent> Event; | 47 | typedef LinkedListItem<BaseEvent> Event; |
| @@ -249,7 +249,7 @@ void AddEventToQueue(Event* ne) | |||
| 249 | 249 | ||
| 250 | // This must be run ONLY from within the cpu thread | 250 | // This must be run ONLY from within the cpu thread |
| 251 | // cyclesIntoFuture may be VERY inaccurate if called from anything else | 251 | // cyclesIntoFuture may be VERY inaccurate if called from anything else |
| 252 | // than Advance | 252 | // than Advance |
| 253 | void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata) | 253 | void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata) |
| 254 | { | 254 | { |
| 255 | Event *ne = GetNewEvent(); | 255 | Event *ne = GetNewEvent(); |
| @@ -469,8 +469,8 @@ void ProcessFifoWaitEvents() | |||
| 469 | { | 469 | { |
| 470 | if (first->time <= globalTimer) | 470 | if (first->time <= globalTimer) |
| 471 | { | 471 | { |
| 472 | // LOG(TIMER, "[Scheduler] %s (%lld, %lld) ", | 472 | //LOG(TIMER, "[Scheduler] %s (%lld, %lld) ", |
| 473 | // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time); | 473 | // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time); |
| 474 | Event* evt = first; | 474 | Event* evt = first; |
| 475 | first = first->next; | 475 | first = first->next; |
| 476 | event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time)); | 476 | event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time)); |
| @@ -516,23 +516,23 @@ void Advance() | |||
| 516 | //currentMIPS->downcount = slicelength; | 516 | //currentMIPS->downcount = slicelength; |
| 517 | 517 | ||
| 518 | //if (Common::AtomicLoadAcquire(hasTsEvents)) | 518 | //if (Common::AtomicLoadAcquire(hasTsEvents)) |
| 519 | // MoveEvents(); | 519 | // MoveEvents(); |
| 520 | //ProcessFifoWaitEvents(); | 520 | //ProcessFifoWaitEvents(); |
| 521 | 521 | ||
| 522 | //if (!first) | 522 | //if (!first) |
| 523 | //{ | 523 | //{ |
| 524 | // // WARN_LOG(TIMER, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000"); | 524 | // // WARN_LOG(TIMER, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000"); |
| 525 | // currentMIPS->downcount += 10000; | 525 | // currentMIPS->downcount += 10000; |
| 526 | //} | 526 | //} |
| 527 | //else | 527 | //else |
| 528 | //{ | 528 | //{ |
| 529 | // slicelength = (int)(first->time - globalTimer); | 529 | // slicelength = (int)(first->time - globalTimer); |
| 530 | // if (slicelength > MAX_SLICE_LENGTH) | 530 | // if (slicelength > MAX_SLICE_LENGTH) |
| 531 | // slicelength = MAX_SLICE_LENGTH; | 531 | // slicelength = MAX_SLICE_LENGTH; |
| 532 | // currentMIPS->downcount = slicelength; | 532 | // currentMIPS->downcount = slicelength; |
| 533 | //} | 533 | //} |
| 534 | //if (advanceCallback) | 534 | //if (advanceCallback) |
| 535 | // advanceCallback(cyclesExecuted); | 535 | // advanceCallback(cyclesExecuted); |
| 536 | } | 536 | } |
| 537 | 537 | ||
| 538 | void LogPendingEvents() | 538 | void LogPendingEvents() |
| @@ -550,20 +550,20 @@ void Idle(int maxIdle) | |||
| 550 | ERROR_LOG(TIME, "Unimplemented function!"); | 550 | ERROR_LOG(TIME, "Unimplemented function!"); |
| 551 | //int cyclesDown = currentMIPS->downcount; | 551 | //int cyclesDown = currentMIPS->downcount; |
| 552 | //if (maxIdle != 0 && cyclesDown > maxIdle) | 552 | //if (maxIdle != 0 && cyclesDown > maxIdle) |
| 553 | // cyclesDown = maxIdle; | 553 | // cyclesDown = maxIdle; |
| 554 | 554 | ||
| 555 | //if (first && cyclesDown > 0) | 555 | //if (first && cyclesDown > 0) |
| 556 | //{ | 556 | //{ |
| 557 | // int cyclesExecuted = slicelength - currentMIPS->downcount; | 557 | // int cyclesExecuted = slicelength - currentMIPS->downcount; |
| 558 | // int cyclesNextEvent = (int) (first->time - globalTimer); | 558 | // int cyclesNextEvent = (int) (first->time - globalTimer); |
| 559 | 559 | ||
| 560 | // if (cyclesNextEvent < cyclesExecuted + cyclesDown) | 560 | // if (cyclesNextEvent < cyclesExecuted + cyclesDown) |
| 561 | // { | 561 | // { |
| 562 | // cyclesDown = cyclesNextEvent - cyclesExecuted; | 562 | // cyclesDown = cyclesNextEvent - cyclesExecuted; |
| 563 | // // Now, now... no time machines, please. | 563 | // // Now, now... no time machines, please. |
| 564 | // if (cyclesDown < 0) | 564 | // if (cyclesDown < 0) |
| 565 | // cyclesDown = 0; | 565 | // cyclesDown = 0; |
| 566 | // } | 566 | // } |
| 567 | //} | 567 | //} |
| 568 | 568 | ||
| 569 | //INFO_LOG(TIME, "Idle for %i cycles! (%f ms)", cyclesDown, cyclesDown / (float)(g_clock_rate_arm11 * 0.001f)); | 569 | //INFO_LOG(TIME, "Idle for %i cycles! (%f ms)", cyclesDown, cyclesDown / (float)(g_clock_rate_arm11 * 0.001f)); |
| @@ -571,7 +571,7 @@ void Idle(int maxIdle) | |||
| 571 | //idledCycles += cyclesDown; | 571 | //idledCycles += cyclesDown; |
| 572 | //currentMIPS->downcount -= cyclesDown; | 572 | //currentMIPS->downcount -= cyclesDown; |
| 573 | //if (currentMIPS->downcount == 0) | 573 | //if (currentMIPS->downcount == 0) |
| 574 | // currentMIPS->downcount = -1; | 574 | // currentMIPS->downcount = -1; |
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | std::string GetScheduledEventsSummary() | 577 | std::string GetScheduledEventsSummary() |
| @@ -623,4 +623,4 @@ void DoState(PointerWrap &p) | |||
| 623 | p.Do(idledCycles); | 623 | p.Do(idledCycles); |
| 624 | } | 624 | } |
| 625 | 625 | ||
| 626 | } // namespace | 626 | } // namespace |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 09fdf7a90..b197cf40c 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -106,4 +106,4 @@ void SetClockFrequencyMHz(int cpuMhz); | |||
| 106 | int GetClockFrequencyMHz(); | 106 | int GetClockFrequencyMHz(); |
| 107 | extern int slicelength; | 107 | extern int slicelength; |
| 108 | 108 | ||
| 109 | }; // namespace | 109 | } // namespace |
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h index 38145eed8..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 | ||
| @@ -74,6 +76,35 @@ public: | |||
| 74 | return type; | 76 | return type; |
| 75 | } | 77 | } |
| 76 | 78 | ||
| 79 | /** | ||
| 80 | * Gets the string representation of the path for debugging | ||
| 81 | * @return String representation of the path for debugging | ||
| 82 | */ | ||
| 83 | const std::string DebugStr() const { | ||
| 84 | switch (GetType()) { | ||
| 85 | case Invalid: | ||
| 86 | return "[Invalid]"; | ||
| 87 | case Empty: | ||
| 88 | return "[Empty]"; | ||
| 89 | case Binary: | ||
| 90 | { | ||
| 91 | std::stringstream res; | ||
| 92 | res << "[Binary: "; | ||
| 93 | for (unsigned byte : binary) | ||
| 94 | res << std::hex << std::setw(2) << std::setfill('0') << byte; | ||
| 95 | res << ']'; | ||
| 96 | return res.str(); | ||
| 97 | } | ||
| 98 | case Char: | ||
| 99 | return "[Char: " + AsString() + ']'; | ||
| 100 | case Wchar: | ||
| 101 | return "[Wchar: " + AsString() + ']'; | ||
| 102 | default: | ||
| 103 | ERROR_LOG(KERNEL, "LowPathType cannot be converted to string!"); | ||
| 104 | return {}; | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 77 | const std::string AsString() const { | 108 | const std::string AsString() const { |
| 78 | switch (GetType()) { | 109 | switch (GetType()) { |
| 79 | case Char: | 110 | case Char: |
| @@ -153,21 +184,35 @@ public: | |||
| 153 | * @param mode Mode to open the file with | 184 | * @param mode Mode to open the file with |
| 154 | * @return Opened file, or nullptr | 185 | * @return Opened file, or nullptr |
| 155 | */ | 186 | */ |
| 156 | virtual std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const = 0; | 187 | virtual std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const = 0; |
| 188 | |||
| 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; | ||
| 157 | 202 | ||
| 158 | /** | 203 | /** |
| 159 | * Create a directory specified by its path | 204 | * Create a directory specified by its path |
| 160 | * @param path Path relative to the archive | 205 | * @param path Path relative to the archive |
| 161 | * @return Whether the directory could be created | 206 | * @return Whether the directory could be created |
| 162 | */ | 207 | */ |
| 163 | virtual bool CreateDirectory(const std::string& path) const = 0; | 208 | virtual bool CreateDirectory(const Path& path) const = 0; |
| 164 | 209 | ||
| 165 | /** | 210 | /** |
| 166 | * Open a directory specified by its path | 211 | * Open a directory specified by its path |
| 167 | * @param path Path relative to the archive | 212 | * @param path Path relative to the archive |
| 168 | * @return Opened directory, or nullptr | 213 | * @return Opened directory, or nullptr |
| 169 | */ | 214 | */ |
| 170 | virtual std::unique_ptr<Directory> OpenDirectory(const std::string& path) const = 0; | 215 | virtual std::unique_ptr<Directory> OpenDirectory(const Path& path) const = 0; |
| 171 | 216 | ||
| 172 | /** | 217 | /** |
| 173 | * Read data from the archive | 218 | * Read data from the archive |
| @@ -193,7 +238,7 @@ public: | |||
| 193 | * @return Size of the archive in bytes | 238 | * @return Size of the archive in bytes |
| 194 | */ | 239 | */ |
| 195 | virtual size_t GetSize() const = 0; | 240 | virtual size_t GetSize() const = 0; |
| 196 | 241 | ||
| 197 | /** | 242 | /** |
| 198 | * Set the size of the archive in bytes | 243 | * Set the size of the archive in bytes |
| 199 | */ | 244 | */ |
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index cc759faa8..53dc57954 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -29,26 +29,46 @@ Archive_RomFS::~Archive_RomFS() { | |||
| 29 | * @param mode Mode to open the file with | 29 | * @param mode Mode to open the file with |
| 30 | * @return Opened file, or nullptr | 30 | * @return Opened file, or nullptr |
| 31 | */ | 31 | */ |
| 32 | std::unique_ptr<File> Archive_RomFS::OpenFile(const std::string& path, const Mode mode) const { | 32 | std::unique_ptr<File> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { |
| 33 | return std::unique_ptr<File>(new File_RomFS); | 33 | return std::unique_ptr<File>(new File_RomFS); |
| 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 |
| 40 | */ | 60 | */ |
| 41 | bool Archive_RomFS::CreateDirectory(const std::string& path) const { | 61 | bool Archive_RomFS::CreateDirectory(const Path& path) const { |
| 42 | ERROR_LOG(FILESYS, "Attempted to create a directory in ROMFS."); | 62 | ERROR_LOG(FILESYS, "Attempted to create a directory in ROMFS."); |
| 43 | return false; | 63 | return false; |
| 44 | }; | 64 | } |
| 45 | 65 | ||
| 46 | /** | 66 | /** |
| 47 | * Open a directory specified by its path | 67 | * Open a directory specified by its path |
| 48 | * @param path Path relative to the archive | 68 | * @param path Path relative to the archive |
| 49 | * @return Opened directory, or nullptr | 69 | * @return Opened directory, or nullptr |
| 50 | */ | 70 | */ |
| 51 | std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const std::string& path) const { | 71 | std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const Path& path) const { |
| 52 | return std::unique_ptr<Directory>(new Directory_RomFS); | 72 | return std::unique_ptr<Directory>(new Directory_RomFS); |
| 53 | } | 73 | } |
| 54 | 74 | ||
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index ae2344e82..0649dde99 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -26,7 +26,7 @@ public: | |||
| 26 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | 26 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) |
| 27 | * @return IdCode of the archive | 27 | * @return IdCode of the archive |
| 28 | */ | 28 | */ |
| 29 | IdCode GetIdCode() const override { return IdCode::RomFS; }; | 29 | IdCode GetIdCode() const override { return IdCode::RomFS; } |
| 30 | 30 | ||
| 31 | /** | 31 | /** |
| 32 | * Open a file specified by its path, using the specified mode | 32 | * Open a file specified by its path, using the specified mode |
| @@ -34,21 +34,35 @@ public: | |||
| 34 | * @param mode Mode to open the file with | 34 | * @param mode Mode to open the file with |
| 35 | * @return Opened file, or nullptr | 35 | * @return Opened file, or nullptr |
| 36 | */ | 36 | */ |
| 37 | std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; | 37 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; |
| 38 | |||
| 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; | ||
| 38 | 52 | ||
| 39 | /** | 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 |
| 43 | */ | 57 | */ |
| 44 | bool CreateDirectory(const std::string& path) const override; | 58 | bool CreateDirectory(const Path& path) const override; |
| 45 | 59 | ||
| 46 | /** | 60 | /** |
| 47 | * Open a directory specified by its path | 61 | * Open a directory specified by its path |
| 48 | * @param path Path relative to the archive | 62 | * @param path Path relative to the archive |
| 49 | * @return Opened directory, or nullptr | 63 | * @return Opened directory, or nullptr |
| 50 | */ | 64 | */ |
| 51 | std::unique_ptr<Directory> OpenDirectory(const std::string& path) const override; | 65 | std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; |
| 52 | 66 | ||
| 53 | /** | 67 | /** |
| 54 | * Read data from the archive | 68 | * Read data from the archive |
| @@ -74,7 +88,7 @@ public: | |||
| 74 | * @return Size of the archive in bytes | 88 | * @return Size of the archive in bytes |
| 75 | */ | 89 | */ |
| 76 | size_t GetSize() const override; | 90 | size_t GetSize() const override; |
| 77 | 91 | ||
| 78 | /** | 92 | /** |
| 79 | * Set the size of the archive in bytes | 93 | * Set the size of the archive in bytes |
| 80 | */ | 94 | */ |
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 66931e93e..789212b17 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -49,8 +49,8 @@ bool Archive_SDMC::Initialize() { | |||
| 49 | * @param mode Mode to open the file with | 49 | * @param mode Mode to open the file with |
| 50 | * @return Opened file, or nullptr | 50 | * @return Opened file, or nullptr |
| 51 | */ | 51 | */ |
| 52 | std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& 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.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,12 +58,30 @@ std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const 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 |
| 64 | */ | 82 | */ |
| 65 | bool Archive_SDMC::CreateDirectory(const std::string& path) const { | 83 | bool Archive_SDMC::CreateDirectory(const Path& path) const { |
| 66 | return FileUtil::CreateDir(GetMountPoint() + path); | 84 | return FileUtil::CreateDir(GetMountPoint() + path.AsString()); |
| 67 | } | 85 | } |
| 68 | 86 | ||
| 69 | /** | 87 | /** |
| @@ -71,8 +89,8 @@ bool Archive_SDMC::CreateDirectory(const std::string& path) const { | |||
| 71 | * @param path Path relative to the archive | 89 | * @param path Path relative to the archive |
| 72 | * @return Opened directory, or nullptr | 90 | * @return Opened directory, or nullptr |
| 73 | */ | 91 | */ |
| 74 | std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const std::string& path) const { | 92 | std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const { |
| 75 | DEBUG_LOG(FILESYS, "called path=%s", path.c_str()); | 93 | DEBUG_LOG(FILESYS, "called path=%s", path.DebugStr().c_str()); |
| 76 | Directory_SDMC* directory = new Directory_SDMC(this, path); | 94 | Directory_SDMC* directory = new Directory_SDMC(this, path); |
| 77 | return std::unique_ptr<Directory>(directory); | 95 | return std::unique_ptr<Directory>(directory); |
| 78 | } | 96 | } |
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 0e059b635..74ce29c0d 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -30,7 +30,7 @@ public: | |||
| 30 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | 30 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) |
| 31 | * @return IdCode of the archive | 31 | * @return IdCode of the archive |
| 32 | */ | 32 | */ |
| 33 | IdCode GetIdCode() const override { return IdCode::SDMC; }; | 33 | IdCode GetIdCode() const override { return IdCode::SDMC; } |
| 34 | 34 | ||
| 35 | /** | 35 | /** |
| 36 | * Open a file specified by its path, using the specified mode | 36 | * Open a file specified by its path, using the specified mode |
| @@ -38,21 +38,35 @@ public: | |||
| 38 | * @param mode Mode to open the file with | 38 | * @param mode Mode to open the file with |
| 39 | * @return Opened file, or nullptr | 39 | * @return Opened file, or nullptr |
| 40 | */ | 40 | */ |
| 41 | std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; | 41 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; |
| 42 | |||
| 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; | ||
| 42 | 56 | ||
| 43 | /** | 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 |
| 47 | */ | 61 | */ |
| 48 | bool CreateDirectory(const std::string& path) const override; | 62 | bool CreateDirectory(const Path& path) const override; |
| 49 | 63 | ||
| 50 | /** | 64 | /** |
| 51 | * Open a directory specified by its path | 65 | * Open a directory specified by its path |
| 52 | * @param path Path relative to the archive | 66 | * @param path Path relative to the archive |
| 53 | * @return Opened directory, or nullptr | 67 | * @return Opened directory, or nullptr |
| 54 | */ | 68 | */ |
| 55 | std::unique_ptr<Directory> OpenDirectory(const std::string& path) const override; | 69 | std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; |
| 56 | 70 | ||
| 57 | /** | 71 | /** |
| 58 | * Read data from the archive | 72 | * Read data from the archive |
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp index fd558def9..60a197ce9 100644 --- a/src/core/file_sys/directory_sdmc.cpp +++ b/src/core/file_sys/directory_sdmc.cpp | |||
| @@ -15,11 +15,11 @@ | |||
| 15 | 15 | ||
| 16 | namespace FileSys { | 16 | namespace FileSys { |
| 17 | 17 | ||
| 18 | Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const std::string& path) { | 18 | Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const Path& path) { |
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass |
| 20 | // the root directory we set while opening the archive. | 20 | // the root directory we set while opening the archive. |
| 21 | // For example, opening /../../usr/bin can give the emulated program your installed programs. | 21 | // For example, opening /../../usr/bin can give the emulated program your installed programs. |
| 22 | std::string absolute_path = archive->GetMountPoint() + path; | 22 | std::string absolute_path = archive->GetMountPoint() + path.AsString(); |
| 23 | FileUtil::ScanDirectoryTree(absolute_path, directory); | 23 | FileUtil::ScanDirectoryTree(absolute_path, directory); |
| 24 | children_iterator = directory.children.begin(); | 24 | children_iterator = directory.children.begin(); |
| 25 | } | 25 | } |
| @@ -45,7 +45,7 @@ u32 Directory_SDMC::Read(const u32 count, Entry* entries) { | |||
| 45 | WARN_LOG(FILESYS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory); | 45 | WARN_LOG(FILESYS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory); |
| 46 | 46 | ||
| 47 | // TODO(Link Mauve): use a proper conversion to UTF-16. | 47 | // TODO(Link Mauve): use a proper conversion to UTF-16. |
| 48 | for (int j = 0; j < FILENAME_LENGTH; ++j) { | 48 | for (size_t j = 0; j < FILENAME_LENGTH; ++j) { |
| 49 | entry.filename[j] = filename[j]; | 49 | entry.filename[j] = filename[j]; |
| 50 | if (!filename[j]) | 50 | if (!filename[j]) |
| 51 | break; | 51 | break; |
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h index cb8d32fda..4520d0401 100644 --- a/src/core/file_sys/directory_sdmc.h +++ b/src/core/file_sys/directory_sdmc.h | |||
| @@ -19,7 +19,7 @@ namespace FileSys { | |||
| 19 | class Directory_SDMC final : public Directory { | 19 | class Directory_SDMC final : public Directory { |
| 20 | public: | 20 | public: |
| 21 | Directory_SDMC(); | 21 | Directory_SDMC(); |
| 22 | Directory_SDMC(const Archive_SDMC* archive, const std::string& path); | 22 | Directory_SDMC(const Archive_SDMC* archive, const Path& path); |
| 23 | ~Directory_SDMC() override; | 23 | ~Directory_SDMC() override; |
| 24 | 24 | ||
| 25 | /** | 25 | /** |
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp index 26204392c..a4b90670a 100644 --- a/src/core/file_sys/file_sdmc.cpp +++ b/src/core/file_sys/file_sdmc.cpp | |||
| @@ -15,11 +15,11 @@ | |||
| 15 | 15 | ||
| 16 | namespace FileSys { | 16 | namespace FileSys { |
| 17 | 17 | ||
| 18 | File_SDMC::File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode) { | 18 | File_SDMC::File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode) { |
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass |
| 20 | // the root directory we set while opening the archive. | 20 | // the root directory we set while opening the archive. |
| 21 | // For example, opening /../../etc/passwd can give the emulated program your users list. | 21 | // For example, opening /../../etc/passwd can give the emulated program your users list. |
| 22 | this->path = archive->GetMountPoint() + path; | 22 | this->path = archive->GetMountPoint() + path.AsString(); |
| 23 | this->mode.hex = mode.hex; | 23 | this->mode.hex = mode.hex; |
| 24 | } | 24 | } |
| 25 | 25 | ||
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h index df032f7c0..80b445968 100644 --- a/src/core/file_sys/file_sdmc.h +++ b/src/core/file_sys/file_sdmc.h | |||
| @@ -19,7 +19,7 @@ namespace FileSys { | |||
| 19 | class File_SDMC final : public File { | 19 | class File_SDMC final : public File { |
| 20 | public: | 20 | public: |
| 21 | File_SDMC(); | 21 | File_SDMC(); |
| 22 | File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode); | 22 | File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode); |
| 23 | ~File_SDMC() override; | 23 | ~File_SDMC() override; |
| 24 | 24 | ||
| 25 | /** | 25 | /** |
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp index a45e61427..c7cf5b1d3 100644 --- a/src/core/hle/config_mem.cpp +++ b/src/core/hle/config_mem.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | 6 | ||
diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp index 1eb33eb86..e34229a57 100644 --- a/src/core/hle/coprocessor.cpp +++ b/src/core/hle/coprocessor.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/hle/coprocessor.h" | 5 | #include "core/hle/coprocessor.h" |
| 6 | #include "core/hle/hle.h" | 6 | #include "core/hle/hle.h" |
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 55eaf0621..3dbe25037 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h | |||
| @@ -50,7 +50,7 @@ template<s32 func(u32*, u32, u32, u32, u32, u32)> void Wrap(){ | |||
| 50 | 50 | ||
| 51 | template<s32 func(s32*, u32*, s32, bool, s64)> void Wrap() { | 51 | template<s32 func(s32*, u32*, s32, bool, s64)> void Wrap() { |
| 52 | s32 param_1 = 0; | 52 | s32 param_1 = 0; |
| 53 | s32 retval = func(¶m_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), | 53 | s32 retval = func(¶m_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), |
| 54 | (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))); | 54 | (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))); |
| 55 | Core::g_app_core->SetReg(1, (u32)param_1); | 55 | Core::g_app_core->SetReg(1, (u32)param_1); |
| 56 | FuncReturn(retval); | 56 | FuncReturn(retval); |
| @@ -103,7 +103,7 @@ template<s32 func(void*)> void Wrap() { | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | template<s32 func(s64*, u32, void*, s32)> void Wrap(){ | 105 | template<s32 func(s64*, u32, void*, s32)> void Wrap(){ |
| 106 | FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), | 106 | FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), |
| 107 | (s32)PARAM(3))); | 107 | (s32)PARAM(3))); |
| 108 | } | 108 | } |
| 109 | 109 | ||
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index b03894ad7..b8ac186f6 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <vector> | 5 | #include <vector> |
| 6 | 6 | ||
| @@ -20,7 +20,7 @@ bool g_reschedule = false; ///< If true, immediately reschedules the CPU to a n | |||
| 20 | const FunctionDef* GetSVCInfo(u32 opcode) { | 20 | const FunctionDef* GetSVCInfo(u32 opcode) { |
| 21 | u32 func_num = opcode & 0xFFFFFF; // 8 bits | 21 | u32 func_num = opcode & 0xFFFFFF; // 8 bits |
| 22 | if (func_num > 0xFF) { | 22 | if (func_num > 0xFF) { |
| 23 | ERROR_LOG(HLE,"unknown svc=0x%02X", func_num); | 23 | ERROR_LOG(HLE,"unknown svc=0x%02X", func_num); |
| 24 | return nullptr; | 24 | return nullptr; |
| 25 | } | 25 | } |
| 26 | return &g_module_db[0].func_table[func_num]; | 26 | return &g_module_db[0].func_table[func_num]; |
| @@ -58,7 +58,7 @@ void RegisterAllModules() { | |||
| 58 | 58 | ||
| 59 | void Init() { | 59 | void Init() { |
| 60 | Service::Init(); | 60 | Service::Init(); |
| 61 | 61 | ||
| 62 | RegisterAllModules(); | 62 | RegisterAllModules(); |
| 63 | 63 | ||
| 64 | NOTICE_LOG(HLE, "initialized OK"); | 64 | NOTICE_LOG(HLE, "initialized OK"); |
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index bf4d84575..4ab258c69 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
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 a483fe466..8a5fb10b4 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | // Address arbiters are an underlying kernel synchronization object that can be created/used via | 11 | // Address arbiters are an underlying kernel synchronization object that can be created/used via |
| 12 | // supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR | 12 | // supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR |
| 13 | // applications use them as an underlying mechanism to implement thread-safe barriers, events, and | 13 | // applications use them as an underlying mechanism to implement thread-safe barriers, events, and |
| 14 | // semphores. | 14 | // semphores. |
| 15 | 15 | ||
| 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 17 | // Kernel namespace | 17 | // Kernel namespace |
| @@ -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 764082d71..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,15 +52,10 @@ 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 | ||
| 63 | switch (cmd) { | 59 | switch (cmd) { |
| 64 | // Read from archive... | 60 | // Read from archive... |
| 65 | case FileCommand::Read: | 61 | case FileCommand::Read: |
| @@ -99,7 +95,6 @@ public: | |||
| 99 | case FileCommand::Close: | 95 | case FileCommand::Close: |
| 100 | { | 96 | { |
| 101 | DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); | 97 | DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); |
| 102 | Kernel::g_object_pool.Destroy<Archive>(GetHandle()); | ||
| 103 | CloseArchive(backend->GetIdCode()); | 98 | CloseArchive(backend->GetIdCode()); |
| 104 | break; | 99 | break; |
| 105 | } | 100 | } |
| @@ -107,42 +102,32 @@ public: | |||
| 107 | default: | 102 | default: |
| 108 | { | 103 | { |
| 109 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 104 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 110 | return -1; | 105 | return UnimplementedFunction(ErrorModule::FS); |
| 111 | } | 106 | } |
| 112 | } | 107 | } |
| 113 | cmd_buff[1] = 0; // No error | 108 | cmd_buff[1] = 0; // No error |
| 114 | return 0; | 109 | return MakeResult<bool>(false); |
| 115 | } | 110 | } |
| 116 | 111 | ||
| 117 | /** | 112 | ResultVal<bool> WaitSynchronization() override { |
| 118 | * Wait for kernel object to synchronize | ||
| 119 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 120 | * @return Result of operation, 0 on success, otherwise error code | ||
| 121 | */ | ||
| 122 | Result WaitSynchronization(bool* wait) override { | ||
| 123 | // TODO(bunnei): ImplementMe | 113 | // TODO(bunnei): ImplementMe |
| 124 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 114 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 125 | return 0; | 115 | return UnimplementedFunction(ErrorModule::FS); |
| 126 | } | 116 | } |
| 127 | }; | 117 | }; |
| 128 | 118 | ||
| 129 | class File : public Object { | 119 | class File : public Object { |
| 130 | public: | 120 | public: |
| 131 | std::string GetTypeName() const override { return "File"; } | 121 | std::string GetTypeName() const override { return "File"; } |
| 132 | std::string GetName() const override { return path; } | 122 | std::string GetName() const override { return path.DebugStr(); } |
| 133 | 123 | ||
| 134 | static Kernel::HandleType GetStaticHandleType() { return HandleType::File; } | 124 | static Kernel::HandleType GetStaticHandleType() { return HandleType::File; } |
| 135 | Kernel::HandleType GetHandleType() const override { return HandleType::File; } | 125 | Kernel::HandleType GetHandleType() const override { return HandleType::File; } |
| 136 | 126 | ||
| 137 | std::string path; ///< Path of the file | 127 | FileSys::Path path; ///< Path of the file |
| 138 | std::unique_ptr<FileSys::File> backend; ///< File backend interface | 128 | std::unique_ptr<FileSys::File> backend; ///< File backend interface |
| 139 | 129 | ||
| 140 | /** | 130 | ResultVal<bool> SyncRequest() override { |
| 141 | * Synchronize kernel object | ||
| 142 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 143 | * @return Result of operation, 0 on success, otherwise error code | ||
| 144 | */ | ||
| 145 | Result SyncRequest(bool* wait) override { | ||
| 146 | u32* cmd_buff = Service::GetCommandBuffer(); | 131 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 147 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | 132 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 148 | switch (cmd) { | 133 | switch (cmd) { |
| @@ -184,7 +169,8 @@ public: | |||
| 184 | case FileCommand::SetSize: | 169 | case FileCommand::SetSize: |
| 185 | { | 170 | { |
| 186 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | 171 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); |
| 187 | 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); | ||
| 188 | backend->SetSize(size); | 174 | backend->SetSize(size); |
| 189 | break; | 175 | break; |
| 190 | } | 176 | } |
| @@ -199,42 +185,33 @@ public: | |||
| 199 | // Unknown command... | 185 | // Unknown command... |
| 200 | default: | 186 | default: |
| 201 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 187 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 202 | cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. | 188 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 203 | return -1; | 189 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 190 | return error; | ||
| 204 | } | 191 | } |
| 205 | cmd_buff[1] = 0; // No error | 192 | cmd_buff[1] = 0; // No error |
| 206 | return 0; | 193 | return MakeResult<bool>(false); |
| 207 | } | 194 | } |
| 208 | 195 | ||
| 209 | /** | 196 | ResultVal<bool> WaitSynchronization() override { |
| 210 | * Wait for kernel object to synchronize | ||
| 211 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 212 | * @return Result of operation, 0 on success, otherwise error code | ||
| 213 | */ | ||
| 214 | Result WaitSynchronization(bool* wait) override { | ||
| 215 | // TODO(bunnei): ImplementMe | 197 | // TODO(bunnei): ImplementMe |
| 216 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 198 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 217 | return 0; | 199 | return UnimplementedFunction(ErrorModule::FS); |
| 218 | } | 200 | } |
| 219 | }; | 201 | }; |
| 220 | 202 | ||
| 221 | class Directory : public Object { | 203 | class Directory : public Object { |
| 222 | public: | 204 | public: |
| 223 | std::string GetTypeName() const override { return "Directory"; } | 205 | std::string GetTypeName() const override { return "Directory"; } |
| 224 | std::string GetName() const override { return path; } | 206 | std::string GetName() const override { return path.DebugStr(); } |
| 225 | 207 | ||
| 226 | static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; } | 208 | static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; } |
| 227 | Kernel::HandleType GetHandleType() const override { return HandleType::Directory; } | 209 | Kernel::HandleType GetHandleType() const override { return HandleType::Directory; } |
| 228 | 210 | ||
| 229 | std::string path; ///< Path of the directory | 211 | FileSys::Path path; ///< Path of the directory |
| 230 | std::unique_ptr<FileSys::Directory> backend; ///< File backend interface | 212 | std::unique_ptr<FileSys::Directory> backend; ///< File backend interface |
| 231 | 213 | ||
| 232 | /** | 214 | ResultVal<bool> SyncRequest() override { |
| 233 | * Synchronize kernel object | ||
| 234 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 235 | * @return Result of operation, 0 on success, otherwise error code | ||
| 236 | */ | ||
| 237 | Result SyncRequest(bool* wait) override { | ||
| 238 | u32* cmd_buff = Service::GetCommandBuffer(); | 215 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 239 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | 216 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); |
| 240 | switch (cmd) { | 217 | switch (cmd) { |
| @@ -244,8 +221,9 @@ public: | |||
| 244 | { | 221 | { |
| 245 | u32 count = cmd_buff[1]; | 222 | u32 count = cmd_buff[1]; |
| 246 | u32 address = cmd_buff[3]; | 223 | u32 address = cmd_buff[3]; |
| 247 | FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); | 224 | auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); |
| 248 | 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); | ||
| 249 | 227 | ||
| 250 | // Number of entries actually read | 228 | // Number of entries actually read |
| 251 | cmd_buff[2] = backend->Read(count, entries); | 229 | cmd_buff[2] = backend->Read(count, entries); |
| @@ -262,22 +240,18 @@ public: | |||
| 262 | // Unknown command... | 240 | // Unknown command... |
| 263 | default: | 241 | default: |
| 264 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 242 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 265 | cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. | 243 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 266 | return -1; | 244 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 245 | return error; | ||
| 267 | } | 246 | } |
| 268 | cmd_buff[1] = 0; // No error | 247 | cmd_buff[1] = 0; // No error |
| 269 | return 0; | 248 | return MakeResult<bool>(false); |
| 270 | } | 249 | } |
| 271 | 250 | ||
| 272 | /** | 251 | ResultVal<bool> WaitSynchronization() override { |
| 273 | * Wait for kernel object to synchronize | ||
| 274 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 275 | * @return Result of operation, 0 on success, otherwise error code | ||
| 276 | */ | ||
| 277 | Result WaitSynchronization(bool* wait) override { | ||
| 278 | // TODO(bunnei): ImplementMe | 252 | // TODO(bunnei): ImplementMe |
| 279 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 253 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 280 | return 0; | 254 | return UnimplementedFunction(ErrorModule::FS); |
| 281 | } | 255 | } |
| 282 | }; | 256 | }; |
| 283 | 257 | ||
| @@ -285,108 +259,124 @@ public: | |||
| 285 | 259 | ||
| 286 | 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 |
| 287 | 261 | ||
| 288 | /** | 262 | ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) { |
| 289 | * Opens an archive | ||
| 290 | * @param id_code IdCode of the archive to open | ||
| 291 | * @return Handle to archive if it exists, otherwise a null handle (0) | ||
| 292 | */ | ||
| 293 | Handle OpenArchive(FileSys::Archive::IdCode id_code) { | ||
| 294 | auto itr = g_archive_map.find(id_code); | 263 | auto itr = g_archive_map.find(id_code); |
| 295 | if (itr == g_archive_map.end()) { | 264 | if (itr == g_archive_map.end()) { |
| 296 | return 0; | 265 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 266 | ErrorSummary::NotFound, ErrorLevel::Permanent); | ||
| 297 | } | 267 | } |
| 298 | return itr->second; | 268 | |
| 269 | return MakeResult<Handle>(itr->second); | ||
| 299 | } | 270 | } |
| 300 | 271 | ||
| 301 | /** | 272 | ResultCode CloseArchive(FileSys::Archive::IdCode id_code) { |
| 302 | * Closes an archive | 273 | auto itr = g_archive_map.find(id_code); |
| 303 | * @param id_code IdCode of the archive to open | 274 | if (itr == g_archive_map.end()) { |
| 304 | * @return Result of operation, 0 on success, otherwise error code | 275 | ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); |
| 305 | */ | 276 | return InvalidHandle(ErrorModule::FS); |
| 306 | Result CloseArchive(FileSys::Archive::IdCode id_code) { | ||
| 307 | if (1 != g_archive_map.erase(id_code)) { | ||
| 308 | ERROR_LOG(KERNEL, "Cannot close archive %d", (int) id_code); | ||
| 309 | return -1; | ||
| 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); |
| 306 | if (result.IsError()) { | ||
| 307 | return result; | ||
| 308 | } | ||
| 346 | 309 | ||
| 347 | return archive; | 310 | return RESULT_SUCCESS; |
| 348 | } | 311 | } |
| 349 | 312 | ||
| 350 | /** | 313 | ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { |
| 351 | * Creates an Archive | 314 | // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create |
| 352 | * @param backend File system backend interface to the archive | 315 | // the archive file handles at app loading, and then keep them persistent throughout execution. |
| 353 | * @param name Optional name of Archive | 316 | // Archives file handles are just reused and not actually freed until emulation shut down. |
| 354 | * @return Handle to newly created Archive object | 317 | // Verify if real hardware works this way, or if new handles are created each time |
| 355 | */ | 318 | if (path.GetType() == FileSys::Binary) |
| 356 | Handle CreateArchive(FileSys::Archive* backend, const std::string& name) { | 319 | // TODO(bunnei): FixMe - this is a hack to compensate for an incorrect FileSys backend |
| 357 | Handle handle; | 320 | // design. While the functionally of this is OK, our implementation decision to separate |
| 358 | CreateArchive(handle, backend, name); | 321 | // normal files from archive file pointers is very likely wrong. |
| 359 | return handle; | 322 | // See https://github.com/citra-emu/citra/issues/205 |
| 360 | } | 323 | return MakeResult<Handle>(archive_handle); |
| 361 | 324 | ||
| 362 | /** | ||
| 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 std::string& path, const FileSys::Mode mode) { | ||
| 370 | File* file = new File; | 325 | File* file = new File; |
| 371 | Handle handle = Kernel::g_object_pool.Create(file); | 326 | Handle handle = Kernel::g_object_pool.Create(file); |
| 372 | 327 | ||
| 373 | 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 | } | ||
| 374 | file->path = path; | 332 | file->path = path; |
| 375 | file->backend = archive->backend->OpenFile(path, mode); | 333 | file->backend = archive->backend->OpenFile(path, mode); |
| 376 | 334 | ||
| 377 | 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)) | ||
| 378 | return 0; | 354 | return 0; |
| 355 | return -1; | ||
| 356 | } | ||
| 379 | 357 | ||
| 380 | 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; | ||
| 381 | } | 371 | } |
| 382 | 372 | ||
| 383 | /** | 373 | /** |
| 384 | * Create a Directory from an Archive | 374 | * Create a Directory from an Archive |
| 385 | * @param archive_handle Handle to an open Archive object | 375 | * @param archive_handle Handle to an open Archive object |
| 386 | * @param path Path to the Directory inside of the Archive | 376 | * @param path Path to the Directory inside of the Archive |
| 387 | * @return Opened Directory object | 377 | * @return Whether creation succeeded |
| 388 | */ | 378 | */ |
| 389 | Result CreateDirectoryFromArchive(Handle archive_handle, const std::string& path) { | 379 | Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { |
| 390 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 380 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); |
| 391 | if (archive == nullptr) | 381 | if (archive == nullptr) |
| 392 | return -1; | 382 | return -1; |
| @@ -401,15 +391,18 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const std::string& path | |||
| 401 | * @param path Path to the Directory inside of the Archive | 391 | * @param path Path to the Directory inside of the Archive |
| 402 | * @return Opened Directory object | 392 | * @return Opened Directory object |
| 403 | */ | 393 | */ |
| 404 | Handle OpenDirectoryFromArchive(Handle archive_handle, const std::string& path) { | 394 | ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { |
| 405 | Directory* directory = new Directory; | 395 | Directory* directory = new Directory; |
| 406 | Handle handle = Kernel::g_object_pool.Create(directory); | 396 | Handle handle = Kernel::g_object_pool.Create(directory); |
| 407 | 397 | ||
| 408 | 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 | } | ||
| 409 | directory->path = path; | 402 | directory->path = path; |
| 410 | directory->backend = archive->backend->OpenDirectory(path); | 403 | directory->backend = archive->backend->OpenDirectory(path); |
| 411 | 404 | ||
| 412 | return handle; | 405 | return MakeResult<Handle>(handle); |
| 413 | } | 406 | } |
| 414 | 407 | ||
| 415 | /// Initialize archives | 408 | /// Initialize archives |
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h index 0230996b6..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 std::string& name, 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 |
| @@ -51,15 +66,15 @@ Handle OpenFileFromArchive(Handle archive_handle, const std::string& name, const | |||
| 51 | * @param path Path to the Directory inside of the Archive | 66 | * @param path Path to the Directory inside of the Archive |
| 52 | * @return Whether creation of directory succeeded | 67 | * @return Whether creation of directory succeeded |
| 53 | */ | 68 | */ |
| 54 | Result CreateDirectoryFromArchive(Handle archive_handle, const std::string& name); | 69 | Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); |
| 55 | 70 | ||
| 56 | /** | 71 | /** |
| 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 std::string& name); | 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 45ed79be8..288080209 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <map> | 5 | #include <map> |
| 6 | #include <algorithm> | 6 | #include <algorithm> |
| @@ -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,16 +81,16 @@ 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; |
| 95 | for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { | 90 | for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { |
| 96 | ResumeThreadFromWait( evt->waiting_threads[i]); | 91 | ResumeThreadFromWait( evt->waiting_threads[i]); |
| 97 | 92 | ||
| 98 | // If any thread is signalled awake by this event, assume the event was "caught" and reset | 93 | // If any thread is signalled awake by this event, assume the event was "caught" and reset |
| 99 | // the event. This will result in the next thread waiting on the event to block. Otherwise, | 94 | // the event. This will result in the next thread waiting on the event to block. Otherwise, |
| 100 | // the event will not be reset, and the next thread to call WaitSynchronization on it will | 95 | // the event will not be reset, and the next thread to call WaitSynchronization on it will |
| 101 | // not block. Not sure if this is correct behavior, but it seems to work. | 96 | // not block. Not sure if this is correct behavior, but it seems to work. |
| @@ -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 c39b33180..73aec4e79 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| @@ -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.cpp b/src/core/hle/kernel/kernel.cpp index 88cbc1af5..018000abd 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project | 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common.h" | 5 | #include "common/common.h" |
| 6 | 6 | ||
| @@ -68,7 +68,7 @@ void ObjectPool::List() { | |||
| 68 | for (int i = 0; i < MAX_COUNT; i++) { | 68 | for (int i = 0; i < MAX_COUNT; i++) { |
| 69 | if (occupied[i]) { | 69 | if (occupied[i]) { |
| 70 | if (pool[i]) { | 70 | if (pool[i]) { |
| 71 | INFO_LOG(KERNEL, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(), | 71 | INFO_LOG(KERNEL, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(), |
| 72 | pool[i]->GetName().c_str()); | 72 | pool[i]->GetName().c_str()); |
| 73 | } | 73 | } |
| 74 | } | 74 | } |
| @@ -110,7 +110,7 @@ void Shutdown() { | |||
| 110 | */ | 110 | */ |
| 111 | bool LoadExec(u32 entry_point) { | 111 | bool LoadExec(u32 entry_point) { |
| 112 | Init(); | 112 | Init(); |
| 113 | 113 | ||
| 114 | Core::g_app_core->SetPC(entry_point); | 114 | Core::g_app_core->SetPC(entry_point); |
| 115 | 115 | ||
| 116 | // 0x30 is the typical main thread priority I've seen used so far | 116 | // 0x30 is the typical main thread priority I've seen used so far |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 867d1b89c..8d3937ce8 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -1,12 +1,13 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project | 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 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; |
| @@ -34,7 +35,7 @@ enum class HandleType : u32 { | |||
| 34 | Archive = 12, | 35 | Archive = 12, |
| 35 | Directory = 13, | 36 | Directory = 13, |
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | enum { | 39 | enum { |
| 39 | DEFAULT_STACK_SIZE = 0x4000, | 40 | DEFAULT_STACK_SIZE = 0x4000, |
| 40 | }; | 41 | }; |
| @@ -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; | 87 | } |
| 90 | }; | ||
| 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 | ||
| @@ -139,7 +129,7 @@ public: | |||
| 139 | } | 129 | } |
| 140 | 130 | ||
| 141 | bool GetIDType(Handle handle, HandleType* type) const { | 131 | bool GetIDType(Handle handle, HandleType* type) const { |
| 142 | if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) || | 132 | if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) || |
| 143 | !occupied[handle - HANDLE_OFFSET]) { | 133 | !occupied[handle - HANDLE_OFFSET]) { |
| 144 | ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); | 134 | ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); |
| 145 | return false; | 135 | return false; |
| @@ -155,7 +145,7 @@ public: | |||
| 155 | int GetCount(); | 145 | int GetCount(); |
| 156 | 146 | ||
| 157 | private: | 147 | private: |
| 158 | 148 | ||
| 159 | enum { | 149 | enum { |
| 160 | MAX_COUNT = 0x1000, | 150 | MAX_COUNT = 0x1000, |
| 161 | HANDLE_OFFSET = 0x100, | 151 | HANDLE_OFFSET = 0x100, |
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index fcfd061ac..d07e9761b 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <map> | 5 | #include <map> |
| 6 | #include <vector> | 6 | #include <vector> |
| @@ -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 7d7b5137e..155449f95 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| @@ -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 f538c6550..cfcc0e0b7 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common.h" | 5 | #include "common/common.h" |
| 6 | 6 | ||
| @@ -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 5312b8854..304cf5b67 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| @@ -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 e15590c49..f59795901 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project | 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <list> | 6 | #include <list> |
| @@ -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; |
| @@ -71,17 +68,17 @@ public: | |||
| 71 | }; | 68 | }; |
| 72 | 69 | ||
| 73 | // Lists all thread ids that aren't deleted/etc. | 70 | // Lists all thread ids that aren't deleted/etc. |
| 74 | std::vector<Handle> g_thread_queue; | 71 | static std::vector<Handle> thread_queue; |
| 75 | 72 | ||
| 76 | // Lists only ready thread ids. | 73 | // Lists only ready thread ids. |
| 77 | Common::ThreadQueueList<Handle> g_thread_ready_queue; | 74 | static Common::ThreadQueueList<Handle> thread_ready_queue; |
| 78 | 75 | ||
| 79 | Handle g_current_thread_handle; | 76 | static Handle current_thread_handle; |
| 80 | Thread* g_current_thread; | 77 | static Thread* current_thread; |
| 81 | 78 | ||
| 82 | /// Gets the current thread | 79 | /// Gets the current thread |
| 83 | inline Thread* GetCurrentThread() { | 80 | inline Thread* GetCurrentThread() { |
| 84 | return g_current_thread; | 81 | return current_thread; |
| 85 | } | 82 | } |
| 86 | 83 | ||
| 87 | /// Gets the current thread handle | 84 | /// Gets the current thread handle |
| @@ -91,8 +88,8 @@ Handle GetCurrentThreadHandle() { | |||
| 91 | 88 | ||
| 92 | /// Sets the current thread | 89 | /// Sets the current thread |
| 93 | inline void SetCurrentThread(Thread* t) { | 90 | inline void SetCurrentThread(Thread* t) { |
| 94 | g_current_thread = t; | 91 | current_thread = t; |
| 95 | g_current_thread_handle = t->GetHandle(); | 92 | current_thread_handle = t->GetHandle(); |
| 96 | } | 93 | } |
| 97 | 94 | ||
| 98 | /// Saves the current CPU context | 95 | /// Saves the current CPU context |
| @@ -113,7 +110,7 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { | |||
| 113 | t->context.pc = t->context.reg_15 = t->entry_point; | 110 | t->context.pc = t->context.reg_15 = t->entry_point; |
| 114 | t->context.sp = t->stack_top; | 111 | t->context.sp = t->stack_top; |
| 115 | t->context.cpsr = 0x1F; // Usermode | 112 | t->context.cpsr = 0x1F; // Usermode |
| 116 | 113 | ||
| 117 | // TODO(bunnei): This instructs the CPU core to start the execution as if it is "resuming" a | 114 | // TODO(bunnei): This instructs the CPU core to start the execution as if it is "resuming" a |
| 118 | // thread. This is somewhat Sky-Eye specific, and should be re-architected in the future to be | 115 | // thread. This is somewhat Sky-Eye specific, and should be re-architected in the future to be |
| 119 | // agnostic of the CPU core. | 116 | // agnostic of the CPU core. |
| @@ -131,40 +128,35 @@ void ChangeReadyState(Thread* t, bool ready) { | |||
| 131 | Handle handle = t->GetHandle(); | 128 | Handle handle = t->GetHandle(); |
| 132 | if (t->IsReady()) { | 129 | if (t->IsReady()) { |
| 133 | if (!ready) { | 130 | if (!ready) { |
| 134 | g_thread_ready_queue.remove(t->current_priority, handle); | 131 | thread_ready_queue.remove(t->current_priority, handle); |
| 135 | } | 132 | } |
| 136 | } else if (ready) { | 133 | } else if (ready) { |
| 137 | if (t->IsRunning()) { | 134 | if (t->IsRunning()) { |
| 138 | g_thread_ready_queue.push_front(t->current_priority, handle); | 135 | thread_ready_queue.push_front(t->current_priority, handle); |
| 139 | } else { | 136 | } else { |
| 140 | g_thread_ready_queue.push_back(t->current_priority, handle); | 137 | thread_ready_queue.push_back(t->current_priority, handle); |
| 141 | } | 138 | } |
| 142 | t->status = THREADSTATUS_READY; | 139 | t->status = THREADSTATUS_READY; |
| 143 | } | 140 | } |
| 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 |
| @@ -181,7 +175,7 @@ void ChangeThreadState(Thread* t, ThreadStatus new_status) { | |||
| 181 | } | 175 | } |
| 182 | ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); | 176 | ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); |
| 183 | t->status = new_status; | 177 | t->status = new_status; |
| 184 | 178 | ||
| 185 | if (new_status == THREADSTATUS_WAIT) { | 179 | if (new_status == THREADSTATUS_WAIT) { |
| 186 | if (t->wait_type == WAITTYPE_NONE) { | 180 | if (t->wait_type == WAITTYPE_NONE) { |
| 187 | ERROR_LOG(KERNEL, "Waittype none not allowed"); | 181 | ERROR_LOG(KERNEL, "Waittype none not allowed"); |
| @@ -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 : g_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; |
| @@ -216,12 +212,13 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { | |||
| 216 | 212 | ||
| 217 | /// Arbitrate all threads currently waiting | 213 | /// Arbitrate all threads currently waiting |
| 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 : g_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 | } |
| @@ -238,11 +235,11 @@ void CallThread(Thread* t) { | |||
| 238 | /// Switches CPU context to that of the specified thread | 235 | /// Switches CPU context to that of the specified thread |
| 239 | void SwitchContext(Thread* t) { | 236 | void SwitchContext(Thread* t) { |
| 240 | Thread* cur = GetCurrentThread(); | 237 | Thread* cur = GetCurrentThread(); |
| 241 | 238 | ||
| 242 | // Save context for current thread | 239 | // Save context for current thread |
| 243 | if (cur) { | 240 | if (cur) { |
| 244 | SaveContext(cur->context); | 241 | SaveContext(cur->context); |
| 245 | 242 | ||
| 246 | if (cur->IsRunning()) { | 243 | if (cur->IsRunning()) { |
| 247 | ChangeReadyState(cur, true); | 244 | ChangeReadyState(cur, true); |
| 248 | } | 245 | } |
| @@ -263,16 +260,16 @@ void SwitchContext(Thread* t) { | |||
| 263 | Thread* NextThread() { | 260 | Thread* NextThread() { |
| 264 | Handle next; | 261 | Handle next; |
| 265 | Thread* cur = GetCurrentThread(); | 262 | Thread* cur = GetCurrentThread(); |
| 266 | 263 | ||
| 267 | if (cur && cur->IsRunning()) { | 264 | if (cur && cur->IsRunning()) { |
| 268 | next = g_thread_ready_queue.pop_first_better(cur->current_priority); | 265 | next = thread_ready_queue.pop_first_better(cur->current_priority); |
| 269 | } else { | 266 | } else { |
| 270 | next = g_thread_ready_queue.pop_first(); | 267 | next = thread_ready_queue.pop_first(); |
| 271 | } | 268 | } |
| 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))) { |
| @@ -306,9 +302,9 @@ void DebugThreadQueue() { | |||
| 306 | return; | 302 | return; |
| 307 | } | 303 | } |
| 308 | INFO_LOG(KERNEL, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThreadHandle()); | 304 | INFO_LOG(KERNEL, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThreadHandle()); |
| 309 | for (u32 i = 0; i < g_thread_queue.size(); i++) { | 305 | for (u32 i = 0; i < thread_queue.size(); i++) { |
| 310 | Handle handle = g_thread_queue[i]; | 306 | Handle handle = thread_queue[i]; |
| 311 | s32 priority = g_thread_ready_queue.contains(handle); | 307 | s32 priority = thread_ready_queue.contains(handle); |
| 312 | if (priority != -1) { | 308 | if (priority != -1) { |
| 313 | INFO_LOG(KERNEL, "0x%02X 0x%08X", priority, handle); | 309 | INFO_LOG(KERNEL, "0x%02X 0x%08X", priority, handle); |
| 314 | } | 310 | } |
| @@ -319,15 +315,15 @@ void DebugThreadQueue() { | |||
| 319 | Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, | 315 | Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, |
| 320 | s32 processor_id, u32 stack_top, int stack_size) { | 316 | s32 processor_id, u32 stack_top, int stack_size) { |
| 321 | 317 | ||
| 322 | _assert_msg_(KERNEL, (priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST), | 318 | _assert_msg_(KERNEL, (priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST), |
| 323 | "CreateThread priority=%d, outside of allowable range!", priority) | 319 | "CreateThread priority=%d, outside of allowable range!", priority) |
| 324 | 320 | ||
| 325 | Thread* thread = new Thread; | 321 | Thread* thread = new Thread; |
| 326 | 322 | ||
| 327 | handle = Kernel::g_object_pool.Create(thread); | 323 | handle = Kernel::g_object_pool.Create(thread); |
| 328 | 324 | ||
| 329 | g_thread_queue.push_back(handle); | 325 | thread_queue.push_back(handle); |
| 330 | g_thread_ready_queue.prepare(priority); | 326 | thread_ready_queue.prepare(priority); |
| 331 | 327 | ||
| 332 | thread->status = THREADSTATUS_DORMANT; | 328 | thread->status = THREADSTATUS_DORMANT; |
| 333 | thread->entry_point = entry_point; | 329 | thread->entry_point = entry_point; |
| @@ -351,7 +347,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 | |||
| 351 | return -1; | 347 | return -1; |
| 352 | } | 348 | } |
| 353 | if ((u32)stack_size < 0x200) { | 349 | if ((u32)stack_size < 0x200) { |
| 354 | ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid stack_size=0x%08X", name, | 350 | ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid stack_size=0x%08X", name, |
| 355 | stack_size); | 351 | stack_size); |
| 356 | return -1; | 352 | return -1; |
| 357 | } | 353 | } |
| @@ -368,7 +364,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 | |||
| 368 | return -1; | 364 | return -1; |
| 369 | } | 365 | } |
| 370 | Handle handle; | 366 | Handle handle; |
| 371 | Thread* thread = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, | 367 | Thread* thread = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, |
| 372 | stack_size); | 368 | stack_size); |
| 373 | 369 | ||
| 374 | ResetThread(thread, arg, 0); | 370 | ResetThread(thread, arg, 0); |
| @@ -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 | ||
| @@ -405,37 +405,37 @@ Result SetThreadPriority(Handle handle, s32 priority) { | |||
| 405 | 405 | ||
| 406 | // Change thread priority | 406 | // Change thread priority |
| 407 | s32 old = thread->current_priority; | 407 | s32 old = thread->current_priority; |
| 408 | g_thread_ready_queue.remove(old, handle); | 408 | thread_ready_queue.remove(old, handle); |
| 409 | thread->current_priority = priority; | 409 | thread->current_priority = priority; |
| 410 | g_thread_ready_queue.prepare(thread->current_priority); | 410 | thread_ready_queue.prepare(thread->current_priority); |
| 411 | 411 | ||
| 412 | // Change thread status to "ready" and push to ready queue | 412 | // Change thread status to "ready" and push to ready queue |
| 413 | if (thread->IsRunning()) { | 413 | if (thread->IsRunning()) { |
| 414 | thread->status = (thread->status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY; | 414 | thread->status = (thread->status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY; |
| 415 | } | 415 | } |
| 416 | if (thread->IsReady()) { | 416 | if (thread->IsReady()) { |
| 417 | g_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 |
| 424 | Handle SetupMainThread(s32 priority, int stack_size) { | 424 | Handle SetupMainThread(s32 priority, int stack_size) { |
| 425 | Handle handle; | 425 | Handle handle; |
| 426 | 426 | ||
| 427 | // Initialize new "main" thread | 427 | // Initialize new "main" thread |
| 428 | Thread* thread = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, | 428 | Thread* thread = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, |
| 429 | THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); | 429 | THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); |
| 430 | 430 | ||
| 431 | ResetThread(thread, 0, 0); | 431 | ResetThread(thread, 0, 0); |
| 432 | 432 | ||
| 433 | // If running another thread already, set it to "ready" state | 433 | // If running another thread already, set it to "ready" state |
| 434 | Thread* cur = GetCurrentThread(); | 434 | Thread* cur = GetCurrentThread(); |
| 435 | if (cur && cur->IsRunning()) { | 435 | if (cur && cur->IsRunning()) { |
| 436 | ChangeReadyState(cur, true); | 436 | ChangeReadyState(cur, true); |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | // Run new "main" thread | 439 | // Run new "main" thread |
| 440 | SetCurrentThread(thread); | 440 | SetCurrentThread(thread); |
| 441 | thread->status = THREADSTATUS_RUNNING; | 441 | thread->status = THREADSTATUS_RUNNING; |
| @@ -452,12 +452,12 @@ void Reschedule() { | |||
| 452 | HLE::g_reschedule = false; | 452 | HLE::g_reschedule = false; |
| 453 | if (next > 0) { | 453 | if (next > 0) { |
| 454 | INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); | 454 | INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); |
| 455 | 455 | ||
| 456 | SwitchContext(next); | 456 | SwitchContext(next); |
| 457 | 457 | ||
| 458 | // Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep | 458 | // Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep |
| 459 | // by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again. | 459 | // by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again. |
| 460 | // This results in the current thread yielding on a VBLANK once, and then it will be | 460 | // This results in the current thread yielding on a VBLANK once, and then it will be |
| 461 | // immediately placed back in the queue for execution. | 461 | // immediately placed back in the queue for execution. |
| 462 | if (prev->wait_type == WAITTYPE_VBLANK) { | 462 | if (prev->wait_type == WAITTYPE_VBLANK) { |
| 463 | ResumeThreadFromWait(prev->GetHandle()); | 463 | ResumeThreadFromWait(prev->GetHandle()); |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 39fa38b75..ce63a70d3 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -1,11 +1,12 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project | 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 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/ac_u.cpp b/src/core/hle/service/ac_u.cpp index b39603bdf..9af96f6b8 100644 --- a/src/core/hle/service/ac_u.cpp +++ b/src/core/hle/service/ac_u.cpp | |||
| @@ -22,12 +22,12 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 22 | {0x000E0042, nullptr, "GetCurrentAPInfo"}, | 22 | {0x000E0042, nullptr, "GetCurrentAPInfo"}, |
| 23 | {0x00100042, nullptr, "GetCurrentNZoneInfo"}, | 23 | {0x00100042, nullptr, "GetCurrentNZoneInfo"}, |
| 24 | {0x00110042, nullptr, "GetNZoneApNumService"}, | 24 | {0x00110042, nullptr, "GetNZoneApNumService"}, |
| 25 | {0x00240042, nullptr, "AddDenyApType "}, | 25 | {0x00240042, nullptr, "AddDenyApType"}, |
| 26 | {0x00270002, nullptr, "GetInfraPriority "}, | 26 | {0x00270002, nullptr, "GetInfraPriority"}, |
| 27 | {0x002D0082, nullptr, "SetRequestEulaVersion"}, | 27 | {0x002D0082, nullptr, "SetRequestEulaVersion"}, |
| 28 | {0x00300004, nullptr, "RegisterDisconnectEvent"}, | 28 | {0x00300004, nullptr, "RegisterDisconnectEvent"}, |
| 29 | {0x003C0042, nullptr, "GetAPSSIDList"}, | 29 | {0x003C0042, nullptr, "GetAPSSIDList"}, |
| 30 | {0x003E0042, nullptr, "IsConnected "}, | 30 | {0x003E0042, nullptr, "IsConnected"}, |
| 31 | {0x00400042, nullptr, "SetClientVersion"}, | 31 | {0x00400042, nullptr, "SetClientVersion"}, |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
diff --git a/src/core/hle/service/ac_u.h b/src/core/hle/service/ac_u.h index 3c5958d27..c91b28353 100644 --- a/src/core/hle/service/ac_u.h +++ b/src/core/hle/service/ac_u.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 10 | // Namespace AC_U | 10 | // Namespace AC_U |
| 11 | 11 | ||
| 12 | // socket service "ac:u" | 12 | // socket service "ac:u" |
| 13 | 13 | ||
| 14 | namespace AC_U { | 14 | namespace AC_U { |
| 15 | 15 | ||
| @@ -21,7 +21,7 @@ public: | |||
| 21 | * Gets the string port name used by CTROS for the service | 21 | * Gets the string port name used by CTROS for the service |
| 22 | * @return Port name of service | 22 | * @return Port name of service |
| 23 | */ | 23 | */ |
| 24 | std::string GetPortName() const { | 24 | std::string GetPortName() const override { |
| 25 | return "ac:u"; | 25 | return "ac:u"; |
| 26 | } | 26 | } |
| 27 | }; | 27 | }; |
diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am_net.cpp new file mode 100644 index 000000000..403cac353 --- /dev/null +++ b/src/core/hle/service/am_net.cpp | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/am_net.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace AM_NET | ||
| 11 | |||
| 12 | namespace AM_NET { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x08010000, nullptr, "OpenTicket"}, | ||
| 16 | {0x08020002, nullptr, "TicketAbortInstall"}, | ||
| 17 | {0x08030002, nullptr, "TicketFinalizeInstall"}, | ||
| 18 | {0x08040100, nullptr, "InstallTitleBegin"}, | ||
| 19 | {0x08050000, nullptr, "InstallTitleAbort"}, | ||
| 20 | {0x080600C0, nullptr, "InstallTitleResume"}, | ||
| 21 | {0x08070000, nullptr, "InstallTitleAbortTMD"}, | ||
| 22 | {0x08080000, nullptr, "InstallTitleFinish"}, | ||
| 23 | {0x080A0000, nullptr, "OpenTMD"}, | ||
| 24 | {0x080B0002, nullptr, "TMDAbortInstall"}, | ||
| 25 | {0x080C0042, nullptr, "TMDFinalizeInstall"}, | ||
| 26 | {0x080E0040, nullptr, "OpenContentCreate"}, | ||
| 27 | {0x080F0002, nullptr, "ContentAbortInstall"}, | ||
| 28 | {0x08100040, nullptr, "OpenContentResume"}, | ||
| 29 | {0x08120002, nullptr, "ContentFinalizeInstall"}, | ||
| 30 | {0x08130000, nullptr, "GetTotalContents"}, | ||
| 31 | {0x08140042, nullptr, "GetContentIndexes"}, | ||
| 32 | {0x08150044, nullptr, "GetContentsInfo"}, | ||
| 33 | {0x08190108, nullptr, "Unknown"}, | ||
| 34 | {0x081B00C2, nullptr, "InstallTitlesFinish"}, | ||
| 35 | }; | ||
| 36 | |||
| 37 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 38 | // Interface class | ||
| 39 | |||
| 40 | Interface::Interface() { | ||
| 41 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 42 | } | ||
| 43 | |||
| 44 | Interface::~Interface() { | ||
| 45 | } | ||
| 46 | |||
| 47 | } // namespace | ||
diff --git a/src/core/hle/service/am_net.h b/src/core/hle/service/am_net.h new file mode 100644 index 000000000..4816e1697 --- /dev/null +++ b/src/core/hle/service/am_net.h | |||
| @@ -0,0 +1,27 @@ | |||
| 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 "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace AM_NET | ||
| 11 | |||
| 12 | namespace AM_NET { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | ~Interface(); | ||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "am:net"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 4f41ec5f4..4bb05ce40 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp | |||
| @@ -27,7 +27,7 @@ enum class SignalType : u32 { | |||
| 27 | 27 | ||
| 28 | void Initialize(Service::Interface* self) { | 28 | void Initialize(Service::Interface* self) { |
| 29 | u32* cmd_buff = Service::GetCommandBuffer(); | 29 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 30 | 30 | ||
| 31 | cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Menu"); // APT menu event handle | 31 | cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Menu"); // APT menu event handle |
| 32 | cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); // APT pause event handle | 32 | cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); // APT pause event handle |
| 33 | 33 | ||
| @@ -168,7 +168,7 @@ void AppletUtility(Service::Interface* self) { | |||
| 168 | cmd_buff[1] = 0; // No error | 168 | cmd_buff[1] = 0; // No error |
| 169 | 169 | ||
| 170 | WARN_LOG(KERNEL, "(STUBBED) called unk=0x%08X, buffer1_size=0x%08x, buffer2_size=0x%08x, " | 170 | WARN_LOG(KERNEL, "(STUBBED) called unk=0x%08X, buffer1_size=0x%08x, buffer2_size=0x%08x, " |
| 171 | "buffer1_addr=0x%08x, buffer2_addr=0x%08x", unk, buffer1_size, buffer2_size, | 171 | "buffer1_addr=0x%08x, buffer2_addr=0x%08x", unk, buffer1_size, buffer2_size, |
| 172 | buffer1_addr, buffer2_addr); | 172 | buffer1_addr, buffer2_addr); |
| 173 | } | 173 | } |
| 174 | 174 | ||
diff --git a/src/core/hle/service/apt_u.h b/src/core/hle/service/apt_u.h index 5af39e085..306730400 100644 --- a/src/core/hle/service/apt_u.h +++ b/src/core/hle/service/apt_u.h | |||
| @@ -13,8 +13,8 @@ namespace APT_U { | |||
| 13 | 13 | ||
| 14 | // Application and title launching service. These services handle signaling for home/power button as | 14 | // Application and title launching service. These services handle signaling for home/power button as |
| 15 | // well. Only one session for either APT service can be open at a time, normally processes close the | 15 | // well. Only one session for either APT service can be open at a time, normally processes close the |
| 16 | // service handle immediately once finished using the service. The commands for APT:U and APT:S are | 16 | // service handle immediately once finished using the service. The commands for APT:U and APT:S are |
| 17 | // exactly the same, however certain commands are only accessible with APT:S(NS module will call | 17 | // exactly the same, however certain commands are only accessible with APT:S(NS module will call |
| 18 | // svcBreak when the command isn't accessible). See http://3dbrew.org/wiki/NS#APT_Services. | 18 | // svcBreak when the command isn't accessible). See http://3dbrew.org/wiki/NS#APT_Services. |
| 19 | 19 | ||
| 20 | /// Interface to "APT:U" service | 20 | /// Interface to "APT:U" service |
diff --git a/src/core/hle/service/boss_u.cpp b/src/core/hle/service/boss_u.cpp new file mode 100644 index 000000000..b2ff4a756 --- /dev/null +++ b/src/core/hle/service/boss_u.cpp | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/boss_u.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace BOSS_U | ||
| 11 | |||
| 12 | namespace BOSS_U { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x00020100, nullptr, "GetStorageInfo"}, | ||
| 16 | }; | ||
| 17 | |||
| 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 19 | // Interface class | ||
| 20 | |||
| 21 | Interface::Interface() { | ||
| 22 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 23 | } | ||
| 24 | |||
| 25 | Interface::~Interface() { | ||
| 26 | } | ||
| 27 | |||
| 28 | } // namespace | ||
diff --git a/src/core/hle/service/boss_u.h b/src/core/hle/service/boss_u.h new file mode 100644 index 000000000..af39b8e65 --- /dev/null +++ b/src/core/hle/service/boss_u.h | |||
| @@ -0,0 +1,27 @@ | |||
| 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 "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace BOSS_U | ||
| 11 | |||
| 12 | namespace BOSS_U { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | ~Interface(); | ||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const { | ||
| 23 | return "boss:U"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/cfg_i.cpp b/src/core/hle/service/cfg_i.cpp new file mode 100644 index 000000000..88d13d459 --- /dev/null +++ b/src/core/hle/service/cfg_i.cpp | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/cfg_i.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace CFG_I | ||
| 11 | |||
| 12 | namespace CFG_I { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x04010082, nullptr, "GetConfigInfoBlk8"}, | ||
| 16 | {0x04020082, nullptr, "GetConfigInfoBlk4"}, | ||
| 17 | {0x04030000, nullptr, "UpdateConfigNANDSavegame"}, | ||
| 18 | {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, | ||
| 19 | {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, | ||
| 20 | {0x04060000, nullptr, "SecureInfoGetRegion"}, | ||
| 21 | {0x04070000, nullptr, "SecureInfoGetByte101"}, | ||
| 22 | {0x04080042, nullptr, "SecureInfoGetSerialNo"}, | ||
| 23 | {0x04090000, nullptr, "UpdateConfigBlk00040003"}, | ||
| 24 | {0x08010082, nullptr, "GetConfigInfoBlk8"}, | ||
| 25 | {0x08020082, nullptr, "GetConfigInfoBlk4"}, | ||
| 26 | {0x08030000, nullptr, "UpdateConfigNANDSavegame"}, | ||
| 27 | {0x080400C2, nullptr, "CreateConfigInfoBlk"}, | ||
| 28 | {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, | ||
| 29 | {0x08060000, nullptr, "FormatConfig"}, | ||
| 30 | {0x08070000, nullptr, "Unknown"}, | ||
| 31 | {0x08080000, nullptr, "UpdateConfigBlk1"}, | ||
| 32 | {0x08090000, nullptr, "UpdateConfigBlk2"}, | ||
| 33 | {0x080A0000, nullptr, "UpdateConfigBlk3"}, | ||
| 34 | {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"}, | ||
| 35 | {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"}, | ||
| 36 | {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"}, | ||
| 37 | {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"}, | ||
| 38 | {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"}, | ||
| 39 | {0x08100000, nullptr, "GetLocalFriendCodeSeed"}, | ||
| 40 | {0x08110084, nullptr, "SetSecureInfo"}, | ||
| 41 | {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"}, | ||
| 42 | {0x08130000, nullptr, "VerifySigSecureInfo"}, | ||
| 43 | {0x08140042, nullptr, "SecureInfoGetData"}, | ||
| 44 | {0x08150042, nullptr, "SecureInfoGetSignature"}, | ||
| 45 | {0x08160000, nullptr, "SecureInfoGetRegion"}, | ||
| 46 | {0x08170000, nullptr, "SecureInfoGetByte101"}, | ||
| 47 | {0x08180042, nullptr, "SecureInfoGetSerialNo"}, | ||
| 48 | }; | ||
| 49 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 50 | // Interface class | ||
| 51 | |||
| 52 | Interface::Interface() { | ||
| 53 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 54 | } | ||
| 55 | |||
| 56 | Interface::~Interface() { | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace | ||
diff --git a/src/core/hle/service/cfg_i.h b/src/core/hle/service/cfg_i.h new file mode 100644 index 000000000..fe343c968 --- /dev/null +++ b/src/core/hle/service/cfg_i.h | |||
| @@ -0,0 +1,27 @@ | |||
| 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 "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace CFG_I | ||
| 11 | |||
| 12 | namespace CFG_I { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | ~Interface(); | ||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "cfg:i"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/cfg_u.h b/src/core/hle/service/cfg_u.h index 7525bd7c6..8075d19a8 100644 --- a/src/core/hle/service/cfg_u.h +++ b/src/core/hle/service/cfg_u.h | |||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | * Gets the string port name used by CTROS for the service | 19 | * Gets the string port name used by CTROS for the service |
| 20 | * @return Port name of service | 20 | * @return Port name of service |
| 21 | */ | 21 | */ |
| 22 | std::string GetPortName() const { | 22 | std::string GetPortName() const override { |
| 23 | return "cfg:u"; | 23 | return "cfg:u"; |
| 24 | } | 24 | } |
| 25 | }; | 25 | }; |
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp new file mode 100644 index 000000000..6e59a9bf3 --- /dev/null +++ b/src/core/hle/service/csnd_snd.cpp | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/csnd_snd.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace CSND_SND | ||
| 11 | |||
| 12 | namespace CSND_SND { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x00010140, nullptr, "Initialize"}, | ||
| 16 | {0x00020000, nullptr, "Shutdown"}, | ||
| 17 | {0x00030040, nullptr, "Unknown"}, | ||
| 18 | {0x00040080, nullptr, "Unknown"}, | ||
| 19 | {0x00050000, nullptr, "Unknown"}, | ||
| 20 | {0x00060000, nullptr, "Unknown"}, | ||
| 21 | {0x00070000, nullptr, "Unknown"}, | ||
| 22 | {0x00080040, nullptr, "Unknown"}, | ||
| 23 | {0x00090082, nullptr, "FlushDCache"}, | ||
| 24 | {0x000A0082, nullptr, "StoreDCache"}, | ||
| 25 | {0x000B0082, nullptr, "InvalidateDCache"}, | ||
| 26 | {0x000C0000, nullptr, "Unknown"}, | ||
| 27 | }; | ||
| 28 | |||
| 29 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 30 | // Interface class | ||
| 31 | |||
| 32 | Interface::Interface() { | ||
| 33 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 34 | } | ||
| 35 | |||
| 36 | Interface::~Interface() { | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace | ||
diff --git a/src/core/hle/service/csnd_snd.h b/src/core/hle/service/csnd_snd.h new file mode 100644 index 000000000..31cc85b07 --- /dev/null +++ b/src/core/hle/service/csnd_snd.h | |||
| @@ -0,0 +1,27 @@ | |||
| 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 "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace CSND_SND | ||
| 11 | |||
| 12 | namespace CSND_SND { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | ~Interface(); | ||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "csnd:SND"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 9e84ac938..bbcf26f61 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp | |||
| @@ -26,12 +26,12 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 26 | {0x001100C2, nullptr, "LoadComponent"}, | 26 | {0x001100C2, nullptr, "LoadComponent"}, |
| 27 | {0x00120000, nullptr, "UnloadComponent"}, | 27 | {0x00120000, nullptr, "UnloadComponent"}, |
| 28 | {0x00130082, nullptr, "FlushDataCache"}, | 28 | {0x00130082, nullptr, "FlushDataCache"}, |
| 29 | {0x00140082, nullptr, "InvalidateDCache "}, | 29 | {0x00140082, nullptr, "InvalidateDCache"}, |
| 30 | {0x00150082, nullptr, "RegisterInterruptEvents"}, | 30 | {0x00150082, nullptr, "RegisterInterruptEvents"}, |
| 31 | {0x00160000, nullptr, "GetSemaphoreEventHandle"}, | 31 | {0x00160000, nullptr, "GetSemaphoreEventHandle"}, |
| 32 | {0x00170040, nullptr, "SetSemaphoreMask"}, | 32 | {0x00170040, nullptr, "SetSemaphoreMask"}, |
| 33 | {0x00180040, nullptr, "GetPhysicalAddress"}, | 33 | {0x00180040, nullptr, "GetPhysicalAddress"}, |
| 34 | {0x00190040, nullptr, "GetVirtualAddress" }, | 34 | {0x00190040, nullptr, "GetVirtualAddress"}, |
| 35 | {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, | 35 | {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, |
| 36 | {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, | 36 | {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, |
| 37 | {0x001C0082, nullptr, "SetIirFilterEQ"}, | 37 | {0x001C0082, nullptr, "SetIirFilterEQ"}, |
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h index c439ed266..c4ce44245 100644 --- a/src/core/hle/service/dsp_dsp.h +++ b/src/core/hle/service/dsp_dsp.h | |||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | * Gets the string port name used by CTROS for the service | 19 | * Gets the string port name used by CTROS for the service |
| 20 | * @return Port name of service | 20 | * @return Port name of service |
| 21 | */ | 21 | */ |
| 22 | std::string GetPortName() const { | 22 | std::string GetPortName() const override { |
| 23 | return "dsp:DSP"; | 23 | return "dsp:DSP"; |
| 24 | } | 24 | } |
| 25 | }; | 25 | }; |
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp index 917b2f8ca..785c351e9 100644 --- a/src/core/hle/service/err_f.cpp +++ b/src/core/hle/service/err_f.cpp | |||
| @@ -20,8 +20,8 @@ namespace ERR_F { | |||
| 20 | Interface::Interface() { | 20 | Interface::Interface() { |
| 21 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | 21 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | Interface::~Interface() { | 24 | Interface::~Interface() { |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | } // namespace | 27 | } // namespace |
diff --git a/src/core/hle/service/err_f.h b/src/core/hle/service/err_f.h index 5da663267..6d7141c1b 100644 --- a/src/core/hle/service/err_f.h +++ b/src/core/hle/service/err_f.h | |||
| @@ -19,9 +19,9 @@ namespace ERR_F { | |||
| 19 | * Gets the string port name used by CTROS for the service | 19 | * Gets the string port name used by CTROS for the service |
| 20 | * @return Port name of service | 20 | * @return Port name of service |
| 21 | */ | 21 | */ |
| 22 | std::string GetPortName() const { | 22 | std::string GetPortName() const override { |
| 23 | return "err:f"; | 23 | return "err:f"; |
| 24 | } | 24 | } |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | } // namespace | 27 | } // namespace |
diff --git a/src/core/hle/service/frd_u.h b/src/core/hle/service/frd_u.h index 9df8a815a..4020c6664 100644 --- a/src/core/hle/service/frd_u.h +++ b/src/core/hle/service/frd_u.h | |||
| @@ -19,7 +19,7 @@ namespace FRD_U { | |||
| 19 | * Gets the string port name used by CTROS for the service | 19 | * Gets the string port name used by CTROS for the service |
| 20 | * @return Port name of service | 20 | * @return Port name of service |
| 21 | */ | 21 | */ |
| 22 | std::string GetPortName() const { | 22 | std::string GetPortName() const override { |
| 23 | return "frd:u"; | 23 | return "frd:u"; |
| 24 | } | 24 | } |
| 25 | }; | 25 | }; |
diff --git a/src/core/hle/service/fs_user.cpp b/src/core/hle/service/fs_user.cpp index 9dc83291d..34af78cb9 100644 --- a/src/core/hle/service/fs_user.cpp +++ b/src/core/hle/service/fs_user.cpp | |||
| @@ -4,31 +4,45 @@ | |||
| 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 | 19 | static void Initialize(Service::Interface* self) { |
| 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 | 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 | } |
| 30 | 28 | ||
| 31 | void OpenFile(Service::Interface* self) { | 29 | /** |
| 30 | * FS_User::OpenFile service function | ||
| 31 | * Inputs: | ||
| 32 | * 1 : Transaction | ||
| 33 | * 2 : Archive handle lower word | ||
| 34 | * 3 : Archive handle upper word | ||
| 35 | * 4 : Low path type | ||
| 36 | * 5 : Low path size | ||
| 37 | * 6 : Open flags | ||
| 38 | * 7 : Attributes | ||
| 39 | * 8 : (LowPathSize << 14) | 2 | ||
| 40 | * 9 : Low path data pointer | ||
| 41 | * Outputs: | ||
| 42 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 43 | * 3 : File handle | ||
| 44 | */ | ||
| 45 | static void OpenFile(Service::Interface* self) { | ||
| 32 | u32* cmd_buff = Service::GetCommandBuffer(); | 46 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 33 | 47 | ||
| 34 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | 48 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to |
| @@ -39,36 +53,41 @@ void OpenFile(Service::Interface* self) { | |||
| 39 | FileSys::Mode mode; mode.hex = cmd_buff[6]; | 53 | FileSys::Mode mode; mode.hex = cmd_buff[6]; |
| 40 | u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. | 54 | u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. |
| 41 | u32 filename_ptr = cmd_buff[9]; | 55 | u32 filename_ptr = cmd_buff[9]; |
| 42 | |||
| 43 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | 56 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); |
| 44 | std::string file_string; | ||
| 45 | switch (file_path.GetType()) { | ||
| 46 | case FileSys::Char: | ||
| 47 | case FileSys::Wchar: | ||
| 48 | file_string = file_path.AsString(); | ||
| 49 | break; | ||
| 50 | default: | ||
| 51 | WARN_LOG(KERNEL, "file LowPath type is currently unsupported; returning archive handle instead"); | ||
| 52 | return; | ||
| 53 | } | ||
| 54 | 57 | ||
| 55 | DEBUG_LOG(KERNEL, "type=%d size=%d mode=%d attrs=%d data=%s", | 58 | DEBUG_LOG(KERNEL, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); |
| 56 | filename_type, filename_size, mode, attributes, file_string.c_str()); | ||
| 57 | 59 | ||
| 58 | Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_string, mode); | 60 | ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode); |
| 59 | if (handle) { | 61 | cmd_buff[1] = handle.Code().raw; |
| 60 | cmd_buff[1] = 0; | 62 | if (handle.Succeeded()) { |
| 61 | cmd_buff[3] = handle; | 63 | cmd_buff[3] = *handle; |
| 62 | } else { | 64 | } else { |
| 63 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_string.c_str()); | 65 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |
| 64 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 65 | cmd_buff[1] = -1; | ||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | DEBUG_LOG(KERNEL, "called"); | 68 | DEBUG_LOG(KERNEL, "called"); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void OpenFileDirectly(Service::Interface* self) { | 71 | /** |
| 72 | * FS_User::OpenFileDirectly service function | ||
| 73 | * Inputs: | ||
| 74 | * 1 : Transaction | ||
| 75 | * 2 : Archive ID | ||
| 76 | * 3 : Archive low path type | ||
| 77 | * 4 : Archive low path size | ||
| 78 | * 5 : File low path type | ||
| 79 | * 6 : File low path size | ||
| 80 | * 7 : Flags | ||
| 81 | * 8 : Attributes | ||
| 82 | * 9 : (ArchiveLowPathSize << 14) | 0x802 | ||
| 83 | * 10 : Archive low path | ||
| 84 | * 11 : (FileLowPathSize << 14) | 2 | ||
| 85 | * 12 : File low path | ||
| 86 | * Outputs: | ||
| 87 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 88 | * 3 : File handle | ||
| 89 | */ | ||
| 90 | static void OpenFileDirectly(Service::Interface* self) { | ||
| 72 | u32* cmd_buff = Service::GetCommandBuffer(); | 91 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 73 | 92 | ||
| 74 | auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); | 93 | auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); |
| @@ -80,55 +99,103 @@ void OpenFileDirectly(Service::Interface* self) { | |||
| 80 | u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. | 99 | u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. |
| 81 | u32 archivename_ptr = cmd_buff[10]; | 100 | u32 archivename_ptr = cmd_buff[10]; |
| 82 | u32 filename_ptr = cmd_buff[12]; | 101 | u32 filename_ptr = cmd_buff[12]; |
| 102 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); | ||
| 103 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | ||
| 83 | 104 | ||
| 84 | DEBUG_LOG(KERNEL, "archive_type=%d archive_size=%d file_type=%d file_size=%d file_mode=%d file_attrs=%d", | 105 | DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%u attributes=%d", |
| 85 | archivename_type, archivename_size, filename_type, filename_size, mode, attributes); | 106 | archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); |
| 86 | 107 | ||
| 87 | if (archivename_type != FileSys::Empty) { | 108 | if (archive_path.GetType() != FileSys::Empty) { |
| 88 | 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"); |
| 89 | cmd_buff[1] = -1; | 110 | cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; |
| 90 | return; | 111 | return; |
| 91 | } | 112 | } |
| 92 | 113 | ||
| 93 | // 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 |
| 94 | Handle archive_handle = Kernel::OpenArchive(archive_id); | 115 | // TODO(yuriks): Why is there all this duplicate (and seemingly useless) code up here? |
| 95 | if (archive_handle) { | 116 | ResultVal<Handle> archive_handle = Kernel::OpenArchive(archive_id); |
| 96 | cmd_buff[1] = 0; | 117 | cmd_buff[1] = archive_handle.Code().raw; |
| 97 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | 118 | if (archive_handle.Failed()) { |
| 98 | cmd_buff[3] = archive_handle; | ||
| 99 | } else { | ||
| 100 | ERROR_LOG(KERNEL, "failed to get a handle for archive"); | 119 | ERROR_LOG(KERNEL, "failed to get a handle for archive"); |
| 101 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 102 | cmd_buff[1] = -1; | ||
| 103 | return; | ||
| 104 | } | ||
| 105 | |||
| 106 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | ||
| 107 | std::string file_string; | ||
| 108 | switch (file_path.GetType()) { | ||
| 109 | case FileSys::Char: | ||
| 110 | case FileSys::Wchar: | ||
| 111 | file_string = file_path.AsString(); | ||
| 112 | break; | ||
| 113 | default: | ||
| 114 | WARN_LOG(KERNEL, "file LowPath type is currently unsupported; returning archive handle instead"); | ||
| 115 | return; | 120 | return; |
| 116 | } | 121 | } |
| 122 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | ||
| 123 | cmd_buff[3] = *archive_handle; | ||
| 117 | 124 | ||
| 118 | Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_string, mode); | 125 | ResultVal<Handle> handle = Kernel::OpenFileFromArchive(*archive_handle, file_path, mode); |
| 119 | if (handle) { | 126 | cmd_buff[1] = handle.Code().raw; |
| 120 | cmd_buff[1] = 0; | 127 | if (handle.Succeeded()) { |
| 121 | cmd_buff[3] = handle; | 128 | cmd_buff[3] = *handle; |
| 122 | } else { | 129 | } else { |
| 123 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_string.c_str()); | 130 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |
| 124 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 125 | cmd_buff[1] = -1; | ||
| 126 | } | 131 | } |
| 127 | 132 | ||
| 128 | DEBUG_LOG(KERNEL, "called"); | 133 | DEBUG_LOG(KERNEL, "called"); |
| 129 | } | 134 | } |
| 130 | 135 | ||
| 131 | /* | 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 | /* | ||
| 132 | * FS_User::CreateDirectory service function | 199 | * FS_User::CreateDirectory service function |
| 133 | * Inputs: | 200 | * Inputs: |
| 134 | * 2 : Archive handle lower word | 201 | * 2 : Archive handle lower word |
| @@ -139,7 +206,7 @@ void OpenFileDirectly(Service::Interface* self) { | |||
| 139 | * Outputs: | 206 | * Outputs: |
| 140 | * 1 : Result of function, 0 on success, otherwise error code | 207 | * 1 : Result of function, 0 on success, otherwise error code |
| 141 | */ | 208 | */ |
| 142 | void CreateDirectory(Service::Interface* self) { | 209 | static void CreateDirectory(Service::Interface* self) { |
| 143 | u32* cmd_buff = Service::GetCommandBuffer(); | 210 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 144 | 211 | ||
| 145 | // TODO: cmd_buff[2], aka archive handle lower word, isn't used according to | 212 | // TODO: cmd_buff[2], aka archive handle lower word, isn't used according to |
| @@ -150,25 +217,15 @@ void CreateDirectory(Service::Interface* self) { | |||
| 150 | u32 dirname_ptr = cmd_buff[8]; | 217 | u32 dirname_ptr = cmd_buff[8]; |
| 151 | 218 | ||
| 152 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); | 219 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); |
| 153 | std::string dir_string; | ||
| 154 | switch (dir_path.GetType()) { | ||
| 155 | case FileSys::Char: | ||
| 156 | case FileSys::Wchar: | ||
| 157 | dir_string = dir_path.AsString(); | ||
| 158 | break; | ||
| 159 | default: | ||
| 160 | cmd_buff[1] = -1; | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | 220 | ||
| 164 | 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()); |
| 165 | 222 | ||
| 166 | cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_string); | 223 | cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path); |
| 167 | 224 | ||
| 168 | DEBUG_LOG(KERNEL, "called"); | 225 | DEBUG_LOG(KERNEL, "called"); |
| 169 | } | 226 | } |
| 170 | 227 | ||
| 171 | void OpenDirectory(Service::Interface* self) { | 228 | static void OpenDirectory(Service::Interface* self) { |
| 172 | u32* cmd_buff = Service::GetCommandBuffer(); | 229 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 173 | 230 | ||
| 174 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | 231 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to |
| @@ -179,57 +236,57 @@ void OpenDirectory(Service::Interface* self) { | |||
| 179 | u32 dirname_ptr = cmd_buff[6]; | 236 | u32 dirname_ptr = cmd_buff[6]; |
| 180 | 237 | ||
| 181 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); | 238 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); |
| 182 | std::string dir_string; | ||
| 183 | switch (dir_path.GetType()) { | ||
| 184 | case FileSys::Char: | ||
| 185 | case FileSys::Wchar: | ||
| 186 | dir_string = dir_path.AsString(); | ||
| 187 | break; | ||
| 188 | default: | ||
| 189 | cmd_buff[1] = -1; | ||
| 190 | return; | ||
| 191 | } | ||
| 192 | 239 | ||
| 193 | 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()); |
| 194 | 241 | ||
| 195 | Handle handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_string); | 242 | ResultVal<Handle> handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_path); |
| 196 | if (handle) { | 243 | cmd_buff[1] = handle.Code().raw; |
| 197 | cmd_buff[1] = 0; | 244 | if (handle.Succeeded()) { |
| 198 | cmd_buff[3] = handle; | 245 | cmd_buff[3] = *handle; |
| 199 | } else { | 246 | } else { |
| 200 | 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"); |
| 201 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 202 | cmd_buff[1] = -1; | ||
| 203 | } | 248 | } |
| 204 | 249 | ||
| 205 | DEBUG_LOG(KERNEL, "called"); | 250 | DEBUG_LOG(KERNEL, "called"); |
| 206 | } | 251 | } |
| 207 | 252 | ||
| 208 | void OpenArchive(Service::Interface* self) { | 253 | /** |
| 254 | * FS_User::OpenArchive service function | ||
| 255 | * Inputs: | ||
| 256 | * 1 : Archive ID | ||
| 257 | * 2 : Archive low path type | ||
| 258 | * 3 : Archive low path size | ||
| 259 | * 4 : (LowPathSize << 14) | 2 | ||
| 260 | * 5 : Archive low path | ||
| 261 | * Outputs: | ||
| 262 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 263 | * 2 : Archive handle lower word (unused) | ||
| 264 | * 3 : Archive handle upper word (same as file handle) | ||
| 265 | */ | ||
| 266 | static void OpenArchive(Service::Interface* self) { | ||
| 209 | u32* cmd_buff = Service::GetCommandBuffer(); | 267 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 210 | 268 | ||
| 211 | auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); | 269 | auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); |
| 212 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); | 270 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); |
| 213 | u32 archivename_size = cmd_buff[3]; | 271 | u32 archivename_size = cmd_buff[3]; |
| 214 | u32 archivename_ptr = cmd_buff[5]; | 272 | u32 archivename_ptr = cmd_buff[5]; |
| 273 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); | ||
| 215 | 274 | ||
| 216 | DEBUG_LOG(KERNEL, "type=%d size=%d", archivename_type, archivename_size); | 275 | DEBUG_LOG(KERNEL, "archive_path=%s", archive_path.DebugStr().c_str()); |
| 217 | 276 | ||
| 218 | if (archivename_type != FileSys::Empty) { | 277 | if (archive_path.GetType() != FileSys::Empty) { |
| 219 | 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"); |
| 220 | cmd_buff[1] = -1; | 279 | cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; |
| 221 | return; | 280 | return; |
| 222 | } | 281 | } |
| 223 | 282 | ||
| 224 | Handle handle = Kernel::OpenArchive(archive_id); | 283 | ResultVal<Handle> handle = Kernel::OpenArchive(archive_id); |
| 225 | if (handle) { | 284 | cmd_buff[1] = handle.Code().raw; |
| 226 | cmd_buff[1] = 0; | 285 | if (handle.Succeeded()) { |
| 227 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | 286 | // cmd_buff[2] isn't used according to 3dmoo's implementation. |
| 228 | cmd_buff[3] = handle; | 287 | cmd_buff[3] = *handle; |
| 229 | } else { | 288 | } else { |
| 230 | ERROR_LOG(KERNEL, "failed to get a handle for archive"); | 289 | ERROR_LOG(KERNEL, "failed to get a handle for archive"); |
| 231 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 232 | cmd_buff[1] = -1; | ||
| 233 | } | 290 | } |
| 234 | 291 | ||
| 235 | DEBUG_LOG(KERNEL, "called"); | 292 | DEBUG_LOG(KERNEL, "called"); |
| @@ -241,12 +298,12 @@ void OpenArchive(Service::Interface* self) { | |||
| 241 | * 1 : Result of function, 0 on success, otherwise error code | 298 | * 1 : Result of function, 0 on success, otherwise error code |
| 242 | * 2 : Whether the Sdmc could be detected | 299 | * 2 : Whether the Sdmc could be detected |
| 243 | */ | 300 | */ |
| 244 | void IsSdmcDetected(Service::Interface* self) { | 301 | static void IsSdmcDetected(Service::Interface* self) { |
| 245 | u32* cmd_buff = Service::GetCommandBuffer(); | 302 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 246 | 303 | ||
| 247 | cmd_buff[1] = 0; | 304 | cmd_buff[1] = 0; |
| 248 | cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0; | 305 | cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0; |
| 249 | 306 | ||
| 250 | DEBUG_LOG(KERNEL, "called"); | 307 | DEBUG_LOG(KERNEL, "called"); |
| 251 | } | 308 | } |
| 252 | 309 | ||
| @@ -256,9 +313,9 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 256 | {0x08010002, Initialize, "Initialize"}, | 313 | {0x08010002, Initialize, "Initialize"}, |
| 257 | {0x080201C2, OpenFile, "OpenFile"}, | 314 | {0x080201C2, OpenFile, "OpenFile"}, |
| 258 | {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, | 315 | {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, |
| 259 | {0x08040142, nullptr, "DeleteFile"}, | 316 | {0x08040142, DeleteFile, "DeleteFile"}, |
| 260 | {0x08050244, nullptr, "RenameFile"}, | 317 | {0x08050244, nullptr, "RenameFile"}, |
| 261 | {0x08060142, nullptr, "DeleteDirectory"}, | 318 | {0x08060142, DeleteDirectory, "DeleteDirectory"}, |
| 262 | {0x08070142, nullptr, "DeleteDirectoryRecursively"}, | 319 | {0x08070142, nullptr, "DeleteDirectoryRecursively"}, |
| 263 | {0x08080202, nullptr, "CreateFile"}, | 320 | {0x08080202, nullptr, "CreateFile"}, |
| 264 | {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 6119e6300..de1bd3f61 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp | |||
| @@ -28,31 +28,26 @@ 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 | 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) { |
| 56 | // TODO: Return proper error codes | 51 | // TODO: Return proper error codes |
| 57 | if (base_address + size_in_bytes >= 0x420000) { | 52 | if (base_address + size_in_bytes >= 0x420000) { |
| 58 | ERROR_LOG(GPU, "Write address out of range! (address=0x%08x, size=0x%08x)", | 53 | ERROR_LOG(GPU, "Write address out of range! (address=0x%08x, size=0x%08x)", |
| @@ -76,7 +71,7 @@ void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { | |||
| 76 | } | 71 | } |
| 77 | 72 | ||
| 78 | /// Write a GSP GPU hardware register | 73 | /// Write a GSP GPU hardware register |
| 79 | void WriteHWRegs(Service::Interface* self) { | 74 | static void WriteHWRegs(Service::Interface* self) { |
| 80 | u32* cmd_buff = Service::GetCommandBuffer(); | 75 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 81 | u32 reg_addr = cmd_buff[1]; | 76 | u32 reg_addr = cmd_buff[1]; |
| 82 | u32 size = cmd_buff[2]; | 77 | u32 size = cmd_buff[2]; |
| @@ -87,7 +82,7 @@ void WriteHWRegs(Service::Interface* self) { | |||
| 87 | } | 82 | } |
| 88 | 83 | ||
| 89 | /// Read a GSP GPU hardware register | 84 | /// Read a GSP GPU hardware register |
| 90 | void ReadHWRegs(Service::Interface* self) { | 85 | static void ReadHWRegs(Service::Interface* self) { |
| 91 | u32* cmd_buff = Service::GetCommandBuffer(); | 86 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 92 | u32 reg_addr = cmd_buff[1]; | 87 | u32 reg_addr = cmd_buff[1]; |
| 93 | u32 size = cmd_buff[2]; | 88 | u32 size = cmd_buff[2]; |
| @@ -115,7 +110,7 @@ void ReadHWRegs(Service::Interface* self) { | |||
| 115 | } | 110 | } |
| 116 | } | 111 | } |
| 117 | 112 | ||
| 118 | void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | 113 | static void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { |
| 119 | u32 base_address = 0x400000; | 114 | u32 base_address = 0x400000; |
| 120 | if (info.active_fb == 0) { | 115 | if (info.active_fb == 0) { |
| 121 | WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_left1), 4, &info.address_left); | 116 | WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_left1), 4, &info.address_left); |
| @@ -140,7 +135,7 @@ void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | |||
| 140 | * Outputs: | 135 | * Outputs: |
| 141 | * 1: Result code | 136 | * 1: Result code |
| 142 | */ | 137 | */ |
| 143 | void SetBufferSwap(Service::Interface* self) { | 138 | static void SetBufferSwap(Service::Interface* self) { |
| 144 | u32* cmd_buff = Service::GetCommandBuffer(); | 139 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 145 | u32 screen_id = cmd_buff[1]; | 140 | u32 screen_id = cmd_buff[1]; |
| 146 | FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2]; | 141 | FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2]; |
| @@ -159,7 +154,7 @@ void SetBufferSwap(Service::Interface* self) { | |||
| 159 | * 2 : Thread index into GSP command buffer | 154 | * 2 : Thread index into GSP command buffer |
| 160 | * 4 : Handle to GSP shared memory | 155 | * 4 : Handle to GSP shared memory |
| 161 | */ | 156 | */ |
| 162 | void RegisterInterruptRelayQueue(Service::Interface* self) { | 157 | static void RegisterInterruptRelayQueue(Service::Interface* self) { |
| 163 | u32* cmd_buff = Service::GetCommandBuffer(); | 158 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 164 | u32 flags = cmd_buff[1]; | 159 | u32 flags = cmd_buff[1]; |
| 165 | g_interrupt_event = cmd_buff[3]; | 160 | g_interrupt_event = cmd_buff[3]; |
| @@ -202,7 +197,7 @@ void SignalInterrupt(InterruptId interrupt_id) { | |||
| 202 | } | 197 | } |
| 203 | 198 | ||
| 204 | /// Executes the next GSP command | 199 | /// Executes the next GSP command |
| 205 | void ExecuteCommand(const Command& command, u32 thread_id) { | 200 | static void ExecuteCommand(const Command& command, u32 thread_id) { |
| 206 | // Utility function to convert register ID to address | 201 | // Utility function to convert register ID to address |
| 207 | auto WriteGPURegister = [](u32 id, u32 data) { | 202 | auto WriteGPURegister = [](u32 id, u32 data) { |
| 208 | GPU::Write<u32>(0x1EF00000 + 4 * id, data); | 203 | GPU::Write<u32>(0x1EF00000 + 4 * id, data); |
| @@ -308,7 +303,7 @@ void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 308 | } | 303 | } |
| 309 | 304 | ||
| 310 | /// This triggers handling of the GX command written to the command buffer in shared memory. | 305 | /// This triggers handling of the GX command written to the command buffer in shared memory. |
| 311 | void TriggerCmdReqQueue(Service::Interface* self) { | 306 | static void TriggerCmdReqQueue(Service::Interface* self) { |
| 312 | 307 | ||
| 313 | // Iterate through each thread's command queue... | 308 | // Iterate through each thread's command queue... |
| 314 | for (unsigned thread_id = 0; thread_id < 0x4; ++thread_id) { | 309 | for (unsigned thread_id = 0; thread_id < 0x4; ++thread_id) { |
diff --git a/src/core/hle/service/hid_user.cpp b/src/core/hle/service/hid_user.cpp index 0eb32ba4a..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 | /** |
| @@ -47,7 +44,7 @@ static inline PadData* GetPadData() { | |||
| 47 | * | 44 | * |
| 48 | * Indicate the circle pad is pushed completely to the edge in 1 of 8 directions. | 45 | * Indicate the circle pad is pushed completely to the edge in 1 of 8 directions. |
| 49 | */ | 46 | */ |
| 50 | void UpdateNextCirclePadState() { | 47 | static void UpdateNextCirclePadState() { |
| 51 | static const s16 max_value = 0x9C; | 48 | static const s16 max_value = 0x9C; |
| 52 | next_circle_x = next_state.circle_left ? -max_value : 0x0; | 49 | next_circle_x = next_state.circle_left ? -max_value : 0x0; |
| 53 | next_circle_x += next_state.circle_right ? max_value : 0x0; | 50 | next_circle_x += next_state.circle_right ? max_value : 0x0; |
| @@ -155,7 +152,7 @@ void PadUpdateComplete() { | |||
| 155 | * 7 : Gyroscope event | 152 | * 7 : Gyroscope event |
| 156 | * 8 : Event signaled by HID_User | 153 | * 8 : Event signaled by HID_User |
| 157 | */ | 154 | */ |
| 158 | void GetIPCHandles(Service::Interface* self) { | 155 | static void GetIPCHandles(Service::Interface* self) { |
| 159 | u32* cmd_buff = Service::GetCommandBuffer(); | 156 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 160 | 157 | ||
| 161 | cmd_buff[1] = 0; // No error | 158 | cmd_buff[1] = 0; // No error |
diff --git a/src/core/hle/service/hid_user.h b/src/core/hle/service/hid_user.h index 9f6c4d5ed..5ed97085d 100644 --- a/src/core/hle/service/hid_user.h +++ b/src/core/hle/service/hid_user.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | namespace HID_User { | 16 | namespace HID_User { |
| 17 | 17 | ||
| 18 | /** | 18 | /** |
| 19 | * Structure of a Pad controller state. | 19 | * Structure of a Pad controller state. |
| 20 | */ | 20 | */ |
| 21 | struct PadState { | 21 | struct PadState { |
diff --git a/src/core/hle/service/ir_rst.cpp b/src/core/hle/service/ir_rst.cpp new file mode 100644 index 000000000..be15db231 --- /dev/null +++ b/src/core/hle/service/ir_rst.cpp | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/ir_rst.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace IR_RST | ||
| 11 | |||
| 12 | namespace IR_RST { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x00010000, nullptr, "GetHandles"}, | ||
| 16 | {0x00020080, nullptr, "Initialize"}, | ||
| 17 | {0x00030000, nullptr, "Shutdown"}, | ||
| 18 | {0x00040000, nullptr, "Unknown"}, | ||
| 19 | {0x00050000, nullptr, "Unknown"}, | ||
| 20 | {0x00060000, nullptr, "Unknown"}, | ||
| 21 | {0x00070080, nullptr, "Unknown"}, | ||
| 22 | {0x00080000, nullptr, "Unknown"}, | ||
| 23 | {0x00090000, nullptr, "Unknown"}, | ||
| 24 | }; | ||
| 25 | |||
| 26 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 27 | // Interface class | ||
| 28 | |||
| 29 | Interface::Interface() { | ||
| 30 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 31 | } | ||
| 32 | |||
| 33 | Interface::~Interface() { | ||
| 34 | } | ||
| 35 | |||
| 36 | } // namespace | ||
diff --git a/src/core/hle/service/ir_rst.h b/src/core/hle/service/ir_rst.h new file mode 100644 index 000000000..73effd7e3 --- /dev/null +++ b/src/core/hle/service/ir_rst.h | |||
| @@ -0,0 +1,27 @@ | |||
| 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 "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace IR_RST | ||
| 11 | |||
| 12 | namespace IR_RST { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | ~Interface(); | ||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "ir:rst"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/ir_u.cpp b/src/core/hle/service/ir_u.cpp new file mode 100644 index 000000000..aa9db6f6d --- /dev/null +++ b/src/core/hle/service/ir_u.cpp | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/ir_u.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace IR_U | ||
| 11 | |||
| 12 | namespace IR_U { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x00010000, nullptr, "Initialize"}, | ||
| 16 | {0x00020000, nullptr, "Shutdown"}, | ||
| 17 | {0x00030042, nullptr, "StartSendTransfer"}, | ||
| 18 | {0x00040000, nullptr, "WaitSendTransfer"}, | ||
| 19 | {0x000500C2, nullptr, "StartRecvTransfer"}, | ||
| 20 | {0x00060000, nullptr, "WaitRecvTransfer"}, | ||
| 21 | {0x00070080, nullptr, "GetRecvTransferCount"}, | ||
| 22 | {0x00080000, nullptr, "GetSendState"}, | ||
| 23 | {0x00090040, nullptr, "SetBitRate"}, | ||
| 24 | {0x000A0000, nullptr, "GetBitRate"}, | ||
| 25 | {0x000B0040, nullptr, "SetIRLEDState"}, | ||
| 26 | {0x000C0000, nullptr, "GetIRLEDRecvState"}, | ||
| 27 | {0x000D0000, nullptr, "GetSendFinishedEvent"}, | ||
| 28 | {0x000E0000, nullptr, "GetRecvFinishedEvent"}, | ||
| 29 | {0x000F0000, nullptr, "GetTransferState"}, | ||
| 30 | {0x00100000, nullptr, "GetErrorStatus"}, | ||
| 31 | {0x00110040, nullptr, "SetSleepModeActive"}, | ||
| 32 | {0x00120040, nullptr, "SetSleepModeState"}, | ||
| 33 | }; | ||
| 34 | |||
| 35 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 36 | // Interface class | ||
| 37 | |||
| 38 | Interface::Interface() { | ||
| 39 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 40 | } | ||
| 41 | |||
| 42 | Interface::~Interface() { | ||
| 43 | } | ||
| 44 | |||
| 45 | } // namespace | ||
diff --git a/src/core/hle/service/ir_u.h b/src/core/hle/service/ir_u.h new file mode 100644 index 000000000..86d98d079 --- /dev/null +++ b/src/core/hle/service/ir_u.h | |||
| @@ -0,0 +1,27 @@ | |||
| 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 "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace IR_U | ||
| 11 | |||
| 12 | namespace IR_U { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | ~Interface(); | ||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "ir:u"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp index 58051f133..d6f30e9ae 100644 --- a/src/core/hle/service/mic_u.cpp +++ b/src/core/hle/service/mic_u.cpp | |||
| @@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 27 | {0x000D0040, nullptr, "SetClamp"}, | 27 | {0x000D0040, nullptr, "SetClamp"}, |
| 28 | {0x000E0000, nullptr, "GetClamp"}, | 28 | {0x000E0000, nullptr, "GetClamp"}, |
| 29 | {0x000F0040, nullptr, "unknown_input1"}, | 29 | {0x000F0040, nullptr, "unknown_input1"}, |
| 30 | {0x00100040, nullptr, "unknown_input2"}, | 30 | {0x00100040, nullptr, "unknown_input2"}, |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 33 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h index 72ba048ef..2a495f3a9 100644 --- a/src/core/hle/service/mic_u.h +++ b/src/core/hle/service/mic_u.h | |||
| @@ -21,7 +21,7 @@ public: | |||
| 21 | * Gets the string port name used by CTROS for the service | 21 | * Gets the string port name used by CTROS for the service |
| 22 | * @return Port name of service | 22 | * @return Port name of service |
| 23 | */ | 23 | */ |
| 24 | std::string GetPortName() const { | 24 | std::string GetPortName() const override { |
| 25 | return "mic:u"; | 25 | return "mic:u"; |
| 26 | } | 26 | } |
| 27 | }; | 27 | }; |
diff --git a/src/core/hle/service/nwm_uds.h b/src/core/hle/service/nwm_uds.h index a956ca812..69d2c2002 100644 --- a/src/core/hle/service/nwm_uds.h +++ b/src/core/hle/service/nwm_uds.h | |||
| @@ -21,7 +21,7 @@ public: | |||
| 21 | * Gets the string port name used by CTROS for the service | 21 | * Gets the string port name used by CTROS for the service |
| 22 | * @return Port name of service | 22 | * @return Port name of service |
| 23 | */ | 23 | */ |
| 24 | std::string GetPortName() const { | 24 | std::string GetPortName() const override { |
| 25 | return "nwm:UDS"; | 25 | return "nwm:UDS"; |
| 26 | } | 26 | } |
| 27 | }; | 27 | }; |
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp new file mode 100644 index 000000000..90e9b1bfa --- /dev/null +++ b/src/core/hle/service/pm_app.cpp | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/pm_app.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace PM_APP | ||
| 11 | |||
| 12 | namespace PM_APP { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x00010140, nullptr, "LaunchTitle"}, | ||
| 16 | {0x00020082, nullptr, "LaunchFIRMSetParams"}, | ||
| 17 | {0x00030080, nullptr, "TerminateProcesse"}, | ||
| 18 | {0x00040100, nullptr, "TerminateProcessTID"}, | ||
| 19 | {0x000500C0, nullptr, "TerminateProcessTID_unknown"}, | ||
| 20 | {0x00070042, nullptr, "GetFIRMLaunchParams"}, | ||
| 21 | {0x00080100, nullptr, "GetTitleExheaderFlags"}, | ||
| 22 | {0x00090042, nullptr, "SetFIRMLaunchParams"}, | ||
| 23 | }; | ||
| 24 | |||
| 25 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 26 | // Interface class | ||
| 27 | |||
| 28 | Interface::Interface() { | ||
| 29 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 30 | } | ||
| 31 | |||
| 32 | Interface::~Interface() { | ||
| 33 | } | ||
| 34 | |||
| 35 | } // namespace | ||
diff --git a/src/core/hle/service/pm_app.h b/src/core/hle/service/pm_app.h new file mode 100644 index 000000000..28c38f582 --- /dev/null +++ b/src/core/hle/service/pm_app.h | |||
| @@ -0,0 +1,27 @@ | |||
| 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 "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace PM_APP | ||
| 11 | |||
| 12 | namespace PM_APP { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | ~Interface(); | ||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "pm:app"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index f6a14d509..d9122dbbc 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp | |||
| @@ -17,13 +17,13 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 17 | {0x00030000, nullptr, "GetRtcAlarm"}, | 17 | {0x00030000, nullptr, "GetRtcAlarm"}, |
| 18 | {0x00040000, nullptr, "CancelRtcAlarm"}, | 18 | {0x00040000, nullptr, "CancelRtcAlarm"}, |
| 19 | {0x00050000, nullptr, "GetAdapterState"}, | 19 | {0x00050000, nullptr, "GetAdapterState"}, |
| 20 | {0x00060000, nullptr, "GetShellState "}, | 20 | {0x00060000, nullptr, "GetShellState"}, |
| 21 | {0x00070000, nullptr, "GetBatteryLevel"}, | 21 | {0x00070000, nullptr, "GetBatteryLevel"}, |
| 22 | {0x00080000, nullptr, "GetBatteryChargeState"}, | 22 | {0x00080000, nullptr, "GetBatteryChargeState"}, |
| 23 | {0x00090000, nullptr, "GetPedometerState"}, | 23 | {0x00090000, nullptr, "GetPedometerState"}, |
| 24 | {0x000A0042, nullptr, "GetStepHistoryEntry"}, | 24 | {0x000A0042, nullptr, "GetStepHistoryEntry"}, |
| 25 | {0x000B00C2, nullptr, "GetStepHistory "}, | 25 | {0x000B00C2, nullptr, "GetStepHistory"}, |
| 26 | {0x000C0000, nullptr, "GetTotalStepCount "}, | 26 | {0x000C0000, nullptr, "GetTotalStepCount"}, |
| 27 | {0x000D0040, nullptr, "SetPedometerRecordingMode"}, | 27 | {0x000D0040, nullptr, "SetPedometerRecordingMode"}, |
| 28 | {0x000E0000, nullptr, "GetPedometerRecordingMode"}, | 28 | {0x000E0000, nullptr, "GetPedometerRecordingMode"}, |
| 29 | {0x000F0084, nullptr, "GetStepHistoryAll"}, | 29 | {0x000F0084, nullptr, "GetStepHistoryAll"}, |
diff --git a/src/core/hle/service/ptm_u.h b/src/core/hle/service/ptm_u.h index 82749fa39..f8d9f57be 100644 --- a/src/core/hle/service/ptm_u.h +++ b/src/core/hle/service/ptm_u.h | |||
| @@ -21,7 +21,7 @@ public: | |||
| 21 | * Gets the string port name used by CTROS for the service | 21 | * Gets the string port name used by CTROS for the service |
| 22 | * @return Port name of service | 22 | * @return Port name of service |
| 23 | */ | 23 | */ |
| 24 | std::string GetPortName() const { | 24 | std::string GetPortName() const override { |
| 25 | return "ptm:u"; | 25 | return "ptm:u"; |
| 26 | } | 26 | } |
| 27 | }; | 27 | }; |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index bb0f80e98..fed2268a0 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -7,17 +7,24 @@ | |||
| 7 | 7 | ||
| 8 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 9 | #include "core/hle/service/ac_u.h" | 9 | #include "core/hle/service/ac_u.h" |
| 10 | #include "core/hle/service/am_net.h" | ||
| 10 | #include "core/hle/service/apt_u.h" | 11 | #include "core/hle/service/apt_u.h" |
| 12 | #include "core/hle/service/boss_u.h" | ||
| 13 | #include "core/hle/service/cfg_i.h" | ||
| 11 | #include "core/hle/service/cfg_u.h" | 14 | #include "core/hle/service/cfg_u.h" |
| 15 | #include "core/hle/service/csnd_snd.h" | ||
| 12 | #include "core/hle/service/dsp_dsp.h" | 16 | #include "core/hle/service/dsp_dsp.h" |
| 13 | #include "core/hle/service/err_f.h" | 17 | #include "core/hle/service/err_f.h" |
| 14 | #include "core/hle/service/fs_user.h" | 18 | #include "core/hle/service/fs_user.h" |
| 15 | #include "core/hle/service/frd_u.h" | 19 | #include "core/hle/service/frd_u.h" |
| 16 | #include "core/hle/service/gsp_gpu.h" | 20 | #include "core/hle/service/gsp_gpu.h" |
| 17 | #include "core/hle/service/hid_user.h" | 21 | #include "core/hle/service/hid_user.h" |
| 22 | #include "core/hle/service/ir_rst.h" | ||
| 23 | #include "core/hle/service/ir_u.h" | ||
| 18 | #include "core/hle/service/mic_u.h" | 24 | #include "core/hle/service/mic_u.h" |
| 19 | #include "core/hle/service/ndm_u.h" | 25 | #include "core/hle/service/ndm_u.h" |
| 20 | #include "core/hle/service/nwm_uds.h" | 26 | #include "core/hle/service/nwm_uds.h" |
| 27 | #include "core/hle/service/pm_app.h" | ||
| 21 | #include "core/hle/service/ptm_u.h" | 28 | #include "core/hle/service/ptm_u.h" |
| 22 | #include "core/hle/service/soc_u.h" | 29 | #include "core/hle/service/soc_u.h" |
| 23 | #include "core/hle/service/srv.h" | 30 | #include "core/hle/service/srv.h" |
| @@ -55,7 +62,7 @@ void Manager::DeleteService(const std::string& port_name) { | |||
| 55 | 62 | ||
| 56 | /// Get a Service Interface from its Handle | 63 | /// Get a Service Interface from its Handle |
| 57 | Interface* Manager::FetchFromHandle(Handle handle) { | 64 | Interface* Manager::FetchFromHandle(Handle handle) { |
| 58 | return Kernel::g_object_pool.GetFast<Interface>(handle); | 65 | return Kernel::g_object_pool.Get<Interface>(handle); |
| 59 | } | 66 | } |
| 60 | 67 | ||
| 61 | /// Get a Service Interface from its port | 68 | /// Get a Service Interface from its port |
| @@ -74,20 +81,27 @@ Interface* Manager::FetchFromPortName(const std::string& port_name) { | |||
| 74 | /// Initialize ServiceManager | 81 | /// Initialize ServiceManager |
| 75 | void Init() { | 82 | void Init() { |
| 76 | g_manager = new Manager; | 83 | g_manager = new Manager; |
| 77 | 84 | ||
| 78 | g_manager->AddService(new SRV::Interface); | 85 | g_manager->AddService(new SRV::Interface); |
| 79 | g_manager->AddService(new AC_U::Interface); | 86 | g_manager->AddService(new AC_U::Interface); |
| 87 | g_manager->AddService(new AM_NET::Interface); | ||
| 80 | g_manager->AddService(new APT_U::Interface); | 88 | g_manager->AddService(new APT_U::Interface); |
| 89 | g_manager->AddService(new BOSS_U::Interface); | ||
| 90 | g_manager->AddService(new CFG_I::Interface); | ||
| 81 | g_manager->AddService(new CFG_U::Interface); | 91 | g_manager->AddService(new CFG_U::Interface); |
| 92 | g_manager->AddService(new CSND_SND::Interface); | ||
| 82 | g_manager->AddService(new DSP_DSP::Interface); | 93 | g_manager->AddService(new DSP_DSP::Interface); |
| 83 | g_manager->AddService(new ERR_F::Interface); | 94 | g_manager->AddService(new ERR_F::Interface); |
| 84 | g_manager->AddService(new FRD_U::Interface); | 95 | g_manager->AddService(new FRD_U::Interface); |
| 85 | g_manager->AddService(new FS_User::Interface); | 96 | g_manager->AddService(new FS_User::Interface); |
| 86 | g_manager->AddService(new GSP_GPU::Interface); | 97 | g_manager->AddService(new GSP_GPU::Interface); |
| 87 | g_manager->AddService(new HID_User::Interface); | 98 | g_manager->AddService(new HID_User::Interface); |
| 99 | g_manager->AddService(new IR_RST::Interface); | ||
| 100 | g_manager->AddService(new IR_U::Interface); | ||
| 88 | g_manager->AddService(new MIC_U::Interface); | 101 | g_manager->AddService(new MIC_U::Interface); |
| 89 | g_manager->AddService(new NDM_U::Interface); | 102 | g_manager->AddService(new NDM_U::Interface); |
| 90 | g_manager->AddService(new NWM_UDS::Interface); | 103 | g_manager->AddService(new NWM_UDS::Interface); |
| 104 | g_manager->AddService(new PM_APP::Interface); | ||
| 91 | g_manager->AddService(new PTM_U::Interface); | 105 | g_manager->AddService(new PTM_U::Interface); |
| 92 | g_manager->AddService(new SOC_U::Interface); | 106 | g_manager->AddService(new SOC_U::Interface); |
| 93 | g_manager->AddService(new SSL_C::Interface); | 107 | g_manager->AddService(new SSL_C::Interface); |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 2f5a866c9..20e7fb4d3 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -38,7 +38,7 @@ class Manager; | |||
| 38 | class Interface : public Kernel::Object { | 38 | class Interface : public Kernel::Object { |
| 39 | friend class Manager; | 39 | friend class Manager; |
| 40 | public: | 40 | public: |
| 41 | 41 | ||
| 42 | std::string GetName() const override { return GetPortName(); } | 42 | std::string GetName() const override { return GetPortName(); } |
| 43 | std::string GetTypeName() const override { return GetPortName(); } | 43 | std::string GetTypeName() const override { return GetPortName(); } |
| 44 | 44 | ||
| @@ -75,48 +75,38 @@ 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 | ||
| 87 | if (itr == m_functions.end()) { | 82 | if (itr == m_functions.end()) { |
| 88 | ERROR_LOG(OSHLE, "unknown/unimplemented function: port=%s, command=0x%08X", | 83 | ERROR_LOG(OSHLE, "unknown/unimplemented function: port=%s, command=0x%08X", |
| 89 | GetPortName().c_str(), cmd_buff[0]); | 84 | GetPortName().c_str(), cmd_buff[0]); |
| 90 | 85 | ||
| 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", |
| 98 | GetPortName().c_str(), itr->second.name.c_str()); | 93 | GetPortName().c_str(), itr->second.name.c_str()); |
| 99 | 94 | ||
| 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/soc_u.h b/src/core/hle/service/soc_u.h index e27a2b1fe..d5590a683 100644 --- a/src/core/hle/service/soc_u.h +++ b/src/core/hle/service/soc_u.h | |||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | * Gets the string port name used by CTROS for the service | 19 | * Gets the string port name used by CTROS for the service |
| 20 | * @return Port name of service | 20 | * @return Port name of service |
| 21 | */ | 21 | */ |
| 22 | std::string GetPortName() const { | 22 | std::string GetPortName() const override { |
| 23 | return "soc:U"; | 23 | return "soc:U"; |
| 24 | } | 24 | } |
| 25 | }; | 25 | }; |
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 6c02a43d9..0e7fa9e3b 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp | |||
| @@ -11,9 +11,9 @@ | |||
| 11 | 11 | ||
| 12 | namespace SRV { | 12 | namespace SRV { |
| 13 | 13 | ||
| 14 | Handle g_event_handle = 0; | 14 | static Handle g_event_handle = 0; |
| 15 | 15 | ||
| 16 | void Initialize(Service::Interface* self) { | 16 | static void Initialize(Service::Interface* self) { |
| 17 | DEBUG_LOG(OSHLE, "called"); | 17 | DEBUG_LOG(OSHLE, "called"); |
| 18 | 18 | ||
| 19 | u32* cmd_buff = Service::GetCommandBuffer(); | 19 | u32* cmd_buff = Service::GetCommandBuffer(); |
| @@ -21,7 +21,7 @@ void Initialize(Service::Interface* self) { | |||
| 21 | cmd_buff[1] = 0; // No error | 21 | cmd_buff[1] = 0; // No error |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | void GetProcSemaphore(Service::Interface* self) { | 24 | static void GetProcSemaphore(Service::Interface* self) { |
| 25 | DEBUG_LOG(OSHLE, "called"); | 25 | DEBUG_LOG(OSHLE, "called"); |
| 26 | 26 | ||
| 27 | u32* cmd_buff = Service::GetCommandBuffer(); | 27 | u32* cmd_buff = Service::GetCommandBuffer(); |
| @@ -34,8 +34,8 @@ void GetProcSemaphore(Service::Interface* self) { | |||
| 34 | cmd_buff[3] = g_event_handle; | 34 | cmd_buff[3] = g_event_handle; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | 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 @@ 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 1eda36c53..43a3cbe03 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <map> | 5 | #include <map> |
| 6 | 6 | ||
| @@ -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 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -29,8 +30,8 @@ enum ControlMemoryOperation { | |||
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 31 | /// Map application or GSP heap memory | 32 | /// Map application or GSP heap memory |
| 32 | Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { | 33 | static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { |
| 33 | DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", | 34 | DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", |
| 34 | operation, addr0, addr1, size, permissions); | 35 | operation, addr0, addr1, size, permissions); |
| 35 | 36 | ||
| 36 | switch (operation) { | 37 | switch (operation) { |
| @@ -53,8 +54,8 @@ Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 siz | |||
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | /// Maps a memory block to specified address | 56 | /// Maps a memory block to specified address |
| 56 | Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { | 57 | static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { |
| 57 | DEBUG_LOG(SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", | 58 | DEBUG_LOG(SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", |
| 58 | handle, addr, permissions, other_permissions); | 59 | handle, addr, permissions, other_permissions); |
| 59 | 60 | ||
| 60 | Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions); | 61 | Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions); |
| @@ -63,7 +64,7 @@ Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permis | |||
| 63 | case Kernel::MemoryPermission::Write: | 64 | case Kernel::MemoryPermission::Write: |
| 64 | case Kernel::MemoryPermission::ReadWrite: | 65 | case Kernel::MemoryPermission::ReadWrite: |
| 65 | case Kernel::MemoryPermission::DontCare: | 66 | case Kernel::MemoryPermission::DontCare: |
| 66 | Kernel::MapSharedMemory(handle, addr, permissions_type, | 67 | Kernel::MapSharedMemory(handle, addr, permissions_type, |
| 67 | static_cast<Kernel::MemoryPermission>(other_permissions)); | 68 | static_cast<Kernel::MemoryPermission>(other_permissions)); |
| 68 | break; | 69 | break; |
| 69 | default: | 70 | default: |
| @@ -73,7 +74,7 @@ Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permis | |||
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | /// Connect to an OS service given the port name, returns the handle to the port to out | 76 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| 76 | Result ConnectToPort(Handle* out, const char* port_name) { | 77 | static Result ConnectToPort(Handle* out, const char* port_name) { |
| 77 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | 78 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); |
| 78 | 79 | ||
| 79 | DEBUG_LOG(SVC, "called port_name=%s", port_name); | 80 | DEBUG_LOG(SVC, "called port_name=%s", port_name); |
| @@ -85,78 +86,83 @@ Result ConnectToPort(Handle* out, const char* port_name) { | |||
| 85 | } | 86 | } |
| 86 | 87 | ||
| 87 | /// Synchronize to an OS service | 88 | /// Synchronize to an OS service |
| 88 | 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 |
| 104 | Result CloseHandle(Handle handle) { | 109 | static Result CloseHandle(Handle handle) { |
| 105 | // ImplementMe | 110 | // ImplementMe |
| 106 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); | 111 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); |
| 107 | return 0; | 112 | return 0; |
| 108 | } | 113 | } |
| 109 | 114 | ||
| 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 | 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 |
| 135 | Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, | 140 | static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, |
| 136 | s64 nano_seconds) { | 141 | s64 nano_seconds) { |
| 137 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this | 142 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this |
| 138 | bool unlock_all = true; | 143 | bool unlock_all = true; |
| 139 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated | 144 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated |
| 140 | 145 | ||
| 141 | DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld", | 146 | DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld", |
| 142 | handle_count, (wait_all ? "true" : "false"), nano_seconds); | 147 | handle_count, (wait_all ? "true" : "false"), nano_seconds); |
| 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 " | 156 | DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), |
| 150 | "is nullptr!", handles[i]); | ||
| 151 | |||
| 152 | 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,17 +170,17 @@ Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wa | |||
| 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) |
| 177 | Result CreateAddressArbiter(u32* arbiter) { | 183 | static Result CreateAddressArbiter(u32* arbiter) { |
| 178 | DEBUG_LOG(SVC, "called"); | 184 | DEBUG_LOG(SVC, "called"); |
| 179 | Handle handle = Kernel::CreateAddressArbiter(); | 185 | Handle handle = Kernel::CreateAddressArbiter(); |
| 180 | *arbiter = handle; | 186 | *arbiter = handle; |
| @@ -182,20 +188,22 @@ Result CreateAddressArbiter(u32* arbiter) { | |||
| 182 | } | 188 | } |
| 183 | 189 | ||
| 184 | /// Arbitrate address | 190 | /// Arbitrate address |
| 185 | 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 |
| 191 | void OutputDebugString(const char* string) { | 199 | static void OutputDebugString(const char* string) { |
| 192 | OS_LOG(SVC, "%s", string); | 200 | OS_LOG(SVC, "%s", string); |
| 193 | } | 201 | } |
| 194 | 202 | ||
| 195 | /// Get resource limit | 203 | /// Get resource limit |
| 196 | Result GetResourceLimit(Handle* resource_limit, Handle process) { | 204 | static Result GetResourceLimit(Handle* resource_limit, Handle process) { |
| 197 | // With regards to proceess values: | 205 | // With regards to proceess values: |
| 198 | // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for | 206 | // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for |
| 199 | // the current KThread. | 207 | // the current KThread. |
| 200 | *resource_limit = 0xDEADBEEF; | 208 | *resource_limit = 0xDEADBEEF; |
| 201 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process); | 209 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process); |
| @@ -203,7 +211,7 @@ Result GetResourceLimit(Handle* resource_limit, Handle process) { | |||
| 203 | } | 211 | } |
| 204 | 212 | ||
| 205 | /// Get resource limit current values | 213 | /// Get resource limit current values |
| 206 | Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, | 214 | static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, |
| 207 | s32 name_count) { | 215 | s32 name_count) { |
| 208 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", | 216 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", |
| 209 | resource_limit, names, name_count); | 217 | resource_limit, names, name_count); |
| @@ -212,7 +220,7 @@ Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* n | |||
| 212 | } | 220 | } |
| 213 | 221 | ||
| 214 | /// Creates a new thread | 222 | /// Creates a new thread |
| 215 | Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { | 223 | static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { |
| 216 | std::string name; | 224 | std::string name; |
| 217 | if (Symbols::HasSymbol(entry_point)) { | 225 | if (Symbols::HasSymbol(entry_point)) { |
| 218 | TSymbol symbol = Symbols::GetSymbol(entry_point); | 226 | TSymbol symbol = Symbols::GetSymbol(entry_point); |
| @@ -227,14 +235,14 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p | |||
| 227 | Core::g_app_core->SetReg(1, thread); | 235 | Core::g_app_core->SetReg(1, thread); |
| 228 | 236 | ||
| 229 | DEBUG_LOG(SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | 237 | DEBUG_LOG(SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " |
| 230 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, | 238 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, |
| 231 | name.c_str(), arg, stack_top, priority, processor_id, thread); | 239 | name.c_str(), arg, stack_top, priority, processor_id, thread); |
| 232 | 240 | ||
| 233 | return 0; | 241 | return 0; |
| 234 | } | 242 | } |
| 235 | 243 | ||
| 236 | /// Called when a thread exits | 244 | /// Called when a thread exits |
| 237 | u32 ExitThread() { | 245 | static u32 ExitThread() { |
| 238 | Handle thread = Kernel::GetCurrentThreadHandle(); | 246 | Handle thread = Kernel::GetCurrentThreadHandle(); |
| 239 | 247 | ||
| 240 | DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C | 248 | DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C |
| @@ -245,54 +253,56 @@ u32 ExitThread() { | |||
| 245 | } | 253 | } |
| 246 | 254 | ||
| 247 | /// Gets the priority for the specified thread | 255 | /// Gets the priority for the specified thread |
| 248 | 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 | 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 |
| 259 | Result CreateMutex(Handle* mutex, u32 initial_locked) { | 270 | static Result CreateMutex(Handle* mutex, u32 initial_locked) { |
| 260 | *mutex = Kernel::CreateMutex((initial_locked != 0)); | 271 | *mutex = Kernel::CreateMutex((initial_locked != 0)); |
| 261 | DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", | 272 | DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", |
| 262 | initial_locked ? "true" : "false", *mutex); | 273 | initial_locked ? "true" : "false", *mutex); |
| 263 | return 0; | 274 | return 0; |
| 264 | } | 275 | } |
| 265 | 276 | ||
| 266 | /// Release a mutex | 277 | /// Release a mutex |
| 267 | 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 |
| 275 | Result GetThreadId(u32* thread_id, Handle thread) { | 285 | static Result GetThreadId(u32* thread_id, Handle thread) { |
| 276 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); | 286 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); |
| 277 | return 0; | 287 | return 0; |
| 278 | } | 288 | } |
| 279 | 289 | ||
| 280 | /// Query memory | 290 | /// Query memory |
| 281 | Result QueryMemory(void* info, void* out, u32 addr) { | 291 | static Result QueryMemory(void* info, void* out, u32 addr) { |
| 282 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); | 292 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); |
| 283 | return 0; | 293 | return 0; |
| 284 | } | 294 | } |
| 285 | 295 | ||
| 286 | /// Create an event | 296 | /// Create an event |
| 287 | Result CreateEvent(Handle* evt, u32 reset_type) { | 297 | static Result CreateEvent(Handle* evt, u32 reset_type) { |
| 288 | *evt = Kernel::CreateEvent((ResetType)reset_type); | 298 | *evt = Kernel::CreateEvent((ResetType)reset_type); |
| 289 | DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", | 299 | DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", |
| 290 | reset_type, *evt); | 300 | reset_type, *evt); |
| 291 | return 0; | 301 | return 0; |
| 292 | } | 302 | } |
| 293 | 303 | ||
| 294 | /// Duplicates a kernel handle | 304 | /// Duplicates a kernel handle |
| 295 | Result DuplicateHandle(Handle* out, Handle handle) { | 305 | static Result DuplicateHandle(Handle* out, Handle handle) { |
| 296 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); | 306 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); |
| 297 | 307 | ||
| 298 | // Translate kernel handles -> real handles | 308 | // Translate kernel handles -> real handles |
| @@ -301,7 +311,7 @@ Result DuplicateHandle(Handle* out, Handle handle) { | |||
| 301 | } | 311 | } |
| 302 | _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), | 312 | _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), |
| 303 | "(UNIMPLEMENTED) process handle duplication!"); | 313 | "(UNIMPLEMENTED) process handle duplication!"); |
| 304 | 314 | ||
| 305 | // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate. | 315 | // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate. |
| 306 | *out = handle; | 316 | *out = handle; |
| 307 | 317 | ||
| @@ -309,26 +319,27 @@ Result DuplicateHandle(Handle* out, Handle handle) { | |||
| 309 | } | 319 | } |
| 310 | 320 | ||
| 311 | /// Signals an event | 321 | /// Signals an event |
| 312 | 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 | 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 | 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 |
| 331 | s64 GetSystemTick() { | 342 | static s64 GetSystemTick() { |
| 332 | return (s64)Core::g_app_core->GetTicks(); | 343 | return (s64)Core::g_app_core->GetTicks(); |
| 333 | } | 344 | } |
| 334 | 345 | ||
diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h index 1d125faf6..6be393d0b 100644 --- a/src/core/hle/svc.h +++ b/src/core/hle/svc.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
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 33f75c50a..ea001673a 100644 --- a/src/core/hw/hw.cpp +++ b/src/core/hw/hw.cpp | |||
| @@ -39,7 +39,7 @@ enum { | |||
| 39 | template <typename T> | 39 | template <typename T> |
| 40 | inline void Read(T &var, const u32 addr) { | 40 | inline void Read(T &var, const u32 addr) { |
| 41 | switch (addr & 0xFFFFF000) { | 41 | switch (addr & 0xFFFFF000) { |
| 42 | 42 | ||
| 43 | // TODO(bunnei): What is the virtual address of NDMA? | 43 | // TODO(bunnei): What is the virtual address of NDMA? |
| 44 | // case VADDR_NDMA: | 44 | // case VADDR_NDMA: |
| 45 | // NDMA::Read(var, addr); | 45 | // NDMA::Read(var, addr); |
| @@ -57,9 +57,9 @@ inline void Read(T &var, const u32 addr) { | |||
| 57 | template <typename T> | 57 | template <typename T> |
| 58 | inline void Write(u32 addr, const T data) { | 58 | inline void Write(u32 addr, const T data) { |
| 59 | switch (addr & 0xFFFFF000) { | 59 | switch (addr & 0xFFFFF000) { |
| 60 | 60 | ||
| 61 | // TODO(bunnei): What is the virtual address of NDMA? | 61 | // TODO(bunnei): What is the virtual address of NDMA? |
| 62 | // case VADDR_NDMA | 62 | // case VADDR_NDMA |
| 63 | // NDMA::Write(addr, data); | 63 | // NDMA::Write(addr, data); |
| 64 | // break; | 64 | // break; |
| 65 | 65 | ||
| @@ -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/loader/elf.cpp b/src/core/loader/elf.cpp index 389d5a8c9..63d2496ed 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -273,13 +273,13 @@ bool ElfReader::LoadInto(u32 vaddr) { | |||
| 273 | 273 | ||
| 274 | for (int i = 0; i < header->e_phnum; i++) { | 274 | for (int i = 0; i < header->e_phnum; i++) { |
| 275 | Elf32_Phdr *p = segments + i; | 275 | Elf32_Phdr *p = segments + i; |
| 276 | INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr, | 276 | INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr, |
| 277 | p->p_filesz, p->p_memsz); | 277 | p->p_filesz, p->p_memsz); |
| 278 | 278 | ||
| 279 | if (p->p_type == PT_LOAD) { | 279 | if (p->p_type == PT_LOAD) { |
| 280 | segment_addr[i] = base_addr + p->p_vaddr; | 280 | segment_addr[i] = base_addr + p->p_vaddr; |
| 281 | memcpy(Memory::GetPointer(segment_addr[i]), GetSegmentPtr(i), p->p_filesz); | 281 | memcpy(Memory::GetPointer(segment_addr[i]), GetSegmentPtr(i), p->p_filesz); |
| 282 | INFO_LOG(MASTER_LOG, "Loadable Segment Copied to %08x, size %08x", segment_addr[i], | 282 | INFO_LOG(MASTER_LOG, "Loadable Segment Copied to %08x, size %08x", segment_addr[i], |
| 283 | p->p_memsz); | 283 | p->p_memsz); |
| 284 | } | 284 | } |
| 285 | } | 285 | } |
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 1e5501e6d..343bb7523 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp | |||
| @@ -24,7 +24,7 @@ static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) | |||
| 24 | * @param size Size of compressed buffer | 24 | * @param size Size of compressed buffer |
| 25 | * @return Size of decompressed buffer | 25 | * @return Size of decompressed buffer |
| 26 | */ | 26 | */ |
| 27 | u32 LZSS_GetDecompressedSize(u8* buffer, u32 size) { | 27 | static u32 LZSS_GetDecompressedSize(u8* buffer, u32 size) { |
| 28 | u32 offset_size = *(u32*)(buffer + size - 4); | 28 | u32 offset_size = *(u32*)(buffer + size - 4); |
| 29 | return offset_size + size; | 29 | return offset_size + size; |
| 30 | } | 30 | } |
| @@ -37,7 +37,7 @@ u32 LZSS_GetDecompressedSize(u8* buffer, u32 size) { | |||
| 37 | * @param decompressed_size Size of decompressed buffer | 37 | * @param decompressed_size Size of decompressed buffer |
| 38 | * @return True on success, otherwise false | 38 | * @return True on success, otherwise false |
| 39 | */ | 39 | */ |
| 40 | bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) { | 40 | static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) { |
| 41 | u8* footer = compressed + compressed_size - 8; | 41 | u8* footer = compressed + compressed_size - 8; |
| 42 | u32 buffer_top_and_bottom = *(u32*)footer; | 42 | u32 buffer_top_and_bottom = *(u32*)footer; |
| 43 | u32 out = decompressed_size; | 43 | u32 out = decompressed_size; |
| @@ -118,7 +118,7 @@ AppLoader_NCCH::~AppLoader_NCCH() { | |||
| 118 | * @return ResultStatus result of function | 118 | * @return ResultStatus result of function |
| 119 | */ | 119 | */ |
| 120 | ResultStatus AppLoader_NCCH::LoadExec() const { | 120 | ResultStatus AppLoader_NCCH::LoadExec() const { |
| 121 | if (!is_loaded) | 121 | if (!is_loaded) |
| 122 | return ResultStatus::ErrorNotLoaded; | 122 | return ResultStatus::ErrorNotLoaded; |
| 123 | 123 | ||
| 124 | std::vector<u8> code; | 124 | std::vector<u8> code; |
| @@ -185,7 +185,7 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& | |||
| 185 | return ResultStatus::Error; | 185 | return ResultStatus::Error; |
| 186 | } | 186 | } |
| 187 | return ResultStatus::ErrorNotUsed; | 187 | return ResultStatus::ErrorNotUsed; |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | /** | 190 | /** |
| 191 | * Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI) | 191 | * Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI) |
| @@ -210,7 +210,7 @@ ResultStatus AppLoader_NCCH::Load() { | |||
| 210 | file.Seek(ncch_offset, 0); | 210 | file.Seek(ncch_offset, 0); |
| 211 | file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); | 211 | file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | // Verify we are loading the correct file type... | 214 | // Verify we are loading the correct file type... |
| 215 | if (0 != memcmp(&ncch_header.magic, "NCCH", 4)) | 215 | if (0 != memcmp(&ncch_header.magic, "NCCH", 4)) |
| 216 | return ResultStatus::ErrorInvalidFormat; | 216 | return ResultStatus::ErrorInvalidFormat; |
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index f40a258b7..03116add8 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h | |||
| @@ -215,7 +215,7 @@ private: | |||
| 215 | u32 entry_point; | 215 | u32 entry_point; |
| 216 | u32 ncch_offset; // Offset to NCCH header, can be 0 or after NCSD header | 216 | u32 ncch_offset; // Offset to NCCH header, can be 0 or after NCSD header |
| 217 | u32 exefs_offset; | 217 | u32 exefs_offset; |
| 218 | 218 | ||
| 219 | NCCH_Header ncch_header; | 219 | NCCH_Header ncch_header; |
| 220 | ExeFs_Header exefs_header; | 220 | ExeFs_Header exefs_header; |
| 221 | ExHeader_Header exheader_header; | 221 | ExHeader_Header exheader_header; |
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp index cf12f24d9..74a93b1d9 100644 --- a/src/core/mem_map.cpp +++ b/src/core/mem_map.cpp | |||
| @@ -11,38 +11,38 @@ | |||
| 11 | 11 | ||
| 12 | namespace Memory { | 12 | namespace Memory { |
| 13 | 13 | ||
| 14 | u8* g_base = NULL; ///< The base pointer to the auto-mirrored arena. | 14 | u8* g_base = nullptr; ///< The base pointer to the auto-mirrored arena. |
| 15 | 15 | ||
| 16 | MemArena g_arena; ///< The MemArena class | 16 | static MemArena arena; ///< The MemArena class |
| 17 | 17 | ||
| 18 | u8* g_exefs_code = NULL; ///< ExeFS:/.code is loaded here | 18 | u8* g_exefs_code = nullptr; ///< ExeFS:/.code is loaded here |
| 19 | u8* g_system_mem = NULL; ///< System memory | 19 | u8* g_system_mem = nullptr; ///< System memory |
| 20 | u8* g_heap = NULL; ///< Application heap (main memory) | 20 | u8* g_heap = nullptr; ///< Application heap (main memory) |
| 21 | u8* g_heap_gsp = NULL; ///< GSP heap (main memory) | 21 | u8* g_heap_gsp = nullptr; ///< GSP heap (main memory) |
| 22 | u8* g_vram = NULL; ///< Video memory (VRAM) pointer | 22 | u8* g_vram = nullptr; ///< Video memory (VRAM) pointer |
| 23 | u8* g_shared_mem = NULL; ///< Shared memory | 23 | u8* g_shared_mem = nullptr; ///< Shared memory |
| 24 | u8* g_kernel_mem; ///< Kernel memory | 24 | u8* g_kernel_mem; ///< Kernel memory |
| 25 | 25 | ||
| 26 | u8* g_physical_bootrom = NULL; ///< Bootrom physical memory | 26 | static u8* physical_bootrom = nullptr; ///< Bootrom physical memory |
| 27 | u8* g_uncached_bootrom = NULL; | 27 | static u8* uncached_bootrom = nullptr; |
| 28 | 28 | ||
| 29 | u8* g_physical_exefs_code = NULL; ///< Phsical ExeFS:/.code is loaded here | 29 | static u8* physical_exefs_code = nullptr; ///< Phsical ExeFS:/.code is loaded here |
| 30 | u8* g_physical_system_mem = NULL; ///< System physical memory | 30 | static u8* physical_system_mem = nullptr; ///< System physical memory |
| 31 | u8* g_physical_fcram = NULL; ///< Main physical memory (FCRAM) | 31 | static u8* physical_fcram = nullptr; ///< Main physical memory (FCRAM) |
| 32 | u8* g_physical_heap_gsp = NULL; ///< GSP heap physical memory | 32 | static u8* physical_heap_gsp = nullptr; ///< GSP heap physical memory |
| 33 | u8* g_physical_vram = NULL; ///< Video physical memory (VRAM) | 33 | static u8* physical_vram = nullptr; ///< Video physical memory (VRAM) |
| 34 | u8* g_physical_shared_mem = NULL; ///< Physical shared memory | 34 | static u8* physical_shared_mem = nullptr; ///< Physical shared memory |
| 35 | u8* g_physical_kernel_mem; ///< Kernel memory | 35 | static u8* physical_kernel_mem; ///< Kernel memory |
| 36 | 36 | ||
| 37 | // We don't declare the IO region in here since its handled by other means. | 37 | // We don't declare the IO region in here since its handled by other means. |
| 38 | static MemoryView g_views[] = { | 38 | static MemoryView g_views[] = { |
| 39 | {&g_exefs_code, &g_physical_exefs_code, EXEFS_CODE_VADDR, EXEFS_CODE_SIZE, 0}, | 39 | {&g_exefs_code, &physical_exefs_code, EXEFS_CODE_VADDR, EXEFS_CODE_SIZE, 0}, |
| 40 | {&g_vram, &g_physical_vram, VRAM_VADDR, VRAM_SIZE, 0}, | 40 | {&g_vram, &physical_vram, VRAM_VADDR, VRAM_SIZE, 0}, |
| 41 | {&g_heap, &g_physical_fcram, HEAP_VADDR, HEAP_SIZE, MV_IS_PRIMARY_RAM}, | 41 | {&g_heap, &physical_fcram, HEAP_VADDR, HEAP_SIZE, MV_IS_PRIMARY_RAM}, |
| 42 | {&g_shared_mem, &g_physical_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, 0}, | 42 | {&g_shared_mem, &physical_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, 0}, |
| 43 | {&g_system_mem, &g_physical_system_mem, SYSTEM_MEMORY_VADDR, SYSTEM_MEMORY_SIZE, 0}, | 43 | {&g_system_mem, &physical_system_mem, SYSTEM_MEMORY_VADDR, SYSTEM_MEMORY_SIZE, 0}, |
| 44 | {&g_kernel_mem, &g_physical_kernel_mem, KERNEL_MEMORY_VADDR, KERNEL_MEMORY_SIZE, 0}, | 44 | {&g_kernel_mem, &physical_kernel_mem, KERNEL_MEMORY_VADDR, KERNEL_MEMORY_SIZE, 0}, |
| 45 | {&g_heap_gsp, &g_physical_heap_gsp, HEAP_GSP_VADDR, HEAP_GSP_SIZE, 0}, | 45 | {&g_heap_gsp, &physical_heap_gsp, HEAP_GSP_VADDR, HEAP_GSP_SIZE, 0}, |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | /*static MemoryView views[] = | 48 | /*static MemoryView views[] = |
| @@ -69,18 +69,18 @@ void Init() { | |||
| 69 | g_views[i].size = FCRAM_SIZE; | 69 | g_views[i].size = FCRAM_SIZE; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &g_arena); | 72 | g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &arena); |
| 73 | 73 | ||
| 74 | NOTICE_LOG(MEMMAP, "initialized OK, RAM at %p (mirror at 0 @ %p)", g_heap, | 74 | NOTICE_LOG(MEMMAP, "initialized OK, RAM at %p (mirror at 0 @ %p)", g_heap, |
| 75 | g_physical_fcram); | 75 | physical_fcram); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | void Shutdown() { | 78 | void Shutdown() { |
| 79 | u32 flags = 0; | 79 | u32 flags = 0; |
| 80 | MemoryMap_Shutdown(g_views, kNumMemViews, flags, &g_arena); | 80 | MemoryMap_Shutdown(g_views, kNumMemViews, flags, &arena); |
| 81 | 81 | ||
| 82 | g_arena.ReleaseSpace(); | 82 | arena.ReleaseSpace(); |
| 83 | g_base = NULL; | 83 | g_base = nullptr; |
| 84 | 84 | ||
| 85 | NOTICE_LOG(MEMMAP, "shutdown OK"); | 85 | NOTICE_LOG(MEMMAP, "shutdown OK"); |
| 86 | } | 86 | } |
diff --git a/src/core/mem_map.h b/src/core/mem_map.h index eed445046..a58c59244 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h | |||
| @@ -147,6 +147,7 @@ u32 Read16_ZX(VAddr addr); | |||
| 147 | void Write8(VAddr addr, u8 data); | 147 | void Write8(VAddr addr, u8 data); |
| 148 | void Write16(VAddr addr, u16 data); | 148 | void Write16(VAddr addr, u16 data); |
| 149 | void Write32(VAddr addr, u32 data); | 149 | void Write32(VAddr addr, u32 data); |
| 150 | void Write64(VAddr addr, u64 data); | ||
| 150 | 151 | ||
| 151 | void WriteBlock(VAddr addr, const u8* data, size_t size); | 152 | void WriteBlock(VAddr addr, const u8* data, size_t size); |
| 152 | 153 | ||
| @@ -156,7 +157,7 @@ u8* GetPointer(VAddr virtual_address); | |||
| 156 | * Maps a block of memory on the heap | 157 | * Maps a block of memory on the heap |
| 157 | * @param size Size of block in bytes | 158 | * @param size Size of block in bytes |
| 158 | * @param operation Memory map operation type | 159 | * @param operation Memory map operation type |
| 159 | * @param flags Memory allocation flags | 160 | * @param permissions Memory allocation permissions |
| 160 | */ | 161 | */ |
| 161 | u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions); | 162 | u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions); |
| 162 | 163 | ||
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp index 90951812b..e8747840c 100644 --- a/src/core/mem_map_funcs.cpp +++ b/src/core/mem_map_funcs.cpp | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | 12 | ||
| 13 | namespace Memory { | 13 | namespace Memory { |
| 14 | 14 | ||
| 15 | std::map<u32, MemoryBlock> g_heap_map; | 15 | static std::map<u32, MemoryBlock> heap_map; |
| 16 | std::map<u32, MemoryBlock> g_heap_gsp_map; | 16 | static std::map<u32, MemoryBlock> heap_gsp_map; |
| 17 | std::map<u32, MemoryBlock> g_shared_map; | 17 | static std::map<u32, MemoryBlock> shared_map; |
| 18 | 18 | ||
| 19 | /// Convert a physical address to virtual address | 19 | /// Convert a physical address to virtual address |
| 20 | VAddr PhysicalToVirtualAddress(const PAddr addr) { | 20 | VAddr PhysicalToVirtualAddress(const PAddr addr) { |
| @@ -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 | ||
| @@ -194,11 +194,11 @@ u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) { | |||
| 194 | block.operation = operation; | 194 | block.operation = operation; |
| 195 | block.permissions = permissions; | 195 | block.permissions = permissions; |
| 196 | 196 | ||
| 197 | if (g_heap_map.size() > 0) { | 197 | if (heap_map.size() > 0) { |
| 198 | const MemoryBlock last_block = g_heap_map.rbegin()->second; | 198 | const MemoryBlock last_block = heap_map.rbegin()->second; |
| 199 | block.address = last_block.address + last_block.size; | 199 | block.address = last_block.address + last_block.size; |
| 200 | } | 200 | } |
| 201 | g_heap_map[block.GetVirtualAddress()] = block; | 201 | heap_map[block.GetVirtualAddress()] = block; |
| 202 | 202 | ||
| 203 | return block.GetVirtualAddress(); | 203 | return block.GetVirtualAddress(); |
| 204 | } | 204 | } |
| @@ -217,11 +217,11 @@ u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) { | |||
| 217 | block.operation = operation; | 217 | block.operation = operation; |
| 218 | block.permissions = permissions; | 218 | block.permissions = permissions; |
| 219 | 219 | ||
| 220 | if (g_heap_gsp_map.size() > 0) { | 220 | if (heap_gsp_map.size() > 0) { |
| 221 | const MemoryBlock last_block = g_heap_gsp_map.rbegin()->second; | 221 | const MemoryBlock last_block = heap_gsp_map.rbegin()->second; |
| 222 | block.address = last_block.address + last_block.size; | 222 | block.address = last_block.address + last_block.size; |
| 223 | } | 223 | } |
| 224 | g_heap_gsp_map[block.GetVirtualAddress()] = block; | 224 | heap_gsp_map[block.GetVirtualAddress()] = block; |
| 225 | 225 | ||
| 226 | return block.GetVirtualAddress(); | 226 | return block.GetVirtualAddress(); |
| 227 | } | 227 | } |
diff --git a/src/core/system.h b/src/core/system.h index 8f8ddf87b..2bc2edc75 100644 --- a/src/core/system.h +++ b/src/core/system.h | |||
| @@ -11,16 +11,16 @@ | |||
| 11 | namespace System { | 11 | namespace System { |
| 12 | 12 | ||
| 13 | // State of the full emulator | 13 | // State of the full emulator |
| 14 | typedef enum { | 14 | enum State { |
| 15 | STATE_NULL = 0, ///< System is in null state, nothing initialized | 15 | STATE_NULL = 0, ///< System is in null state, nothing initialized |
| 16 | STATE_IDLE, ///< System is in an initialized state, but not running | 16 | STATE_IDLE, ///< System is in an initialized state, but not running |
| 17 | STATE_RUNNING, ///< System is running | 17 | STATE_RUNNING, ///< System is running |
| 18 | STATE_LOADING, ///< System is loading a ROM | 18 | STATE_LOADING, ///< System is loading a ROM |
| 19 | STATE_HALTED, ///< System is halted (error) | 19 | STATE_HALTED, ///< System is halted (error) |
| 20 | STATE_STALLED, ///< System is stalled (unused) | 20 | STATE_STALLED, ///< System is stalled (unused) |
| 21 | STATE_DEBUG, ///< System is in a special debug mode (unused) | 21 | STATE_DEBUG, ///< System is in a special debug mode (unused) |
| 22 | STATE_DIE ///< System is shutting down | 22 | STATE_DIE ///< System is shutting down |
| 23 | } State; | 23 | }; |
| 24 | 24 | ||
| 25 | extern volatile State g_state; | 25 | extern volatile State g_state; |
| 26 | 26 | ||
| @@ -30,4 +30,4 @@ void RunLoopFor(int cycles); | |||
| 30 | void RunLoopUntil(u64 global_cycles); | 30 | void RunLoopUntil(u64 global_cycles); |
| 31 | void Shutdown(); | 31 | void Shutdown(); |
| 32 | 32 | ||
| 33 | }; | 33 | } |
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index 22b8e9950..275b06b7c 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp | |||
| @@ -318,9 +318,9 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { | |||
| 318 | return; | 318 | return; |
| 319 | 319 | ||
| 320 | #ifndef HAVE_PNG | 320 | #ifndef HAVE_PNG |
| 321 | return; | 321 | return; |
| 322 | #else | 322 | #else |
| 323 | if (!data) | 323 | if (!data) |
| 324 | return; | 324 | return; |
| 325 | 325 | ||
| 326 | // Write data to file | 326 | // Write data to file |
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h index 8b1499bf2..b1558cfae 100644 --- a/src/video_core/debug_utils/debug_utils.h +++ b/src/video_core/debug_utils/debug_utils.h | |||
| @@ -41,7 +41,7 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data | |||
| 41 | // Utility class to log Pica commands. | 41 | // Utility class to log Pica commands. |
| 42 | struct PicaTrace { | 42 | struct PicaTrace { |
| 43 | struct Write : public std::pair<u32,u32> { | 43 | struct Write : public std::pair<u32,u32> { |
| 44 | Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {} | 44 | Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {} |
| 45 | 45 | ||
| 46 | u32& Id() { return first; } | 46 | u32& Id() { return first; } |
| 47 | const u32& Id() const { return first; } | 47 | const u32& Id() const { return first; } |
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index f1dbc9d17..bce402b88 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -25,7 +25,7 @@ public: | |||
| 25 | /// Swap buffers (render frame) | 25 | /// Swap buffers (render frame) |
| 26 | virtual void SwapBuffers() = 0; | 26 | virtual void SwapBuffers() = 0; |
| 27 | 27 | ||
| 28 | /** | 28 | /** |
| 29 | * Set the emulator window to use for renderer | 29 | * Set the emulator window to use for renderer |
| 30 | * @param window EmuWindow handle to emulator window to use for rendering | 30 | * @param window EmuWindow handle to emulator window to use for rendering |
| 31 | */ | 31 | */ |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 8483f79be..abbb4c2cb 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -191,7 +191,8 @@ void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x | |||
| 191 | * Draws the emulated screens to the emulator window. | 191 | * Draws the emulated screens to the emulator window. |
| 192 | */ | 192 | */ |
| 193 | void RendererOpenGL::DrawScreens() { | 193 | void RendererOpenGL::DrawScreens() { |
| 194 | glViewport(0, 0, resolution_width, resolution_height); | 194 | auto viewport_extent = GetViewportExtent(); |
| 195 | glViewport(viewport_extent.left, viewport_extent.top, viewport_extent.GetWidth(), viewport_extent.GetHeight()); // TODO: Or bottom? | ||
| 195 | glClear(GL_COLOR_BUFFER_BIT); | 196 | glClear(GL_COLOR_BUFFER_BIT); |
| 196 | 197 | ||
| 197 | glUseProgram(program_id); | 198 | glUseProgram(program_id); |
| @@ -228,6 +229,34 @@ void RendererOpenGL::SetWindow(EmuWindow* window) { | |||
| 228 | render_window = window; | 229 | render_window = window; |
| 229 | } | 230 | } |
| 230 | 231 | ||
| 232 | MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() { | ||
| 233 | unsigned framebuffer_width; | ||
| 234 | unsigned framebuffer_height; | ||
| 235 | std::tie(framebuffer_width, framebuffer_height) = render_window->GetFramebufferSize(); | ||
| 236 | |||
| 237 | float window_aspect_ratio = static_cast<float>(framebuffer_height) / framebuffer_width; | ||
| 238 | float emulation_aspect_ratio = static_cast<float>(resolution_height) / resolution_width; | ||
| 239 | |||
| 240 | MathUtil::Rectangle<unsigned> viewport_extent; | ||
| 241 | if (window_aspect_ratio > emulation_aspect_ratio) { | ||
| 242 | // Window is narrower than the emulation content => apply borders to the top and bottom | ||
| 243 | unsigned viewport_height = emulation_aspect_ratio * framebuffer_width; | ||
| 244 | viewport_extent.left = 0; | ||
| 245 | viewport_extent.top = (framebuffer_height - viewport_height) / 2; | ||
| 246 | viewport_extent.right = viewport_extent.left + framebuffer_width; | ||
| 247 | viewport_extent.bottom = viewport_extent.top + viewport_height; | ||
| 248 | } else { | ||
| 249 | // Otherwise, apply borders to the left and right sides of the window. | ||
| 250 | unsigned viewport_width = framebuffer_height / emulation_aspect_ratio; | ||
| 251 | viewport_extent.left = (framebuffer_width - viewport_width) / 2; | ||
| 252 | viewport_extent.top = 0; | ||
| 253 | viewport_extent.right = viewport_extent.left + viewport_width; | ||
| 254 | viewport_extent.bottom = viewport_extent.top + framebuffer_height; | ||
| 255 | } | ||
| 256 | |||
| 257 | return viewport_extent; | ||
| 258 | } | ||
| 259 | |||
| 231 | /// Initialize the renderer | 260 | /// Initialize the renderer |
| 232 | void RendererOpenGL::Init() { | 261 | void RendererOpenGL::Init() { |
| 233 | render_window->MakeCurrent(); | 262 | render_window->MakeCurrent(); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index eed201a95..7fdcec731 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -4,13 +4,15 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 8 | |||
| 7 | #include "generated/gl_3_2_core.h" | 9 | #include "generated/gl_3_2_core.h" |
| 8 | 10 | ||
| 9 | #include "common/common.h" | 11 | #include "common/math_util.h" |
| 12 | |||
| 10 | #include "core/hw/gpu.h" | 13 | #include "core/hw/gpu.h" |
| 11 | #include "video_core/renderer_base.h" | ||
| 12 | 14 | ||
| 13 | #include <array> | 15 | #include "video_core/renderer_base.h" |
| 14 | 16 | ||
| 15 | class EmuWindow; | 17 | class EmuWindow; |
| 16 | 18 | ||
| @@ -52,6 +54,9 @@ private: | |||
| 52 | static void LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& framebuffer, | 54 | static void LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& framebuffer, |
| 53 | const TextureInfo& texture); | 55 | const TextureInfo& texture); |
| 54 | 56 | ||
| 57 | /// Computes the viewport rectangle | ||
| 58 | MathUtil::Rectangle<unsigned> GetViewportExtent(); | ||
| 59 | |||
| 55 | EmuWindow* render_window; ///< Handle to render window | 60 | EmuWindow* render_window; ///< Handle to render window |
| 56 | u32 last_mode; ///< Last render mode | 61 | u32 last_mode; ///< Last render mode |
| 57 | 62 | ||
diff --git a/src/video_core/utils.cpp b/src/video_core/utils.cpp index c1848f923..f1156a493 100644 --- a/src/video_core/utils.cpp +++ b/src/video_core/utils.cpp | |||
| @@ -20,7 +20,7 @@ namespace VideoCore { | |||
| 20 | void DumpTGA(std::string filename, short width, short height, u8* raw_data) { | 20 | void DumpTGA(std::string filename, short width, short height, u8* raw_data) { |
| 21 | TGAHeader hdr = {0, 0, 2, 0, 0, 0, 0, width, height, 24, 0}; | 21 | TGAHeader hdr = {0, 0, 2, 0, 0, 0, 0, width, height, 24, 0}; |
| 22 | FILE* fout = fopen(filename.c_str(), "wb"); | 22 | FILE* fout = fopen(filename.c_str(), "wb"); |
| 23 | 23 | ||
| 24 | fwrite(&hdr, sizeof(TGAHeader), 1, fout); | 24 | fwrite(&hdr, sizeof(TGAHeader), 1, fout); |
| 25 | 25 | ||
| 26 | for (int y = 0; y < height; y++) { | 26 | for (int y = 0; y < height; y++) { |
| @@ -30,7 +30,7 @@ void DumpTGA(std::string filename, short width, short height, u8* raw_data) { | |||
| 30 | putc(raw_data[(3 * (y * width)) + (3 * x) + 2], fout); // r | 30 | putc(raw_data[(3 * (y * width)) + (3 * x) + 2], fout); // r |
| 31 | } | 31 | } |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | fclose(fout); | 34 | fclose(fout); |
| 35 | } | 35 | } |
| 36 | } // namespace | 36 | } // namespace |
diff --git a/src/video_core/utils.h b/src/video_core/utils.h index 9cb3d4d43..21380a908 100644 --- a/src/video_core/utils.h +++ b/src/video_core/utils.h | |||
| @@ -12,24 +12,24 @@ namespace FormatPrecision { | |||
| 12 | 12 | ||
| 13 | /// Adjust RGBA8 color with RGBA6 precision | 13 | /// Adjust RGBA8 color with RGBA6 precision |
| 14 | static inline u32 rgba8_with_rgba6(u32 src) { | 14 | static inline u32 rgba8_with_rgba6(u32 src) { |
| 15 | u32 color = src; | 15 | u32 color = src; |
| 16 | color &= 0xFCFCFCFC; | 16 | color &= 0xFCFCFCFC; |
| 17 | color |= (color >> 6) & 0x03030303; | 17 | color |= (color >> 6) & 0x03030303; |
| 18 | return color; | 18 | return color; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | /// Adjust RGBA8 color with RGB565 precision | 21 | /// Adjust RGBA8 color with RGB565 precision |
| 22 | static inline u32 rgba8_with_rgb565(u32 src) { | 22 | static inline u32 rgba8_with_rgb565(u32 src) { |
| 23 | u32 color = (src & 0xF8FCF8); | 23 | u32 color = (src & 0xF8FCF8); |
| 24 | color |= (color >> 5) & 0x070007; | 24 | color |= (color >> 5) & 0x070007; |
| 25 | color |= (color >> 6) & 0x000300; | 25 | color |= (color >> 6) & 0x000300; |
| 26 | color |= 0xFF000000; | 26 | color |= 0xFF000000; |
| 27 | return color; | 27 | return color; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | /// Adjust Z24 depth value with Z16 precision | 30 | /// Adjust Z24 depth value with Z16 precision |
| 31 | static inline u32 z24_with_z16(u32 src) { | 31 | static inline u32 z24_with_z16(u32 src) { |
| 32 | return (src & 0xFFFF00) | (src >> 16); | 32 | return (src & 0xFFFF00) | (src >> 16); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | } // namespace | 35 | } // namespace |
diff --git a/src/video_core/vertex_shader.h b/src/video_core/vertex_shader.h index 607a8e803..bfb6fb6e3 100644 --- a/src/video_core/vertex_shader.h +++ b/src/video_core/vertex_shader.h | |||
| @@ -141,7 +141,7 @@ union Instruction { | |||
| 141 | return BitFieldType::Value(); | 141 | return BitFieldType::Value(); |
| 142 | else if (GetRegisterType() == Temporary) | 142 | else if (GetRegisterType() == Temporary) |
| 143 | return BitFieldType::Value() - 0x10; | 143 | return BitFieldType::Value() - 0x10; |
| 144 | else if (GetRegisterType() == FloatUniform) | 144 | else // if (GetRegisterType() == FloatUniform) |
| 145 | return BitFieldType::Value() - 0x20; | 145 | return BitFieldType::Value() - 0x20; |
| 146 | } | 146 | } |
| 147 | 147 | ||