aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--CONTRIBUTING.md43
-rw-r--r--src/citra/citra.cpp2
-rw-r--r--src/citra/emu_window/emu_window_glfw.cpp78
-rw-r--r--src/citra/emu_window/emu_window_glfw.h18
-rw-r--r--src/citra_qt/bootmanager.cpp80
-rw-r--r--src/citra_qt/bootmanager.hxx22
-rw-r--r--src/citra_qt/config/controller_config_util.cpp4
-rw-r--r--src/citra_qt/debugger/callstack.cpp6
-rw-r--r--src/citra_qt/debugger/registers.cpp28
-rw-r--r--src/citra_qt/debugger/registers.hxx10
-rw-r--r--src/citra_qt/main.cpp3
-rw-r--r--src/common/chunk_file.h14
-rw-r--r--src/common/common_funcs.h14
-rw-r--r--src/common/common_types.h6
-rw-r--r--src/common/console_listener.cpp24
-rw-r--r--src/common/emu_window.h128
-rw-r--r--src/common/extended_trace.cpp26
-rw-r--r--src/common/fifo_queue.h2
-rw-r--r--src/common/file_search.cpp2
-rw-r--r--src/common/file_util.cpp62
-rw-r--r--src/common/file_util.h186
-rw-r--r--src/common/hash.cpp32
-rw-r--r--src/common/linear_disk_cache.h6
-rw-r--r--src/common/log.h7
-rw-r--r--src/common/log_manager.cpp12
-rw-r--r--src/common/log_manager.h4
-rw-r--r--src/common/math_util.cpp14
-rw-r--r--src/common/math_util.h9
-rw-r--r--src/common/mem_arena.cpp12
-rw-r--r--src/common/memory_util.cpp8
-rw-r--r--src/common/msg_handler.h42
-rw-r--r--src/common/string_util.cpp18
-rw-r--r--src/common/string_util.h2
-rw-r--r--src/common/symbols.cpp4
-rw-r--r--src/common/symbols.h2
-rw-r--r--src/common/thread.cpp6
-rw-r--r--src/common/thread.h10
-rw-r--r--src/common/thread_queue_list.h4
-rw-r--r--src/core/CMakeLists.txt15
-rw-r--r--src/core/arm/arm_interface.h6
-rw-r--r--src/core/arm/disassembler/load_symbol_map.cpp4
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp4
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h4
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp54
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.h2
-rw-r--r--src/core/arm/interpreter/arm_interpreter.cpp4
-rw-r--r--src/core/arm/interpreter/arm_interpreter.h4
-rw-r--r--src/core/arm/skyeye_common/armcpu.h2
-rw-r--r--src/core/arm/skyeye_common/armdefs.h34
-rw-r--r--src/core/arm/skyeye_common/armemu.h18
-rw-r--r--src/core/core.cpp14
-rw-r--r--src/core/core_timing.cpp50
-rw-r--r--src/core/core_timing.h2
-rw-r--r--src/core/file_sys/archive.h53
-rw-r--r--src/core/file_sys/archive_romfs.cpp28
-rw-r--r--src/core/file_sys/archive_romfs.h24
-rw-r--r--src/core/file_sys/archive_sdmc.cpp30
-rw-r--r--src/core/file_sys/archive_sdmc.h22
-rw-r--r--src/core/file_sys/directory_sdmc.cpp6
-rw-r--r--src/core/file_sys/directory_sdmc.h2
-rw-r--r--src/core/file_sys/file_sdmc.cpp4
-rw-r--r--src/core/file_sys/file_sdmc.h2
-rw-r--r--src/core/hle/config_mem.cpp2
-rw-r--r--src/core/hle/coprocessor.cpp2
-rw-r--r--src/core/hle/function_wrappers.h4
-rw-r--r--src/core/hle/hle.cpp6
-rw-r--r--src/core/hle/hle.h2
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp15
-rw-r--r--src/core/hle/kernel/address_arbiter.h4
-rw-r--r--src/core/hle/kernel/archive.cpp229
-rw-r--r--src/core/hle/kernel/archive.h41
-rw-r--r--src/core/hle/kernel/event.cpp47
-rw-r--r--src/core/hle/kernel/event.h14
-rw-r--r--src/core/hle/kernel/kernel.cpp6
-rw-r--r--src/core/hle/kernel/kernel.h54
-rw-r--r--src/core/hle/kernel/mutex.cpp52
-rw-r--r--src/core/hle/kernel/mutex.h5
-rw-r--r--src/core/hle/kernel/shared_memory.cpp45
-rw-r--r--src/core/hle/kernel/shared_memory.h7
-rw-r--r--src/core/hle/kernel/thread.cpp154
-rw-r--r--src/core/hle/kernel/thread.h9
-rw-r--r--src/core/hle/result.h400
-rw-r--r--src/core/hle/service/ac_u.cpp6
-rw-r--r--src/core/hle/service/ac_u.h4
-rw-r--r--src/core/hle/service/am_net.cpp47
-rw-r--r--src/core/hle/service/am_net.h27
-rw-r--r--src/core/hle/service/apt_u.cpp4
-rw-r--r--src/core/hle/service/apt_u.h4
-rw-r--r--src/core/hle/service/boss_u.cpp28
-rw-r--r--src/core/hle/service/boss_u.h27
-rw-r--r--src/core/hle/service/cfg_i.cpp59
-rw-r--r--src/core/hle/service/cfg_i.h27
-rw-r--r--src/core/hle/service/cfg_u.h2
-rw-r--r--src/core/hle/service/csnd_snd.cpp39
-rw-r--r--src/core/hle/service/csnd_snd.h27
-rw-r--r--src/core/hle/service/dsp_dsp.cpp4
-rw-r--r--src/core/hle/service/dsp_dsp.h2
-rw-r--r--src/core/hle/service/err_f.cpp4
-rw-r--r--src/core/hle/service/err_f.h4
-rw-r--r--src/core/hle/service/frd_u.h2
-rw-r--r--src/core/hle/service/fs_user.cpp279
-rw-r--r--src/core/hle/service/gsp_gpu.cpp33
-rw-r--r--src/core/hle/service/hid_user.cpp9
-rw-r--r--src/core/hle/service/hid_user.h2
-rw-r--r--src/core/hle/service/ir_rst.cpp36
-rw-r--r--src/core/hle/service/ir_rst.h27
-rw-r--r--src/core/hle/service/ir_u.cpp45
-rw-r--r--src/core/hle/service/ir_u.h27
-rw-r--r--src/core/hle/service/mic_u.cpp2
-rw-r--r--src/core/hle/service/mic_u.h2
-rw-r--r--src/core/hle/service/nwm_uds.h2
-rw-r--r--src/core/hle/service/pm_app.cpp35
-rw-r--r--src/core/hle/service/pm_app.h27
-rw-r--r--src/core/hle/service/ptm_u.cpp6
-rw-r--r--src/core/hle/service/ptm_u.h2
-rw-r--r--src/core/hle/service/service.cpp18
-rw-r--r--src/core/hle/service/service.h30
-rw-r--r--src/core/hle/service/soc_u.h2
-rw-r--r--src/core/hle/service/srv.cpp14
-rw-r--r--src/core/hle/svc.cpp151
-rw-r--r--src/core/hle/svc.h2
-rw-r--r--src/core/hw/gpu.cpp6
-rw-r--r--src/core/hw/hw.cpp8
-rw-r--r--src/core/hw/ndma.cpp2
-rw-r--r--src/core/loader/elf.cpp4
-rw-r--r--src/core/loader/ncch.cpp10
-rw-r--r--src/core/loader/ncch.h2
-rw-r--r--src/core/mem_map.cpp60
-rw-r--r--src/core/mem_map.h3
-rw-r--r--src/core/mem_map_funcs.cpp22
-rw-r--r--src/core/system.h22
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp4
-rw-r--r--src/video_core/debug_utils/debug_utils.h2
-rw-r--r--src/video_core/renderer_base.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp31
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h11
-rw-r--r--src/video_core/utils.cpp4
-rw-r--r--src/video_core/utils.h20
-rw-r--r--src/video_core/vertex_shader.h2
140 files changed, 2465 insertions, 1260 deletions
diff --git a/.gitignore b/.gitignore
index 659736ff..5e4a6eef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,10 @@
# Build directory
-build/
+[Bb]uild/
doc-build/
# Generated source files
src/common/scm_rev.cpp
+
+# Project/editor files
+*.swp
+.idea/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cb1067c9..82b66be7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -24,27 +24,36 @@ Citra is a brand new project, so we have a great opportunity to keep things clea
### Indentation/Whitespace Style
Follow the indentation/whitespace style shown below. Do not use tabs, use 4-spaces instead.
+### Comments
+* For regular comments, use C++ style (`//`) comments, even for multi-line ones.
+* For doc-comments (Doxygen comments), use `/// ` if it's a single line, else use the `/**` `*/` style featured in the example. Start the text on the second line, not the first containing `/**`.
+
```cpp
namespace Example {
// Namespace contents are not indented
-
+
// Declare globals at the top
int g_foo = 0;
char* g_some_pointer; // Notice the position of the *
-
+
+/// A colorful enum.
enum SomeEnum {
- COLOR_RED,
- COLOR_GREEN,
- COLOR_BLUE
+ COLOR_RED, ///< The color of fire.
+ COLOR_GREEN, ///< The color of grass.
+ COLOR_BLUE ///< Not actually the color of water.
};
-
+
+/**
+ * Very important struct that does a lot of stuff.
+ * Note that the asterisks are indented by one space.
+ */
struct Position {
int x, y;
};
-
+
// Use "typename" rather than "class" here, just to be consistent
-template
+template
void FooBar() {
int some_array[] = {
5,
@@ -52,29 +61,29 @@ void FooBar() {
7,
42
};
-
+
if (note == the_space_after_the_if) {
CallAfunction();
} else {
// Use a space after the // when commenting
}
-
+
// Comment directly above code when possible
if (some_condition) single_statement();
-
+
// Place a single space after the for loop semicolons
for (int i = 0; i != 25; ++i) {
// This is how we write loops
}
-
+
DoStuff(this, function, call, takes, up, multiple,
lines, like, this);
-
+
if (this || condition_takes_up_multiple &&
lines && like && this || everything ||
alright || then) {
}
-
+
switch (var) {
// No indentation for case label
case 1: {
@@ -85,18 +94,18 @@ void FooBar() {
case 3:
DoSomething(var);
return;
-
+
default:
// Yes, even break for the last case
break;
}
-
+
std::vector
you_can_declare,
a_few,
variables,
like_this;
}
-
+
}
```
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp
index 41b62ac1..f2aeb510 100644
--- a/src/citra/citra.cpp
+++ b/src/citra/citra.cpp
@@ -23,7 +23,7 @@ int __cdecl main(int argc, char **argv) {
}
Config config;
-
+
if (!Settings::values.enable_log)
LogManager::Shutdown();
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp
index 0c774bbc..697bf469 100644
--- a/src/citra/emu_window/emu_window_glfw.cpp
+++ b/src/citra/emu_window/emu_window_glfw.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
+#include <GLFW/glfw3.h>
+
#include "common/common.h"
#include "video_core/video_core.h"
@@ -10,22 +12,21 @@
#include "citra/emu_window/emu_window_glfw.h"
+EmuWindow_GLFW* EmuWindow_GLFW::GetEmuWindow(GLFWwindow* win) {
+ return static_cast<EmuWindow_GLFW*>(glfwGetWindowUserPointer(win));
+}
+
/// Called by GLFW when a key event occurs
void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) {
- if (!VideoCore::g_emu_window) {
- return;
- }
-
- int keyboard_id = ((EmuWindow_GLFW*)VideoCore::g_emu_window)->keyboard_id;
+ int keyboard_id = GetEmuWindow(win)->keyboard_id;
if (action == GLFW_PRESS) {
EmuWindow::KeyPressed({key, keyboard_id});
- }
-
- if (action == GLFW_RELEASE) {
+ } else if (action == GLFW_RELEASE) {
EmuWindow::KeyReleased({key, keyboard_id});
}
+
HID_User::PadUpdateComplete();
}
@@ -34,15 +35,36 @@ const bool EmuWindow_GLFW::IsOpen() {
return glfwWindowShouldClose(m_render_window) == 0;
}
+void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) {
+ _dbg_assert_(GUI, width > 0);
+ _dbg_assert_(GUI, height > 0);
+
+ GetEmuWindow(win)->NotifyFramebufferSizeChanged(std::pair<unsigned,unsigned>(width, height));
+}
+
+void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) {
+ _dbg_assert_(GUI, width > 0);
+ _dbg_assert_(GUI, height > 0);
+
+ // NOTE: GLFW provides no proper way to set a minimal window size.
+ // Hence, we just ignore the corresponding EmuWindow hint.
+
+ GetEmuWindow(win)->NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(width, height));
+}
+
/// EmuWindow_GLFW constructor
EmuWindow_GLFW::EmuWindow_GLFW() {
keyboard_id = KeyMap::NewDeviceId();
ReloadSetKeymaps();
+ glfwSetErrorCallback([](int error, const char *desc){
+ ERROR_LOG(GUI, "GLFW 0x%08x: %s", error, desc);
+ });
+
// Initialize the window
if(glfwInit() != GL_TRUE) {
- printf("Failed to initialize GLFW! Exiting...");
+ ERROR_LOG(GUI, "Failed to initialize GLFW! Exiting...");
exit(1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
@@ -50,19 +72,31 @@ EmuWindow_GLFW::EmuWindow_GLFW() {
// GLFW on OSX requires these window hints to be set to create a 3.2+ GL context.
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
- m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth,
- (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight),
- m_window_title.c_str(), NULL, NULL);
+
+ std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
+ m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth,
+ (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight),
+ window_title.c_str(), NULL, NULL);
if (m_render_window == NULL) {
- printf("Failed to create GLFW window! Exiting...");
+ ERROR_LOG(GUI, "Failed to create GLFW window! Exiting...");
exit(1);
}
-
- // Setup callbacks
+
glfwSetWindowUserPointer(m_render_window, this);
+
+ // Notify base interface about window state
+ int width, height;
+ glfwGetFramebufferSize(m_render_window, &width, &height);
+ OnFramebufferResizeEvent(m_render_window, width, height);
+
+ glfwGetWindowSize(m_render_window, &width, &height);
+ OnClientAreaResizeEvent(m_render_window, width, height);
+
+ // Setup callbacks
glfwSetKeyCallback(m_render_window, OnKeyEvent);
+ glfwSetFramebufferSizeCallback(m_render_window, OnFramebufferResizeEvent);
+ glfwSetWindowSizeCallback(m_render_window, OnClientAreaResizeEvent);
DoneCurrent();
}
@@ -110,3 +144,15 @@ void EmuWindow_GLFW::ReloadSetKeymaps() {
KeyMap::SetKeyMapping({Settings::values.pad_sup_key, keyboard_id}, HID_User::PAD_CIRCLE_UP);
KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, HID_User::PAD_CIRCLE_DOWN);
}
+
+void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) {
+ std::pair<int,int> current_size;
+ glfwGetWindowSize(m_render_window, &current_size.first, &current_size.second);
+
+ _dbg_assert_(GUI, (int)minimal_size.first > 0 && (int)minimal_size.second > 0);
+ int new_width = std::max(current_size.first, (int)minimal_size.first);
+ int new_height = std::max(current_size.second, (int)minimal_size.second);
+
+ if (current_size != std::make_pair(new_width, new_height))
+ glfwSetWindowSize(m_render_window, new_width, new_height);
+}
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h
index 7c307214..5b04e87b 100644
--- a/src/citra/emu_window/emu_window_glfw.h
+++ b/src/citra/emu_window/emu_window_glfw.h
@@ -4,10 +4,10 @@
#pragma once
-#include <GLFW/glfw3.h>
-
#include "common/emu_window.h"
+struct GLFWwindow;
+
class EmuWindow_GLFW : public EmuWindow {
public:
EmuWindow_GLFW();
@@ -16,12 +16,12 @@ public:
/// Swap buffers to display the next frame
void SwapBuffers() override;
- /// Polls window events
- void PollEvents() override;
+ /// Polls window events
+ void PollEvents() override;
/// Makes the graphics context current for the caller thread
void MakeCurrent() override;
-
+
/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
void DoneCurrent() override;
@@ -30,9 +30,17 @@ public:
/// Whether the window is still open, and a close request hasn't yet been sent
const bool IsOpen();
+ static void OnClientAreaResizeEvent(GLFWwindow* win, int width, int height);
+
+ static void OnFramebufferResizeEvent(GLFWwindow* win, int width, int height);
+
void ReloadSetKeymaps() override;
private:
+ void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override;
+
+ static EmuWindow_GLFW* GetEmuWindow(GLFWwindow* win);
+
GLFWwindow* m_render_window; ///< Internal GLFW render window
/// Device id of keyboard for use with KeyMap
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 20824692..9bf07991 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -2,6 +2,12 @@
#include <QKeyEvent>
#include <QApplication>
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+// Required for screen DPI information
+#include <QScreen>
+#include <QWindow>
+#endif
+
#include "common/common.h"
#include "bootmanager.hxx"
@@ -17,7 +23,7 @@
#define APP_TITLE APP_NAME " " APP_VERSION
#define COPYRIGHT "Copyright (C) 2013-2014 Citra Team"
-EmuThread::EmuThread(GRenderWindow* render_window) :
+EmuThread::EmuThread(GRenderWindow* render_window) :
filename(""), exec_cpu_step(false), cpu_running(false),
stop_run(false), render_window(render_window)
{
@@ -36,7 +42,7 @@ void EmuThread::run()
if (cpu_running)
{
Core::RunLoop();
- }
+ }
else if (exec_cpu_step)
{
exec_cpu_step = false;
@@ -82,20 +88,20 @@ void EmuThread::Stop()
class GGLWidgetInternal : public QGLWidget
{
public:
- GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) : QGLWidget(fmt, parent)
- {
- parent_ = parent;
+ GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent)
+ : QGLWidget(fmt, parent), parent(parent) {
}
- void paintEvent(QPaintEvent* ev) override
- {
+ void paintEvent(QPaintEvent* ev) override {
}
+
void resizeEvent(QResizeEvent* ev) override {
- parent_->SetClientAreaWidth(size().width());
- parent_->SetClientAreaHeight(size().height());
+ parent->OnClientAreaResized(ev->size().width(), ev->size().height());
+ parent->OnFramebufferSizeChanged();
}
+
private:
- GRenderWindow* parent_;
+ GRenderWindow* parent;
};
EmuThread& GRenderWindow::GetEmuThread()
@@ -105,6 +111,9 @@ EmuThread& GRenderWindow::GetEmuThread()
GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this), keyboard_id(0)
{
+ std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
+ setWindowTitle(QString::fromStdString(window_title));
+
keyboard_id = KeyMap::NewDeviceId();
ReloadSetKeymaps();
@@ -114,16 +123,25 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this
fmt.setProfile(QGLFormat::CoreProfile);
// Requests a forward-compatible context, which is required to get a 3.2+ context on OS X
fmt.setOption(QGL::NoDeprecatedFunctions);
-
+
child = new GGLWidgetInternal(fmt, this);
QBoxLayout* layout = new QHBoxLayout(this);
resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight);
layout->addWidget(child);
layout->setMargin(0);
setLayout(layout);
- QObject::connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext()));
+ connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext()));
+
+ OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
+
+ OnFramebufferSizeChanged();
+ NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(child->width(), child->height()));
BackupGeometry();
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+ connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, SLOT(OnFramebufferSizeChanged()));
+#endif
}
void GRenderWindow::moveContext()
@@ -166,14 +184,28 @@ void GRenderWindow::DoneCurrent()
}
void GRenderWindow::PollEvents() {
- // TODO(ShizZy): Does this belong here? This is a reasonable place to update the window title
- // from the main thread, but this should probably be in an event handler...
- /*
- static char title[128];
- sprintf(title, "%s (FPS: %02.02f)", window_title_.c_str(),
- video_core::g_renderer->current_fps());
- setWindowTitle(title);
- */
+}
+
+// On Qt 5.0+, this correctly gets the size of the framebuffer (pixels).
+//
+// Older versions get the window size (density independent pixels),
+// and hence, do not support DPI scaling ("retina" displays).
+// The result will be a viewport that is smaller than the extent of the window.
+void GRenderWindow::OnFramebufferSizeChanged()
+{
+ // Screen changes potentially incur a change in screen DPI, hence we should update the framebuffer size
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+ // windowHandle() might not be accessible until the window is displayed to screen.
+ auto pixel_ratio = windowHandle() ? (windowHandle()->screen()->devicePixelRatio()) : 1.0;
+
+ unsigned width = child->QPaintDevice::width() * pixel_ratio;
+ unsigned height = child->QPaintDevice::height() * pixel_ratio;
+#else
+ unsigned width = child->QPaintDevice::width();
+ unsigned height = child->QPaintDevice::height();
+#endif
+
+ NotifyFramebufferSizeChanged(std::make_pair(width, height));
}
void GRenderWindow::BackupGeometry()
@@ -236,3 +268,11 @@ void GRenderWindow::ReloadSetKeymaps()
KeyMap::SetKeyMapping({Settings::values.pad_sdown_key, keyboard_id}, HID_User::PAD_CIRCLE_DOWN);
}
+void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height)
+{
+ NotifyClientAreaSizeChanged(std::make_pair(width, height));
+}
+
+void GRenderWindow::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) {
+ setMinimumSize(minimal_size.first, minimal_size.second);
+}
diff --git a/src/citra_qt/bootmanager.hxx b/src/citra_qt/bootmanager.hxx
index f8afc403..5f69f15e 100644
--- a/src/citra_qt/bootmanager.hxx
+++ b/src/citra_qt/bootmanager.hxx
@@ -1,12 +1,16 @@
+#include <atomic>
+
#include <QThread>
#include <QGLWidget>
-#include <atomic>
+
#include "common/common.h"
#include "common/emu_window.h"
-class GRenderWindow;
+class QScreen;
class QKeyEvent;
+class GRenderWindow;
+
class EmuThread : public QThread
{
Q_OBJECT
@@ -14,7 +18,7 @@ class EmuThread : public QThread
public:
/**
* Set image filename
- *
+ *
* @param filename
* @warning Only call when not running!
*/
@@ -74,7 +78,7 @@ private:
signals:
/**
* Emitted when CPU when we've finished processing a single Gekko instruction
- *
+ *
* @warning This will only be emitted when the CPU is not running (SetCpuRunning(false))
* @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)
*/
@@ -100,7 +104,7 @@ public:
void BackupGeometry();
void RestoreGeometry();
void restoreGeometry(const QByteArray& geometry); // overridden
- QByteArray saveGeometry(); // overridden
+ QByteArray saveGeometry(); // overridden
EmuThread& GetEmuThread();
@@ -109,10 +113,16 @@ public:
void ReloadSetKeymaps() override;
+ void OnClientAreaResized(unsigned width, unsigned height);
+
+ void OnFramebufferSizeChanged();
+
public slots:
- void moveContext();
+ void moveContext(); // overridden
private:
+ void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override;
+
QGLWidget* child;
EmuThread emu_thread;
diff --git a/src/citra_qt/config/controller_config_util.cpp b/src/citra_qt/config/controller_config_util.cpp
index c5426570..aee3f861 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&
else if (config.keys.key_code[id] == Qt::Key_Control) text = tr("Control");
else if (config.keys.key_code[id] == Qt::Key_Alt) text = tr("Alt");
else if (config.keys.key_code[id] == Qt::Key_Meta) text = tr("Meta");
- setText(text);
+ setText(text);
}
void GKeyConfigButton::OnClicked()
@@ -118,4 +118,4 @@ GButtonConfigGroup::GButtonConfigGroup(const QString& name, common::Config::Cont
setLayout(layout);
}
-*/ \ No newline at end of file
+*/
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp
index 77fb0c9e..895851be 100644
--- a/src/citra_qt/debugger/callstack.cpp
+++ b/src/citra_qt/debugger/callstack.cpp
@@ -28,7 +28,7 @@ void CallstackWidget::OnCPUStepped()
u32 sp = app_core->GetReg(13); //stack pointer
u32 addr, ret_addr, call_addr, func_addr;
-
+
int counter = 0;
for (int addr = 0x10000000; addr >= sp; addr -= 4)
{
@@ -55,7 +55,7 @@ void CallstackWidget::OnCPUStepped()
callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0'))));
callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0'))));
callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(call_addr, 8, 16, QLatin1Char('0'))));
-
+
name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown";
callstack_model->setItem(counter, 3, new QStandardItem(QString("%1_%2").arg(QString::fromStdString(name))
.arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0')))));
@@ -63,4 +63,4 @@ void CallstackWidget::OnCPUStepped()
counter++;
}
}
-} \ No newline at end of file
+}
diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp
index 96ceed48..ed17ee4b 100644
--- a/src/citra_qt/debugger/registers.cpp
+++ b/src/citra_qt/debugger/registers.cpp
@@ -46,18 +46,18 @@ void RegistersWidget::OnCPUStepped()
CSPR->setText(1, QString("0x%1").arg(app_core->GetCPSR(), 8, 16, QLatin1Char('0')));
CSPR->child(0)->setText(1, QString("b%1").arg(app_core->GetCPSR() & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode
- CSPR->child(1)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 5) & 0x1)); // T - State
- CSPR->child(2)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 6) & 0x1)); // F - FIQ disable
- CSPR->child(3)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 7) & 0x1)); // I - IRQ disable
- CSPR->child(4)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 8) & 0x1)); // A - Imprecise abort
- CSPR->child(5)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 9) & 0x1)); // E - Data endianess
- CSPR->child(6)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 10) & 0x3F)); // IT - If-Then state (DNM)
- CSPR->child(7)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 16) & 0xF)); // GE - Greater-than-or-Equal
- CSPR->child(8)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 20) & 0xF)); // DNM - Do not modify
- CSPR->child(9)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 24) & 0x1)); // J - Java state
- CSPR->child(10)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 27) & 0x1)); // Q - Sticky overflow
- CSPR->child(11)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 28) & 0x1)); // V - Overflow
- CSPR->child(12)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 29) & 0x1)); // C - Carry/Borrow/Extend
- CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero
- CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than
+ CSPR->child(1)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 5) & 0x1)); // T - State
+ CSPR->child(2)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 6) & 0x1)); // F - FIQ disable
+ CSPR->child(3)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 7) & 0x1)); // I - IRQ disable
+ CSPR->child(4)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 8) & 0x1)); // A - Imprecise abort
+ CSPR->child(5)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 9) & 0x1)); // E - Data endianess
+ CSPR->child(6)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 10) & 0x3F)); // IT - If-Then state (DNM)
+ CSPR->child(7)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 16) & 0xF)); // GE - Greater-than-or-Equal
+ CSPR->child(8)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 20) & 0xF)); // DNM - Do not modify
+ CSPR->child(9)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 24) & 0x1)); // J - Java state
+ CSPR->child(10)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 27) & 0x1)); // Q - Sticky overflow
+ CSPR->child(11)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 28) & 0x1)); // V - Overflow
+ CSPR->child(12)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 29) & 0x1)); // C - Carry/Borrow/Extend
+ CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero
+ CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than
}
diff --git a/src/citra_qt/debugger/registers.hxx b/src/citra_qt/debugger/registers.hxx
index 9645feb2..4cca957c 100644
--- a/src/citra_qt/debugger/registers.hxx
+++ b/src/citra_qt/debugger/registers.hxx
@@ -16,10 +16,10 @@ public slots:
void OnCPUStepped();
private:
- Ui::ARMRegisters cpu_regs_ui;
+ Ui::ARMRegisters cpu_regs_ui;
- QTreeWidget* tree;
-
- QTreeWidgetItem* registers;
- QTreeWidgetItem* CSPR;
+ QTreeWidget* tree;
+
+ QTreeWidgetItem* registers;
+ QTreeWidgetItem* CSPR;
};
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 9a4e36ad..d5554d91 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -117,7 +117,8 @@ GMainWindow::GMainWindow()
connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile()));
connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame()));
- setWindowTitle(render_window->GetWindowTitle().c_str());
+ std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
+ setWindowTitle(window_title.c_str());
show();
diff --git a/src/common/chunk_file.h b/src/common/chunk_file.h
index dc8ac1fd..60978407 100644
--- a/src/common/chunk_file.h
+++ b/src/common/chunk_file.h
@@ -51,7 +51,7 @@ public:
PointerWrapSection(PointerWrap &p, int ver, const char *title) : p_(p), ver_(ver), title_(title) {
}
~PointerWrapSection();
-
+
bool operator == (const int &v) const { return ver_ == v; }
bool operator != (const int &v) const { return ver_ != v; }
bool operator <= (const int &v) const { return ver_ <= v; }
@@ -196,7 +196,7 @@ public:
}
(*ptr) += size;
}
-
+
template<class K, class T>
void Do(std::map<K, T *> &x)
{
@@ -364,7 +364,7 @@ public:
if (vec_size > 0)
DoArray(&x[0], vec_size);
}
-
+
// Store deques.
template<class T>
void Do(std::deque<T *> &x)
@@ -481,11 +481,11 @@ public:
}
// Store strings.
- void Do(std::string &x)
+ void Do(std::string &x)
{
int stringLen = (int)x.length() + 1;
Do(stringLen);
-
+
switch (mode) {
case MODE_READ: x = (char*)*ptr; break;
case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
@@ -495,7 +495,7 @@ public:
(*ptr) += stringLen;
}
- void Do(std::wstring &x)
+ void Do(std::wstring &x)
{
int stringLen = sizeof(wchar_t)*((int)x.length() + 1);
Do(stringLen);
@@ -534,7 +534,7 @@ public:
void Do(T &x) {
DoHelper<T>::Do(this, x);
}
-
+
template<class T>
void DoPOD(T &x) {
DoHelper<T>::Do(this, x);
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index c18afe11..d84ec4c4 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -17,7 +17,7 @@ template<> struct CompileTimeAssert<true> {};
#define b2(x) ( (x) | ( (x) >> 1) )
#define b4(x) ( b2(x) | ( b2(x) >> 2) )
#define b8(x) ( b4(x) | ( b4(x) >> 4) )
-#define b16(x) ( b8(x) | ( b8(x) >> 8) )
+#define b16(x) ( b8(x) | ( b8(x) >> 8) )
#define b32(x) (b16(x) | (b16(x) >>16) )
#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
@@ -79,12 +79,12 @@ inline u64 _rotr64(u64 x, unsigned int shift){
#define unlink _unlink
#define snprintf _snprintf
#define vscprintf _vscprintf
-
+
// Locale Cross-Compatibility
#define locale_t _locale_t
#define freelocale _free_locale
#define newlocale(mask, locale, base) _create_locale(mask, locale)
-
+
#define LC_GLOBAL_LOCALE ((locale_t)-1)
#define LC_ALL_MASK LC_ALL
#define LC_COLLATE_MASK LC_COLLATE
@@ -92,7 +92,7 @@ inline u64 _rotr64(u64 x, unsigned int shift){
#define LC_MONETARY_MASK LC_MONETARY
#define LC_NUMERIC_MASK LC_NUMERIC
#define LC_TIME_MASK LC_TIME
-
+
inline locale_t uselocale(locale_t new_locale)
{
// Retrieve the current per thread locale setting
@@ -168,8 +168,8 @@ inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);}
inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);}
inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);}
#elif _M_ARM
-inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;}
-inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;}
+inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;}
+inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;}
inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);}
#elif __linux__
inline u16 swap16(u16 _data) {return bswap_16(_data);}
@@ -226,7 +226,7 @@ template <typename T>
inline T FromBigEndian(T data)
{
//static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
-
+
swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
return data;
}
diff --git a/src/common/common_types.h b/src/common/common_types.h
index 7ce6b224..fcc8b9a4 100644
--- a/src/common/common_types.h
+++ b/src/common/common_types.h
@@ -22,7 +22,7 @@
* http://code.google.com/p/gekko-gc-emu/
*/
-#pragma once
+#pragma once
#include <cmath>
#include <cstdint>
@@ -45,8 +45,8 @@ typedef double f64; ///< 64-bit floating point
/// Union for fast 16-bit type casting
union t16 {
- u8 _u8[2]; ///< 8-bit unsigned char(s)
- u16 _u16; ///< 16-bit unsigned shorts(s)
+ u8 _u8[2]; ///< 8-bit unsigned char(s)
+ u16 _u16; ///< 16-bit unsigned shorts(s)
};
/// Union for fast 32-bit type casting
diff --git a/src/common/console_listener.cpp b/src/common/console_listener.cpp
index 53f20d75..d7f27c35 100644
--- a/src/common/console_listener.cpp
+++ b/src/common/console_listener.cpp
@@ -86,7 +86,7 @@ bool ConsoleListener::IsOpen()
/*
LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are
- dependent on each other, that's the reason for the additional checks.
+ dependent on each other, that's the reason for the additional checks.
*/
void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst)
{
@@ -225,7 +225,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
BytesWritten += cAttrWritten;
coordScreen = GetCoordinates(BytesWritten, LBufWidth);
- }
+ }
const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X;
COORD Coo = GetCoordinates(OldCursor, LBufWidth);
@@ -296,23 +296,23 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
}
// Clear console screen
void ConsoleListener::ClearScreen(bool Cursor)
-{
+{
#if defined(_WIN32)
- COORD coordScreen = { 0, 0 };
- DWORD cCharsWritten;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- DWORD dwConSize;
+ COORD coordScreen = { 0, 0 };
+ DWORD cCharsWritten;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ DWORD dwConSize;
- HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- GetConsoleScreenBufferInfo(hConsole, &csbi);
+ GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
// Write space to the entire console
- FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
- GetConsoleScreenBufferInfo(hConsole, &csbi);
+ FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
+ GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
// Reset cursor
- if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
+ if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
#endif
}
diff --git a/src/common/emu_window.h b/src/common/emu_window.h
index 4d09acb8..4cb94fed 100644
--- a/src/common/emu_window.h
+++ b/src/common/emu_window.h
@@ -9,17 +9,33 @@
#include "common/string_util.h"
#include "common/key_map.h"
-// Abstraction class used to provide an interface between emulation code and the frontend (e.g. SDL,
-// QGLWidget, GLFW, etc...)
+/**
+ * Abstraction class used to provide an interface between emulation code and the frontend
+ * (e.g. SDL, QGLWidget, GLFW, etc...).
+ *
+ * Design notes on the interaction between EmuWindow and the emulation core:
+ * - Generally, decisions on anything visible to the user should be left up to the GUI.
+ * For example, the emulation core should not try to dictate some window title or size.
+ * This stuff is not the core's business and only causes problems with regards to thread-safety
+ * anyway.
+ * - Under certain circumstances, it may be desirable for the core to politely request the GUI
+ * to set e.g. a minimum window size. However, the GUI should always be free to ignore any
+ * such hints.
+ * - EmuWindow may expose some of its state as read-only to the emulation core, however care
+ * should be taken to make sure the provided information is self-consistent. This requires
+ * some sort of synchronization (most of this is still a TODO).
+ * - DO NOT TREAT THIS CLASS AS A GUI TOOLKIT ABSTRACTION LAYER. That's not what it is. Please
+ * re-read the upper points again and think about it if you don't see this.
+ */
class EmuWindow
{
-
public:
- /// Data structure to store an emuwindow configuration
+ /// Data structure to store emuwindow configuration
struct WindowConfig {
bool fullscreen;
int res_width;
int res_height;
+ std::pair<unsigned,unsigned> min_client_area_size;
};
/// Swap buffers to display the next frame
@@ -42,52 +58,96 @@ public:
/// Signals a key release action to the HID module
static void KeyReleased(KeyMap::HostDeviceKey key);
- WindowConfig GetConfig() const {
- return m_config;
+ /**
+ * Returns currently active configuration.
+ * @note Accesses to the returned object need not be consistent because it may be modified in another thread
+ */
+ const WindowConfig& GetActiveConfig() const {
+ return active_config;
}
+ /**
+ * Requests the internal configuration to be replaced by the specified argument at some point in the future.
+ * @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.
+ */
void SetConfig(const WindowConfig& val) {
- m_config = val;
- }
-
- int GetClientAreaWidth() const {
- return m_client_area_width;
+ config = val;
}
- void SetClientAreaWidth(const int val) {
- m_client_area_width = val;
+ /**
+ * Gets the framebuffer size in pixels.
+ * @note This method is thread-safe
+ */
+ const std::pair<unsigned,unsigned> GetFramebufferSize() const {
+ return framebuffer_size;
}
- int GetClientAreaHeight() const {
- return m_client_area_height;
+ /**
+ * Gets window client area width in logical coordinates.
+ * @note For high-DPI systems, this is smaller than the framebuffer size.
+ * @note This method is thread-safe
+ */
+ std::pair<unsigned,unsigned> GetClientAreaSize() const {
+ return std::make_pair(client_area_width, client_area_height);
}
- void SetClientAreaHeight(const int val) {
- m_client_area_height = val;
+protected:
+ EmuWindow()
+ {
+ // TODO: Find a better place to set this.
+ config.min_client_area_size = std::make_pair(400u, 480u);
+ active_config = config;
}
+ virtual ~EmuWindow() {}
- std::string GetWindowTitle() const {
- return m_window_title;
+ /**
+ * Processes any pending configuration changes from the last SetConfig call.
+ * This method invokes OnMinimalClientAreaChangeRequest if the corresponding configuration
+ * field changed.
+ * @note Implementations will usually want to call this from the GUI thread.
+ * @todo Actually call this in existing implementations.
+ */
+ void ProcessConfigurationChanges() {
+ // TODO: For proper thread safety, we should eventually implement a proper
+ // multiple-writer/single-reader queue...
+
+ if (config.min_client_area_size != active_config.min_client_area_size) {
+ OnMinimalClientAreaChangeRequest(config.min_client_area_size);
+ config.min_client_area_size = active_config.min_client_area_size;
+ }
}
-
- void SetWindowTitle(std::string val) {
- m_window_title = val;
+
+ /**
+ * Update internal framebuffer size with the given parameter.
+ * @note EmuWindow implementations will usually use this in window resize event handlers.
+ */
+ void NotifyFramebufferSizeChanged(const std::pair<unsigned,unsigned>& size) {
+ framebuffer_size = size;
}
-protected:
- EmuWindow():
- m_client_area_width(640),
- m_client_area_height(480),
- m_window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc))
- {}
- virtual ~EmuWindow() {}
+ /**
+ * Update internal client area size with the given parameter.
+ * @note EmuWindow implementations will usually use this in window resize event handlers.
+ */
+ void NotifyClientAreaSizeChanged(const std::pair<unsigned,unsigned>& size) {
+ client_area_width = size.first;
+ client_area_height = size.second;
+ }
- std::string m_window_title; ///< Current window title, should be used by window impl.
+private:
+ /**
+ * Handler called when the minimal client area was requested to be changed via SetConfig.
+ * For the request to be honored, EmuWindow implementations will usually reimplement this function.
+ */
+ virtual void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) {
+ // By default, ignore this request and do nothing.
+ }
- int m_client_area_width; ///< Current client width, should be set by window impl.
- int m_client_area_height; ///< Current client height, should be set by window impl.
+ std::pair<unsigned,unsigned> framebuffer_size;
-private:
- WindowConfig m_config; ///< Internal configuration
+ unsigned client_area_width; ///< Current client width, should be set by window impl.
+ unsigned client_area_height; ///< Current client height, should be set by window impl.
+ WindowConfig config; ///< Internal configuration (changes pending for being applied in ProcessConfigurationChanges)
+ WindowConfig active_config; ///< Internal active configuration
};
diff --git a/src/common/extended_trace.cpp b/src/common/extended_trace.cpp
index 9cd0398e..bf61ac1d 100644
--- a/src/common/extended_trace.cpp
+++ b/src/common/extended_trace.cpp
@@ -29,7 +29,7 @@ using namespace std;
void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut )
{
#if defined(UNICODE)||defined(_UNICODE)
- ULONG index = 0;
+ ULONG index = 0;
PCSTR lpAct = lpszIn;
for( ; ; lpAct++ )
@@ -37,7 +37,7 @@ void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut )
lpszOut[index++] = (TCHAR)(*lpAct);
if ( *lpAct == 0 )
break;
- }
+ }
#else
// This is trivial :)
strcpy( lpszOut, lpszIn );
@@ -101,7 +101,7 @@ BOOL InitSymInfo( PCSTR lpszInitialSymbolPath )
CHAR lpszSymbolPath[BUFFERSIZE];
DWORD symOptions = SymGetOptions();
- symOptions |= SYMOPT_LOAD_LINES;
+ symOptions |= SYMOPT_LOAD_LINES;
symOptions &= ~SYMOPT_UNDNAME;
SymSetOptions( symOptions );
InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath );
@@ -153,15 +153,15 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
#ifndef _M_X64
DWORD dwDisp = 0;
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) )
-#else
+#else
//makes it compile but hell im not sure if this works...
DWORD64 dwDisp = 0;
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) )
#endif
{
// Make the symbol readable for humans
- UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
- UNDNAME_COMPLETE |
+ UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
+ UNDNAME_COMPLETE |
UNDNAME_NO_THISTYPE |
UNDNAME_NO_SPECIAL_SYMS |
UNDNAME_NO_MEMBER_TYPE |
@@ -219,7 +219,7 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
_tcscat( lpszSymbol, lpszParsed );
ret = TRUE;
- }
+ }
GlobalFree( pSym );
return ret;
@@ -325,14 +325,14 @@ void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
PrintFunctionAndSourceInfo(file, callStack);
- for( ULONG index = 0; ; index++ )
+ for( ULONG index = 0; ; index++ )
{
bResult = StackWalk(
IMAGE_FILE_MACHINE_I386,
hProcess,
hThread,
&callStack,
- NULL,
+ NULL,
NULL,
SymFunctionTableAccess,
SymGetModuleBase,
@@ -341,7 +341,7 @@ void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
if ( index == 0 )
continue;
- if( !bResult || callStack.AddrFrame.Offset == 0 )
+ if( !bResult || callStack.AddrFrame.Offset == 0 )
break;
PrintFunctionAndSourceInfo(file, callStack);
@@ -382,14 +382,14 @@ void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip,
PrintFunctionAndSourceInfo(file, callStack);
- for( ULONG index = 0; ; index++ )
+ for( ULONG index = 0; ; index++ )
{
bResult = StackWalk(
IMAGE_FILE_MACHINE_I386,
hProcess,
hThread,
&callStack,
- NULL,
+ NULL,
NULL,
SymFunctionTableAccess,
SymGetModuleBase,
@@ -398,7 +398,7 @@ void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip,
if ( index == 0 )
continue;
- if( !bResult || callStack.AddrFrame.Offset == 0 )
+ if( !bResult || callStack.AddrFrame.Offset == 0 )
break;
PrintFunctionAndSourceInfo(file, callStack);
diff --git a/src/common/fifo_queue.h b/src/common/fifo_queue.h
index 78a8f561..2c18285d 100644
--- a/src/common/fifo_queue.h
+++ b/src/common/fifo_queue.h
@@ -45,7 +45,7 @@ public:
// create the element, add it to the queue
m_write_ptr->current = new T(std::forward<Arg>(t));
// set the next pointer to a new element ptr
- // then advance the write pointer
+ // then advance the write pointer
m_write_ptr = m_write_ptr->next = new ElementPtr();
Common::AtomicIncrement(m_size);
}
diff --git a/src/common/file_search.cpp b/src/common/file_search.cpp
index 63580f68..bfb54ce7 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&
bool bkeepLooping = true;
while (bkeepLooping)
- {
+ {
if (findData.cFileName[0] != '.')
{
std::string strFilename;
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 35da0730..b6dec838 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -88,7 +88,7 @@ bool IsDirectory(const std::string &filename)
#endif
if (result < 0) {
- WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
+ WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
@@ -102,7 +102,7 @@ bool Delete(const std::string &filename)
{
INFO_LOG(COMMON, "Delete: file %s", filename.c_str());
- // Return true because we care about the file no
+ // Return true because we care about the file no
// being there, not the actual delete.
if (!Exists(filename))
{
@@ -120,13 +120,13 @@ bool Delete(const std::string &filename)
#ifdef _WIN32
if (!DeleteFile(Common::UTF8ToTStr(filename).c_str()))
{
- WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
+ WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
#else
if (unlink(filename.c_str()) == -1) {
- WARN_LOG(COMMON, "Delete: unlink failed on %s: %s",
+ WARN_LOG(COMMON, "Delete: unlink failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
@@ -232,28 +232,28 @@ bool DeleteDir(const std::string &filename)
return false;
}
-// renames file srcFilename to destFilename, returns true on success
+// renames file srcFilename to destFilename, returns true on success
bool Rename(const std::string &srcFilename, const std::string &destFilename)
{
- INFO_LOG(COMMON, "Rename: %s --> %s",
+ INFO_LOG(COMMON, "Rename: %s --> %s",
srcFilename.c_str(), destFilename.c_str());
if (rename(srcFilename.c_str(), destFilename.c_str()) == 0)
return true;
- ERROR_LOG(COMMON, "Rename: failed %s --> %s: %s",
+ ERROR_LOG(COMMON, "Rename: failed %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
return false;
}
-// copies file srcFilename to destFilename, returns true on success
+// copies file srcFilename to destFilename, returns true on success
bool Copy(const std::string &srcFilename, const std::string &destFilename)
{
- INFO_LOG(COMMON, "Copy: %s --> %s",
+ INFO_LOG(COMMON, "Copy: %s --> %s",
srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
if (CopyFile(Common::UTF8ToTStr(srcFilename).c_str(), Common::UTF8ToTStr(destFilename).c_str(), FALSE))
return true;
- ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
+ ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
return false;
#else
@@ -267,7 +267,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
FILE *input = fopen(srcFilename.c_str(), "rb");
if (!input)
{
- ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s",
+ ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
return false;
}
@@ -277,7 +277,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
if (!output)
{
fclose(input);
- ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s",
+ ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
return false;
}
@@ -291,8 +291,8 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
{
if (ferror(input) != 0)
{
- ERROR_LOG(COMMON,
- "Copy: failed reading from source, %s --> %s: %s",
+ ERROR_LOG(COMMON,
+ "Copy: failed reading from source, %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
goto bail;
}
@@ -302,8 +302,8 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
int wnum = fwrite(buffer, sizeof(char), rnum, output);
if (wnum != rnum)
{
- ERROR_LOG(COMMON,
- "Copy: failed writing to output, %s --> %s: %s",
+ ERROR_LOG(COMMON,
+ "Copy: failed writing to output, %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
goto bail;
}
@@ -335,7 +335,7 @@ u64 GetSize(const std::string &filename)
WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str());
return 0;
}
-
+
struct stat64 buf;
#ifdef _WIN32
if (_tstat64(Common::UTF8ToTStr(filename).c_str(), &buf) == 0)
@@ -384,10 +384,10 @@ u64 GetSize(FILE *f)
return size;
}
-// creates an empty file filename, returns true on success
+// creates an empty file filename, returns true on success
bool CreateEmptyFile(const std::string &filename)
{
- INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
+ INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
if (!FileUtil::IOFile(filename, "wb"))
{
@@ -437,7 +437,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
#endif
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
- ((virtualName[0] == '.') && (virtualName[1] == '.') &&
+ ((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
continue;
entry.virtualName = virtualName;
@@ -452,14 +452,14 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
foundEntries += (u32)entry.size;
}
else
- { // is a file
+ { // is a file
entry.isDirectory = false;
entry.size = GetSize(entry.physicalName.c_str());
}
++foundEntries;
// Push into the tree
- parentEntry.children.push_back(entry);
-#ifdef _WIN32
+ parentEntry.children.push_back(entry);
+#ifdef _WIN32
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
#else
@@ -504,7 +504,7 @@ bool DeleteDirRecursively(const std::string &directory)
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
- ((virtualName[0] == '.') && (virtualName[1] == '.') &&
+ ((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
continue;
@@ -540,7 +540,7 @@ bool DeleteDirRecursively(const std::string &directory)
closedir(dirp);
#endif
FileUtil::DeleteDir(directory);
-
+
return true;
}
@@ -585,7 +585,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path)
std::string GetCurrentDir()
{
char *dir;
- // Get the current working directory (getcwd uses malloc)
+ // Get the current working directory (getcwd uses malloc)
if (!(dir = __getcwd(NULL, 0))) {
ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
@@ -604,7 +604,7 @@ bool SetCurrentDir(const std::string &directory)
}
#if defined(__APPLE__)
-std::string GetBundleDirectory()
+std::string GetBundleDirectory()
{
CFURLRef BundleRef;
char AppBundlePath[MAXPATHLEN];
@@ -666,8 +666,8 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR))
paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
else
- paths[D_USER_IDX] = std::string(getenv("HOME") ?
- getenv("HOME") : getenv("PWD") ?
+ paths[D_USER_IDX] = std::string(getenv("HOME") ?
+ getenv("HOME") : getenv("PWD") ?
getenv("PWD") : "") + DIR_SEP EMU_DATA_DIR DIR_SEP;
#endif
@@ -749,7 +749,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG;
}
}
-
+
return paths[DirIDX];
}
@@ -762,7 +762,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
// if (!FileUtil::Exists(dir))
// dir = SHARED_USER_DIR THEMES_DIR "/" + theme_name + "/";
//#endif
-//
+//
// return dir;
//}
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 173ce662..72b80be8 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -16,33 +16,33 @@
// User directory indices for GetUserPath
enum {
- D_USER_IDX,
- D_ROOT_IDX,
- D_CONFIG_IDX,
- D_GAMECONFIG_IDX,
- D_MAPS_IDX,
- D_CACHE_IDX,
- D_SHADERCACHE_IDX,
- D_SHADERS_IDX,
- D_STATESAVES_IDX,
- D_SCREENSHOTS_IDX,
- D_SDMC_IDX,
- D_HIRESTEXTURES_IDX,
- D_DUMP_IDX,
- D_DUMPFRAMES_IDX,
- D_DUMPAUDIO_IDX,
- D_DUMPTEXTURES_IDX,
- D_DUMPDSP_IDX,
- D_LOGS_IDX,
- D_SYSCONF_IDX,
- F_EMUCONFIG_IDX,
- F_DEBUGGERCONFIG_IDX,
- F_LOGGERCONFIG_IDX,
- F_MAINLOG_IDX,
- F_RAMDUMP_IDX,
- F_ARAMDUMP_IDX,
- F_SYSCONF_IDX,
- NUM_PATH_INDICES
+ D_USER_IDX,
+ D_ROOT_IDX,
+ D_CONFIG_IDX,
+ D_GAMECONFIG_IDX,
+ D_MAPS_IDX,
+ D_CACHE_IDX,
+ D_SHADERCACHE_IDX,
+ D_SHADERS_IDX,
+ D_STATESAVES_IDX,
+ D_SCREENSHOTS_IDX,
+ D_SDMC_IDX,
+ D_HIRESTEXTURES_IDX,
+ D_DUMP_IDX,
+ D_DUMPFRAMES_IDX,
+ D_DUMPAUDIO_IDX,
+ D_DUMPTEXTURES_IDX,
+ D_DUMPDSP_IDX,
+ D_LOGS_IDX,
+ D_SYSCONF_IDX,
+ F_EMUCONFIG_IDX,
+ F_DEBUGGERCONFIG_IDX,
+ F_LOGGERCONFIG_IDX,
+ F_MAINLOG_IDX,
+ F_RAMDUMP_IDX,
+ F_ARAMDUMP_IDX,
+ F_SYSCONF_IDX,
+ NUM_PATH_INDICES
};
namespace FileUtil
@@ -51,11 +51,11 @@ namespace FileUtil
// FileSystem tree node/
struct FSTEntry
{
- bool isDirectory;
- u64 size; // file length or number of entries from children
- std::string physicalName; // name on disk
- std::string virtualName; // name in FST names table
- std::vector<FSTEntry> children;
+ bool isDirectory;
+ u64 size; // file length or number of entries from children
+ std::string physicalName; // name on disk
+ std::string virtualName; // name in FST names table
+ std::vector<FSTEntry> children;
};
// Returns true if file filename exists
@@ -148,86 +148,86 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
class IOFile : public NonCopyable
{
public:
- IOFile();
- IOFile(std::FILE* file);
- IOFile(const std::string& filename, const char openmode[]);
+ IOFile();
+ IOFile(std::FILE* file);
+ IOFile(const std::string& filename, const char openmode[]);
- ~IOFile();
+ ~IOFile();
- IOFile(IOFile&& other);
- IOFile& operator=(IOFile&& other);
+ IOFile(IOFile&& other);
+ IOFile& operator=(IOFile&& other);
- void Swap(IOFile& other);
+ void Swap(IOFile& other);
- bool Open(const std::string& filename, const char openmode[]);
- bool Close();
+ bool Open(const std::string& filename, const char openmode[]);
+ bool Close();
- template <typename T>
- size_t ReadArray(T* data, size_t length)
- {
- if (!IsOpen()) {
- m_good = false;
- return -1;
- }
+ template <typename T>
+ size_t ReadArray(T* data, size_t length)
+ {
+ if (!IsOpen()) {
+ m_good = false;
+ return -1;
+ }
- size_t items_read = std::fread(data, sizeof(T), length, m_file);
- if (items_read != length)
- m_good = false;
+ size_t items_read = std::fread(data, sizeof(T), length, m_file);
+ if (items_read != length)
+ m_good = false;
- return items_read;
- }
+ return items_read;
+ }
- template <typename T>
- size_t WriteArray(const T* data, size_t length)
- {
- if (!IsOpen()) {
- m_good = false;
- return -1;
- }
+ template <typename T>
+ size_t WriteArray(const T* data, size_t length)
+ {
+ if (!IsOpen()) {
+ m_good = false;
+ return -1;
+ }
- size_t items_written = std::fwrite(data, sizeof(T), length, m_file);
- if (items_written != length)
- m_good = false;
+ size_t items_written = std::fwrite(data, sizeof(T), length, m_file);
+ if (items_written != length)
+ m_good = false;
- return items_written;
- }
+ return items_written;
+ }
- size_t ReadBytes(void* data, size_t length)
- {
- return ReadArray(reinterpret_cast<char*>(data), length);
- }
+ size_t ReadBytes(void* data, size_t length)
+ {
+ return ReadArray(reinterpret_cast<char*>(data), length);
+ }
- size_t WriteBytes(const void* data, size_t length)
- {
- return WriteArray(reinterpret_cast<const char*>(data), length);
- }
+ size_t WriteBytes(const void* data, size_t length)
+ {
+ return WriteArray(reinterpret_cast<const char*>(data), length);
+ }
- bool IsOpen() { return NULL != m_file; }
+ bool IsOpen() { return NULL != m_file; }
- // m_good is set to false when a read, write or other function fails
- bool IsGood() { return m_good; }
- operator void*() { return m_good ? m_file : NULL; }
+ // m_good is set to false when a read, write or other function fails
+ bool IsGood() { return m_good; }
+ operator void*() { return m_good ? m_file : NULL; }
- std::FILE* ReleaseHandle();
+ std::FILE* ReleaseHandle();
- std::FILE* GetHandle() { return m_file; }
+ std::FILE* GetHandle() { return m_file; }
- void SetHandle(std::FILE* file);
+ void SetHandle(std::FILE* file);
- bool Seek(s64 off, int origin);
- u64 Tell();
- u64 GetSize();
- bool Resize(u64 size);
- bool Flush();
+ bool Seek(s64 off, int origin);
+ u64 Tell();
+ u64 GetSize();
+ bool Resize(u64 size);
+ bool Flush();
- // clear error state
- void Clear() { m_good = true; std::clearerr(m_file); }
+ // clear error state
+ void Clear() { m_good = true; std::clearerr(m_file); }
- std::FILE* m_file;
- bool m_good;
+ std::FILE* m_file;
+ bool m_good;
private:
- IOFile(IOFile&);
- IOFile& operator=(IOFile& other);
+ IOFile(IOFile&);
+ IOFile& operator=(IOFile& other);
};
} // namespace
@@ -237,8 +237,8 @@ template <typename T>
void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode)
{
#ifdef _WIN32
- fstream.open(Common::UTF8ToTStr(filename).c_str(), openmode);
+ fstream.open(Common::UTF8ToTStr(filename).c_str(), openmode);
#else
- fstream.open(filename.c_str(), openmode);
+ fstream.open(filename.c_str(), openmode);
#endif
}
diff --git a/src/common/hash.cpp b/src/common/hash.cpp
index d2ebc734..2ddcfe6b 100644
--- a/src/common/hash.cpp
+++ b/src/common/hash.cpp
@@ -115,15 +115,15 @@ inline u64 getblock(const u64 * p, int i)
inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
{
- k1 *= c1;
- k1 = _rotl64(k1,23);
+ k1 *= c1;
+ k1 = _rotl64(k1,23);
k1 *= c2;
h1 ^= k1;
h1 += h2;
h2 = _rotl64(h2,41);
- k2 *= c2;
+ k2 *= c2;
k2 = _rotl64(k2,23);
k2 *= c1;
h2 ^= k2;
@@ -250,7 +250,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
}
-/*
+/*
* NOTE: This hash function is used for custom texture loading/dumping, so
* it should not be changed, which would require all custom textures to be
* recalculated for their new hash values. If the hashing function is
@@ -273,7 +273,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
u64 k = data[0];
data+=Step;
k *= m;
- k ^= k >> r;
+ k ^= k >> r;
k *= m;
h ^= k;
h *= m;
@@ -292,13 +292,13 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
case 1: h ^= u64(data2[0]);
h *= m;
};
-
+
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
-}
+}
#else
// CRC32 hash using the SSE4.2 instruction
u64 GetCRC32(const u8 *src, int len, u32 samples)
@@ -351,15 +351,15 @@ inline u32 fmix32(u32 h)
inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2)
{
- k1 *= c1;
- k1 = _rotl(k1,11);
+ k1 *= c1;
+ k1 = _rotl(k1,11);
k1 *= c2;
h1 ^= k1;
h1 += h2;
h2 = _rotl(h2,17);
- k2 *= c2;
+ k2 *= c2;
k2 = _rotl(k2,11);
k2 *= c1;
h2 ^= k2;
@@ -405,7 +405,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
//----------
// tail
-
+
const u8 * tail = (const u8*)(data + nblocks*8);
u32 k1 = 0;
@@ -439,7 +439,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
out[0] = h1;
out[1] = h2;
-
+
return *((u64 *)&out);
}
@@ -463,11 +463,11 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
u64 k = data[0];
data+=Step;
- k *= m;
- k ^= k >> r;
+ k *= m;
+ k ^= k >> r;
k *= m;
h ^= k;
- h *= m;
+ h *= m;
}
const u8 * data2 = (const u8*)end;
@@ -483,7 +483,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
case 1: h ^= u64(data2[0]);
h *= m;
};
-
+
h ^= h >> r;
h *= m;
h ^= h >> r;
diff --git a/src/common/linear_disk_cache.h b/src/common/linear_disk_cache.h
index 96dce315..f4263f72 100644
--- a/src/common/linear_disk_cache.h
+++ b/src/common/linear_disk_cache.h
@@ -64,7 +64,7 @@ public:
m_file.seekg(0, std::ios::beg);
std::fstream::pos_type start_pos = m_file.tellg();
std::streamoff file_size = end_pos - start_pos;
-
+
if (m_file.is_open() && ValidateHeader())
{
// good header, read some key/value pairs
@@ -87,7 +87,7 @@ public:
// read key/value and pass to reader
if (Read(&key) &&
- Read(value, value_size) &&
+ Read(value, value_size) &&
Read(&entry_number) &&
entry_number == m_num_entries+1)
{
@@ -115,7 +115,7 @@ public:
WriteHeader();
return 0;
}
-
+
void Sync()
{
m_file.flush();
diff --git a/src/common/log.h b/src/common/log.h
index bfd73f8a..14ad98c0 100644
--- a/src/common/log.h
+++ b/src/common/log.h
@@ -11,7 +11,7 @@
enum {
OS_LEVEL, // Printed by the emulated operating system
NOTICE_LEVEL, // VERY important information that is NOT errors. Like startup and OSReports.
- ERROR_LEVEL, // Critical errors
+ ERROR_LEVEL, // Critical errors
WARNING_LEVEL, // Something is suspicious.
INFO_LEVEL, // General information.
DEBUG_LEVEL, // Detailed debugging - might make things slow.
@@ -46,7 +46,7 @@ enum LOG_TYPE {
MEMMAP,
MEMCARD_MANAGER,
OSREPORT,
- PAD,
+ PAD,
PROCESSORINTERFACE,
PIXELENGINE,
SERIALINTERFACE,
@@ -69,6 +69,7 @@ enum LOG_TYPE {
HW,
TIME,
NETPLAY,
+ GUI,
NUMBER_OF_LOGS // Must be last
};
@@ -88,7 +89,7 @@ enum LOG_LEVELS {
} // namespace
-void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int line,
+void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int line,
const char* function, const char* fmt, ...)
#ifdef __GNUC__
__attribute__((format(printf, 6, 7)))
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp
index 4d590d98..2ef7d98c 100644
--- a/src/common/log_manager.cpp
+++ b/src/common/log_manager.cpp
@@ -7,9 +7,8 @@
#include "common/log_manager.h"
#include "common/console_listener.h"
#include "common/timer.h"
-#include "common/thread.h"
-void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
+void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
const char* function, const char* fmt, ...)
{
va_list args;
@@ -75,6 +74,7 @@ LogManager::LogManager()
m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
+ m_Log[LogTypes::GUI] = new LogContainer("GUI", "GUI");
m_fileLog = new FileLogListener(FileUtil::GetUserPath(F_MAINLOG_IDX).c_str());
m_consoleLog = new ConsoleListener();
@@ -111,7 +111,7 @@ LogManager::~LogManager()
delete m_debuggerLog;
}
-void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file,
+void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file,
int line, const char* function, const char *fmt, va_list args)
{
char temp[MAX_MSGLEN];
@@ -124,11 +124,11 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const
Common::CharArrayFromFormatV(temp, MAX_MSGLEN, fmt, args);
static const char level_to_char[7] = "ONEWID";
- sprintf(msg, "%s %s:%u %c[%s] %s: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line,
+ sprintf(msg, "%s %s:%u %c[%s] %s: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line,
level_to_char[(int)level], log->GetShortName(), function, temp);
-
+
#ifdef ANDROID
- Host_SysMessage(msg);
+ Host_SysMessage(msg);
#endif
log->Trigger(level, msg);
}
diff --git a/src/common/log_manager.h b/src/common/log_manager.h
index de1d16ee..baefc4ba 100644
--- a/src/common/log_manager.h
+++ b/src/common/log_manager.h
@@ -54,7 +54,7 @@ class LogContainer
{
public:
LogContainer(const char* shortName, const char* fullName, bool enable = false);
-
+
const char* GetShortName() const { return m_shortName; }
const char* GetFullName() const { return m_fullName; }
@@ -98,7 +98,7 @@ public:
static u32 GetMaxLevel() { return LogTypes::MAX_LOGLEVEL; }
- void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
+ void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
const char* function, const char *fmt, va_list args);
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 ab0e6b75..3613e82a 100644
--- a/src/common/math_util.cpp
+++ b/src/common/math_util.cpp
@@ -18,7 +18,7 @@ u32 ClassifyDouble(double dvalue)
value.d = dvalue;
u64 sign = value.i & DOUBLE_SIGN;
u64 exp = value.i & DOUBLE_EXP;
- if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
+ if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
{
// Nice normalized number.
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
@@ -58,7 +58,7 @@ u32 ClassifyFloat(float fvalue)
value.f = fvalue;
u32 sign = value.i & FLOAT_SIGN;
u32 exp = value.i & FLOAT_EXP;
- if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
+ if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
{
// Nice normalized number.
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
@@ -77,13 +77,13 @@ u32 ClassifyFloat(float fvalue)
// Denormalized number.
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
}
- }
- else if (exp)
+ }
+ else if (exp)
{
// Infinite
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
- }
- else
+ }
+ else
{
//Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
@@ -143,7 +143,7 @@ void Matrix33::RotateY(Matrix33 &mtx, float rad)
mtx.data[0] = c;
mtx.data[2] = s;
mtx.data[4] = 1;
- mtx.data[6] = -s;
+ mtx.data[6] = -s;
mtx.data[8] = c;
}
diff --git a/src/common/math_util.h b/src/common/math_util.h
index b32e7bb1..b10a25c1 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -7,6 +7,7 @@
#include "common/common.h"
#include <algorithm>
+#include <type_traits>
#include <vector>
namespace MathUtil
@@ -109,11 +110,11 @@ struct Rectangle
Rectangle(T theLeft, T theTop, T theRight, T theBottom)
: left(theLeft), top(theTop), right(theRight), bottom(theBottom)
{ }
-
+
bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
- T GetWidth() const { return abs(right - left); }
- T GetHeight() const { return abs(bottom - top); }
+ T GetWidth() const { return std::abs(static_cast<typename std::make_signed<T>::type>(right - left)); }
+ T GetHeight() const { return std::abs(static_cast<typename std::make_signed<T>::type>(bottom - top)); }
// If the rectangle is in a coordinate system with a lower-left origin, use
// this Clamp.
@@ -127,7 +128,7 @@ struct Rectangle
// If the rectangle is in a coordinate system with an upper-left origin,
// use this Clamp.
- void ClampUL(T x1, T y1, T x2, T y2)
+ void ClampUL(T x1, T y1, T x2, T y2)
{
if (left < x1) left = x1;
if (right > x2) right = x2;
diff --git a/src/common/mem_arena.cpp b/src/common/mem_arena.cpp
index 40d9c03a..67dbaf50 100644
--- a/src/common/mem_arena.cpp
+++ b/src/common/mem_arena.cpp
@@ -38,7 +38,7 @@ void* globalbase = NULL;
// Hopefully this ABI will never change...
-#define ASHMEM_DEVICE "/dev/ashmem"
+#define ASHMEM_DEVICE "/dev/ashmem"
/*
* ashmem_create_region - creates a new ashmem region and returns the file
@@ -272,11 +272,11 @@ u8* MemArena::Find4GBBase()
// yeah, this could also be done in like two bitwise ops...
-#define SKIP(a_flags, b_flags)
-// if (!(a_flags & MV_WII_ONLY) && (b_flags & MV_WII_ONLY))
-// continue;
-// if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM))
-// continue;
+#define SKIP(a_flags, b_flags)
+//if (!(a_flags & MV_WII_ONLY) && (b_flags & MV_WII_ONLY))
+// continue;
+//if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM))
+// continue;
static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) {
// 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 bab7d9f7..b6f66e4e 100644
--- a/src/common/memory_util.cpp
+++ b/src/common/memory_util.cpp
@@ -47,7 +47,7 @@ void* AllocateExecutableMemory(size_t size, bool low)
// printf("Mapped executable memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
-
+
#ifdef _WIN32
if (ptr == nullptr)
{
@@ -55,7 +55,7 @@ void* AllocateExecutableMemory(size_t size, bool low)
if (ptr == MAP_FAILED)
{
ptr = nullptr;
-#endif
+#endif
PanicAlert("Failed to allocate executable memory");
}
#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
@@ -127,11 +127,11 @@ void FreeMemoryPages(void* ptr, size_t size)
if (ptr)
{
#ifdef _WIN32
-
+
if (!VirtualFree(ptr, 0, MEM_RELEASE))
PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
ptr = NULL; // Is this our responsibility?
-
+
#else
munmap(ptr, size);
#endif
diff --git a/src/common/msg_handler.h b/src/common/msg_handler.h
index 7c5319ec..9bfdf950 100644
--- a/src/common/msg_handler.h
+++ b/src/common/msg_handler.h
@@ -15,7 +15,7 @@ enum MSG_TYPE
CRITICAL
};
-typedef bool (*MsgAlertHandler)(const char* caption, const char* text,
+typedef bool (*MsgAlertHandler)(const char* caption, const char* text,
bool yes_no, int Style);
typedef std::string (*StringTranslator)(const char* text);
@@ -31,29 +31,29 @@ void SetEnableAlert(bool enable);
#ifndef GEKKO
#ifdef _WIN32
- #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
- #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
- #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
- #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
- #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
+ #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
+ #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
+ #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
+ #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
+ #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
// Use these macros (that do the same thing) if the message should be translated.
- #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
- #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
- #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
- #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
- #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
+ #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
+ #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
+ #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
+ #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
+ #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
#else
- #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
- #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
- #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
- #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
- #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
+ #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
+ #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
+ #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
+ #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
+ #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
// Use these macros (that do the same thing) if the message should be translated.
- #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
- #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
- #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
- #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
- #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
+ #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
+ #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
+ #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
+ #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
+ #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
#endif
#else
// GEKKO
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 54943d30..dcec9275 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)
{
std::ostringstream oss;
oss << std::setfill('0') << std::hex;
-
+
for (int line = 0; size; ++data, --size)
{
oss << std::setw(2) << (int)*data;
-
+
if (line_len == ++line)
{
oss << '\n';
@@ -168,7 +168,7 @@ bool TryParse(const std::string &str, u32 *const output)
errno = 0;
unsigned long value = strtoul(str.c_str(), &endptr, 0);
-
+
if (!endptr || *endptr)
return false;
@@ -294,7 +294,7 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
//#include <string>
//#include <assert.h>
-const char HEX2DEC[256] =
+const char HEX2DEC[256] =
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 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)
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
const size_t SRC_LEN = sSrc.length();
const unsigned char * const SRC_END = pSrc + SRC_LEN;
- const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%'
+ const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%'
char * const pStart = new char[SRC_LEN];
char * pEnd = pStart;
@@ -394,7 +394,7 @@ std::string UriEncode(const std::string & sSrc)
for (; pSrc < SRC_END; ++pSrc)
{
- if (SAFE[*pSrc])
+ if (SAFE[*pSrc])
*pEnd++ = *pSrc;
else
{
@@ -518,9 +518,9 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
out_buffer.resize(out_buffer_size - dst_bytes);
out_buffer.swap(result);
-
+
iconv_close(conv_desc);
-
+
return result;
}
@@ -576,7 +576,7 @@ std::u16string UTF8ToUTF16(const std::string& input)
out_buffer.swap(result);
iconv_close(conv_desc);
-
+
return result;
}
diff --git a/src/common/string_util.h b/src/common/string_util.h
index 787a5663..ae5bbada 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -63,7 +63,7 @@ template <typename N>
static bool TryParse(const std::string &str, N *const output)
{
std::istringstream iss(str);
-
+
N tmp = 0;
if (iss >> tmp)
{
diff --git a/src/common/symbols.cpp b/src/common/symbols.cpp
index d61f4c0c..63ad6218 100644
--- a/src/common/symbols.cpp
+++ b/src/common/symbols.cpp
@@ -31,7 +31,7 @@ namespace Symbols
{
TSymbolsMap::iterator foundSymbolItr;
TSymbol symbol;
-
+
foundSymbolItr = g_symbols.find(_address);
if (foundSymbolItr != g_symbols.end())
{
@@ -44,7 +44,7 @@ namespace Symbols
{
return GetSymbol(_address).name;
}
-
+
void Remove(u32 _address)
{
g_symbols.erase(_address);
diff --git a/src/common/symbols.h b/src/common/symbols.h
index b13a8001..4560f524 100644
--- a/src/common/symbols.h
+++ b/src/common/symbols.h
@@ -33,5 +33,5 @@ namespace Symbols
const std::string GetName(u32 _address);
void Remove(u32 _address);
void Clear();
-};
+}
diff --git a/src/common/thread.cpp b/src/common/thread.cpp
index 60d8ed07..dc153ba7 100644
--- a/src/common/thread.cpp
+++ b/src/common/thread.cpp
@@ -25,7 +25,7 @@ int CurrentThreadId()
return 0;
#endif
}
-
+
#ifdef _WIN32
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
@@ -52,7 +52,7 @@ void SwitchCurrentThread()
// Sets the debugger-visible name of the current thread.
// Uses undocumented (actually, it is now documented) trick.
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
-
+
// This is implemented much nicer in upcoming msvc++, see:
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
void SetCurrentThreadName(const char* szThreadName)
@@ -81,7 +81,7 @@ void SetCurrentThreadName(const char* szThreadName)
__except(EXCEPTION_CONTINUE_EXECUTION)
{}
}
-
+
#else // !WIN32, so must be POSIX threads
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
diff --git a/src/common/thread.h b/src/common/thread.h
index f7ace21b..be9b5cbe 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -30,13 +30,13 @@ int CurrentThreadId();
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
void SetCurrentThreadAffinity(u32 mask);
-
+
class Event
{
public:
Event()
: is_set(false)
- {};
+ {}
void Set()
{
@@ -135,7 +135,7 @@ private:
const size_t m_count;
volatile size_t m_waiting;
};
-
+
void SleepCurrentThread(int ms);
void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
@@ -146,7 +146,7 @@ inline void YieldCPU()
{
std::this_thread::yield();
}
-
+
void SetCurrentThreadName(const char *name);
-
+
} // namespace Common
diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h
index 4a89572f..59efbce4 100644
--- a/src/common/thread_queue_list.h
+++ b/src/common/thread_queue_list.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project / PPSSPP Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
@@ -12,7 +12,7 @@ template<class IdType>
struct ThreadQueueList {
// Number of queues (number of priority levels starting at 0.)
static const int NUM_QUEUES = 128;
-
+
// Initial number of threads a single queue can handle.
static const int INITIAL_CAPACITY = 32;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f41d52e8..48241c3d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -31,17 +31,24 @@ set(SRCS
hle/kernel/shared_memory.cpp
hle/kernel/thread.cpp
hle/service/ac_u.cpp
+ hle/service/am_net.cpp
hle/service/apt_u.cpp
+ hle/service/boss_u.cpp
+ hle/service/cfg_i.cpp
hle/service/cfg_u.cpp
+ hle/service/csnd_snd.cpp
hle/service/dsp_dsp.cpp
hle/service/err_f.cpp
hle/service/fs_user.cpp
hle/service/frd_u.cpp
hle/service/gsp_gpu.cpp
hle/service/hid_user.cpp
+ hle/service/ir_rst.cpp
+ hle/service/ir_u.cpp
hle/service/mic_u.cpp
hle/service/ndm_u.cpp
hle/service/nwm_uds.cpp
+ hle/service/pm_app.cpp
hle/service/ptm_u.cpp
hle/service/service.cpp
hle/service/soc_u.cpp
@@ -102,23 +109,31 @@ set(HEADERS
hle/kernel/shared_memory.h
hle/kernel/thread.h
hle/service/ac_u.h
+ hle/service/am_net.h
hle/service/apt_u.h
+ hle/service/boss_u.h
+ hle/service/cfg_i.h
hle/service/cfg_u.h
+ hle/service/csnd_snd.h
hle/service/dsp_dsp.h
hle/service/err_f.h
hle/service/fs_user.h
hle/service/frd_u.h
hle/service/gsp_gpu.h
hle/service/hid_user.h
+ hle/service/ir_rst.h
+ hle/service/ir_u.h
hle/service/mic_u.h
hle/service/ndm_u.h
hle/service/nwm_uds.h
+ hle/service/pm_app.h
hle/service/ptm_u.h
hle/service/service.h
hle/service/soc_u.h
hle/service/srv.h
hle/service/ssl_c.h
hle/config_mem.h
+ hle/result.h
hle/function_wrappers.h
hle/hle.h
hle/svc.h
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 4b93d331..3ae52856 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
@@ -63,7 +63,7 @@ public:
* Get the current CPSR register
* @return Returns the value of the CPSR register
*/
- virtual u32 GetCPSR() const = 0;
+ virtual u32 GetCPSR() const = 0;
/**
* Set the current CPSR register
@@ -98,7 +98,7 @@ public:
}
protected:
-
+
/**
* Executes the given number of instructions
* @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 0f384ad3..55278474 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) {
while (std::getline(infile, line)) {
std::istringstream iss(line);
- if (!(iss >> address_str >> size >> function_name)) {
- break; // Error parsing
+ if (!(iss >> address_str >> size >> function_name)) {
+ break; // Error parsing
}
u32 address = std::stoul(address_str, nullptr, 16);
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index a3ed3e31..6c8ea211 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include "core/arm/skyeye_common/armcpu.h"
#include "core/arm/skyeye_common/armemu.h"
@@ -113,7 +113,7 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
state->NumInstrsToExecute = num_instructions;
// Dyncom only breaks on instruction dispatch. This only happens on every instruction when
- // executing one instruction at a time. Otherwise, if a block is being executed, more
+ // executing one instruction at a time. Otherwise, if a block is being executed, more
// instructions may actually be executed than specified.
ticks += InterpreterMainLoop(state.get());
}
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 1f8cd3a3..51eea41e 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
@@ -19,7 +19,7 @@ public:
/**
* Set the Program Counter to an address
- * @param addr Address to set PC to
+ * @param pc Address to set PC to
*/
void SetPC(u32 pc) override;
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index f899e2e8..233cd3e3 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -26,7 +26,7 @@
#define CITRA_IGNORE_EXIT(x)
#include <algorithm>
-#include <map>
+#include <unordered_map>
#include <stdio.h>
#include <assert.h>
#include <cstdio>
@@ -94,9 +94,8 @@ typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper);
/* exclusive memory access */
static int exclusive_detect(ARMul_State* state, ARMword addr){
- int i;
#if 0
- for(i = 0; i < 128; i++){
+ for(int i = 0; i < 128; i++){
if(state->exclusive_tag_array[i] == addr)
return 0;
}
@@ -108,9 +107,8 @@ static int exclusive_detect(ARMul_State* state, ARMword addr){
}
static void add_exclusive_addr(ARMul_State* state, ARMword addr){
- int i;
#if 0
- for(i = 0; i < 128; i++){
+ for(int i = 0; i < 128; i++){
if(state->exclusive_tag_array[i] == 0xffffffff){
state->exclusive_tag_array[i] = addr;
//DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr);
@@ -3309,9 +3307,8 @@ const transop_fp_t arm_instruction_trans[] = {
INTERPRETER_TRANSLATE(blx_1_thumb)
};
-typedef map<unsigned int, int> bb_map;
-bb_map CreamCache[65536];
-bb_map ProfileCache[65536];
+typedef std::unordered_map<u32, int> bb_map;
+bb_map CreamCache;
//#define USE_DUMMY_CACHE
@@ -3319,14 +3316,12 @@ bb_map ProfileCache[65536];
unsigned int DummyCache[0x100000];
#endif
-#define HASH(x) ((x + (x << 3) + (x >> 6)) % 65536)
void insert_bb(unsigned int addr, int start)
{
#ifdef USE_DUMMY_CACHE
DummyCache[addr] = start;
#else
-// CreamCache[addr] = start;
- CreamCache[HASH(addr)][addr] = start;
+ CreamCache[addr] = start;
#endif
}
@@ -3341,8 +3336,8 @@ int find_bb(unsigned int addr, int &start)
} else
ret = -1;
#else
- bb_map::const_iterator it = CreamCache[HASH(addr)].find(addr);
- if (it != CreamCache[HASH(addr)].end()) {
+ bb_map::const_iterator it = CreamCache.find(addr);
+ if (it != CreamCache.end()) {
start = static_cast<int>(it->second);
ret = 0;
#if HYBRID_MODE
@@ -3473,30 +3468,15 @@ void flush_bb(uint32_t addr)
uint32_t start;
addr &= 0xfffff000;
- for (int i = 0; i < 65536; i ++) {
- for (it = CreamCache[i].begin(); it != CreamCache[i].end(); ) {
- start = static_cast<uint32_t>(it->first);
- //start = (start >> 12) << 12;
- start &= 0xfffff000;
- if (start == addr) {
- //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
- CreamCache[i].erase(it ++);
- } else
- ++it;
- }
- }
-
- for (int i = 0; i < 65536; i ++) {
- for (it = ProfileCache[i].begin(); it != ProfileCache[i].end(); ) {
- start = static_cast<uint32_t>(it->first);
- //start = (start >> 12) << 12;
- start &= 0xfffff000;
- if (start == addr) {
- //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
- ProfileCache[i].erase(it ++);
- } else
- ++it;
- }
+ for (it = CreamCache.begin(); it != CreamCache.end(); ) {
+ start = static_cast<uint32_t>(it->first);
+ //start = (start >> 12) << 12;
+ start &= 0xfffff000;
+ if (start == addr) {
+ //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
+ CreamCache.erase(it++);
+ } else
+ ++it;
}
//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 c65eb23f..3a2462f5 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.h
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
index ed441508..e2aa5ce9 100644
--- a/src/core/arm/interpreter/arm_interpreter.cpp
+++ b/src/core/arm/interpreter/arm_interpreter.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include "core/arm/interpreter/arm_interpreter.h"
@@ -24,7 +24,7 @@ ARM_Interpreter::ARM_Interpreter() {
state->lateabtSig = LOW;
// Reset the core to initial state
- ARMul_CoProInit(state);
+ ARMul_CoProInit(state);
ARMul_Reset(state);
state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
state->Emulate = 3;
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
index ceb1be43..ed53d997 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
@@ -18,7 +18,7 @@ public:
/**
* Set the Program Counter to an address
- * @param addr Address to set PC to
+ * @param pc Address to set PC to
*/
void SetPC(u32 pc) override;
diff --git a/src/core/arm/skyeye_common/armcpu.h b/src/core/arm/skyeye_common/armcpu.h
index 3a029f0e..2b756c5b 100644
--- a/src/core/arm/skyeye_common/armcpu.h
+++ b/src/core/arm/skyeye_common/armcpu.h
@@ -24,8 +24,6 @@
#include <stddef.h>
#include <stdio.h>
-#include "common/thread.h"
-
#include "core/arm/skyeye_common/armdefs.h"
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 8e71948c..8343aaa0 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 */
#include "list.h"
#include "tb.h"
*/
-#define EQ 0
-#define NE 1
-#define CS 2
-#define CC 3
-#define MI 4
-#define PL 5
-#define VS 6
-#define VC 7
-#define HI 8
-#define LS 9
-#define GE 10
-#define LT 11
-#define GT 12
-#define LE 13
-#define AL 14
-#define NV 15
+enum ConditionCode {
+ EQ = 0,
+ NE = 1,
+ CS = 2,
+ CC = 3,
+ MI = 4,
+ PL = 5,
+ VS = 6,
+ VC = 7,
+ HI = 8,
+ LS = 9,
+ GE = 10,
+ LT = 11,
+ GT = 12,
+ LE = 13,
+ AL = 14,
+ NV = 15,
+};
#ifndef NFLAG
#define NFLAG state->NFlag
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index c0f0270f..075fc7e9 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -25,24 +25,6 @@
#define DEBUG(...) DEBUG_LOG(ARM11, __VA_ARGS__)
-/* Condition code values. */
-#define EQ 0
-#define NE 1
-#define CS 2
-#define CC 3
-#define MI 4
-#define PL 5
-#define VS 6
-#define VC 7
-#define HI 8
-#define LS 9
-#define GE 10
-#define LT 11
-#define GT 12
-#define LE 13
-#define AL 14
-#define NV 15
-
/* Shift Opcodes. */
#define LSL 0
#define LSR 1
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 25c78d33..865898b2 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -16,10 +16,10 @@
namespace Core {
-u64 g_last_ticks = 0; ///< Last CPU ticks
-ARM_Disasm* g_disasm = nullptr; ///< ARM disassembler
-ARM_Interface* g_app_core = nullptr; ///< ARM11 application core
-ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core
+static u64 last_ticks = 0; ///< Last CPU ticks
+static ARM_Disasm* disasm = nullptr; ///< ARM disassembler
+ARM_Interface* g_app_core = nullptr; ///< ARM11 application core
+ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core
/// Run the core CPU loop
void RunLoop(int tight_loop) {
@@ -49,7 +49,7 @@ void Stop() {
int Init() {
NOTICE_LOG(MASTER_LOG, "initialized OK");
- g_disasm = new ARM_Disasm();
+ disasm = new ARM_Disasm();
g_sys_core = new ARM_Interpreter();
switch (Settings::values.cpu_core) {
@@ -62,13 +62,13 @@ int Init() {
break;
}
- g_last_ticks = Core::g_app_core->GetTicks();
+ last_ticks = Core::g_app_core->GetTicks();
return 0;
}
void Shutdown() {
- delete g_disasm;
+ delete disasm;
delete g_app_core;
delete g_sys_core;
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 0116cb37..558c6cbf 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -41,7 +41,7 @@ struct BaseEvent
s64 time;
u64 userdata;
int type;
- // Event *next;
+ // Event *next;
};
typedef LinkedListItem<BaseEvent> Event;
@@ -249,7 +249,7 @@ void AddEventToQueue(Event* ne)
// This must be run ONLY from within the cpu thread
// cyclesIntoFuture may be VERY inaccurate if called from anything else
-// than Advance
+// than Advance
void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata)
{
Event *ne = GetNewEvent();
@@ -469,8 +469,8 @@ void ProcessFifoWaitEvents()
{
if (first->time <= globalTimer)
{
- // LOG(TIMER, "[Scheduler] %s (%lld, %lld) ",
- // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
+ //LOG(TIMER, "[Scheduler] %s (%lld, %lld) ",
+ // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
Event* evt = first;
first = first->next;
event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time));
@@ -516,23 +516,23 @@ void Advance()
//currentMIPS->downcount = slicelength;
//if (Common::AtomicLoadAcquire(hasTsEvents))
- // MoveEvents();
+ // MoveEvents();
//ProcessFifoWaitEvents();
//if (!first)
//{
- // // WARN_LOG(TIMER, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000");
- // currentMIPS->downcount += 10000;
+ // // WARN_LOG(TIMER, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000");
+ // currentMIPS->downcount += 10000;
//}
//else
//{
- // slicelength = (int)(first->time - globalTimer);
- // if (slicelength > MAX_SLICE_LENGTH)
- // slicelength = MAX_SLICE_LENGTH;
- // currentMIPS->downcount = slicelength;
+ // slicelength = (int)(first->time - globalTimer);
+ // if (slicelength > MAX_SLICE_LENGTH)
+ // slicelength = MAX_SLICE_LENGTH;
+ // currentMIPS->downcount = slicelength;
//}
//if (advanceCallback)
- // advanceCallback(cyclesExecuted);
+ // advanceCallback(cyclesExecuted);
}
void LogPendingEvents()
@@ -550,20 +550,20 @@ void Idle(int maxIdle)
ERROR_LOG(TIME, "Unimplemented function!");
//int cyclesDown = currentMIPS->downcount;
//if (maxIdle != 0 && cyclesDown > maxIdle)
- // cyclesDown = maxIdle;
+ // cyclesDown = maxIdle;
//if (first && cyclesDown > 0)
//{
- // int cyclesExecuted = slicelength - currentMIPS->downcount;
- // int cyclesNextEvent = (int) (first->time - globalTimer);
-
- // if (cyclesNextEvent < cyclesExecuted + cyclesDown)
- // {
- // cyclesDown = cyclesNextEvent - cyclesExecuted;
- // // Now, now... no time machines, please.
- // if (cyclesDown < 0)
- // cyclesDown = 0;
- // }
+ // int cyclesExecuted = slicelength - currentMIPS->downcount;
+ // int cyclesNextEvent = (int) (first->time - globalTimer);
+
+ // if (cyclesNextEvent < cyclesExecuted + cyclesDown)
+ // {
+ // cyclesDown = cyclesNextEvent - cyclesExecuted;
+ // // Now, now... no time machines, please.
+ // if (cyclesDown < 0)
+ // cyclesDown = 0;
+ // }
//}
//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)
//idledCycles += cyclesDown;
//currentMIPS->downcount -= cyclesDown;
//if (currentMIPS->downcount == 0)
- // currentMIPS->downcount = -1;
+ // currentMIPS->downcount = -1;
}
std::string GetScheduledEventsSummary()
@@ -623,4 +623,4 @@ void DoState(PointerWrap &p)
p.Do(idledCycles);
}
-} // namespace
+} // namespace
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 09fdf7a9..b197cf40 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -106,4 +106,4 @@ void SetClockFrequencyMHz(int cpuMhz);
int GetClockFrequencyMHz();
extern int slicelength;
-}; // namespace
+} // namespace
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h
index 38145eed..c2426a15 100644
--- a/src/core/file_sys/archive.h
+++ b/src/core/file_sys/archive.h
@@ -67,6 +67,8 @@ public:
u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated.
break;
}
+ default:
+ break;
}
}
@@ -74,6 +76,35 @@ public:
return type;
}
+ /**
+ * Gets the string representation of the path for debugging
+ * @return String representation of the path for debugging
+ */
+ const std::string DebugStr() const {
+ switch (GetType()) {
+ case Invalid:
+ return "[Invalid]";
+ case Empty:
+ return "[Empty]";
+ case Binary:
+ {
+ std::stringstream res;
+ res << "[Binary: ";
+ for (unsigned byte : binary)
+ res << std::hex << std::setw(2) << std::setfill('0') << byte;
+ res << ']';
+ return res.str();
+ }
+ case Char:
+ return "[Char: " + AsString() + ']';
+ case Wchar:
+ return "[Wchar: " + AsString() + ']';
+ default:
+ ERROR_LOG(KERNEL, "LowPathType cannot be converted to string!");
+ return {};
+ }
+ }
+
const std::string AsString() const {
switch (GetType()) {
case Char:
@@ -153,21 +184,35 @@ public:
* @param mode Mode to open the file with
* @return Opened file, or nullptr
*/
- virtual std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const = 0;
+ virtual std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const = 0;
+
+ /**
+ * Delete a file specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the file could be deleted
+ */
+ virtual bool DeleteFile(const FileSys::Path& path) const = 0;
+
+ /**
+ * Delete a directory specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the directory could be deleted
+ */
+ virtual bool DeleteDirectory(const FileSys::Path& path) const = 0;
/**
* Create a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be created
*/
- virtual bool CreateDirectory(const std::string& path) const = 0;
+ virtual bool CreateDirectory(const Path& path) const = 0;
/**
* Open a directory specified by its path
* @param path Path relative to the archive
* @return Opened directory, or nullptr
*/
- virtual std::unique_ptr<Directory> OpenDirectory(const std::string& path) const = 0;
+ virtual std::unique_ptr<Directory> OpenDirectory(const Path& path) const = 0;
/**
* Read data from the archive
@@ -193,7 +238,7 @@ public:
* @return Size of the archive in bytes
*/
virtual size_t GetSize() const = 0;
-
+
/**
* Set the size of the archive in bytes
*/
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index cc759faa..53dc5795 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() {
* @param mode Mode to open the file with
* @return Opened file, or nullptr
*/
-std::unique_ptr<File> Archive_RomFS::OpenFile(const std::string& path, const Mode mode) const {
+std::unique_ptr<File> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const {
return std::unique_ptr<File>(new File_RomFS);
}
/**
+ * Delete a file specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the file could be deleted
+ */
+bool Archive_RomFS::DeleteFile(const FileSys::Path& path) const {
+ ERROR_LOG(FILESYS, "Attempted to delete a file from ROMFS.");
+ return false;
+}
+
+/**
+ * Delete a directory specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the directory could be deleted
+ */
+bool Archive_RomFS::DeleteDirectory(const FileSys::Path& path) const {
+ ERROR_LOG(FILESYS, "Attempted to delete a directory from ROMFS.");
+ return false;
+}
+
+/**
* Create a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be created
*/
-bool Archive_RomFS::CreateDirectory(const std::string& path) const {
+bool Archive_RomFS::CreateDirectory(const Path& path) const {
ERROR_LOG(FILESYS, "Attempted to create a directory in ROMFS.");
return false;
-};
+}
/**
* Open a directory specified by its path
* @param path Path relative to the archive
* @return Opened directory, or nullptr
*/
-std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const std::string& path) const {
+std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const Path& path) const {
return std::unique_ptr<Directory>(new Directory_RomFS);
}
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index ae2344e8..0649dde9 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -26,7 +26,7 @@ public:
* Get the IdCode of the archive (e.g. RomFS, SaveData, etc.)
* @return IdCode of the archive
*/
- IdCode GetIdCode() const override { return IdCode::RomFS; };
+ IdCode GetIdCode() const override { return IdCode::RomFS; }
/**
* Open a file specified by its path, using the specified mode
@@ -34,21 +34,35 @@ public:
* @param mode Mode to open the file with
* @return Opened file, or nullptr
*/
- std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override;
+ std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override;
+
+ /**
+ * Delete a file specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the file could be deleted
+ */
+ bool DeleteFile(const FileSys::Path& path) const override;
+
+ /**
+ * Delete a directory specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the directory could be deleted
+ */
+ bool DeleteDirectory(const FileSys::Path& path) const override;
/**
* Create a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be created
*/
- bool CreateDirectory(const std::string& path) const override;
+ bool CreateDirectory(const Path& path) const override;
/**
* Open a directory specified by its path
* @param path Path relative to the archive
* @return Opened directory, or nullptr
*/
- std::unique_ptr<Directory> OpenDirectory(const std::string& path) const override;
+ std::unique_ptr<Directory> OpenDirectory(const Path& path) const override;
/**
* Read data from the archive
@@ -74,7 +88,7 @@ public:
* @return Size of the archive in bytes
*/
size_t GetSize() const override;
-
+
/**
* Set the size of the archive in bytes
*/
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 66931e93..789212b1 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() {
* @param mode Mode to open the file with
* @return Opened file, or nullptr
*/
-std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const Mode mode) const {
- DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.c_str(), mode);
+std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const {
+ DEBUG_LOG(FILESYS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex);
File_SDMC* file = new File_SDMC(this, path, mode);
if (!file->Open())
return nullptr;
@@ -58,12 +58,30 @@ std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const Mode
}
/**
+ * Delete a file specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the file could be deleted
+ */
+bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const {
+ return FileUtil::Delete(GetMountPoint() + path.AsString());
+}
+
+/**
+ * Delete a directory specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the directory could be deleted
+ */
+bool Archive_SDMC::DeleteDirectory(const FileSys::Path& path) const {
+ return FileUtil::DeleteDir(GetMountPoint() + path.AsString());
+}
+
+/**
* Create a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be created
*/
-bool Archive_SDMC::CreateDirectory(const std::string& path) const {
- return FileUtil::CreateDir(GetMountPoint() + path);
+bool Archive_SDMC::CreateDirectory(const Path& path) const {
+ return FileUtil::CreateDir(GetMountPoint() + path.AsString());
}
/**
@@ -71,8 +89,8 @@ bool Archive_SDMC::CreateDirectory(const std::string& path) const {
* @param path Path relative to the archive
* @return Opened directory, or nullptr
*/
-std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const std::string& path) const {
- DEBUG_LOG(FILESYS, "called path=%s", path.c_str());
+std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const {
+ DEBUG_LOG(FILESYS, "called path=%s", path.DebugStr().c_str());
Directory_SDMC* directory = new Directory_SDMC(this, path);
return std::unique_ptr<Directory>(directory);
}
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 0e059b63..74ce29c0 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -30,7 +30,7 @@ public:
* Get the IdCode of the archive (e.g. RomFS, SaveData, etc.)
* @return IdCode of the archive
*/
- IdCode GetIdCode() const override { return IdCode::SDMC; };
+ IdCode GetIdCode() const override { return IdCode::SDMC; }
/**
* Open a file specified by its path, using the specified mode
@@ -38,21 +38,35 @@ public:
* @param mode Mode to open the file with
* @return Opened file, or nullptr
*/
- std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override;
+ std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override;
+
+ /**
+ * Delete a file specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the file could be deleted
+ */
+ bool DeleteFile(const FileSys::Path& path) const override;
+
+ /**
+ * Delete a directory specified by its path
+ * @param path Path relative to the archive
+ * @return Whether the directory could be deleted
+ */
+ bool DeleteDirectory(const FileSys::Path& path) const override;
/**
* Create a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be created
*/
- bool CreateDirectory(const std::string& path) const override;
+ bool CreateDirectory(const Path& path) const override;
/**
* Open a directory specified by its path
* @param path Path relative to the archive
* @return Opened directory, or nullptr
*/
- std::unique_ptr<Directory> OpenDirectory(const std::string& path) const override;
+ std::unique_ptr<Directory> OpenDirectory(const Path& path) const override;
/**
* Read data from the archive
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp
index fd558def..60a197ce 100644
--- a/src/core/file_sys/directory_sdmc.cpp
+++ b/src/core/file_sys/directory_sdmc.cpp
@@ -15,11 +15,11 @@
namespace FileSys {
-Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const std::string& path) {
+Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const Path& path) {
// TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
// the root directory we set while opening the archive.
// For example, opening /../../usr/bin can give the emulated program your installed programs.
- std::string absolute_path = archive->GetMountPoint() + path;
+ std::string absolute_path = archive->GetMountPoint() + path.AsString();
FileUtil::ScanDirectoryTree(absolute_path, directory);
children_iterator = directory.children.begin();
}
@@ -45,7 +45,7 @@ u32 Directory_SDMC::Read(const u32 count, Entry* entries) {
WARN_LOG(FILESYS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory);
// TODO(Link Mauve): use a proper conversion to UTF-16.
- for (int j = 0; j < FILENAME_LENGTH; ++j) {
+ for (size_t j = 0; j < FILENAME_LENGTH; ++j) {
entry.filename[j] = filename[j];
if (!filename[j])
break;
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h
index cb8d32fd..4520d040 100644
--- a/src/core/file_sys/directory_sdmc.h
+++ b/src/core/file_sys/directory_sdmc.h
@@ -19,7 +19,7 @@ namespace FileSys {
class Directory_SDMC final : public Directory {
public:
Directory_SDMC();
- Directory_SDMC(const Archive_SDMC* archive, const std::string& path);
+ Directory_SDMC(const Archive_SDMC* archive, const Path& path);
~Directory_SDMC() override;
/**
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp
index 26204392..a4b90670 100644
--- a/src/core/file_sys/file_sdmc.cpp
+++ b/src/core/file_sys/file_sdmc.cpp
@@ -15,11 +15,11 @@
namespace FileSys {
-File_SDMC::File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode) {
+File_SDMC::File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode) {
// TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
// the root directory we set while opening the archive.
// For example, opening /../../etc/passwd can give the emulated program your users list.
- this->path = archive->GetMountPoint() + path;
+ this->path = archive->GetMountPoint() + path.AsString();
this->mode.hex = mode.hex;
}
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h
index df032f7c..80b44596 100644
--- a/src/core/file_sys/file_sdmc.h
+++ b/src/core/file_sys/file_sdmc.h
@@ -19,7 +19,7 @@ namespace FileSys {
class File_SDMC final : public File {
public:
File_SDMC();
- File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode);
+ File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode);
~File_SDMC() override;
/**
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp
index a45e6142..c7cf5b1d 100644
--- a/src/core/hle/config_mem.cpp
+++ b/src/core/hle/config_mem.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include "common/common_types.h"
diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp
index 1eb33eb8..e34229a5 100644
--- a/src/core/hle/coprocessor.cpp
+++ b/src/core/hle/coprocessor.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include "core/hle/coprocessor.h"
#include "core/hle/hle.h"
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 55eaf062..3dbe2503 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(){
template<s32 func(s32*, u32*, s32, bool, s64)> void Wrap() {
s32 param_1 = 0;
- s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2),
+ s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2),
(PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0)));
Core::g_app_core->SetReg(1, (u32)param_1);
FuncReturn(retval);
@@ -103,7 +103,7 @@ template<s32 func(void*)> void Wrap() {
}
template<s32 func(s64*, u32, void*, s32)> void Wrap(){
- FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)),
+ FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)),
(s32)PARAM(3)));
}
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index b03894ad..b8ac186f 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include <vector>
@@ -20,7 +20,7 @@ bool g_reschedule = false; ///< If true, immediately reschedules the CPU to a n
const FunctionDef* GetSVCInfo(u32 opcode) {
u32 func_num = opcode & 0xFFFFFF; // 8 bits
if (func_num > 0xFF) {
- ERROR_LOG(HLE,"unknown svc=0x%02X", func_num);
+ ERROR_LOG(HLE,"unknown svc=0x%02X", func_num);
return nullptr;
}
return &g_module_db[0].func_table[func_num];
@@ -58,7 +58,7 @@ void RegisterAllModules() {
void Init() {
Service::Init();
-
+
RegisterAllModules();
NOTICE_LOG(HLE, "initialized OK");
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h
index bf4d8457..4ab258c6 100644
--- a/src/core/hle/hle.h
+++ b/src/core/hle/hle.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 2b21657d..db571b89 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -25,22 +25,17 @@ public:
std::string name; ///< Name of address arbiter object (optional)
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
+ ResultVal<bool> WaitSynchronization() override {
// TODO(bunnei): ImplementMe
ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
- return 0;
+ return UnimplementedFunction(ErrorModule::OS);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Arbitrate an address
-Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) {
+ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) {
switch (type) {
// Signal thread(s) waiting for arbitrate address...
@@ -65,9 +60,9 @@ Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 va
default:
ERROR_LOG(KERNEL, "unknown type=%d", type);
- return -1;
+ return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage);
}
- return 0;
+ return RESULT_SUCCESS;
}
/// Create an address arbiter
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index a483fe46..8a5fb10b 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -11,7 +11,7 @@
// Address arbiters are an underlying kernel synchronization object that can be created/used via
// supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR
// applications use them as an underlying mechanism to implement thread-safe barriers, events, and
-// semphores.
+// semphores.
////////////////////////////////////////////////////////////////////////////////////////////////////
// Kernel namespace
@@ -28,7 +28,7 @@ enum class ArbitrationType : u32 {
};
/// Arbitrate an address
-Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value);
+ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value);
/// Create an address arbiter
Handle CreateAddressArbiter(const std::string& name = "Unknown");
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
index 764082d7..e273444c 100644
--- a/src/core/hle/kernel/archive.cpp
+++ b/src/core/hle/kernel/archive.cpp
@@ -9,8 +9,9 @@
#include "core/file_sys/archive.h"
#include "core/file_sys/archive_sdmc.h"
#include "core/file_sys/directory.h"
-#include "core/hle/service/service.h"
#include "core/hle/kernel/archive.h"
+#include "core/hle/result.h"
+#include "core/hle/service/service.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Kernel namespace
@@ -51,15 +52,10 @@ public:
std::string name; ///< Name of archive (optional)
FileSys::Archive* backend; ///< Archive backend interface
- /**
- * Synchronize kernel object
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result SyncRequest(bool* wait) override {
+ ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer();
FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
-
+
switch (cmd) {
// Read from archive...
case FileCommand::Read:
@@ -99,7 +95,6 @@ public:
case FileCommand::Close:
{
DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
- Kernel::g_object_pool.Destroy<Archive>(GetHandle());
CloseArchive(backend->GetIdCode());
break;
}
@@ -107,42 +102,32 @@ public:
default:
{
ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
- return -1;
+ return UnimplementedFunction(ErrorModule::FS);
}
}
cmd_buff[1] = 0; // No error
- return 0;
+ return MakeResult<bool>(false);
}
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
+ ResultVal<bool> WaitSynchronization() override {
// TODO(bunnei): ImplementMe
ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
- return 0;
+ return UnimplementedFunction(ErrorModule::FS);
}
};
class File : public Object {
public:
std::string GetTypeName() const override { return "File"; }
- std::string GetName() const override { return path; }
+ std::string GetName() const override { return path.DebugStr(); }
static Kernel::HandleType GetStaticHandleType() { return HandleType::File; }
Kernel::HandleType GetHandleType() const override { return HandleType::File; }
- std::string path; ///< Path of the file
+ FileSys::Path path; ///< Path of the file
std::unique_ptr<FileSys::File> backend; ///< File backend interface
- /**
- * Synchronize kernel object
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result SyncRequest(bool* wait) override {
+ ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer();
FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
switch (cmd) {
@@ -184,7 +169,8 @@ public:
case FileCommand::SetSize:
{
u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
- DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(), size);
+ DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu",
+ GetTypeName().c_str(), GetName().c_str(), size);
backend->SetSize(size);
break;
}
@@ -199,42 +185,33 @@ public:
// Unknown command...
default:
ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
- cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that.
- return -1;
+ ResultCode error = UnimplementedFunction(ErrorModule::FS);
+ cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
+ return error;
}
cmd_buff[1] = 0; // No error
- return 0;
+ return MakeResult<bool>(false);
}
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
+ ResultVal<bool> WaitSynchronization() override {
// TODO(bunnei): ImplementMe
ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
- return 0;
+ return UnimplementedFunction(ErrorModule::FS);
}
};
class Directory : public Object {
public:
std::string GetTypeName() const override { return "Directory"; }
- std::string GetName() const override { return path; }
+ std::string GetName() const override { return path.DebugStr(); }
static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; }
Kernel::HandleType GetHandleType() const override { return HandleType::Directory; }
- std::string path; ///< Path of the directory
+ FileSys::Path path; ///< Path of the directory
std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
- /**
- * Synchronize kernel object
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result SyncRequest(bool* wait) override {
+ ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer();
DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
switch (cmd) {
@@ -244,8 +221,9 @@ public:
{
u32 count = cmd_buff[1];
u32 address = cmd_buff[3];
- FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address));
- DEBUG_LOG(KERNEL, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), count);
+ auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address));
+ DEBUG_LOG(KERNEL, "Read %s %s: count=%d",
+ GetTypeName().c_str(), GetName().c_str(), count);
// Number of entries actually read
cmd_buff[2] = backend->Read(count, entries);
@@ -262,22 +240,18 @@ public:
// Unknown command...
default:
ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
- cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that.
- return -1;
+ ResultCode error = UnimplementedFunction(ErrorModule::FS);
+ cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
+ return error;
}
cmd_buff[1] = 0; // No error
- return 0;
+ return MakeResult<bool>(false);
}
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
+ ResultVal<bool> WaitSynchronization() override {
// TODO(bunnei): ImplementMe
ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
- return 0;
+ return UnimplementedFunction(ErrorModule::FS);
}
};
@@ -285,108 +259,124 @@ public:
std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode
-/**
- * Opens an archive
- * @param id_code IdCode of the archive to open
- * @return Handle to archive if it exists, otherwise a null handle (0)
- */
-Handle OpenArchive(FileSys::Archive::IdCode id_code) {
+ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) {
auto itr = g_archive_map.find(id_code);
if (itr == g_archive_map.end()) {
- return 0;
+ return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
+ ErrorSummary::NotFound, ErrorLevel::Permanent);
}
- return itr->second;
+
+ return MakeResult<Handle>(itr->second);
}
-/**
- * Closes an archive
- * @param id_code IdCode of the archive to open
- * @return Result of operation, 0 on success, otherwise error code
- */
-Result CloseArchive(FileSys::Archive::IdCode id_code) {
- if (1 != g_archive_map.erase(id_code)) {
- ERROR_LOG(KERNEL, "Cannot close archive %d", (int) id_code);
- return -1;
+ResultCode CloseArchive(FileSys::Archive::IdCode id_code) {
+ auto itr = g_archive_map.find(id_code);
+ if (itr == g_archive_map.end()) {
+ ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code);
+ return InvalidHandle(ErrorModule::FS);
}
INFO_LOG(KERNEL, "Closed archive %d", (int) id_code);
- return 0;
+ return RESULT_SUCCESS;
}
/**
* Mounts an archive
* @param archive Pointer to the archive to mount
- * @return Result of operation, 0 on success, otherwise error code
*/
-Result MountArchive(Archive* archive) {
+ResultCode MountArchive(Archive* archive) {
FileSys::Archive::IdCode id_code = archive->backend->GetIdCode();
- if (0 != OpenArchive(id_code)) {
+ ResultVal<Handle> archive_handle = OpenArchive(id_code);
+ if (archive_handle.Succeeded()) {
ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code);
- return -1;
+ return archive_handle.Code();
}
g_archive_map[id_code] = archive->GetHandle();
INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str());
- return 0;
+ return RESULT_SUCCESS;
}
-/**
- * Creates an Archive
- * @param handle Handle to newly created archive object
- * @param backend File system backend interface to the archive
- * @param name Optional name of Archive
- * @return Newly created Archive object
- */
-Archive* CreateArchive(Handle& handle, FileSys::Archive* backend, const std::string& name) {
+ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name) {
Archive* archive = new Archive;
- handle = Kernel::g_object_pool.Create(archive);
+ Handle handle = Kernel::g_object_pool.Create(archive);
archive->name = name;
archive->backend = backend;
- MountArchive(archive);
+ ResultCode result = MountArchive(archive);
+ if (result.IsError()) {
+ return result;
+ }
- return archive;
+ return RESULT_SUCCESS;
}
-/**
- * Creates an Archive
- * @param backend File system backend interface to the archive
- * @param name Optional name of Archive
- * @return Handle to newly created Archive object
- */
-Handle CreateArchive(FileSys::Archive* backend, const std::string& name) {
- Handle handle;
- CreateArchive(handle, backend, name);
- return handle;
-}
+ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) {
+ // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create
+ // the archive file handles at app loading, and then keep them persistent throughout execution.
+ // Archives file handles are just reused and not actually freed until emulation shut down.
+ // Verify if real hardware works this way, or if new handles are created each time
+ if (path.GetType() == FileSys::Binary)
+ // TODO(bunnei): FixMe - this is a hack to compensate for an incorrect FileSys backend
+ // design. While the functionally of this is OK, our implementation decision to separate
+ // normal files from archive file pointers is very likely wrong.
+ // See https://github.com/citra-emu/citra/issues/205
+ return MakeResult<Handle>(archive_handle);
-/**
- * Open a File from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the File inside of the Archive
- * @param mode Mode under which to open the File
- * @return Opened File object
- */
-Handle OpenFileFromArchive(Handle archive_handle, const std::string& path, const FileSys::Mode mode) {
File* file = new File;
Handle handle = Kernel::g_object_pool.Create(file);
- Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
+ Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
+ if (archive == nullptr) {
+ return InvalidHandle(ErrorModule::FS);
+ }
file->path = path;
file->backend = archive->backend->OpenFile(path, mode);
- if (!file->backend)
+ if (!file->backend) {
+ return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
+ ErrorSummary::NotFound, ErrorLevel::Permanent);
+ }
+
+ return MakeResult<Handle>(handle);
+}
+
+/**
+ * Delete a File from an Archive
+ * @param archive_handle Handle to an open Archive object
+ * @param path Path to the File inside of the Archive
+ * @return Whether deletion succeeded
+ */
+Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) {
+ Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
+ if (archive == nullptr)
+ return -1;
+ if (archive->backend->DeleteFile(path))
return 0;
+ return -1;
+}
- return handle;
+/**
+ * Delete a Directory from an Archive
+ * @param archive_handle Handle to an open Archive object
+ * @param path Path to the Directory inside of the Archive
+ * @return Whether deletion succeeded
+ */
+Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
+ Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
+ if (archive == nullptr)
+ return -1;
+ if (archive->backend->DeleteDirectory(path))
+ return 0;
+ return -1;
}
/**
* Create a Directory from an Archive
* @param archive_handle Handle to an open Archive object
* @param path Path to the Directory inside of the Archive
- * @return Opened Directory object
+ * @return Whether creation succeeded
*/
-Result CreateDirectoryFromArchive(Handle archive_handle, const std::string& path) {
+Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
if (archive == nullptr)
return -1;
@@ -401,15 +391,18 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const std::string& path
* @param path Path to the Directory inside of the Archive
* @return Opened Directory object
*/
-Handle OpenDirectoryFromArchive(Handle archive_handle, const std::string& path) {
+ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
Directory* directory = new Directory;
Handle handle = Kernel::g_object_pool.Create(directory);
- Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
+ Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
+ if (archive == nullptr) {
+ return InvalidHandle(ErrorModule::FS);
+ }
directory->path = path;
directory->backend = archive->backend->OpenDirectory(path);
- return handle;
+ return MakeResult<Handle>(handle);
}
/// Initialize archives
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h
index 0230996b..6fc4f0f2 100644
--- a/src/core/hle/kernel/archive.h
+++ b/src/core/hle/kernel/archive.h
@@ -6,8 +6,9 @@
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
#include "core/file_sys/archive.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/result.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Kernel namespace
@@ -17,33 +18,47 @@ namespace Kernel {
/**
* Opens an archive
* @param id_code IdCode of the archive to open
- * @return Handle to archive if it exists, otherwise a null handle (0)
+ * @return Handle to the opened archive
*/
-Handle OpenArchive(FileSys::Archive::IdCode id_code);
+ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code);
/**
* Closes an archive
* @param id_code IdCode of the archive to open
- * @return true if it worked fine
*/
-Result CloseArchive(FileSys::Archive::IdCode id_code);
+ResultCode CloseArchive(FileSys::Archive::IdCode id_code);
/**
* Creates an Archive
* @param backend File system backend interface to the archive
- * @param name Optional name of Archive
- * @return Handle to newly created Archive object
+ * @param name Name of Archive
*/
-Handle CreateArchive(FileSys::Archive* backend, const std::string& name);
+ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name);
/**
* Open a File from an Archive
* @param archive_handle Handle to an open Archive object
* @param path Path to the File inside of the Archive
* @param mode Mode under which to open the File
- * @return Opened File object
+ * @return Handle to the opened File object
+ */
+ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode);
+
+/**
+ * Delete a File from an Archive
+ * @param archive_handle Handle to an open Archive object
+ * @param path Path to the File inside of the Archive
+ * @return Whether deletion succeeded
+ */
+Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
+
+/**
+ * Delete a Directory from an Archive
+ * @param archive_handle Handle to an open Archive object
+ * @param path Path to the Directory inside of the Archive
+ * @return Whether deletion succeeded
*/
-Handle OpenFileFromArchive(Handle archive_handle, const std::string& name, const FileSys::Mode mode);
+Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
/**
* Create a Directory from an Archive
@@ -51,15 +66,15 @@ Handle OpenFileFromArchive(Handle archive_handle, const std::string& name, const
* @param path Path to the Directory inside of the Archive
* @return Whether creation of directory succeeded
*/
-Result CreateDirectoryFromArchive(Handle archive_handle, const std::string& name);
+Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
/**
* Open a Directory from an Archive
* @param archive_handle Handle to an open Archive object
* @param path Path to the Directory inside of the Archive
- * @return Opened Directory object
+ * @return Handle to the opened File object
*/
-Handle OpenDirectoryFromArchive(Handle archive_handle, const std::string& name);
+ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
/// Initialize archives
void ArchiveInit();
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 45ed79be..28808020 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include <map>
#include <algorithm>
@@ -30,13 +30,8 @@ public:
std::vector<Handle> waiting_threads; ///< Threads that are waiting for the event
std::string name; ///< Name of event (optional)
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
- *wait = locked;
+ ResultVal<bool> WaitSynchronization() override {
+ bool wait = locked;
if (locked) {
Handle thread = GetCurrentThreadHandle();
if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
@@ -47,7 +42,7 @@ public:
if (reset_type != RESETTYPE_STICKY && !permanent_locked) {
locked = true;
}
- return 0;
+ return MakeResult<bool>(wait);
}
};
@@ -57,12 +52,12 @@ public:
* @param permanent_locked Boolean permanent locked value to set event
* @return Result of operation, 0 on success, otherwise error code
*/
-Result SetPermanentLock(Handle handle, const bool permanent_locked) {
- Event* evt = g_object_pool.GetFast<Event>(handle);
- _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!");
+ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
+ Event* evt = g_object_pool.Get<Event>(handle);
+ if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
evt->permanent_locked = permanent_locked;
- return 0;
+ return RESULT_SUCCESS;
}
/**
@@ -71,14 +66,14 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) {
* @param locked Boolean locked value to set event
* @return Result of operation, 0 on success, otherwise error code
*/
-Result SetEventLocked(const Handle handle, const bool locked) {
- Event* evt = g_object_pool.GetFast<Event>(handle);
- _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!");
+ResultCode SetEventLocked(const Handle handle, const bool locked) {
+ Event* evt = g_object_pool.Get<Event>(handle);
+ if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
if (!evt->permanent_locked) {
evt->locked = locked;
}
- return 0;
+ return RESULT_SUCCESS;
}
/**
@@ -86,16 +81,16 @@ Result SetEventLocked(const Handle handle, const bool locked) {
* @param handle Handle to event to signal
* @return Result of operation, 0 on success, otherwise error code
*/
-Result SignalEvent(const Handle handle) {
- Event* evt = g_object_pool.GetFast<Event>(handle);
- _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!");
+ResultCode SignalEvent(const Handle handle) {
+ Event* evt = g_object_pool.Get<Event>(handle);
+ if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
// Resume threads waiting for event to signal
bool event_caught = false;
for (size_t i = 0; i < evt->waiting_threads.size(); ++i) {
ResumeThreadFromWait( evt->waiting_threads[i]);
- // If any thread is signalled awake by this event, assume the event was "caught" and reset
+ // If any thread is signalled awake by this event, assume the event was "caught" and reset
// the event. This will result in the next thread waiting on the event to block. Otherwise,
// the event will not be reset, and the next thread to call WaitSynchronization on it will
// not block. Not sure if this is correct behavior, but it seems to work.
@@ -106,7 +101,7 @@ Result SignalEvent(const Handle handle) {
if (!evt->permanent_locked) {
evt->locked = event_caught;
}
- return 0;
+ return RESULT_SUCCESS;
}
/**
@@ -114,14 +109,14 @@ Result SignalEvent(const Handle handle) {
* @param handle Handle to event to clear
* @return Result of operation, 0 on success, otherwise error code
*/
-Result ClearEvent(Handle handle) {
- Event* evt = g_object_pool.GetFast<Event>(handle);
- _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!");
+ResultCode ClearEvent(Handle handle) {
+ Event* evt = g_object_pool.Get<Event>(handle);
+ if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
if (!evt->permanent_locked) {
evt->locked = true;
}
- return 0;
+ return RESULT_SUCCESS;
}
/**
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index c39b3318..73aec4e7 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
@@ -15,31 +15,27 @@ namespace Kernel {
* Changes whether an event is locked or not
* @param handle Handle to event to change
* @param locked Boolean locked value to set event
- * @return Result of operation, 0 on success, otherwise error code
*/
-Result SetEventLocked(const Handle handle, const bool locked);
+ResultCode SetEventLocked(const Handle handle, const bool locked);
/**
* Hackish function to set an events permanent lock state, used to pass through synch blocks
* @param handle Handle to event to change
* @param permanent_locked Boolean permanent locked value to set event
- * @return Result of operation, 0 on success, otherwise error code
*/
-Result SetPermanentLock(Handle handle, const bool permanent_locked);
+ResultCode SetPermanentLock(Handle handle, const bool permanent_locked);
/**
* Signals an event
* @param handle Handle to event to signal
- * @return Result of operation, 0 on success, otherwise error code
*/
-Result SignalEvent(const Handle handle);
+ResultCode SignalEvent(const Handle handle);
/**
* Clears an event
* @param handle Handle to event to clear
- * @return Result of operation, 0 on success, otherwise error code
*/
-Result ClearEvent(Handle handle);
+ResultCode ClearEvent(Handle handle);
/**
* Creates an event
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 88cbc1af..018000ab 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project / PPSSPP Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include "common/common.h"
@@ -68,7 +68,7 @@ void ObjectPool::List() {
for (int i = 0; i < MAX_COUNT; i++) {
if (occupied[i]) {
if (pool[i]) {
- INFO_LOG(KERNEL, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(),
+ INFO_LOG(KERNEL, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(),
pool[i]->GetName().c_str());
}
}
@@ -110,7 +110,7 @@ void Shutdown() {
*/
bool LoadExec(u32 entry_point) {
Init();
-
+
Core::g_app_core->SetPC(entry_point);
// 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 867d1b89..8d3937ce 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -1,12 +1,13 @@
// Copyright 2014 Citra Emulator Project / PPSSPP Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
#include <array>
#include <string>
#include "common/common.h"
+#include "core/hle/result.h"
typedef u32 Handle;
typedef s32 Result;
@@ -34,7 +35,7 @@ enum class HandleType : u32 {
Archive = 12,
Directory = 13,
};
-
+
enum {
DEFAULT_STACK_SIZE = 0x4000,
};
@@ -52,21 +53,19 @@ public:
virtual Kernel::HandleType GetHandleType() const = 0;
/**
- * Synchronize kernel object
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
+ * Synchronize kernel object.
+ * @return True if the current thread should wait as a result of the sync
*/
- virtual Result SyncRequest(bool* wait) {
+ virtual ResultVal<bool> SyncRequest() {
ERROR_LOG(KERNEL, "(UNIMPLEMENTED)");
- return -1;
+ return UnimplementedFunction(ErrorModule::Kernel);
}
/**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
+ * Wait for kernel object to synchronize.
+ * @return True if the current thread should wait as a result of the wait
*/
- virtual Result WaitSynchronization(bool* wait) = 0;
+ virtual ResultVal<bool> WaitSynchronization() = 0;
};
class ObjectPool : NonCopyable {
@@ -80,38 +79,29 @@ public:
static Object* CreateByIDType(int type);
template <class T>
- u32 Destroy(Handle handle) {
- u32 error;
- if (Get<T>(handle, error)) {
+ void Destroy(Handle handle) {
+ if (Get<T>(handle)) {
occupied[handle - HANDLE_OFFSET] = false;
delete pool[handle - HANDLE_OFFSET];
}
- return error;
- };
+ }
bool IsValid(Handle handle);
template <class T>
- T* Get(Handle handle, u32& outError) {
+ T* Get(Handle handle) {
if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) {
- // Tekken 6 spams 0x80020001 gets wrong with no ill effects, also on the real PSP
- if (handle != 0 && (u32)handle != 0x80020001) {
+ if (handle != 0) {
WARN_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
}
- outError = 0;//T::GetMissingErrorCode();
- return 0;
+ return nullptr;
} else {
- // Previously we had a dynamic_cast here, but since RTTI was disabled traditionally,
- // it just acted as a static case and everything worked. This means that we will never
- // see the Wrong type object error below, but we'll just have to live with that danger.
- T* t = static_cast<T*>(pool[handle - HANDLE_OFFSET]);
- if (t == 0 || t->GetHandleType() != T::GetStaticHandleType()) {
+ Object* t = pool[handle - HANDLE_OFFSET];
+ if (t->GetHandleType() != T::GetStaticHandleType()) {
WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle);
- outError = 0;//T::GetMissingErrorCode();
- return 0;
+ return nullptr;
}
- outError = 0;//SCE_KERNEL_ERROR_OK;
- return t;
+ return static_cast<T*>(t);
}
}
@@ -139,7 +129,7 @@ public:
}
bool GetIDType(Handle handle, HandleType* type) const {
- if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) ||
+ if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) ||
!occupied[handle - HANDLE_OFFSET]) {
ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
return false;
@@ -155,7 +145,7 @@ public:
int GetCount();
private:
-
+
enum {
MAX_COUNT = 0x1000,
HANDLE_OFFSET = 0x100,
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index fcfd061a..d07e9761 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include <map>
#include <vector>
@@ -27,31 +27,20 @@ public:
std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex
std::string name; ///< Name of mutex (optional)
- /**
- * Synchronize kernel object
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result SyncRequest(bool* wait) override {
+ ResultVal<bool> SyncRequest() override {
// TODO(bunnei): ImplementMe
locked = true;
- return 0;
+ return MakeResult<bool>(false);
}
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
+ ResultVal<bool> WaitSynchronization() override {
// TODO(bunnei): ImplementMe
- *wait = locked;
-
+ bool wait = locked;
if (locked) {
Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle());
}
- return 0;
+ return MakeResult<bool>(wait);
}
};
@@ -99,35 +88,36 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) {
bool ReleaseMutex(Mutex* mutex) {
MutexEraseLock(mutex);
- bool woke_threads = false;
// Find the next waiting thread for the mutex...
- while (!woke_threads && !mutex->waiting_threads.empty()) {
+ while (!mutex->waiting_threads.empty()) {
std::vector<Handle>::iterator iter = mutex->waiting_threads.begin();
- woke_threads |= ReleaseMutexForThread(mutex, *iter);
+ ReleaseMutexForThread(mutex, *iter);
mutex->waiting_threads.erase(iter);
}
+
// Reset mutex lock thread handle, nothing is waiting
- if (!woke_threads) {
- mutex->locked = false;
- mutex->lock_thread = -1;
- }
- return woke_threads;
+ mutex->locked = false;
+ mutex->lock_thread = -1;
+
+ return true;
}
/**
* Releases a mutex
* @param handle Handle to mutex to release
*/
-Result ReleaseMutex(Handle handle) {
- Mutex* mutex = Kernel::g_object_pool.GetFast<Mutex>(handle);
-
- _assert_msg_(KERNEL, (mutex != nullptr), "ReleaseMutex tried to release a nullptr mutex!");
+ResultCode ReleaseMutex(Handle handle) {
+ Mutex* mutex = Kernel::g_object_pool.Get<Mutex>(handle);
+ if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
if (!ReleaseMutex(mutex)) {
- return -1;
+ // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure
+ // what error condition this is supposed to be signaling.
+ return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel,
+ ErrorSummary::NothingHappened, ErrorLevel::Temporary);
}
- return 0;
+ return RESULT_SUCCESS;
}
/**
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 7d7b5137..155449f9 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
@@ -13,9 +13,8 @@ namespace Kernel {
/**
* Releases a mutex
* @param handle Handle to mutex to release
- * @return Result of operation, 0 on success, otherwise error code
*/
-Result ReleaseMutex(Handle handle);
+ResultCode ReleaseMutex(Handle handle);
/**
* Creates a mutex
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index f538c655..cfcc0e0b 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include "common/common.h"
@@ -16,15 +16,10 @@ public:
static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; }
Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; }
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
+ ResultVal<bool> WaitSynchronization() override {
// TODO(bunnei): ImplementMe
ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
- return 0;
+ return UnimplementedFunction(ErrorModule::OS);
}
u32 base_address; ///< Address of shared memory block in RAM
@@ -48,11 +43,6 @@ SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
return shared_memory;
}
-/**
- * Creates a shared memory object
- * @param name Optional name of shared memory object
- * @return Handle of newly created shared memory object
- */
Handle CreateSharedMemory(const std::string& name) {
Handle handle;
CreateSharedMemory(handle, name);
@@ -67,39 +57,36 @@ Handle CreateSharedMemory(const std::string& name) {
* @param other_permissions Memory block map other permissions (specified by SVC field)
* @return Result of operation, 0 on success, otherwise error code
*/
-Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
+ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
MemoryPermission other_permissions) {
if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
handle, address);
- return -1;
+ return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
+ ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
}
- SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
- _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle);
+ SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle);
+ if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
shared_memory->base_address = address;
shared_memory->permissions = permissions;
shared_memory->other_permissions = other_permissions;
- return 0;
+ return RESULT_SUCCESS;
}
-/**
- * Gets a pointer to the shared memory block
- * @param handle Shared memory block handle
- * @param offset Offset from the start of the shared memory block to get pointer
- * @return Pointer to the shared memory block from the specified offset
- */
-u8* GetSharedMemoryPointer(Handle handle, u32 offset) {
- SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
- _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle);
+ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) {
+ SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle);
+ if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
if (0 != shared_memory->base_address)
- return Memory::GetPointer(shared_memory->base_address + offset);
+ return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset));
ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle);
- return nullptr;
+ // TODO(yuriks): Verify error code.
+ return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
+ ErrorSummary::InvalidState, ErrorLevel::Permanent);
}
} // namespace
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 5312b885..304cf5b6 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
@@ -32,9 +32,8 @@ Handle CreateSharedMemory(const std::string& name="Unknown");
* @param address Address in system memory to map shared memory block to
* @param permissions Memory block map permissions (specified by SVC field)
* @param other_permissions Memory block map other permissions (specified by SVC field)
- * @return Result of operation, 0 on success, otherwise error code
*/
-Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
+ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions,
MemoryPermission other_permissions);
/**
@@ -43,6 +42,6 @@ Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
* @param offset Offset from the start of the shared memory block to get pointer
* @return Pointer to the shared memory block from the specified offset
*/
-u8* GetSharedMemoryPointer(Handle handle, u32 offset);
+ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset);
} // namespace
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index e15590c4..f5979590 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project / PPSSPP Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include <algorithm>
#include <list>
@@ -11,10 +11,11 @@
#include "common/thread_queue_list.h"
#include "core/core.h"
-#include "core/mem_map.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h"
+#include "core/hle/result.h"
+#include "core/mem_map.h"
namespace Kernel {
@@ -33,21 +34,17 @@ public:
inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; }
inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; }
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
- if (status != THREADSTATUS_DORMANT) {
+ ResultVal<bool> WaitSynchronization() override {
+ const bool wait = status != THREADSTATUS_DORMANT;
+ if (wait) {
Handle thread = GetCurrentThreadHandle();
if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
waiting_threads.push_back(thread);
}
WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle());
- *wait = true;
}
- return 0;
+
+ return MakeResult<bool>(wait);
}
ThreadContext context;
@@ -71,17 +68,17 @@ public:
};
// Lists all thread ids that aren't deleted/etc.
-std::vector<Handle> g_thread_queue;
+static std::vector<Handle> thread_queue;
// Lists only ready thread ids.
-Common::ThreadQueueList<Handle> g_thread_ready_queue;
+static Common::ThreadQueueList<Handle> thread_ready_queue;
-Handle g_current_thread_handle;
-Thread* g_current_thread;
+static Handle current_thread_handle;
+static Thread* current_thread;
/// Gets the current thread
inline Thread* GetCurrentThread() {
- return g_current_thread;
+ return current_thread;
}
/// Gets the current thread handle
@@ -91,8 +88,8 @@ Handle GetCurrentThreadHandle() {
/// Sets the current thread
inline void SetCurrentThread(Thread* t) {
- g_current_thread = t;
- g_current_thread_handle = t->GetHandle();
+ current_thread = t;
+ current_thread_handle = t->GetHandle();
}
/// Saves the current CPU context
@@ -113,7 +110,7 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) {
t->context.pc = t->context.reg_15 = t->entry_point;
t->context.sp = t->stack_top;
t->context.cpsr = 0x1F; // Usermode
-
+
// TODO(bunnei): This instructs the CPU core to start the execution as if it is "resuming" a
// thread. This is somewhat Sky-Eye specific, and should be re-architected in the future to be
// agnostic of the CPU core.
@@ -131,40 +128,35 @@ void ChangeReadyState(Thread* t, bool ready) {
Handle handle = t->GetHandle();
if (t->IsReady()) {
if (!ready) {
- g_thread_ready_queue.remove(t->current_priority, handle);
+ thread_ready_queue.remove(t->current_priority, handle);
}
} else if (ready) {
if (t->IsRunning()) {
- g_thread_ready_queue.push_front(t->current_priority, handle);
+ thread_ready_queue.push_front(t->current_priority, handle);
} else {
- g_thread_ready_queue.push_back(t->current_priority, handle);
+ thread_ready_queue.push_back(t->current_priority, handle);
}
t->status = THREADSTATUS_READY;
}
}
/// Verify that a thread has not been released from waiting
-inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) {
- Thread* thread = g_object_pool.GetFast<Thread>(handle);
- _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
-
- if (type != thread->wait_type || wait_handle != thread->wait_handle)
- return false;
-
- return true;
+inline bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) {
+ _dbg_assert_(KERNEL, thread != nullptr);
+ return (type == thread->wait_type) && (wait_handle == thread->wait_handle) && (thread->IsWaiting());
}
/// Stops the current thread
-void StopThread(Handle handle, const char* reason) {
- Thread* thread = g_object_pool.GetFast<Thread>(handle);
- _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
-
+ResultCode StopThread(Handle handle, const char* reason) {
+ Thread* thread = g_object_pool.Get<Thread>(handle);
+ if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
+
ChangeReadyState(thread, false);
thread->status = THREADSTATUS_DORMANT;
- for (size_t i = 0; i < thread->waiting_threads.size(); ++i) {
- const Handle waiting_thread = thread->waiting_threads[i];
+ for (Handle waiting_handle : thread->waiting_threads) {
+ Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle);
if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) {
- ResumeThreadFromWait(waiting_thread);
+ ResumeThreadFromWait(waiting_handle);
}
}
thread->waiting_threads.clear();
@@ -172,6 +164,8 @@ void StopThread(Handle handle, const char* reason) {
// Stopped threads are never waiting.
thread->wait_type = WAITTYPE_NONE;
thread->wait_handle = 0;
+
+ return RESULT_SUCCESS;
}
/// Changes a threads state
@@ -181,7 +175,7 @@ void ChangeThreadState(Thread* t, ThreadStatus new_status) {
}
ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0);
t->status = new_status;
-
+
if (new_status == THREADSTATUS_WAIT) {
if (t->wait_type == WAITTYPE_NONE) {
ERROR_LOG(KERNEL, "Waittype none not allowed");
@@ -195,13 +189,15 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
s32 priority = THREADPRIO_LOWEST;
// Iterate through threads, find highest priority thread that is waiting to be arbitrated...
- for (const auto& handle : g_thread_queue) {
+ for (Handle handle : thread_queue) {
+ Thread* thread = g_object_pool.Get<Thread>(handle);
// TODO(bunnei): Verify arbiter address...
- if (!VerifyWait(handle, WAITTYPE_ARB, arbiter))
+ if (!VerifyWait(thread, WAITTYPE_ARB, arbiter))
continue;
- Thread* thread = g_object_pool.GetFast<Thread>(handle);
+ if (thread == nullptr)
+ continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
if(thread->current_priority <= priority) {
highest_priority_thread = handle;
priority = thread->current_priority;
@@ -216,12 +212,13 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
/// Arbitrate all threads currently waiting
void ArbitrateAllThreads(u32 arbiter, u32 address) {
-
+
// Iterate through threads, find highest priority thread that is waiting to be arbitrated...
- for (const auto& handle : g_thread_queue) {
+ for (Handle handle : thread_queue) {
+ Thread* thread = g_object_pool.Get<Thread>(handle);
// TODO(bunnei): Verify arbiter address...
- if (VerifyWait(handle, WAITTYPE_ARB, arbiter))
+ if (VerifyWait(thread, WAITTYPE_ARB, arbiter))
ResumeThreadFromWait(handle);
}
}
@@ -238,11 +235,11 @@ void CallThread(Thread* t) {
/// Switches CPU context to that of the specified thread
void SwitchContext(Thread* t) {
Thread* cur = GetCurrentThread();
-
+
// Save context for current thread
if (cur) {
SaveContext(cur->context);
-
+
if (cur->IsRunning()) {
ChangeReadyState(cur, true);
}
@@ -263,16 +260,16 @@ void SwitchContext(Thread* t) {
Thread* NextThread() {
Handle next;
Thread* cur = GetCurrentThread();
-
+
if (cur && cur->IsRunning()) {
- next = g_thread_ready_queue.pop_first_better(cur->current_priority);
+ next = thread_ready_queue.pop_first_better(cur->current_priority);
} else {
- next = g_thread_ready_queue.pop_first();
+ next = thread_ready_queue.pop_first();
}
if (next == 0) {
return nullptr;
}
- return Kernel::g_object_pool.GetFast<Thread>(next);
+ return Kernel::g_object_pool.Get<Thread>(next);
}
/**
@@ -289,8 +286,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
/// Resumes a thread from waiting by marking it as "ready"
void ResumeThreadFromWait(Handle handle) {
- u32 error;
- Thread* thread = Kernel::g_object_pool.Get<Thread>(handle, error);
+ Thread* thread = Kernel::g_object_pool.Get<Thread>(handle);
if (thread) {
thread->status &= ~THREADSTATUS_WAIT;
if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
@@ -306,9 +302,9 @@ void DebugThreadQueue() {
return;
}
INFO_LOG(KERNEL, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThreadHandle());
- for (u32 i = 0; i < g_thread_queue.size(); i++) {
- Handle handle = g_thread_queue[i];
- s32 priority = g_thread_ready_queue.contains(handle);
+ for (u32 i = 0; i < thread_queue.size(); i++) {
+ Handle handle = thread_queue[i];
+ s32 priority = thread_ready_queue.contains(handle);
if (priority != -1) {
INFO_LOG(KERNEL, "0x%02X 0x%08X", priority, handle);
}
@@ -319,15 +315,15 @@ void DebugThreadQueue() {
Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority,
s32 processor_id, u32 stack_top, int stack_size) {
- _assert_msg_(KERNEL, (priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST),
+ _assert_msg_(KERNEL, (priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST),
"CreateThread priority=%d, outside of allowable range!", priority)
Thread* thread = new Thread;
handle = Kernel::g_object_pool.Create(thread);
- g_thread_queue.push_back(handle);
- g_thread_ready_queue.prepare(priority);
+ thread_queue.push_back(handle);
+ thread_ready_queue.prepare(priority);
thread->status = THREADSTATUS_DORMANT;
thread->entry_point = entry_point;
@@ -351,7 +347,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
return -1;
}
if ((u32)stack_size < 0x200) {
- ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid stack_size=0x%08X", name,
+ ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid stack_size=0x%08X", name,
stack_size);
return -1;
}
@@ -368,7 +364,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
return -1;
}
Handle handle;
- Thread* thread = CreateThread(handle, name, entry_point, priority, processor_id, stack_top,
+ Thread* thread = CreateThread(handle, name, entry_point, priority, processor_id, stack_top,
stack_size);
ResetThread(thread, arg, 0);
@@ -378,19 +374,23 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
}
/// Get the priority of the thread specified by handle
-u32 GetThreadPriority(const Handle handle) {
- Thread* thread = g_object_pool.GetFast<Thread>(handle);
- _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
- return thread->current_priority;
+ResultVal<u32> GetThreadPriority(const Handle handle) {
+ Thread* thread = g_object_pool.Get<Thread>(handle);
+ if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
+
+ return MakeResult<u32>(thread->current_priority);
}
/// Set the priority of the thread specified by handle
-Result SetThreadPriority(Handle handle, s32 priority) {
+ResultCode SetThreadPriority(Handle handle, s32 priority) {
Thread* thread = nullptr;
if (!handle) {
thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior?
} else {
- thread = g_object_pool.GetFast<Thread>(handle);
+ thread = g_object_pool.Get<Thread>(handle);
+ if (thread == nullptr) {
+ return InvalidHandle(ErrorModule::Kernel);
+ }
}
_assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
@@ -405,37 +405,37 @@ Result SetThreadPriority(Handle handle, s32 priority) {
// Change thread priority
s32 old = thread->current_priority;
- g_thread_ready_queue.remove(old, handle);
+ thread_ready_queue.remove(old, handle);
thread->current_priority = priority;
- g_thread_ready_queue.prepare(thread->current_priority);
+ thread_ready_queue.prepare(thread->current_priority);
// Change thread status to "ready" and push to ready queue
if (thread->IsRunning()) {
thread->status = (thread->status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY;
}
if (thread->IsReady()) {
- g_thread_ready_queue.push_back(thread->current_priority, handle);
+ thread_ready_queue.push_back(thread->current_priority, handle);
}
- return 0;
+ return RESULT_SUCCESS;
}
/// Sets up the primary application thread
Handle SetupMainThread(s32 priority, int stack_size) {
Handle handle;
-
+
// Initialize new "main" thread
- Thread* thread = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority,
+ Thread* thread = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority,
THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size);
-
+
ResetThread(thread, 0, 0);
-
+
// If running another thread already, set it to "ready" state
Thread* cur = GetCurrentThread();
if (cur && cur->IsRunning()) {
ChangeReadyState(cur, true);
}
-
+
// Run new "main" thread
SetCurrentThread(thread);
thread->status = THREADSTATUS_RUNNING;
@@ -452,12 +452,12 @@ void Reschedule() {
HLE::g_reschedule = false;
if (next > 0) {
INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle());
-
+
SwitchContext(next);
// Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep
// by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again.
- // This results in the current thread yielding on a VBLANK once, and then it will be
+ // This results in the current thread yielding on a VBLANK once, and then it will be
// immediately placed back in the queue for execution.
if (prev->wait_type == WAITTYPE_VBLANK) {
ResumeThreadFromWait(prev->GetHandle());
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 39fa38b7..ce63a70d 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -1,11 +1,12 @@
// Copyright 2014 Citra Emulator Project / PPSSPP Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/result.h"
enum ThreadPriority {
THREADPRIO_HIGHEST = 0, ///< Highest thread priority
@@ -55,7 +56,7 @@ Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE);
void Reschedule();
/// Stops the current thread
-void StopThread(Handle thread, const char* reason);
+ResultCode StopThread(Handle thread, const char* reason);
/// Resumes a thread from waiting by marking it as "ready"
void ResumeThreadFromWait(Handle handle);
@@ -80,10 +81,10 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHa
void WaitThread_Synchronization();
/// Get the priority of the thread specified by handle
-u32 GetThreadPriority(const Handle handle);
+ResultVal<u32> GetThreadPriority(const Handle handle);
/// Set the priority of the thread specified by handle
-Result SetThreadPriority(Handle handle, s32 priority);
+ResultCode SetThreadPriority(Handle handle, s32 priority);
/// Initialize threading
void ThreadingInit();
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
new file mode 100644
index 00000000..15c4a267
--- /dev/null
+++ b/src/core/hle/result.h
@@ -0,0 +1,400 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <cassert>
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+#include "common/common_types.h"
+#include "common/bit_field.h"
+
+// All the constants in this file come from http://3dbrew.org/wiki/Error_codes
+
+/// Detailed description of the error. This listing is likely incomplete.
+enum class ErrorDescription : u32 {
+ Success = 0,
+ InvalidSection = 1000,
+ TooLarge = 1001,
+ NotAuthorized = 1002,
+ AlreadyDone = 1003,
+ InvalidSize = 1004,
+ InvalidEnumValue = 1005,
+ InvalidCombination = 1006,
+ NoData = 1007,
+ Busy = 1008,
+ MisalignedAddress = 1009,
+ MisalignedSize = 1010,
+ OutOfMemory = 1011,
+ NotImplemented = 1012,
+ InvalidAddress = 1013,
+ InvalidPointer = 1014,
+ InvalidHandle = 1015,
+ NotInitialized = 1016,
+ AlreadyInitialized = 1017,
+ NotFound = 1018,
+ CancelRequested = 1019,
+ AlreadyExists = 1020,
+ OutOfRange = 1021,
+ Timeout = 1022,
+ InvalidResultValue = 1023,
+};
+
+/**
+ * Identifies the module which caused the error. Error codes can be propagated through a call
+ * chain, meaning that this doesn't always correspond to the module where the API call made is
+ * contained.
+ */
+enum class ErrorModule : u32 {
+ Common = 0,
+ Kernel = 1,
+ Util = 2,
+ FileServer = 3,
+ LoaderServer = 4,
+ TCB = 5,
+ OS = 6,
+ DBG = 7,
+ DMNT = 8,
+ PDN = 9,
+ GX = 10,
+ I2C = 11,
+ GPIO = 12,
+ DD = 13,
+ CODEC = 14,
+ SPI = 15,
+ PXI = 16,
+ FS = 17,
+ DI = 18,
+ HID = 19,
+ CAM = 20,
+ PI = 21,
+ PM = 22,
+ PM_LOW = 23,
+ FSI = 24,
+ SRV = 25,
+ NDM = 26,
+ NWM = 27,
+ SOC = 28,
+ LDR = 29,
+ ACC = 30,
+ RomFS = 31,
+ AM = 32,
+ HIO = 33,
+ Updater = 34,
+ MIC = 35,
+ FND = 36,
+ MP = 37,
+ MPWL = 38,
+ AC = 39,
+ HTTP = 40,
+ DSP = 41,
+ SND = 42,
+ DLP = 43,
+ HIO_LOW = 44,
+ CSND = 45,
+ SSL = 46,
+ AM_LOW = 47,
+ NEX = 48,
+ Friends = 49,
+ RDT = 50,
+ Applet = 51,
+ NIM = 52,
+ PTM = 53,
+ MIDI = 54,
+ MC = 55,
+ SWC = 56,
+ FatFS = 57,
+ NGC = 58,
+ CARD = 59,
+ CARDNOR = 60,
+ SDMC = 61,
+ BOSS = 62,
+ DBM = 63,
+ Config = 64,
+ PS = 65,
+ CEC = 66,
+ IR = 67,
+ UDS = 68,
+ PL = 69,
+ CUP = 70,
+ Gyroscope = 71,
+ MCU = 72,
+ NS = 73,
+ News = 74,
+ RO_1 = 75,
+ GD = 76,
+ CardSPI = 77,
+ EC = 78,
+ RO_2 = 79,
+ WebBrowser = 80,
+ Test = 81,
+ ENC = 82,
+ PIA = 83,
+
+ Application = 254,
+ InvalidResult = 255
+};
+
+/// A less specific error cause.
+enum class ErrorSummary : u32 {
+ Success = 0,
+ NothingHappened = 1,
+ WouldBlock = 2,
+ OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to
+ ///< execute the operation.
+ NotFound = 4, ///< A file or resource was not found.
+ InvalidState = 5,
+ NotSupported = 6, ///< The operation is not supported or not implemented.
+ InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime
+ ///< context. (Invalid handle, out-of-bounds pointer or size, etc.)
+ WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use
+ ///< with the function. (E.g. Invalid enum value)
+ Canceled = 9,
+ StatusChanged = 10,
+ Internal = 11,
+
+ InvalidResult = 63
+};
+
+/// The severity of the error.
+enum class ErrorLevel : u32 {
+ Success = 0,
+ Info = 1,
+
+ Status = 25,
+ Temporary = 26,
+ Permanent = 27,
+ Usage = 28,
+ Reinitialize = 29,
+ Reset = 30,
+ Fatal = 31
+};
+
+/// Encapsulates a CTR-OS error code, allowing it to be separated into its constituent fields.
+union ResultCode {
+ u32 raw;
+
+ BitField<0, 10, ErrorDescription> description;
+ BitField<10, 8, ErrorModule> module;
+
+ BitField<21, 6, ErrorSummary> summary;
+ BitField<27, 5, ErrorLevel> level;
+
+ // The last bit of `level` is checked by apps and the kernel to determine if a result code is an error
+ BitField<31, 1, u32> is_error;
+
+ explicit ResultCode(u32 raw) : raw(raw) {}
+ ResultCode(ErrorDescription description_, ErrorModule module_,
+ ErrorSummary summary_, ErrorLevel level_) : raw(0) {
+ description = description_;
+ module = module_;
+ summary = summary_;
+ level = level_;
+ }
+
+ ResultCode& operator=(const ResultCode& o) { raw = o.raw; return *this; }
+
+ bool IsSuccess() const {
+ return is_error == 0;
+ }
+
+ bool IsError() const {
+ return is_error == 1;
+ }
+};
+
+inline bool operator==(const ResultCode a, const ResultCode b) {
+ return a.raw == b.raw;
+}
+
+inline bool operator!=(const ResultCode a, const ResultCode b) {
+ return a.raw != b.raw;
+}
+
+// Convenience functions for creating some common kinds of errors:
+
+/// The default success `ResultCode`.
+const ResultCode RESULT_SUCCESS(0);
+
+/// Might be returned instead of a dummy success for unimplemented APIs.
+inline ResultCode UnimplementedFunction(ErrorModule module) {
+ return ResultCode(ErrorDescription::NotImplemented, module,
+ ErrorSummary::NotSupported, ErrorLevel::Permanent);
+}
+/// Returned when a function is passed an invalid handle.
+inline ResultCode InvalidHandle(ErrorModule module) {
+ return ResultCode(ErrorDescription::InvalidHandle, module,
+ ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
+}
+
+/**
+ * This is an optional value type. It holds a `ResultCode` and, if that code is a success code,
+ * also holds a result of type `T`. If the code is an error code then trying to access the inner
+ * value fails, thus ensuring that the ResultCode of functions is always checked properly before
+ * their return value is used. It is similar in concept to the `std::optional` type
+ * (http://en.cppreference.com/w/cpp/experimental/optional) originally proposed for inclusion in
+ * C++14, or the `Result` type in Rust (http://doc.rust-lang.org/std/result/index.html).
+ *
+ * An example of how it could be used:
+ * \code
+ * ResultVal<int> Frobnicate(float strength) {
+ * if (strength < 0.f || strength > 1.0f) {
+ * // Can't frobnicate too weakly or too strongly
+ * return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Common,
+ * ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
+ * } else {
+ * // Frobnicated! Give caller a cookie
+ * return MakeResult<int>(42);
+ * }
+ * }
+ * \endcode
+ *
+ * \code
+ * ResultVal<int> frob_result = Frobnicate(0.75f);
+ * if (frob_result) {
+ * // Frobbed ok
+ * printf("My cookie is %d\n", *frob_result);
+ * } else {
+ * printf("Guess I overdid it. :( Error code: %ux\n", frob_result.code().hex);
+ * }
+ * \endcode
+ */
+template <typename T>
+class ResultVal {
+public:
+ /// Constructs an empty `ResultVal` with the given error code. The code must not be a success code.
+ ResultVal(ResultCode error_code = ResultCode(-1))
+ : result_code(error_code)
+ {
+ assert(error_code.IsError());
+ UpdateDebugPtr();
+ }
+
+ /**
+ * Similar to the non-member function `MakeResult`, with the exception that you can manually
+ * specify the success code. `success_code` must not be an error code.
+ */
+ template <typename... Args>
+ static ResultVal WithCode(ResultCode success_code, Args&&... args) {
+ ResultVal<T> result;
+ result.emplace(success_code, std::forward<Args>(args)...);
+ return result;
+ }
+
+ ResultVal(const ResultVal& o)
+ : result_code(o.result_code)
+ {
+ if (!o.empty()) {
+ new (&storage) T(*o.GetPointer());
+ }
+ UpdateDebugPtr();
+ }
+
+ ResultVal(ResultVal&& o)
+ : result_code(o.result_code)
+ {
+ if (!o.empty()) {
+ new (&storage) T(std::move(*o.GetPointer()));
+ }
+ UpdateDebugPtr();
+ }
+
+ ~ResultVal() {
+ if (!empty()) {
+ GetPointer()->~T();
+ }
+ }
+
+ ResultVal& operator=(const ResultVal& o) {
+ if (*this) {
+ if (o) {
+ *GetPointer() = *o.GetPointer();
+ } else {
+ GetPointer()->~T();
+ }
+ } else {
+ if (o) {
+ new (&storage) T(*o.GetPointer());
+ }
+ }
+ result_code = o.result_code;
+ UpdateDebugPtr();
+
+ return *this;
+ }
+
+ /**
+ * Replaces the current result with a new constructed result value in-place. The code must not
+ * be an error code.
+ */
+ template <typename... Args>
+ void emplace(ResultCode success_code, Args&&... args) {
+ assert(success_code.IsSuccess());
+ if (!empty()) {
+ GetPointer()->~T();
+ }
+ new (&storage) T(std::forward<Args>(args)...);
+ result_code = success_code;
+ UpdateDebugPtr();
+ }
+
+ /// Returns true if the `ResultVal` contains an error code and no value.
+ bool empty() const { return result_code.IsError(); }
+
+ /// Returns true if the `ResultVal` contains a return value.
+ bool Succeeded() const { return result_code.IsSuccess(); }
+ /// Returns true if the `ResultVal` contains an error code and no value.
+ bool Failed() const { return empty(); }
+
+ ResultCode Code() const { return result_code; }
+
+ const T& operator* () const { return *GetPointer(); }
+ T& operator* () { return *GetPointer(); }
+ const T* operator->() const { return GetPointer(); }
+ T* operator->() { return GetPointer(); }
+
+ /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
+ template <typename U>
+ T ValueOr(U&& value) const {
+ return !empty() ? *GetPointer() : std::move(value);
+ }
+
+private:
+ typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType;
+
+ StorageType storage;
+ ResultCode result_code;
+#if _DEBUG
+ // The purpose of this pointer is to aid inspecting the type with a debugger, eliminating the
+ // need to cast `storage` to a pointer or pay attention to `result_code`.
+ const T* debug_ptr;
+#endif
+
+ void UpdateDebugPtr() {
+#if _DEBUG
+ debug_ptr = empty() ? nullptr : static_cast<const T*>(static_cast<const void*>(&storage));
+#endif
+ }
+
+ const T* GetPointer() const {
+ assert(!empty());
+ return static_cast<const T*>(static_cast<const void*>(&storage));
+ }
+
+ T* GetPointer() {
+ assert(!empty());
+ return static_cast<T*>(static_cast<void*>(&storage));
+ }
+};
+
+/**
+ * This function is a helper used to construct `ResultVal`s. It receives the arguments to construct
+ * `T` with and creates a success `ResultVal` contained the constructed value.
+ */
+template <typename T, typename... Args>
+ResultVal<T> MakeResult(Args&&... args) {
+ return ResultVal<T>::WithCode(RESULT_SUCCESS, std::forward<Args>(args)...);
+}
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index b39603bd..9af96f6b 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[] = {
{0x000E0042, nullptr, "GetCurrentAPInfo"},
{0x00100042, nullptr, "GetCurrentNZoneInfo"},
{0x00110042, nullptr, "GetNZoneApNumService"},
- {0x00240042, nullptr, "AddDenyApType "},
- {0x00270002, nullptr, "GetInfraPriority "},
+ {0x00240042, nullptr, "AddDenyApType"},
+ {0x00270002, nullptr, "GetInfraPriority"},
{0x002D0082, nullptr, "SetRequestEulaVersion"},
{0x00300004, nullptr, "RegisterDisconnectEvent"},
{0x003C0042, nullptr, "GetAPSSIDList"},
- {0x003E0042, nullptr, "IsConnected "},
+ {0x003E0042, nullptr, "IsConnected"},
{0x00400042, nullptr, "SetClientVersion"},
};
diff --git a/src/core/hle/service/ac_u.h b/src/core/hle/service/ac_u.h
index 3c5958d2..c91b2835 100644
--- a/src/core/hle/service/ac_u.h
+++ b/src/core/hle/service/ac_u.h
@@ -9,7 +9,7 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace AC_U
-// socket service "ac:u"
+// socket service "ac:u"
namespace AC_U {
@@ -21,7 +21,7 @@ public:
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "ac:u";
}
};
diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am_net.cpp
new file mode 100644
index 00000000..403cac35
--- /dev/null
+++ b/src/core/hle/service/am_net.cpp
@@ -0,0 +1,47 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/am_net.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace AM_NET
+
+namespace AM_NET {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x08010000, nullptr, "OpenTicket"},
+ {0x08020002, nullptr, "TicketAbortInstall"},
+ {0x08030002, nullptr, "TicketFinalizeInstall"},
+ {0x08040100, nullptr, "InstallTitleBegin"},
+ {0x08050000, nullptr, "InstallTitleAbort"},
+ {0x080600C0, nullptr, "InstallTitleResume"},
+ {0x08070000, nullptr, "InstallTitleAbortTMD"},
+ {0x08080000, nullptr, "InstallTitleFinish"},
+ {0x080A0000, nullptr, "OpenTMD"},
+ {0x080B0002, nullptr, "TMDAbortInstall"},
+ {0x080C0042, nullptr, "TMDFinalizeInstall"},
+ {0x080E0040, nullptr, "OpenContentCreate"},
+ {0x080F0002, nullptr, "ContentAbortInstall"},
+ {0x08100040, nullptr, "OpenContentResume"},
+ {0x08120002, nullptr, "ContentFinalizeInstall"},
+ {0x08130000, nullptr, "GetTotalContents"},
+ {0x08140042, nullptr, "GetContentIndexes"},
+ {0x08150044, nullptr, "GetContentsInfo"},
+ {0x08190108, nullptr, "Unknown"},
+ {0x081B00C2, nullptr, "InstallTitlesFinish"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+}
+
+Interface::~Interface() {
+}
+
+} // namespace
diff --git a/src/core/hle/service/am_net.h b/src/core/hle/service/am_net.h
new file mode 100644
index 00000000..4816e169
--- /dev/null
+++ b/src/core/hle/service/am_net.h
@@ -0,0 +1,27 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace AM_NET
+
+namespace AM_NET {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+ ~Interface();
+ /**
+ * Gets the string port name used by CTROS for the service
+ * @return Port name of service
+ */
+ std::string GetPortName() const override {
+ return "am:net";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 4f41ec5f..4bb05ce4 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 {
void Initialize(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
-
+
cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Menu"); // APT menu event handle
cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); // APT pause event handle
@@ -168,7 +168,7 @@ void AppletUtility(Service::Interface* self) {
cmd_buff[1] = 0; // No error
WARN_LOG(KERNEL, "(STUBBED) called unk=0x%08X, buffer1_size=0x%08x, buffer2_size=0x%08x, "
- "buffer1_addr=0x%08x, buffer2_addr=0x%08x", unk, buffer1_size, buffer2_size,
+ "buffer1_addr=0x%08x, buffer2_addr=0x%08x", unk, buffer1_size, buffer2_size,
buffer1_addr, buffer2_addr);
}
diff --git a/src/core/hle/service/apt_u.h b/src/core/hle/service/apt_u.h
index 5af39e08..30673040 100644
--- a/src/core/hle/service/apt_u.h
+++ b/src/core/hle/service/apt_u.h
@@ -13,8 +13,8 @@ namespace APT_U {
// Application and title launching service. These services handle signaling for home/power button as
// well. Only one session for either APT service can be open at a time, normally processes close the
-// service handle immediately once finished using the service. The commands for APT:U and APT:S are
-// exactly the same, however certain commands are only accessible with APT:S(NS module will call
+// service handle immediately once finished using the service. The commands for APT:U and APT:S are
+// exactly the same, however certain commands are only accessible with APT:S(NS module will call
// svcBreak when the command isn't accessible). See http://3dbrew.org/wiki/NS#APT_Services.
/// 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 00000000..b2ff4a75
--- /dev/null
+++ b/src/core/hle/service/boss_u.cpp
@@ -0,0 +1,28 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/boss_u.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace BOSS_U
+
+namespace BOSS_U {
+
+ const Interface::FunctionInfo FunctionTable[] = {
+ {0x00020100, nullptr, "GetStorageInfo"},
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Interface class
+
+ Interface::Interface() {
+ Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ }
+
+ Interface::~Interface() {
+ }
+
+} // namespace
diff --git a/src/core/hle/service/boss_u.h b/src/core/hle/service/boss_u.h
new file mode 100644
index 00000000..af39b8e6
--- /dev/null
+++ b/src/core/hle/service/boss_u.h
@@ -0,0 +1,27 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace BOSS_U
+
+namespace BOSS_U {
+
+ class Interface : public Service::Interface {
+ public:
+ Interface();
+ ~Interface();
+ /**
+ * Gets the string port name used by CTROS for the service
+ * @return Port name of service
+ */
+ std::string GetPortName() const {
+ return "boss:U";
+ }
+ };
+
+} // namespace
diff --git a/src/core/hle/service/cfg_i.cpp b/src/core/hle/service/cfg_i.cpp
new file mode 100644
index 00000000..88d13d45
--- /dev/null
+++ b/src/core/hle/service/cfg_i.cpp
@@ -0,0 +1,59 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/cfg_i.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CFG_I
+
+namespace CFG_I {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x04010082, nullptr, "GetConfigInfoBlk8"},
+ {0x04020082, nullptr, "GetConfigInfoBlk4"},
+ {0x04030000, nullptr, "UpdateConfigNANDSavegame"},
+ {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
+ {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
+ {0x04060000, nullptr, "SecureInfoGetRegion"},
+ {0x04070000, nullptr, "SecureInfoGetByte101"},
+ {0x04080042, nullptr, "SecureInfoGetSerialNo"},
+ {0x04090000, nullptr, "UpdateConfigBlk00040003"},
+ {0x08010082, nullptr, "GetConfigInfoBlk8"},
+ {0x08020082, nullptr, "GetConfigInfoBlk4"},
+ {0x08030000, nullptr, "UpdateConfigNANDSavegame"},
+ {0x080400C2, nullptr, "CreateConfigInfoBlk"},
+ {0x08050000, nullptr, "DeleteConfigNANDSavefile"},
+ {0x08060000, nullptr, "FormatConfig"},
+ {0x08070000, nullptr, "Unknown"},
+ {0x08080000, nullptr, "UpdateConfigBlk1"},
+ {0x08090000, nullptr, "UpdateConfigBlk2"},
+ {0x080A0000, nullptr, "UpdateConfigBlk3"},
+ {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"},
+ {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"},
+ {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"},
+ {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"},
+ {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"},
+ {0x08100000, nullptr, "GetLocalFriendCodeSeed"},
+ {0x08110084, nullptr, "SetSecureInfo"},
+ {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"},
+ {0x08130000, nullptr, "VerifySigSecureInfo"},
+ {0x08140042, nullptr, "SecureInfoGetData"},
+ {0x08150042, nullptr, "SecureInfoGetSignature"},
+ {0x08160000, nullptr, "SecureInfoGetRegion"},
+ {0x08170000, nullptr, "SecureInfoGetByte101"},
+ {0x08180042, nullptr, "SecureInfoGetSerialNo"},
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+}
+
+Interface::~Interface() {
+}
+
+} // namespace
diff --git a/src/core/hle/service/cfg_i.h b/src/core/hle/service/cfg_i.h
new file mode 100644
index 00000000..fe343c96
--- /dev/null
+++ b/src/core/hle/service/cfg_i.h
@@ -0,0 +1,27 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CFG_I
+
+namespace CFG_I {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+ ~Interface();
+ /**
+ * Gets the string port name used by CTROS for the service
+ * @return Port name of service
+ */
+ std::string GetPortName() const override {
+ return "cfg:i";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/cfg_u.h b/src/core/hle/service/cfg_u.h
index 7525bd7c..8075d19a 100644
--- a/src/core/hle/service/cfg_u.h
+++ b/src/core/hle/service/cfg_u.h
@@ -19,7 +19,7 @@ public:
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "cfg:u";
}
};
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
new file mode 100644
index 00000000..6e59a9bf
--- /dev/null
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -0,0 +1,39 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/csnd_snd.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CSND_SND
+
+namespace CSND_SND {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010140, nullptr, "Initialize"},
+ {0x00020000, nullptr, "Shutdown"},
+ {0x00030040, nullptr, "Unknown"},
+ {0x00040080, nullptr, "Unknown"},
+ {0x00050000, nullptr, "Unknown"},
+ {0x00060000, nullptr, "Unknown"},
+ {0x00070000, nullptr, "Unknown"},
+ {0x00080040, nullptr, "Unknown"},
+ {0x00090082, nullptr, "FlushDCache"},
+ {0x000A0082, nullptr, "StoreDCache"},
+ {0x000B0082, nullptr, "InvalidateDCache"},
+ {0x000C0000, nullptr, "Unknown"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+}
+
+Interface::~Interface() {
+}
+
+} // namespace
diff --git a/src/core/hle/service/csnd_snd.h b/src/core/hle/service/csnd_snd.h
new file mode 100644
index 00000000..31cc85b0
--- /dev/null
+++ b/src/core/hle/service/csnd_snd.h
@@ -0,0 +1,27 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CSND_SND
+
+namespace CSND_SND {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+ ~Interface();
+ /**
+ * Gets the string port name used by CTROS for the service
+ * @return Port name of service
+ */
+ std::string GetPortName() const override {
+ return "csnd:SND";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index 9e84ac93..bbcf26f6 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[] = {
{0x001100C2, nullptr, "LoadComponent"},
{0x00120000, nullptr, "UnloadComponent"},
{0x00130082, nullptr, "FlushDataCache"},
- {0x00140082, nullptr, "InvalidateDCache "},
+ {0x00140082, nullptr, "InvalidateDCache"},
{0x00150082, nullptr, "RegisterInterruptEvents"},
{0x00160000, nullptr, "GetSemaphoreEventHandle"},
{0x00170040, nullptr, "SetSemaphoreMask"},
{0x00180040, nullptr, "GetPhysicalAddress"},
- {0x00190040, nullptr, "GetVirtualAddress" },
+ {0x00190040, nullptr, "GetVirtualAddress"},
{0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
{0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
{0x001C0082, nullptr, "SetIirFilterEQ"},
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h
index c439ed26..c4ce4424 100644
--- a/src/core/hle/service/dsp_dsp.h
+++ b/src/core/hle/service/dsp_dsp.h
@@ -19,7 +19,7 @@ public:
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "dsp:DSP";
}
};
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 917b2f8c..785c351e 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -20,8 +20,8 @@ namespace ERR_F {
Interface::Interface() {
Register(FunctionTable, ARRAY_SIZE(FunctionTable));
}
-
+
Interface::~Interface() {
}
-
+
} // namespace
diff --git a/src/core/hle/service/err_f.h b/src/core/hle/service/err_f.h
index 5da66326..6d7141c1 100644
--- a/src/core/hle/service/err_f.h
+++ b/src/core/hle/service/err_f.h
@@ -19,9 +19,9 @@ namespace ERR_F {
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "err:f";
}
};
-
+
} // namespace
diff --git a/src/core/hle/service/frd_u.h b/src/core/hle/service/frd_u.h
index 9df8a815..4020c666 100644
--- a/src/core/hle/service/frd_u.h
+++ b/src/core/hle/service/frd_u.h
@@ -19,7 +19,7 @@ namespace FRD_U {
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "frd:u";
}
};
diff --git a/src/core/hle/service/fs_user.cpp b/src/core/hle/service/fs_user.cpp
index 9dc83291..34af78cb 100644
--- a/src/core/hle/service/fs_user.cpp
+++ b/src/core/hle/service/fs_user.cpp
@@ -4,31 +4,45 @@
#include "common/common.h"
-#include "fs_user.h"
#include "common/string_util.h"
-#include "core/settings.h"
#include "core/hle/kernel/archive.h"
+#include "core/hle/kernel/archive.h"
+#include "core/hle/result.h"
+#include "core/hle/service/fs_user.h"
+#include "core/settings.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace FS_User
namespace FS_User {
-// We currently return 0 for success and -1 for failure in cmd_buff[1]. -1 was chosen because it
-// puts all the sections of the http://3dbrew.org/wiki/Error_codes to something non-zero, to make
-// sure we don't mislead the application into thinking something worked.
-
-void Initialize(Service::Interface* self) {
+static void Initialize(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
// TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per
// http://3dbrew.org/wiki/FS:Initialize#Request
- cmd_buff[1] = 0;
+ cmd_buff[1] = RESULT_SUCCESS.raw;
DEBUG_LOG(KERNEL, "called");
}
-void OpenFile(Service::Interface* self) {
+/**
+ * FS_User::OpenFile service function
+ * Inputs:
+ * 1 : Transaction
+ * 2 : Archive handle lower word
+ * 3 : Archive handle upper word
+ * 4 : Low path type
+ * 5 : Low path size
+ * 6 : Open flags
+ * 7 : Attributes
+ * 8 : (LowPathSize << 14) | 2
+ * 9 : Low path data pointer
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 3 : File handle
+ */
+static void OpenFile(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
// 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) {
FileSys::Mode mode; mode.hex = cmd_buff[6];
u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes.
u32 filename_ptr = cmd_buff[9];
-
FileSys::Path file_path(filename_type, filename_size, filename_ptr);
- std::string file_string;
- switch (file_path.GetType()) {
- case FileSys::Char:
- case FileSys::Wchar:
- file_string = file_path.AsString();
- break;
- default:
- WARN_LOG(KERNEL, "file LowPath type is currently unsupported; returning archive handle instead");
- return;
- }
- DEBUG_LOG(KERNEL, "type=%d size=%d mode=%d attrs=%d data=%s",
- filename_type, filename_size, mode, attributes, file_string.c_str());
+ DEBUG_LOG(KERNEL, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
- Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_string, mode);
- if (handle) {
- cmd_buff[1] = 0;
- cmd_buff[3] = handle;
+ ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode);
+ cmd_buff[1] = handle.Code().raw;
+ if (handle.Succeeded()) {
+ cmd_buff[3] = *handle;
} else {
- ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_string.c_str());
- // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
- cmd_buff[1] = -1;
+ ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str());
}
DEBUG_LOG(KERNEL, "called");
}
-void OpenFileDirectly(Service::Interface* self) {
+/**
+ * FS_User::OpenFileDirectly service function
+ * Inputs:
+ * 1 : Transaction
+ * 2 : Archive ID
+ * 3 : Archive low path type
+ * 4 : Archive low path size
+ * 5 : File low path type
+ * 6 : File low path size
+ * 7 : Flags
+ * 8 : Attributes
+ * 9 : (ArchiveLowPathSize << 14) | 0x802
+ * 10 : Archive low path
+ * 11 : (FileLowPathSize << 14) | 2
+ * 12 : File low path
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 3 : File handle
+ */
+static void OpenFileDirectly(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]);
@@ -80,55 +99,103 @@ void OpenFileDirectly(Service::Interface* self) {
u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes.
u32 archivename_ptr = cmd_buff[10];
u32 filename_ptr = cmd_buff[12];
+ FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
+ FileSys::Path file_path(filename_type, filename_size, filename_ptr);
- DEBUG_LOG(KERNEL, "archive_type=%d archive_size=%d file_type=%d file_size=%d file_mode=%d file_attrs=%d",
- archivename_type, archivename_size, filename_type, filename_size, mode, attributes);
+ DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%u attributes=%d",
+ archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes);
- if (archivename_type != FileSys::Empty) {
+ if (archive_path.GetType() != FileSys::Empty) {
ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported");
- cmd_buff[1] = -1;
+ cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw;
return;
}
- // TODO(Link Mauve): check if we should even get a handle for the archive, and don't leak it.
- Handle archive_handle = Kernel::OpenArchive(archive_id);
- if (archive_handle) {
- cmd_buff[1] = 0;
- // cmd_buff[2] isn't used according to 3dmoo's implementation.
- cmd_buff[3] = archive_handle;
- } else {
+ // TODO(Link Mauve): Check if we should even get a handle for the archive, and don't leak it
+ // TODO(yuriks): Why is there all this duplicate (and seemingly useless) code up here?
+ ResultVal<Handle> archive_handle = Kernel::OpenArchive(archive_id);
+ cmd_buff[1] = archive_handle.Code().raw;
+ if (archive_handle.Failed()) {
ERROR_LOG(KERNEL, "failed to get a handle for archive");
- // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
- cmd_buff[1] = -1;
- return;
- }
-
- FileSys::Path file_path(filename_type, filename_size, filename_ptr);
- std::string file_string;
- switch (file_path.GetType()) {
- case FileSys::Char:
- case FileSys::Wchar:
- file_string = file_path.AsString();
- break;
- default:
- WARN_LOG(KERNEL, "file LowPath type is currently unsupported; returning archive handle instead");
return;
}
+ // cmd_buff[2] isn't used according to 3dmoo's implementation.
+ cmd_buff[3] = *archive_handle;
- Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_string, mode);
- if (handle) {
- cmd_buff[1] = 0;
- cmd_buff[3] = handle;
+ ResultVal<Handle> handle = Kernel::OpenFileFromArchive(*archive_handle, file_path, mode);
+ cmd_buff[1] = handle.Code().raw;
+ if (handle.Succeeded()) {
+ cmd_buff[3] = *handle;
} else {
- ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_string.c_str());
- // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
- cmd_buff[1] = -1;
+ ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str());
}
DEBUG_LOG(KERNEL, "called");
}
/*
+ * FS_User::DeleteFile service function
+ * Inputs:
+ * 2 : Archive handle lower word
+ * 3 : Archive handle upper word
+ * 4 : File path string type
+ * 5 : File path string size
+ * 7 : File path string data
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void DeleteFile(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
+ // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
+ Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
+ auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
+ u32 filename_size = cmd_buff[5];
+ u32 filename_ptr = cmd_buff[7];
+
+ FileSys::Path file_path(filename_type, filename_size, filename_ptr);
+
+ DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
+ filename_type, filename_size, file_path.DebugStr().c_str());
+
+ cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path);
+
+ DEBUG_LOG(KERNEL, "called");
+}
+
+/*
+ * FS_User::DeleteDirectory service function
+ * Inputs:
+ * 2 : Archive handle lower word
+ * 3 : Archive handle upper word
+ * 4 : Directory path string type
+ * 5 : Directory path string size
+ * 7 : Directory path string data
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void DeleteDirectory(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
+ // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
+ Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
+ auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
+ u32 dirname_size = cmd_buff[5];
+ u32 dirname_ptr = cmd_buff[7];
+
+ FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
+
+ DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
+ dirname_type, dirname_size, dir_path.DebugStr().c_str());
+
+ cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path);
+
+ DEBUG_LOG(KERNEL, "called");
+}
+
+/*
* FS_User::CreateDirectory service function
* Inputs:
* 2 : Archive handle lower word
@@ -139,7 +206,7 @@ void OpenFileDirectly(Service::Interface* self) {
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
-void CreateDirectory(Service::Interface* self) {
+static void CreateDirectory(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
// TODO: cmd_buff[2], aka archive handle lower word, isn't used according to
@@ -150,25 +217,15 @@ void CreateDirectory(Service::Interface* self) {
u32 dirname_ptr = cmd_buff[8];
FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
- std::string dir_string;
- switch (dir_path.GetType()) {
- case FileSys::Char:
- case FileSys::Wchar:
- dir_string = dir_path.AsString();
- break;
- default:
- cmd_buff[1] = -1;
- return;
- }
- DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_string.c_str());
+ DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
- cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_string);
+ cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path);
DEBUG_LOG(KERNEL, "called");
}
-void OpenDirectory(Service::Interface* self) {
+static void OpenDirectory(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
// 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) {
u32 dirname_ptr = cmd_buff[6];
FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
- std::string dir_string;
- switch (dir_path.GetType()) {
- case FileSys::Char:
- case FileSys::Wchar:
- dir_string = dir_path.AsString();
- break;
- default:
- cmd_buff[1] = -1;
- return;
- }
- DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_string.c_str());
+ DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
- Handle handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_string);
- if (handle) {
- cmd_buff[1] = 0;
- cmd_buff[3] = handle;
+ ResultVal<Handle> handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_path);
+ cmd_buff[1] = handle.Code().raw;
+ if (handle.Succeeded()) {
+ cmd_buff[3] = *handle;
} else {
- ERROR_LOG(KERNEL, "failed to get a handle for directory %s", dir_string.c_str());
- // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
- cmd_buff[1] = -1;
+ ERROR_LOG(KERNEL, "failed to get a handle for directory");
}
DEBUG_LOG(KERNEL, "called");
}
-void OpenArchive(Service::Interface* self) {
+/**
+ * FS_User::OpenArchive service function
+ * Inputs:
+ * 1 : Archive ID
+ * 2 : Archive low path type
+ * 3 : Archive low path size
+ * 4 : (LowPathSize << 14) | 2
+ * 5 : Archive low path
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Archive handle lower word (unused)
+ * 3 : Archive handle upper word (same as file handle)
+ */
+static void OpenArchive(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
- auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]);
+ auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]);
auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
- u32 archivename_size = cmd_buff[3];
- u32 archivename_ptr = cmd_buff[5];
+ u32 archivename_size = cmd_buff[3];
+ u32 archivename_ptr = cmd_buff[5];
+ FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
- DEBUG_LOG(KERNEL, "type=%d size=%d", archivename_type, archivename_size);
+ DEBUG_LOG(KERNEL, "archive_path=%s", archive_path.DebugStr().c_str());
- if (archivename_type != FileSys::Empty) {
+ if (archive_path.GetType() != FileSys::Empty) {
ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported");
- cmd_buff[1] = -1;
+ cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw;
return;
}
- Handle handle = Kernel::OpenArchive(archive_id);
- if (handle) {
- cmd_buff[1] = 0;
+ ResultVal<Handle> handle = Kernel::OpenArchive(archive_id);
+ cmd_buff[1] = handle.Code().raw;
+ if (handle.Succeeded()) {
// cmd_buff[2] isn't used according to 3dmoo's implementation.
- cmd_buff[3] = handle;
+ cmd_buff[3] = *handle;
} else {
ERROR_LOG(KERNEL, "failed to get a handle for archive");
- // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily.
- cmd_buff[1] = -1;
}
DEBUG_LOG(KERNEL, "called");
@@ -241,12 +298,12 @@ void OpenArchive(Service::Interface* self) {
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Whether the Sdmc could be detected
*/
-void IsSdmcDetected(Service::Interface* self) {
+static void IsSdmcDetected(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
cmd_buff[1] = 0;
cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0;
-
+
DEBUG_LOG(KERNEL, "called");
}
@@ -256,9 +313,9 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x08010002, Initialize, "Initialize"},
{0x080201C2, OpenFile, "OpenFile"},
{0x08030204, OpenFileDirectly, "OpenFileDirectly"},
- {0x08040142, nullptr, "DeleteFile"},
+ {0x08040142, DeleteFile, "DeleteFile"},
{0x08050244, nullptr, "RenameFile"},
- {0x08060142, nullptr, "DeleteDirectory"},
+ {0x08060142, DeleteDirectory, "DeleteDirectory"},
{0x08070142, nullptr, "DeleteDirectoryRecursively"},
{0x08080202, nullptr, "CreateFile"},
{0x08090182, CreateDirectory, "CreateDirectory"},
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 6119e630..de1bd3f6 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
/// Gets a pointer to a thread command buffer in GSP shared memory
static inline u8* GetCommandBuffer(u32 thread_id) {
- if (0 == g_shared_memory)
- return nullptr;
-
- return Kernel::GetSharedMemoryPointer(g_shared_memory,
- 0x800 + (thread_id * sizeof(CommandBuffer)));
+ ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * sizeof(CommandBuffer)));
+ return ptr.ValueOr(nullptr);
}
static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) {
- if (0 == g_shared_memory)
- return nullptr;
-
_dbg_assert_msg_(GSP, screen_index < 2, "Invalid screen index");
// For each thread there are two FrameBufferUpdate fields
u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate);
- return (FrameBufferUpdate*)Kernel::GetSharedMemoryPointer(g_shared_memory, offset);
+ ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, offset);
+ return reinterpret_cast<FrameBufferUpdate*>(ptr.ValueOr(nullptr));
}
/// Gets a pointer to the interrupt relay queue for a given thread index
static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
- return (InterruptRelayQueue*)Kernel::GetSharedMemoryPointer(g_shared_memory,
- sizeof(InterruptRelayQueue) * thread_id);
+ ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, sizeof(InterruptRelayQueue) * thread_id);
+ return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr));
}
-void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
+static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
// TODO: Return proper error codes
if (base_address + size_in_bytes >= 0x420000) {
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) {
}
/// Write a GSP GPU hardware register
-void WriteHWRegs(Service::Interface* self) {
+static void WriteHWRegs(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
u32 reg_addr = cmd_buff[1];
u32 size = cmd_buff[2];
@@ -87,7 +82,7 @@ void WriteHWRegs(Service::Interface* self) {
}
/// Read a GSP GPU hardware register
-void ReadHWRegs(Service::Interface* self) {
+static void ReadHWRegs(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
u32 reg_addr = cmd_buff[1];
u32 size = cmd_buff[2];
@@ -115,7 +110,7 @@ void ReadHWRegs(Service::Interface* self) {
}
}
-void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
+static void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
u32 base_address = 0x400000;
if (info.active_fb == 0) {
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) {
* Outputs:
* 1: Result code
*/
-void SetBufferSwap(Service::Interface* self) {
+static void SetBufferSwap(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
u32 screen_id = cmd_buff[1];
FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2];
@@ -159,7 +154,7 @@ void SetBufferSwap(Service::Interface* self) {
* 2 : Thread index into GSP command buffer
* 4 : Handle to GSP shared memory
*/
-void RegisterInterruptRelayQueue(Service::Interface* self) {
+static void RegisterInterruptRelayQueue(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
u32 flags = cmd_buff[1];
g_interrupt_event = cmd_buff[3];
@@ -202,7 +197,7 @@ void SignalInterrupt(InterruptId interrupt_id) {
}
/// Executes the next GSP command
-void ExecuteCommand(const Command& command, u32 thread_id) {
+static void ExecuteCommand(const Command& command, u32 thread_id) {
// Utility function to convert register ID to address
auto WriteGPURegister = [](u32 id, u32 data) {
GPU::Write<u32>(0x1EF00000 + 4 * id, data);
@@ -308,7 +303,7 @@ void ExecuteCommand(const Command& command, u32 thread_id) {
}
/// This triggers handling of the GX command written to the command buffer in shared memory.
-void TriggerCmdReqQueue(Service::Interface* self) {
+static void TriggerCmdReqQueue(Service::Interface* self) {
// Iterate through each thread's command queue...
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 0eb32ba4..d29de1a5 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;
* Gets a pointer to the PadData structure inside HID shared memory
*/
static inline PadData* GetPadData() {
- if (0 == shared_mem)
- return nullptr;
-
- return reinterpret_cast<PadData*>(Kernel::GetSharedMemoryPointer(shared_mem, 0));
+ return reinterpret_cast<PadData*>(Kernel::GetSharedMemoryPointer(shared_mem, 0).ValueOr(nullptr));
}
/**
@@ -47,7 +44,7 @@ static inline PadData* GetPadData() {
*
* Indicate the circle pad is pushed completely to the edge in 1 of 8 directions.
*/
-void UpdateNextCirclePadState() {
+static void UpdateNextCirclePadState() {
static const s16 max_value = 0x9C;
next_circle_x = next_state.circle_left ? -max_value : 0x0;
next_circle_x += next_state.circle_right ? max_value : 0x0;
@@ -155,7 +152,7 @@ void PadUpdateComplete() {
* 7 : Gyroscope event
* 8 : Event signaled by HID_User
*/
-void GetIPCHandles(Service::Interface* self) {
+static void GetIPCHandles(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
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 9f6c4d5e..5ed97085 100644
--- a/src/core/hle/service/hid_user.h
+++ b/src/core/hle/service/hid_user.h
@@ -15,7 +15,7 @@
namespace HID_User {
-/**
+/**
* Structure of a Pad controller state.
*/
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 00000000..be15db23
--- /dev/null
+++ b/src/core/hle/service/ir_rst.cpp
@@ -0,0 +1,36 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/ir_rst.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace IR_RST
+
+namespace IR_RST {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010000, nullptr, "GetHandles"},
+ {0x00020080, nullptr, "Initialize"},
+ {0x00030000, nullptr, "Shutdown"},
+ {0x00040000, nullptr, "Unknown"},
+ {0x00050000, nullptr, "Unknown"},
+ {0x00060000, nullptr, "Unknown"},
+ {0x00070080, nullptr, "Unknown"},
+ {0x00080000, nullptr, "Unknown"},
+ {0x00090000, nullptr, "Unknown"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+}
+
+Interface::~Interface() {
+}
+
+} // namespace
diff --git a/src/core/hle/service/ir_rst.h b/src/core/hle/service/ir_rst.h
new file mode 100644
index 00000000..73effd7e
--- /dev/null
+++ b/src/core/hle/service/ir_rst.h
@@ -0,0 +1,27 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace IR_RST
+
+namespace IR_RST {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+ ~Interface();
+ /**
+ * Gets the string port name used by CTROS for the service
+ * @return Port name of service
+ */
+ std::string GetPortName() const override {
+ return "ir:rst";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/ir_u.cpp b/src/core/hle/service/ir_u.cpp
new file mode 100644
index 00000000..aa9db6f6
--- /dev/null
+++ b/src/core/hle/service/ir_u.cpp
@@ -0,0 +1,45 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/ir_u.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace IR_U
+
+namespace IR_U {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010000, nullptr, "Initialize"},
+ {0x00020000, nullptr, "Shutdown"},
+ {0x00030042, nullptr, "StartSendTransfer"},
+ {0x00040000, nullptr, "WaitSendTransfer"},
+ {0x000500C2, nullptr, "StartRecvTransfer"},
+ {0x00060000, nullptr, "WaitRecvTransfer"},
+ {0x00070080, nullptr, "GetRecvTransferCount"},
+ {0x00080000, nullptr, "GetSendState"},
+ {0x00090040, nullptr, "SetBitRate"},
+ {0x000A0000, nullptr, "GetBitRate"},
+ {0x000B0040, nullptr, "SetIRLEDState"},
+ {0x000C0000, nullptr, "GetIRLEDRecvState"},
+ {0x000D0000, nullptr, "GetSendFinishedEvent"},
+ {0x000E0000, nullptr, "GetRecvFinishedEvent"},
+ {0x000F0000, nullptr, "GetTransferState"},
+ {0x00100000, nullptr, "GetErrorStatus"},
+ {0x00110040, nullptr, "SetSleepModeActive"},
+ {0x00120040, nullptr, "SetSleepModeState"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+}
+
+Interface::~Interface() {
+}
+
+} // namespace
diff --git a/src/core/hle/service/ir_u.h b/src/core/hle/service/ir_u.h
new file mode 100644
index 00000000..86d98d07
--- /dev/null
+++ b/src/core/hle/service/ir_u.h
@@ -0,0 +1,27 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace IR_U
+
+namespace IR_U {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+ ~Interface();
+ /**
+ * Gets the string port name used by CTROS for the service
+ * @return Port name of service
+ */
+ std::string GetPortName() const override {
+ return "ir:u";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index 58051f13..d6f30e9a 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[] = {
{0x000D0040, nullptr, "SetClamp"},
{0x000E0000, nullptr, "GetClamp"},
{0x000F0040, nullptr, "unknown_input1"},
- {0x00100040, nullptr, "unknown_input2"},
+ {0x00100040, nullptr, "unknown_input2"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h
index 72ba048e..2a495f3a 100644
--- a/src/core/hle/service/mic_u.h
+++ b/src/core/hle/service/mic_u.h
@@ -21,7 +21,7 @@ public:
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "mic:u";
}
};
diff --git a/src/core/hle/service/nwm_uds.h b/src/core/hle/service/nwm_uds.h
index a956ca81..69d2c200 100644
--- a/src/core/hle/service/nwm_uds.h
+++ b/src/core/hle/service/nwm_uds.h
@@ -21,7 +21,7 @@ public:
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "nwm:UDS";
}
};
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp
new file mode 100644
index 00000000..90e9b1bf
--- /dev/null
+++ b/src/core/hle/service/pm_app.cpp
@@ -0,0 +1,35 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/pm_app.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace PM_APP
+
+namespace PM_APP {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010140, nullptr, "LaunchTitle"},
+ {0x00020082, nullptr, "LaunchFIRMSetParams"},
+ {0x00030080, nullptr, "TerminateProcesse"},
+ {0x00040100, nullptr, "TerminateProcessTID"},
+ {0x000500C0, nullptr, "TerminateProcessTID_unknown"},
+ {0x00070042, nullptr, "GetFIRMLaunchParams"},
+ {0x00080100, nullptr, "GetTitleExheaderFlags"},
+ {0x00090042, nullptr, "SetFIRMLaunchParams"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+}
+
+Interface::~Interface() {
+}
+
+} // namespace
diff --git a/src/core/hle/service/pm_app.h b/src/core/hle/service/pm_app.h
new file mode 100644
index 00000000..28c38f58
--- /dev/null
+++ b/src/core/hle/service/pm_app.h
@@ -0,0 +1,27 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace PM_APP
+
+namespace PM_APP {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+ ~Interface();
+ /**
+ * Gets the string port name used by CTROS for the service
+ * @return Port name of service
+ */
+ std::string GetPortName() const override {
+ return "pm:app";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp
index f6a14d50..d9122dbb 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[] = {
{0x00030000, nullptr, "GetRtcAlarm"},
{0x00040000, nullptr, "CancelRtcAlarm"},
{0x00050000, nullptr, "GetAdapterState"},
- {0x00060000, nullptr, "GetShellState "},
+ {0x00060000, nullptr, "GetShellState"},
{0x00070000, nullptr, "GetBatteryLevel"},
{0x00080000, nullptr, "GetBatteryChargeState"},
{0x00090000, nullptr, "GetPedometerState"},
{0x000A0042, nullptr, "GetStepHistoryEntry"},
- {0x000B00C2, nullptr, "GetStepHistory "},
- {0x000C0000, nullptr, "GetTotalStepCount "},
+ {0x000B00C2, nullptr, "GetStepHistory"},
+ {0x000C0000, nullptr, "GetTotalStepCount"},
{0x000D0040, nullptr, "SetPedometerRecordingMode"},
{0x000E0000, nullptr, "GetPedometerRecordingMode"},
{0x000F0084, nullptr, "GetStepHistoryAll"},
diff --git a/src/core/hle/service/ptm_u.h b/src/core/hle/service/ptm_u.h
index 82749fa3..f8d9f57b 100644
--- a/src/core/hle/service/ptm_u.h
+++ b/src/core/hle/service/ptm_u.h
@@ -21,7 +21,7 @@ public:
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "ptm:u";
}
};
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index bb0f80e9..fed2268a 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -7,17 +7,24 @@
#include "core/hle/service/service.h"
#include "core/hle/service/ac_u.h"
+#include "core/hle/service/am_net.h"
#include "core/hle/service/apt_u.h"
+#include "core/hle/service/boss_u.h"
+#include "core/hle/service/cfg_i.h"
#include "core/hle/service/cfg_u.h"
+#include "core/hle/service/csnd_snd.h"
#include "core/hle/service/dsp_dsp.h"
#include "core/hle/service/err_f.h"
#include "core/hle/service/fs_user.h"
#include "core/hle/service/frd_u.h"
#include "core/hle/service/gsp_gpu.h"
#include "core/hle/service/hid_user.h"
+#include "core/hle/service/ir_rst.h"
+#include "core/hle/service/ir_u.h"
#include "core/hle/service/mic_u.h"
#include "core/hle/service/ndm_u.h"
#include "core/hle/service/nwm_uds.h"
+#include "core/hle/service/pm_app.h"
#include "core/hle/service/ptm_u.h"
#include "core/hle/service/soc_u.h"
#include "core/hle/service/srv.h"
@@ -55,7 +62,7 @@ void Manager::DeleteService(const std::string& port_name) {
/// Get a Service Interface from its Handle
Interface* Manager::FetchFromHandle(Handle handle) {
- return Kernel::g_object_pool.GetFast<Interface>(handle);
+ return Kernel::g_object_pool.Get<Interface>(handle);
}
/// Get a Service Interface from its port
@@ -74,20 +81,27 @@ Interface* Manager::FetchFromPortName(const std::string& port_name) {
/// Initialize ServiceManager
void Init() {
g_manager = new Manager;
-
+
g_manager->AddService(new SRV::Interface);
g_manager->AddService(new AC_U::Interface);
+ g_manager->AddService(new AM_NET::Interface);
g_manager->AddService(new APT_U::Interface);
+ g_manager->AddService(new BOSS_U::Interface);
+ g_manager->AddService(new CFG_I::Interface);
g_manager->AddService(new CFG_U::Interface);
+ g_manager->AddService(new CSND_SND::Interface);
g_manager->AddService(new DSP_DSP::Interface);
g_manager->AddService(new ERR_F::Interface);
g_manager->AddService(new FRD_U::Interface);
g_manager->AddService(new FS_User::Interface);
g_manager->AddService(new GSP_GPU::Interface);
g_manager->AddService(new HID_User::Interface);
+ g_manager->AddService(new IR_RST::Interface);
+ g_manager->AddService(new IR_U::Interface);
g_manager->AddService(new MIC_U::Interface);
g_manager->AddService(new NDM_U::Interface);
g_manager->AddService(new NWM_UDS::Interface);
+ g_manager->AddService(new PM_APP::Interface);
g_manager->AddService(new PTM_U::Interface);
g_manager->AddService(new SOC_U::Interface);
g_manager->AddService(new SSL_C::Interface);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 2f5a866c..20e7fb4d 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -38,7 +38,7 @@ class Manager;
class Interface : public Kernel::Object {
friend class Manager;
public:
-
+
std::string GetName() const override { return GetPortName(); }
std::string GetTypeName() const override { return GetPortName(); }
@@ -75,48 +75,38 @@ public:
m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
}
- /**
- * Synchronize kernel object
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result SyncRequest(bool* wait) override {
+ ResultVal<bool> SyncRequest() override {
u32* cmd_buff = GetCommandBuffer();
auto itr = m_functions.find(cmd_buff[0]);
if (itr == m_functions.end()) {
- ERROR_LOG(OSHLE, "unknown/unimplemented function: port=%s, command=0x%08X",
+ ERROR_LOG(OSHLE, "unknown/unimplemented function: port=%s, command=0x%08X",
GetPortName().c_str(), cmd_buff[0]);
// TODO(bunnei): Hack - ignore error
u32* cmd_buff = Service::GetCommandBuffer();
cmd_buff[1] = 0;
- return 0;
+ return MakeResult<bool>(false);
}
if (itr->second.func == nullptr) {
- ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s",
+ ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s",
GetPortName().c_str(), itr->second.name.c_str());
// TODO(bunnei): Hack - ignore error
u32* cmd_buff = Service::GetCommandBuffer();
cmd_buff[1] = 0;
- return 0;
- }
+ return MakeResult<bool>(false);
+ }
itr->second.func(this);
- return 0; // TODO: Implement return from actual function
+ return MakeResult<bool>(false); // TODO: Implement return from actual function
}
- /**
- * Wait for kernel object to synchronize
- * @param wait Boolean wait set if current thread should wait as a result of sync operation
- * @return Result of operation, 0 on success, otherwise error code
- */
- Result WaitSynchronization(bool* wait) override {
+ ResultVal<bool> WaitSynchronization() override {
// TODO(bunnei): ImplementMe
ERROR_LOG(OSHLE, "unimplemented function");
- return 0;
+ return UnimplementedFunction(ErrorModule::OS);
}
protected:
diff --git a/src/core/hle/service/soc_u.h b/src/core/hle/service/soc_u.h
index e27a2b1f..d5590a68 100644
--- a/src/core/hle/service/soc_u.h
+++ b/src/core/hle/service/soc_u.h
@@ -19,7 +19,7 @@ public:
* Gets the string port name used by CTROS for the service
* @return Port name of service
*/
- std::string GetPortName() const {
+ std::string GetPortName() const override {
return "soc:U";
}
};
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 6c02a43d..0e7fa9e3 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -11,9 +11,9 @@
namespace SRV {
-Handle g_event_handle = 0;
+static Handle g_event_handle = 0;
-void Initialize(Service::Interface* self) {
+static void Initialize(Service::Interface* self) {
DEBUG_LOG(OSHLE, "called");
u32* cmd_buff = Service::GetCommandBuffer();
@@ -21,7 +21,7 @@ void Initialize(Service::Interface* self) {
cmd_buff[1] = 0; // No error
}
-void GetProcSemaphore(Service::Interface* self) {
+static void GetProcSemaphore(Service::Interface* self) {
DEBUG_LOG(OSHLE, "called");
u32* cmd_buff = Service::GetCommandBuffer();
@@ -34,8 +34,8 @@ void GetProcSemaphore(Service::Interface* self) {
cmd_buff[3] = g_event_handle;
}
-void GetServiceHandle(Service::Interface* self) {
- Result res = 0;
+static void GetServiceHandle(Service::Interface* self) {
+ ResultCode res = RESULT_SUCCESS;
u32* cmd_buff = Service::GetCommandBuffer();
std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
@@ -46,9 +46,9 @@ void GetServiceHandle(Service::Interface* self) {
DEBUG_LOG(OSHLE, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]);
} else {
ERROR_LOG(OSHLE, "(UNIMPLEMENTED) called port=%s", port_name.c_str());
- res = -1;
+ res = UnimplementedFunction(ErrorModule::SRV);
}
- cmd_buff[1] = res;
+ cmd_buff[1] = res.raw;
}
const Interface::FunctionInfo FunctionTable[] = {
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 1eda36c5..43a3cbe0 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#include <map>
@@ -16,6 +16,7 @@
#include "core/hle/kernel/thread.h"
#include "core/hle/function_wrappers.h"
+#include "core/hle/result.h"
#include "core/hle/service/service.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -29,8 +30,8 @@ enum ControlMemoryOperation {
};
/// Map application or GSP heap memory
-Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
- DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X",
+static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
+ DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X",
operation, addr0, addr1, size, permissions);
switch (operation) {
@@ -53,8 +54,8 @@ Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 siz
}
/// Maps a memory block to specified address
-Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) {
- DEBUG_LOG(SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
+static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) {
+ DEBUG_LOG(SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
handle, addr, permissions, other_permissions);
Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions);
@@ -63,7 +64,7 @@ Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permis
case Kernel::MemoryPermission::Write:
case Kernel::MemoryPermission::ReadWrite:
case Kernel::MemoryPermission::DontCare:
- Kernel::MapSharedMemory(handle, addr, permissions_type,
+ Kernel::MapSharedMemory(handle, addr, permissions_type,
static_cast<Kernel::MemoryPermission>(other_permissions));
break;
default:
@@ -73,7 +74,7 @@ Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permis
}
/// Connect to an OS service given the port name, returns the handle to the port to out
-Result ConnectToPort(Handle* out, const char* port_name) {
+static Result ConnectToPort(Handle* out, const char* port_name) {
Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
DEBUG_LOG(SVC, "called port_name=%s", port_name);
@@ -85,78 +86,83 @@ Result ConnectToPort(Handle* out, const char* port_name) {
}
/// Synchronize to an OS service
-Result SendSyncRequest(Handle handle) {
+static Result SendSyncRequest(Handle handle) {
+ // TODO(yuriks): ObjectPool::Get tries to check the Object type, which fails since this is a generic base Object,
+ // so we are forced to use GetFast and manually verify the handle.
+ if (!Kernel::g_object_pool.IsValid(handle)) {
+ return InvalidHandle(ErrorModule::Kernel).raw;
+ }
Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
_assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!");
DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str());
- bool wait = false;
- Result res = object->SyncRequest(&wait);
- if (wait) {
+ ResultVal<bool> wait = object->SyncRequest();
+ if (wait.Succeeded() && *wait) {
Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
}
- return res;
+ return wait.Code().raw;
}
/// Close a handle
-Result CloseHandle(Handle handle) {
+static Result CloseHandle(Handle handle) {
// ImplementMe
ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle);
return 0;
}
/// Wait for a handle to synchronize, timeout after the specified nanoseconds
-Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
+static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
// TODO(bunnei): Do something with nano_seconds, currently ignoring this
- bool wait = false;
bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
+ if (!Kernel::g_object_pool.IsValid(handle)) {
+ return InvalidHandle(ErrorModule::Kernel).raw;
+ }
Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
+ _dbg_assert_(KERNEL, object != nullptr);
- DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(),
+ DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(),
object->GetName().c_str(), nano_seconds);
- _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!");
-
- Result res = object->WaitSynchronization(&wait);
+ ResultVal<bool> wait = object->WaitSynchronization();
// Check for next thread to schedule
- if (wait) {
+ if (wait.Succeeded() && *wait) {
HLE::Reschedule(__func__);
- return 0;
}
- return res;
+ return wait.Code().raw;
}
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all,
+static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all,
s64 nano_seconds) {
// TODO(bunnei): Do something with nano_seconds, currently ignoring this
bool unlock_all = true;
bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
- DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld",
+ DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld",
handle_count, (wait_all ? "true" : "false"), nano_seconds);
// Iterate through each handle, synchronize kernel object
for (s32 i = 0; i < handle_count; i++) {
- bool wait = false;
+ if (!Kernel::g_object_pool.IsValid(handles[i])) {
+ return InvalidHandle(ErrorModule::Kernel).raw;
+ }
Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]);
- _assert_msg_(KERNEL, (object != nullptr), "called handle=0x%08X, but kernel object "
- "is nullptr!", handles[i]);
-
- DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(),
+ DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(),
object->GetName().c_str());
- Result res = object->WaitSynchronization(&wait);
+ // TODO(yuriks): Verify how the real function behaves when an error happens here
+ ResultVal<bool> wait_result = object->WaitSynchronization();
+ bool wait = wait_result.Succeeded() && *wait_result;
if (!wait && !wait_all) {
*out = i;
- return 0;
+ return RESULT_SUCCESS.raw;
} else {
unlock_all = false;
}
@@ -164,17 +170,17 @@ Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wa
if (wait_all && unlock_all) {
*out = handle_count;
- return 0;
+ return RESULT_SUCCESS.raw;
}
// Check for next thread to schedule
HLE::Reschedule(__func__);
- return 0;
+ return RESULT_SUCCESS.raw;
}
/// Create an address arbiter (to allocate access to shared resources)
-Result CreateAddressArbiter(u32* arbiter) {
+static Result CreateAddressArbiter(u32* arbiter) {
DEBUG_LOG(SVC, "called");
Handle handle = Kernel::CreateAddressArbiter();
*arbiter = handle;
@@ -182,20 +188,22 @@ Result CreateAddressArbiter(u32* arbiter) {
}
/// Arbitrate address
-Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) {
- return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), address,
- value);
+static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) {
+ DEBUG_LOG(SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter,
+ address, type, value);
+ return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type),
+ address, value).raw;
}
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
-void OutputDebugString(const char* string) {
+static void OutputDebugString(const char* string) {
OS_LOG(SVC, "%s", string);
}
/// Get resource limit
-Result GetResourceLimit(Handle* resource_limit, Handle process) {
+static Result GetResourceLimit(Handle* resource_limit, Handle process) {
// With regards to proceess values:
- // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for
+ // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for
// the current KThread.
*resource_limit = 0xDEADBEEF;
ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process);
@@ -203,7 +211,7 @@ Result GetResourceLimit(Handle* resource_limit, Handle process) {
}
/// Get resource limit current values
-Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names,
+static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names,
s32 name_count) {
ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d",
resource_limit, names, name_count);
@@ -212,7 +220,7 @@ Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* n
}
/// Creates a new thread
-Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) {
+static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) {
std::string name;
if (Symbols::HasSymbol(entry_point)) {
TSymbol symbol = Symbols::GetSymbol(entry_point);
@@ -227,14 +235,14 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p
Core::g_app_core->SetReg(1, thread);
DEBUG_LOG(SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
- "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point,
+ "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point,
name.c_str(), arg, stack_top, priority, processor_id, thread);
-
+
return 0;
}
/// Called when a thread exits
-u32 ExitThread() {
+static u32 ExitThread() {
Handle thread = Kernel::GetCurrentThreadHandle();
DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C
@@ -245,54 +253,56 @@ u32 ExitThread() {
}
/// Gets the priority for the specified thread
-Result GetThreadPriority(s32* priority, Handle handle) {
- *priority = Kernel::GetThreadPriority(handle);
- return 0;
+static Result GetThreadPriority(s32* priority, Handle handle) {
+ ResultVal<u32> priority_result = Kernel::GetThreadPriority(handle);
+ if (priority_result.Succeeded()) {
+ *priority = *priority_result;
+ }
+ return priority_result.Code().raw;
}
/// Sets the priority for the specified thread
-Result SetThreadPriority(Handle handle, s32 priority) {
- return Kernel::SetThreadPriority(handle, priority);
+static Result SetThreadPriority(Handle handle, s32 priority) {
+ return Kernel::SetThreadPriority(handle, priority).raw;
}
/// Create a mutex
-Result CreateMutex(Handle* mutex, u32 initial_locked) {
+static Result CreateMutex(Handle* mutex, u32 initial_locked) {
*mutex = Kernel::CreateMutex((initial_locked != 0));
- DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X",
+ DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X",
initial_locked ? "true" : "false", *mutex);
return 0;
}
/// Release a mutex
-Result ReleaseMutex(Handle handle) {
+static Result ReleaseMutex(Handle handle) {
DEBUG_LOG(SVC, "called handle=0x%08X", handle);
- _assert_msg_(KERNEL, (handle != 0), "called, but handle is nullptr!");
- Kernel::ReleaseMutex(handle);
- return 0;
+ ResultCode res = Kernel::ReleaseMutex(handle);
+ return res.raw;
}
/// Get current thread ID
-Result GetThreadId(u32* thread_id, Handle thread) {
+static Result GetThreadId(u32* thread_id, Handle thread) {
ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread);
return 0;
}
/// Query memory
-Result QueryMemory(void* info, void* out, u32 addr) {
+static Result QueryMemory(void* info, void* out, u32 addr) {
ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr);
return 0;
}
/// Create an event
-Result CreateEvent(Handle* evt, u32 reset_type) {
+static Result CreateEvent(Handle* evt, u32 reset_type) {
*evt = Kernel::CreateEvent((ResetType)reset_type);
- DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X",
+ DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X",
reset_type, *evt);
return 0;
}
/// Duplicates a kernel handle
-Result DuplicateHandle(Handle* out, Handle handle) {
+static Result DuplicateHandle(Handle* out, Handle handle) {
DEBUG_LOG(SVC, "called handle=0x%08X", handle);
// Translate kernel handles -> real handles
@@ -301,7 +311,7 @@ Result DuplicateHandle(Handle* out, Handle handle) {
}
_assert_msg_(KERNEL, (handle != Kernel::CurrentProcess),
"(UNIMPLEMENTED) process handle duplication!");
-
+
// TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate.
*out = handle;
@@ -309,26 +319,27 @@ Result DuplicateHandle(Handle* out, Handle handle) {
}
/// Signals an event
-Result SignalEvent(Handle evt) {
- Result res = Kernel::SignalEvent(evt);
+static Result SignalEvent(Handle evt) {
DEBUG_LOG(SVC, "called event=0x%08X", evt);
- return res;
+ return Kernel::SignalEvent(evt).raw;
}
/// Clears an event
-Result ClearEvent(Handle evt) {
- Result res = Kernel::ClearEvent(evt);
+static Result ClearEvent(Handle evt) {
DEBUG_LOG(SVC, "called event=0x%08X", evt);
- return res;
+ return Kernel::ClearEvent(evt).raw;
}
/// Sleep the current thread
-void SleepThread(s64 nanoseconds) {
+static void SleepThread(s64 nanoseconds) {
DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds);
+
+ // Check for next thread to schedule
+ HLE::Reschedule(__func__);
}
/// This returns the total CPU ticks elapsed since the CPU was powered-on
-s64 GetSystemTick() {
+static s64 GetSystemTick() {
return (s64)Core::g_app_core->GetTicks();
}
diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h
index 1d125faf..6be393d0 100644
--- a/src/core/hle/svc.h
+++ b/src/core/hle/svc.h
@@ -1,6 +1,6 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
-// Refer to the license.txt file included.
+// Refer to the license.txt file included.
#pragma once
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 3ad801c6..af5e1b39 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) {
// Writes other than u32 are untested, so I'd rather have them abort than silently fail
if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) {
- ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
+ ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
return;
}
@@ -140,8 +140,8 @@ inline void Write(u32 addr, const T data) {
DEBUG_LOG(GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x",
config.output_height * config.output_width * 4,
- config.GetPhysicalInputAddress(), config.input_width, config.input_height,
- config.GetPhysicalOutputAddress(), config.output_width, config.output_height,
+ config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height,
+ config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height,
config.output_format.Value());
}
break;
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index 33f75c50..ea001673 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -39,7 +39,7 @@ enum {
template <typename T>
inline void Read(T &var, const u32 addr) {
switch (addr & 0xFFFFF000) {
-
+
// TODO(bunnei): What is the virtual address of NDMA?
// case VADDR_NDMA:
// NDMA::Read(var, addr);
@@ -57,9 +57,9 @@ inline void Read(T &var, const u32 addr) {
template <typename T>
inline void Write(u32 addr, const T data) {
switch (addr & 0xFFFFF000) {
-
+
// TODO(bunnei): What is the virtual address of NDMA?
- // case VADDR_NDMA
+ // case VADDR_NDMA
// NDMA::Write(addr, data);
// break;
@@ -68,7 +68,7 @@ inline void Write(u32 addr, const T data) {
break;
default:
- ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
+ ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
}
}
diff --git a/src/core/hw/ndma.cpp b/src/core/hw/ndma.cpp
index e29a773f..593e5de3 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) {
template <typename T>
inline void Write(u32 addr, const T data) {
- ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
+ ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
}
// 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 389d5a8c..63d2496e 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -273,13 +273,13 @@ bool ElfReader::LoadInto(u32 vaddr) {
for (int i = 0; i < header->e_phnum; i++) {
Elf32_Phdr *p = segments + i;
- INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr,
+ INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr,
p->p_filesz, p->p_memsz);
if (p->p_type == PT_LOAD) {
segment_addr[i] = base_addr + p->p_vaddr;
memcpy(Memory::GetPointer(segment_addr[i]), GetSegmentPtr(i), p->p_filesz);
- INFO_LOG(MASTER_LOG, "Loadable Segment Copied to %08x, size %08x", segment_addr[i],
+ INFO_LOG(MASTER_LOG, "Loadable Segment Copied to %08x, size %08x", segment_addr[i],
p->p_memsz);
}
}
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 1e5501e6..343bb752 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)
* @param size Size of compressed buffer
* @return Size of decompressed buffer
*/
-u32 LZSS_GetDecompressedSize(u8* buffer, u32 size) {
+static u32 LZSS_GetDecompressedSize(u8* buffer, u32 size) {
u32 offset_size = *(u32*)(buffer + size - 4);
return offset_size + size;
}
@@ -37,7 +37,7 @@ u32 LZSS_GetDecompressedSize(u8* buffer, u32 size) {
* @param decompressed_size Size of decompressed buffer
* @return True on success, otherwise false
*/
-bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) {
+static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) {
u8* footer = compressed + compressed_size - 8;
u32 buffer_top_and_bottom = *(u32*)footer;
u32 out = decompressed_size;
@@ -118,7 +118,7 @@ AppLoader_NCCH::~AppLoader_NCCH() {
* @return ResultStatus result of function
*/
ResultStatus AppLoader_NCCH::LoadExec() const {
- if (!is_loaded)
+ if (!is_loaded)
return ResultStatus::ErrorNotLoaded;
std::vector<u8> code;
@@ -185,7 +185,7 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>&
return ResultStatus::Error;
}
return ResultStatus::ErrorNotUsed;
-}
+}
/**
* Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI)
@@ -210,7 +210,7 @@ ResultStatus AppLoader_NCCH::Load() {
file.Seek(ncch_offset, 0);
file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
}
-
+
// Verify we are loading the correct file type...
if (0 != memcmp(&ncch_header.magic, "NCCH", 4))
return ResultStatus::ErrorInvalidFormat;
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index f40a258b..03116add 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -215,7 +215,7 @@ private:
u32 entry_point;
u32 ncch_offset; // Offset to NCCH header, can be 0 or after NCSD header
u32 exefs_offset;
-
+
NCCH_Header ncch_header;
ExeFs_Header exefs_header;
ExHeader_Header exheader_header;
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp
index cf12f24d..74a93b1d 100644
--- a/src/core/mem_map.cpp
+++ b/src/core/mem_map.cpp
@@ -11,38 +11,38 @@
namespace Memory {
-u8* g_base = NULL; ///< The base pointer to the auto-mirrored arena.
+u8* g_base = nullptr; ///< The base pointer to the auto-mirrored arena.
-MemArena g_arena; ///< The MemArena class
+static MemArena arena; ///< The MemArena class
-u8* g_exefs_code = NULL; ///< ExeFS:/.code is loaded here
-u8* g_system_mem = NULL; ///< System memory
-u8* g_heap = NULL; ///< Application heap (main memory)
-u8* g_heap_gsp = NULL; ///< GSP heap (main memory)
-u8* g_vram = NULL; ///< Video memory (VRAM) pointer
-u8* g_shared_mem = NULL; ///< Shared memory
-u8* g_kernel_mem; ///< Kernel memory
+u8* g_exefs_code = nullptr; ///< ExeFS:/.code is loaded here
+u8* g_system_mem = nullptr; ///< System memory
+u8* g_heap = nullptr; ///< Application heap (main memory)
+u8* g_heap_gsp = nullptr; ///< GSP heap (main memory)
+u8* g_vram = nullptr; ///< Video memory (VRAM) pointer
+u8* g_shared_mem = nullptr; ///< Shared memory
+u8* g_kernel_mem; ///< Kernel memory
-u8* g_physical_bootrom = NULL; ///< Bootrom physical memory
-u8* g_uncached_bootrom = NULL;
+static u8* physical_bootrom = nullptr; ///< Bootrom physical memory
+static u8* uncached_bootrom = nullptr;
-u8* g_physical_exefs_code = NULL; ///< Phsical ExeFS:/.code is loaded here
-u8* g_physical_system_mem = NULL; ///< System physical memory
-u8* g_physical_fcram = NULL; ///< Main physical memory (FCRAM)
-u8* g_physical_heap_gsp = NULL; ///< GSP heap physical memory
-u8* g_physical_vram = NULL; ///< Video physical memory (VRAM)
-u8* g_physical_shared_mem = NULL; ///< Physical shared memory
-u8* g_physical_kernel_mem; ///< Kernel memory
+static u8* physical_exefs_code = nullptr; ///< Phsical ExeFS:/.code is loaded here
+static u8* physical_system_mem = nullptr; ///< System physical memory
+static u8* physical_fcram = nullptr; ///< Main physical memory (FCRAM)
+static u8* physical_heap_gsp = nullptr; ///< GSP heap physical memory
+static u8* physical_vram = nullptr; ///< Video physical memory (VRAM)
+static u8* physical_shared_mem = nullptr; ///< Physical shared memory
+static u8* physical_kernel_mem; ///< Kernel memory
// We don't declare the IO region in here since its handled by other means.
static MemoryView g_views[] = {
- {&g_exefs_code, &g_physical_exefs_code, EXEFS_CODE_VADDR, EXEFS_CODE_SIZE, 0},
- {&g_vram, &g_physical_vram, VRAM_VADDR, VRAM_SIZE, 0},
- {&g_heap, &g_physical_fcram, HEAP_VADDR, HEAP_SIZE, MV_IS_PRIMARY_RAM},
- {&g_shared_mem, &g_physical_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, 0},
- {&g_system_mem, &g_physical_system_mem, SYSTEM_MEMORY_VADDR, SYSTEM_MEMORY_SIZE, 0},
- {&g_kernel_mem, &g_physical_kernel_mem, KERNEL_MEMORY_VADDR, KERNEL_MEMORY_SIZE, 0},
- {&g_heap_gsp, &g_physical_heap_gsp, HEAP_GSP_VADDR, HEAP_GSP_SIZE, 0},
+ {&g_exefs_code, &physical_exefs_code, EXEFS_CODE_VADDR, EXEFS_CODE_SIZE, 0},
+ {&g_vram, &physical_vram, VRAM_VADDR, VRAM_SIZE, 0},
+ {&g_heap, &physical_fcram, HEAP_VADDR, HEAP_SIZE, MV_IS_PRIMARY_RAM},
+ {&g_shared_mem, &physical_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, 0},
+ {&g_system_mem, &physical_system_mem, SYSTEM_MEMORY_VADDR, SYSTEM_MEMORY_SIZE, 0},
+ {&g_kernel_mem, &physical_kernel_mem, KERNEL_MEMORY_VADDR, KERNEL_MEMORY_SIZE, 0},
+ {&g_heap_gsp, &physical_heap_gsp, HEAP_GSP_VADDR, HEAP_GSP_SIZE, 0},
};
/*static MemoryView views[] =
@@ -69,18 +69,18 @@ void Init() {
g_views[i].size = FCRAM_SIZE;
}
- g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &g_arena);
+ g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &arena);
NOTICE_LOG(MEMMAP, "initialized OK, RAM at %p (mirror at 0 @ %p)", g_heap,
- g_physical_fcram);
+ physical_fcram);
}
void Shutdown() {
u32 flags = 0;
- MemoryMap_Shutdown(g_views, kNumMemViews, flags, &g_arena);
+ MemoryMap_Shutdown(g_views, kNumMemViews, flags, &arena);
- g_arena.ReleaseSpace();
- g_base = NULL;
+ arena.ReleaseSpace();
+ g_base = nullptr;
NOTICE_LOG(MEMMAP, "shutdown OK");
}
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index eed44504..a58c5924 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -147,6 +147,7 @@ u32 Read16_ZX(VAddr addr);
void Write8(VAddr addr, u8 data);
void Write16(VAddr addr, u16 data);
void Write32(VAddr addr, u32 data);
+void Write64(VAddr addr, u64 data);
void WriteBlock(VAddr addr, const u8* data, size_t size);
@@ -156,7 +157,7 @@ u8* GetPointer(VAddr virtual_address);
* Maps a block of memory on the heap
* @param size Size of block in bytes
* @param operation Memory map operation type
- * @param flags Memory allocation flags
+ * @param permissions Memory allocation permissions
*/
u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions);
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 90951812..e8747840 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -12,9 +12,9 @@
namespace Memory {
-std::map<u32, MemoryBlock> g_heap_map;
-std::map<u32, MemoryBlock> g_heap_gsp_map;
-std::map<u32, MemoryBlock> g_shared_map;
+static std::map<u32, MemoryBlock> heap_map;
+static std::map<u32, MemoryBlock> heap_gsp_map;
+static std::map<u32, MemoryBlock> shared_map;
/// Convert a physical address to virtual address
VAddr PhysicalToVirtualAddress(const PAddr addr) {
@@ -92,7 +92,7 @@ inline void Read(T &var, const VAddr vaddr) {
var = *((const T*)&g_vram[vaddr & VRAM_MASK]);
} else {
- ERROR_LOG(MEMMAP, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
+ ERROR_LOG(MEMMAP, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, vaddr);
}
}
@@ -141,7 +141,7 @@ inline void Write(const VAddr vaddr, const T data) {
// Error out...
} else {
- ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr);
+ ERROR_LOG(MEMMAP, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, vaddr);
}
}
@@ -194,11 +194,11 @@ u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
block.operation = operation;
block.permissions = permissions;
- if (g_heap_map.size() > 0) {
- const MemoryBlock last_block = g_heap_map.rbegin()->second;
+ if (heap_map.size() > 0) {
+ const MemoryBlock last_block = heap_map.rbegin()->second;
block.address = last_block.address + last_block.size;
}
- g_heap_map[block.GetVirtualAddress()] = block;
+ heap_map[block.GetVirtualAddress()] = block;
return block.GetVirtualAddress();
}
@@ -217,11 +217,11 @@ u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) {
block.operation = operation;
block.permissions = permissions;
- if (g_heap_gsp_map.size() > 0) {
- const MemoryBlock last_block = g_heap_gsp_map.rbegin()->second;
+ if (heap_gsp_map.size() > 0) {
+ const MemoryBlock last_block = heap_gsp_map.rbegin()->second;
block.address = last_block.address + last_block.size;
}
- g_heap_gsp_map[block.GetVirtualAddress()] = block;
+ heap_gsp_map[block.GetVirtualAddress()] = block;
return block.GetVirtualAddress();
}
diff --git a/src/core/system.h b/src/core/system.h
index 8f8ddf87..2bc2edc7 100644
--- a/src/core/system.h
+++ b/src/core/system.h
@@ -11,16 +11,16 @@
namespace System {
// State of the full emulator
-typedef enum {
- STATE_NULL = 0, ///< System is in null state, nothing initialized
- STATE_IDLE, ///< System is in an initialized state, but not running
- STATE_RUNNING, ///< System is running
- STATE_LOADING, ///< System is loading a ROM
- STATE_HALTED, ///< System is halted (error)
- STATE_STALLED, ///< System is stalled (unused)
- STATE_DEBUG, ///< System is in a special debug mode (unused)
- STATE_DIE ///< System is shutting down
-} State;
+enum State {
+ STATE_NULL = 0, ///< System is in null state, nothing initialized
+ STATE_IDLE, ///< System is in an initialized state, but not running
+ STATE_RUNNING, ///< System is running
+ STATE_LOADING, ///< System is loading a ROM
+ STATE_HALTED, ///< System is halted (error)
+ STATE_STALLED, ///< System is stalled (unused)
+ STATE_DEBUG, ///< System is in a special debug mode (unused)
+ STATE_DIE ///< System is shutting down
+};
extern volatile State g_state;
@@ -30,4 +30,4 @@ void RunLoopFor(int cycles);
void RunLoopUntil(u64 global_cycles);
void Shutdown();
-};
+}
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 22b8e995..275b06b7 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) {
return;
#ifndef HAVE_PNG
- return;
+ return;
#else
- if (!data)
+ if (!data)
return;
// 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 8b1499bf..b1558cfa 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
// Utility class to log Pica commands.
struct PicaTrace {
struct Write : public std::pair<u32,u32> {
- Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {}
+ Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {}
u32& Id() { return first; }
const u32& Id() const { return first; }
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index f1dbc9d1..bce402b8 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -25,7 +25,7 @@ public:
/// Swap buffers (render frame)
virtual void SwapBuffers() = 0;
- /**
+ /**
* Set the emulator window to use for renderer
* @param window EmuWindow handle to emulator window to use for rendering
*/
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 8483f79b..abbb4c2c 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
* Draws the emulated screens to the emulator window.
*/
void RendererOpenGL::DrawScreens() {
- glViewport(0, 0, resolution_width, resolution_height);
+ auto viewport_extent = GetViewportExtent();
+ glViewport(viewport_extent.left, viewport_extent.top, viewport_extent.GetWidth(), viewport_extent.GetHeight()); // TODO: Or bottom?
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program_id);
@@ -228,6 +229,34 @@ void RendererOpenGL::SetWindow(EmuWindow* window) {
render_window = window;
}
+MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() {
+ unsigned framebuffer_width;
+ unsigned framebuffer_height;
+ std::tie(framebuffer_width, framebuffer_height) = render_window->GetFramebufferSize();
+
+ float window_aspect_ratio = static_cast<float>(framebuffer_height) / framebuffer_width;
+ float emulation_aspect_ratio = static_cast<float>(resolution_height) / resolution_width;
+
+ MathUtil::Rectangle<unsigned> viewport_extent;
+ if (window_aspect_ratio > emulation_aspect_ratio) {
+ // Window is narrower than the emulation content => apply borders to the top and bottom
+ unsigned viewport_height = emulation_aspect_ratio * framebuffer_width;
+ viewport_extent.left = 0;
+ viewport_extent.top = (framebuffer_height - viewport_height) / 2;
+ viewport_extent.right = viewport_extent.left + framebuffer_width;
+ viewport_extent.bottom = viewport_extent.top + viewport_height;
+ } else {
+ // Otherwise, apply borders to the left and right sides of the window.
+ unsigned viewport_width = framebuffer_height / emulation_aspect_ratio;
+ viewport_extent.left = (framebuffer_width - viewport_width) / 2;
+ viewport_extent.top = 0;
+ viewport_extent.right = viewport_extent.left + viewport_width;
+ viewport_extent.bottom = viewport_extent.top + framebuffer_height;
+ }
+
+ return viewport_extent;
+}
+
/// Initialize the renderer
void RendererOpenGL::Init() {
render_window->MakeCurrent();
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index eed201a9..7fdcec73 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -4,13 +4,15 @@
#pragma once
+#include <array>
+
#include "generated/gl_3_2_core.h"
-#include "common/common.h"
+#include "common/math_util.h"
+
#include "core/hw/gpu.h"
-#include "video_core/renderer_base.h"
-#include <array>
+#include "video_core/renderer_base.h"
class EmuWindow;
@@ -52,6 +54,9 @@ private:
static void LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& framebuffer,
const TextureInfo& texture);
+ /// Computes the viewport rectangle
+ MathUtil::Rectangle<unsigned> GetViewportExtent();
+
EmuWindow* render_window; ///< Handle to render window
u32 last_mode; ///< Last render mode
diff --git a/src/video_core/utils.cpp b/src/video_core/utils.cpp
index c1848f92..f1156a49 100644
--- a/src/video_core/utils.cpp
+++ b/src/video_core/utils.cpp
@@ -20,7 +20,7 @@ namespace VideoCore {
void DumpTGA(std::string filename, short width, short height, u8* raw_data) {
TGAHeader hdr = {0, 0, 2, 0, 0, 0, 0, width, height, 24, 0};
FILE* fout = fopen(filename.c_str(), "wb");
-
+
fwrite(&hdr, sizeof(TGAHeader), 1, fout);
for (int y = 0; y < height; y++) {
@@ -30,7 +30,7 @@ void DumpTGA(std::string filename, short width, short height, u8* raw_data) {
putc(raw_data[(3 * (y * width)) + (3 * x) + 2], fout); // r
}
}
-
+
fclose(fout);
}
} // namespace
diff --git a/src/video_core/utils.h b/src/video_core/utils.h
index 9cb3d4d4..21380a90 100644
--- a/src/video_core/utils.h
+++ b/src/video_core/utils.h
@@ -12,24 +12,24 @@ namespace FormatPrecision {
/// Adjust RGBA8 color with RGBA6 precision
static inline u32 rgba8_with_rgba6(u32 src) {
- u32 color = src;
- color &= 0xFCFCFCFC;
- color |= (color >> 6) & 0x03030303;
- return color;
+ u32 color = src;
+ color &= 0xFCFCFCFC;
+ color |= (color >> 6) & 0x03030303;
+ return color;
}
/// Adjust RGBA8 color with RGB565 precision
static inline u32 rgba8_with_rgb565(u32 src) {
- u32 color = (src & 0xF8FCF8);
- color |= (color >> 5) & 0x070007;
- color |= (color >> 6) & 0x000300;
- color |= 0xFF000000;
- return color;
+ u32 color = (src & 0xF8FCF8);
+ color |= (color >> 5) & 0x070007;
+ color |= (color >> 6) & 0x000300;
+ color |= 0xFF000000;
+ return color;
}
/// Adjust Z24 depth value with Z16 precision
static inline u32 z24_with_z16(u32 src) {
- return (src & 0xFFFF00) | (src >> 16);
+ return (src & 0xFFFF00) | (src >> 16);
}
} // namespace
diff --git a/src/video_core/vertex_shader.h b/src/video_core/vertex_shader.h
index 607a8e80..bfb6fb6e 100644
--- a/src/video_core/vertex_shader.h
+++ b/src/video_core/vertex_shader.h
@@ -141,7 +141,7 @@ union Instruction {
return BitFieldType::Value();
else if (GetRegisterType() == Temporary)
return BitFieldType::Value() - 0x10;
- else if (GetRegisterType() == FloatUniform)
+ else // if (GetRegisterType() == FloatUniform)
return BitFieldType::Value() - 0x20;
}