summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--CONTRIBUTING.md1
-rw-r--r--src/citra/config.cpp17
-rw-r--r--src/citra/config.h5
-rw-r--r--src/citra/emu_window/emu_window_glfw.cpp14
-rw-r--r--src/citra_qt/bootmanager.cpp2
-rw-r--r--src/citra_qt/config.cpp52
-rw-r--r--src/citra_qt/config.h11
-rw-r--r--src/citra_qt/hotkeys.cpp4
-rw-r--r--src/citra_qt/main.cpp10
-rw-r--r--src/common/chunk_file.h24
-rw-r--r--src/common/common_funcs.h2
-rw-r--r--src/common/console_listener.cpp10
-rw-r--r--src/common/extended_trace.cpp24
-rw-r--r--src/common/fifo_queue.h4
-rw-r--r--src/common/file_util.cpp24
-rw-r--r--src/common/file_util.h4
-rw-r--r--src/common/linear_disk_cache.h2
-rw-r--r--src/common/log_manager.cpp5
-rw-r--r--src/common/mem_arena.cpp20
-rw-r--r--src/common/memory_util.cpp10
-rw-r--r--src/common/misc.cpp4
-rw-r--r--src/common/platform.h2
-rw-r--r--src/common/string_util.cpp8
-rw-r--r--src/common/thread_queue_list.h12
-rw-r--r--src/common/timer.cpp6
-rw-r--r--src/common/utf8.cpp24
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp54
-rw-r--r--src/core/arm/interpreter/armemu.cpp8
-rw-r--r--src/core/arm/skyeye_common/armcpu.h2
-rw-r--r--src/core/core_timing.cpp12
-rw-r--r--src/core/file_sys/archive.h18
-rw-r--r--src/core/file_sys/archive_romfs.cpp10
-rw-r--r--src/core/file_sys/archive_romfs.h16
-rw-r--r--src/core/file_sys/archive_sdmc.cpp12
-rw-r--r--src/core/file_sys/archive_sdmc.h16
-rw-r--r--src/core/file_sys/directory.h6
-rw-r--r--src/core/file_sys/directory_romfs.cpp4
-rw-r--r--src/core/file_sys/directory_romfs.h6
-rw-r--r--src/core/file_sys/directory_sdmc.cpp13
-rw-r--r--src/core/file_sys/directory_sdmc.h7
-rw-r--r--src/core/file_sys/file_sdmc.cpp9
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp2
-rw-r--r--src/core/hle/kernel/archive.cpp84
-rw-r--r--src/core/hle/kernel/archive.h28
-rw-r--r--src/core/hle/kernel/kernel.cpp13
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/mutex.cpp15
-rw-r--r--src/core/hle/kernel/thread.cpp49
-rw-r--r--src/core/hle/kernel/thread.h19
-rw-r--r--src/core/hle/service/ac_u.cpp20
-rw-r--r--src/core/hle/service/cfg_u.cpp88
-rw-r--r--src/core/hle/service/dsp_dsp.cpp150
-rw-r--r--src/core/hle/service/dsp_dsp.h2
-rw-r--r--src/core/hle/service/fs_user.cpp100
-rw-r--r--src/core/hle/service/hid_user.cpp4
-rw-r--r--src/core/hle/service/hid_user.h4
-rw-r--r--src/core/hle/service/ptm_u.cpp94
-rw-r--r--src/core/hle/svc.cpp14
-rw-r--r--src/core/hw/gpu.cpp6
-rw-r--r--src/core/hw/hw.cpp2
-rw-r--r--src/core/hw/ndma.cpp2
-rw-r--r--src/core/loader/3dsx.cpp236
-rw-r--r--src/core/loader/3dsx.h32
-rw-r--r--src/core/loader/loader.cpp7
-rw-r--r--src/core/loader/loader.h1
-rw-r--r--src/core/mem_map.h16
-rw-r--r--src/core/mem_map_funcs.cpp46
-rw-r--r--src/video_core/command_processor.cpp2
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp10
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp6
-rw-r--r--src/video_core/video_core.cpp4
74 files changed, 1178 insertions, 388 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bbe9f76cd..05a560404 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,6 +9,8 @@ if (NOT MSVC)
9else() 9else()
10 # Silence deprecation warnings 10 # Silence deprecation warnings
11 add_definitions(/D_CRT_SECURE_NO_WARNINGS) 11 add_definitions(/D_CRT_SECURE_NO_WARNINGS)
12 # set up output paths for executable binaries (.exe-files, and .dll-files on DLL-capable platforms)
13 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
12endif() 14endif()
13add_definitions(-DSINGLETHREADED) 15add_definitions(-DSINGLETHREADED)
14 16
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 82b66be75..c8c8e3884 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -27,6 +27,7 @@ Follow the indentation/whitespace style shown below. Do not use tabs, use 4-spac
27### Comments 27### Comments
28* For regular comments, use C++ style (`//`) comments, even for multi-line ones. 28* For regular comments, use C++ style (`//`) comments, even for multi-line ones.
29* For doc-comments (Doxygen comments), use `/// ` if it's a single line, else use the `/**` `*/` style featured in the example. Start the text on the second line, not the first containing `/**`. 29* For doc-comments (Doxygen comments), use `/// ` if it's a single line, else use the `/**` `*/` style featured in the example. Start the text on the second line, not the first containing `/**`.
30* For items that are both defined and declared in two separate files, put the doc-comment only next to the associated declaration. (In a header file, usually.) Otherwise, put it next to the implementation. Never duplicate doc-comments in both places.
30 31
31```cpp 32```cpp
32namespace Example { 33namespace Example {
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index f45d09fc2..1f8f5922b 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -36,7 +36,8 @@ bool Config::LoadINI(INIReader* config, const char* location, const std::string&
36 return true; 36 return true;
37} 37}
38 38
39void Config::ReadControls() { 39void Config::ReadValues() {
40 // Controls
40 Settings::values.pad_a_key = glfw_config->GetInteger("Controls", "pad_a", GLFW_KEY_A); 41 Settings::values.pad_a_key = glfw_config->GetInteger("Controls", "pad_a", GLFW_KEY_A);
41 Settings::values.pad_b_key = glfw_config->GetInteger("Controls", "pad_b", GLFW_KEY_S); 42 Settings::values.pad_b_key = glfw_config->GetInteger("Controls", "pad_b", GLFW_KEY_S);
42 Settings::values.pad_x_key = glfw_config->GetInteger("Controls", "pad_x", GLFW_KEY_Z); 43 Settings::values.pad_x_key = glfw_config->GetInteger("Controls", "pad_x", GLFW_KEY_Z);
@@ -54,27 +55,21 @@ void Config::ReadControls() {
54 Settings::values.pad_sdown_key = glfw_config->GetInteger("Controls", "pad_sdown", GLFW_KEY_DOWN); 55 Settings::values.pad_sdown_key = glfw_config->GetInteger("Controls", "pad_sdown", GLFW_KEY_DOWN);
55 Settings::values.pad_sleft_key = glfw_config->GetInteger("Controls", "pad_sleft", GLFW_KEY_LEFT); 56 Settings::values.pad_sleft_key = glfw_config->GetInteger("Controls", "pad_sleft", GLFW_KEY_LEFT);
56 Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); 57 Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT);
57}
58 58
59void Config::ReadCore() { 59 // Core
60 Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter); 60 Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter);
61 Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 60); 61 Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 60);
62}
63 62
64void Config::ReadData() { 63 // Data Storage
65 Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true); 64 Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true);
66}
67 65
68void Config::ReadMiscellaneous() { 66 // Miscellaneous
69 Settings::values.enable_log = glfw_config->GetBoolean("Miscellaneous", "enable_log", true); 67 Settings::values.enable_log = glfw_config->GetBoolean("Miscellaneous", "enable_log", true);
70} 68}
71 69
72void Config::Reload() { 70void Config::Reload() {
73 LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file); 71 LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file);
74 ReadControls(); 72 ReadValues();
75 ReadCore();
76 ReadData();
77 ReadMiscellaneous();
78} 73}
79 74
80Config::~Config() { 75Config::~Config() {
diff --git a/src/citra/config.h b/src/citra/config.h
index 19bb83700..2b46fa8aa 100644
--- a/src/citra/config.h
+++ b/src/citra/config.h
@@ -15,10 +15,7 @@ class Config {
15 std::string glfw_config_loc; 15 std::string glfw_config_loc;
16 16
17 bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true); 17 bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true);
18 void ReadControls(); 18 void ReadValues();
19 void ReadCore();
20 void ReadData();
21 void ReadMiscellaneous();
22public: 19public:
23 Config(); 20 Config();
24 ~Config(); 21 ~Config();
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp
index 8efb39e2e..982619126 100644
--- a/src/citra/emu_window/emu_window_glfw.cpp
+++ b/src/citra/emu_window/emu_window_glfw.cpp
@@ -58,9 +58,13 @@ EmuWindow_GLFW::EmuWindow_GLFW() {
58 58
59 ReloadSetKeymaps(); 59 ReloadSetKeymaps();
60 60
61 glfwSetErrorCallback([](int error, const char *desc){
62 ERROR_LOG(GUI, "GLFW 0x%08x: %s", error, desc);
63 });
64
61 // Initialize the window 65 // Initialize the window
62 if(glfwInit() != GL_TRUE) { 66 if(glfwInit() != GL_TRUE) {
63 printf("Failed to initialize GLFW! Exiting..."); 67 ERROR_LOG(GUI, "Failed to initialize GLFW! Exiting...");
64 exit(1); 68 exit(1);
65 } 69 }
66 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 70 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
@@ -72,10 +76,10 @@ EmuWindow_GLFW::EmuWindow_GLFW() {
72 std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); 76 std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
73 m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth, 77 m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth,
74 (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight), 78 (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight),
75 window_title.c_str(), NULL, NULL); 79 window_title.c_str(), nullptr, nullptr);
76 80
77 if (m_render_window == NULL) { 81 if (m_render_window == nullptr) {
78 printf("Failed to create GLFW window! Exiting..."); 82 ERROR_LOG(GUI, "Failed to create GLFW window! Exiting...");
79 exit(1); 83 exit(1);
80 } 84 }
81 85
@@ -119,7 +123,7 @@ void EmuWindow_GLFW::MakeCurrent() {
119 123
120/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread 124/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
121void EmuWindow_GLFW::DoneCurrent() { 125void EmuWindow_GLFW::DoneCurrent() {
122 glfwMakeContextCurrent(NULL); 126 glfwMakeContextCurrent(nullptr);
123} 127}
124 128
125void EmuWindow_GLFW::ReloadSetKeymaps() { 129void EmuWindow_GLFW::ReloadSetKeymaps() {
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 9bf079919..9a29f974b 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -230,7 +230,7 @@ QByteArray GRenderWindow::saveGeometry()
230{ 230{
231 // If we are a top-level widget, store the current geometry 231 // If we are a top-level widget, store the current geometry
232 // otherwise, store the last backup 232 // otherwise, store the last backup
233 if (parent() == NULL) 233 if (parent() == nullptr)
234 return ((QGLWidget*)this)->saveGeometry(); 234 return ((QGLWidget*)this)->saveGeometry();
235 else 235 else
236 return geometry; 236 return geometry;
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 09fce4d6f..3209e5900 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -21,7 +21,7 @@ Config::Config() {
21 Reload(); 21 Reload();
22} 22}
23 23
24void Config::ReadControls() { 24void Config::ReadValues() {
25 qt_config->beginGroup("Controls"); 25 qt_config->beginGroup("Controls");
26 Settings::values.pad_a_key = qt_config->value("pad_a", Qt::Key_A).toInt(); 26 Settings::values.pad_a_key = qt_config->value("pad_a", Qt::Key_A).toInt();
27 Settings::values.pad_b_key = qt_config->value("pad_b", Qt::Key_S).toInt(); 27 Settings::values.pad_b_key = qt_config->value("pad_b", Qt::Key_S).toInt();
@@ -41,9 +41,22 @@ void Config::ReadControls() {
41 Settings::values.pad_sleft_key = qt_config->value("pad_sleft", Qt::Key_Left).toInt(); 41 Settings::values.pad_sleft_key = qt_config->value("pad_sleft", Qt::Key_Left).toInt();
42 Settings::values.pad_sright_key = qt_config->value("pad_sright", Qt::Key_Right).toInt(); 42 Settings::values.pad_sright_key = qt_config->value("pad_sright", Qt::Key_Right).toInt();
43 qt_config->endGroup(); 43 qt_config->endGroup();
44
45 qt_config->beginGroup("Core");
46 Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt();
47 Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 60).toInt();
48 qt_config->endGroup();
49
50 qt_config->beginGroup("Data Storage");
51 Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
52 qt_config->endGroup();
53
54 qt_config->beginGroup("Miscellaneous");
55 Settings::values.enable_log = qt_config->value("enable_log", true).toBool();
56 qt_config->endGroup();
44} 57}
45 58
46void Config::SaveControls() { 59void Config::SaveValues() {
47 qt_config->beginGroup("Controls"); 60 qt_config->beginGroup("Controls");
48 qt_config->setValue("pad_a", Settings::values.pad_a_key); 61 qt_config->setValue("pad_a", Settings::values.pad_a_key);
49 qt_config->setValue("pad_b", Settings::values.pad_b_key); 62 qt_config->setValue("pad_b", Settings::values.pad_b_key);
@@ -63,58 +76,27 @@ void Config::SaveControls() {
63 qt_config->setValue("pad_sleft", Settings::values.pad_sleft_key); 76 qt_config->setValue("pad_sleft", Settings::values.pad_sleft_key);
64 qt_config->setValue("pad_sright", Settings::values.pad_sright_key); 77 qt_config->setValue("pad_sright", Settings::values.pad_sright_key);
65 qt_config->endGroup(); 78 qt_config->endGroup();
66}
67
68void Config::ReadCore() {
69 qt_config->beginGroup("Core");
70 Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt();
71 Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 60).toInt();
72 qt_config->endGroup();
73}
74 79
75void Config::SaveCore() {
76 qt_config->beginGroup("Core"); 80 qt_config->beginGroup("Core");
77 qt_config->setValue("cpu_core", Settings::values.cpu_core); 81 qt_config->setValue("cpu_core", Settings::values.cpu_core);
78 qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate); 82 qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate);
79 qt_config->endGroup(); 83 qt_config->endGroup();
80}
81
82void Config::ReadData() {
83 qt_config->beginGroup("Data Storage");
84 Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
85 qt_config->endGroup();
86}
87 84
88void Config::SaveData() {
89 qt_config->beginGroup("Data Storage"); 85 qt_config->beginGroup("Data Storage");
90 qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); 86 qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
91 qt_config->endGroup(); 87 qt_config->endGroup();
92}
93
94void Config::ReadMiscellaneous() {
95 qt_config->beginGroup("Miscellaneous");
96 Settings::values.enable_log = qt_config->value("enable_log", true).toBool();
97 qt_config->endGroup();
98}
99 88
100void Config::SaveMiscellaneous() {
101 qt_config->beginGroup("Miscellaneous"); 89 qt_config->beginGroup("Miscellaneous");
102 qt_config->setValue("enable_log", Settings::values.enable_log); 90 qt_config->setValue("enable_log", Settings::values.enable_log);
103 qt_config->endGroup(); 91 qt_config->endGroup();
104} 92}
105 93
106void Config::Reload() { 94void Config::Reload() {
107 ReadControls(); 95 ReadValues();
108 ReadCore();
109 ReadData();
110 ReadMiscellaneous();
111} 96}
112 97
113void Config::Save() { 98void Config::Save() {
114 SaveControls(); 99 SaveValues();
115 SaveCore();
116 SaveData();
117 SaveMiscellaneous();
118} 100}
119 101
120Config::~Config() { 102Config::~Config() {
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h
index 8c6568cb2..4c95d0cb9 100644
--- a/src/citra_qt/config.h
+++ b/src/citra_qt/config.h
@@ -12,15 +12,8 @@ class Config {
12 QSettings* qt_config; 12 QSettings* qt_config;
13 std::string qt_config_loc; 13 std::string qt_config_loc;
14 14
15 void ReadControls(); 15 void ReadValues();
16 void SaveControls(); 16 void SaveValues();
17 void ReadCore();
18 void SaveCore();
19 void ReadData();
20 void SaveData();
21
22 void ReadMiscellaneous();
23 void SaveMiscellaneous();
24public: 17public:
25 Config(); 18 Config();
26 ~Config(); 19 ~Config();
diff --git a/src/citra_qt/hotkeys.cpp b/src/citra_qt/hotkeys.cpp
index bbaa4a8dc..5d0b52e4f 100644
--- a/src/citra_qt/hotkeys.cpp
+++ b/src/citra_qt/hotkeys.cpp
@@ -5,7 +5,7 @@
5 5
6struct Hotkey 6struct Hotkey
7{ 7{
8 Hotkey() : shortcut(NULL), context(Qt::WindowShortcut) {} 8 Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) {}
9 9
10 QKeySequence keyseq; 10 QKeySequence keyseq;
11 QShortcut* shortcut; 11 QShortcut* shortcut;
@@ -81,7 +81,7 @@ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widge
81 Hotkey& hk = hotkey_groups[group][action]; 81 Hotkey& hk = hotkey_groups[group][action];
82 82
83 if (!hk.shortcut) 83 if (!hk.shortcut)
84 hk.shortcut = new QShortcut(hk.keyseq, widget, NULL, NULL, hk.context); 84 hk.shortcut = new QShortcut(hk.keyseq, widget, nullptr, nullptr, hk.context);
85 85
86 return hk.shortcut; 86 return hk.shortcut;
87} 87}
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index d5554d917..0701decef 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -131,7 +131,7 @@ GMainWindow::GMainWindow()
131GMainWindow::~GMainWindow() 131GMainWindow::~GMainWindow()
132{ 132{
133 // will get automatically deleted otherwise 133 // will get automatically deleted otherwise
134 if (render_window->parent() == NULL) 134 if (render_window->parent() == nullptr)
135 delete render_window; 135 delete render_window;
136} 136}
137 137
@@ -164,7 +164,7 @@ void GMainWindow::BootGame(std::string filename)
164 164
165void GMainWindow::OnMenuLoadFile() 165void GMainWindow::OnMenuLoadFile()
166{ 166{
167 QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS executable (*.elf *.axf *.bin *.cci *.cxi)")); 167 QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS executable (*.3dsx *.elf *.axf *.bin *.cci *.cxi)"));
168 if (filename.size()) 168 if (filename.size())
169 BootGame(filename.toLatin1().data()); 169 BootGame(filename.toLatin1().data());
170} 170}
@@ -213,14 +213,14 @@ void GMainWindow::OnOpenHotkeysDialog()
213void GMainWindow::ToggleWindowMode() 213void GMainWindow::ToggleWindowMode()
214{ 214{
215 bool enable = ui.action_Popout_Window_Mode->isChecked(); 215 bool enable = ui.action_Popout_Window_Mode->isChecked();
216 if (enable && render_window->parent() != NULL) 216 if (enable && render_window->parent() != nullptr)
217 { 217 {
218 ui.horizontalLayout->removeWidget(render_window); 218 ui.horizontalLayout->removeWidget(render_window);
219 render_window->setParent(NULL); 219 render_window->setParent(nullptr);
220 render_window->setVisible(true); 220 render_window->setVisible(true);
221 render_window->RestoreGeometry(); 221 render_window->RestoreGeometry();
222 } 222 }
223 else if (!enable && render_window->parent() == NULL) 223 else if (!enable && render_window->parent() == nullptr)
224 { 224 {
225 render_window->BackupGeometry(); 225 render_window->BackupGeometry();
226 ui.horizontalLayout->addWidget(render_window); 226 ui.horizontalLayout->addWidget(render_window);
diff --git a/src/common/chunk_file.h b/src/common/chunk_file.h
index 609784076..32af74594 100644
--- a/src/common/chunk_file.h
+++ b/src/common/chunk_file.h
@@ -204,11 +204,11 @@ public:
204 { 204 {
205 for (auto it = x.begin(), end = x.end(); it != end; ++it) 205 for (auto it = x.begin(), end = x.end(); it != end; ++it)
206 { 206 {
207 if (it->second != NULL) 207 if (it->second != nullptr)
208 delete it->second; 208 delete it->second;
209 } 209 }
210 } 210 }
211 T *dv = NULL; 211 T *dv = nullptr;
212 DoMap(x, dv); 212 DoMap(x, dv);
213 } 213 }
214 214
@@ -264,11 +264,11 @@ public:
264 { 264 {
265 for (auto it = x.begin(), end = x.end(); it != end; ++it) 265 for (auto it = x.begin(), end = x.end(); it != end; ++it)
266 { 266 {
267 if (it->second != NULL) 267 if (it->second != nullptr)
268 delete it->second; 268 delete it->second;
269 } 269 }
270 } 270 }
271 T *dv = NULL; 271 T *dv = nullptr;
272 DoMultimap(x, dv); 272 DoMultimap(x, dv);
273 } 273 }
274 274
@@ -320,7 +320,7 @@ public:
320 template<class T> 320 template<class T>
321 void Do(std::vector<T *> &x) 321 void Do(std::vector<T *> &x)
322 { 322 {
323 T *dv = NULL; 323 T *dv = nullptr;
324 DoVector(x, dv); 324 DoVector(x, dv);
325 } 325 }
326 326
@@ -369,7 +369,7 @@ public:
369 template<class T> 369 template<class T>
370 void Do(std::deque<T *> &x) 370 void Do(std::deque<T *> &x)
371 { 371 {
372 T *dv = NULL; 372 T *dv = nullptr;
373 DoDeque(x, dv); 373 DoDeque(x, dv);
374 } 374 }
375 375
@@ -395,7 +395,7 @@ public:
395 template<class T> 395 template<class T>
396 void Do(std::list<T *> &x) 396 void Do(std::list<T *> &x)
397 { 397 {
398 T *dv = NULL; 398 T *dv = nullptr;
399 Do(x, dv); 399 Do(x, dv);
400 } 400 }
401 401
@@ -433,7 +433,7 @@ public:
433 { 433 {
434 for (auto it = x.begin(), end = x.end(); it != end; ++it) 434 for (auto it = x.begin(), end = x.end(); it != end; ++it)
435 { 435 {
436 if (*it != NULL) 436 if (*it != nullptr)
437 delete *it; 437 delete *it;
438 } 438 }
439 } 439 }
@@ -518,7 +518,7 @@ public:
518 void DoClass(T *&x) { 518 void DoClass(T *&x) {
519 if (mode == MODE_READ) 519 if (mode == MODE_READ)
520 { 520 {
521 if (x != NULL) 521 if (x != nullptr)
522 delete x; 522 delete x;
523 x = new T(); 523 x = new T();
524 } 524 }
@@ -567,7 +567,7 @@ public:
567 { 567 {
568 if (mode == MODE_READ) 568 if (mode == MODE_READ)
569 { 569 {
570 cur->next = 0; 570 cur->next = nullptr;
571 list_cur = cur; 571 list_cur = cur;
572 if (prev) 572 if (prev)
573 prev->next = cur; 573 prev->next = cur;
@@ -586,13 +586,13 @@ public:
586 if (mode == MODE_READ) 586 if (mode == MODE_READ)
587 { 587 {
588 if (prev) 588 if (prev)
589 prev->next = 0; 589 prev->next = nullptr;
590 if (list_end) 590 if (list_end)
591 *list_end = prev; 591 *list_end = prev;
592 if (list_cur) 592 if (list_cur)
593 { 593 {
594 if (list_start == list_cur) 594 if (list_start == list_cur)
595 list_start = 0; 595 list_start = nullptr;
596 do 596 do
597 { 597 {
598 LinkedListItem<T>* next = list_cur->next; 598 LinkedListItem<T>* next = list_cur->next;
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index d84ec4c42..1139dc3b8 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -106,7 +106,7 @@ inline u64 _rotr64(u64 x, unsigned int shift){
106 // Restore the global locale 106 // Restore the global locale
107 _configthreadlocale(_DISABLE_PER_THREAD_LOCALE); 107 _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
108 } 108 }
109 else if(new_locale != NULL) 109 else if(new_locale != nullptr)
110 { 110 {
111 // Configure the thread to set the locale only for this thread 111 // Configure the thread to set the locale only for this thread
112 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); 112 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
diff --git a/src/common/console_listener.cpp b/src/common/console_listener.cpp
index d7f27c358..b6042796d 100644
--- a/src/common/console_listener.cpp
+++ b/src/common/console_listener.cpp
@@ -16,7 +16,7 @@
16ConsoleListener::ConsoleListener() 16ConsoleListener::ConsoleListener()
17{ 17{
18#ifdef _WIN32 18#ifdef _WIN32
19 hConsole = NULL; 19 hConsole = nullptr;
20 bUseColor = true; 20 bUseColor = true;
21#else 21#else
22 bUseColor = isatty(fileno(stdout)); 22 bUseColor = isatty(fileno(stdout));
@@ -66,19 +66,19 @@ void ConsoleListener::UpdateHandle()
66void ConsoleListener::Close() 66void ConsoleListener::Close()
67{ 67{
68#ifdef _WIN32 68#ifdef _WIN32
69 if (hConsole == NULL) 69 if (hConsole == nullptr)
70 return; 70 return;
71 FreeConsole(); 71 FreeConsole();
72 hConsole = NULL; 72 hConsole = nullptr;
73#else 73#else
74 fflush(NULL); 74 fflush(nullptr);
75#endif 75#endif
76} 76}
77 77
78bool ConsoleListener::IsOpen() 78bool ConsoleListener::IsOpen()
79{ 79{
80#ifdef _WIN32 80#ifdef _WIN32
81 return (hConsole != NULL); 81 return (hConsole != nullptr);
82#else 82#else
83 return true; 83 return true;
84#endif 84#endif
diff --git a/src/common/extended_trace.cpp b/src/common/extended_trace.cpp
index bf61ac1d1..cf7c346d4 100644
--- a/src/common/extended_trace.cpp
+++ b/src/common/extended_trace.cpp
@@ -82,7 +82,7 @@ static void InitSymbolPath( PSTR lpszSymbolPath, PCSTR lpszIniPath )
82 } 82 }
83 83
84 // Add user defined path 84 // Add user defined path
85 if ( lpszIniPath != NULL ) 85 if ( lpszIniPath != nullptr )
86 if ( lpszIniPath[0] != '\0' ) 86 if ( lpszIniPath[0] != '\0' )
87 { 87 {
88 strcat( lpszSymbolPath, ";" ); 88 strcat( lpszSymbolPath, ";" );
@@ -138,7 +138,7 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
138 DWORD dwSymSize = 10000; 138 DWORD dwSymSize = 10000;
139 TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?"); 139 TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?");
140 CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?"; 140 CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?";
141 LPTSTR lpszParamSep = NULL; 141 LPTSTR lpszParamSep = nullptr;
142 LPTSTR lpszParsed = lpszUnDSymbol; 142 LPTSTR lpszParsed = lpszUnDSymbol;
143 PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize ); 143 PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize );
144 144
@@ -187,13 +187,13 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
187 187
188 // Let's go through the stack, and modify the function prototype, and insert the actual 188 // Let's go through the stack, and modify the function prototype, and insert the actual
189 // parameter values from the stack 189 // parameter values from the stack
190 if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == NULL && _tcsstr( lpszUnDSymbol, _T("()") ) == NULL) 190 if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == nullptr && _tcsstr( lpszUnDSymbol, _T("()") ) == nullptr)
191 { 191 {
192 ULONG index = 0; 192 ULONG index = 0;
193 for( ; ; index++ ) 193 for( ; ; index++ )
194 { 194 {
195 lpszParamSep = _tcschr( lpszParsed, _T(',') ); 195 lpszParamSep = _tcschr( lpszParsed, _T(',') );
196 if ( lpszParamSep == NULL ) 196 if ( lpszParamSep == nullptr )
197 break; 197 break;
198 198
199 *lpszParamSep = _T('\0'); 199 *lpszParamSep = _T('\0');
@@ -205,7 +205,7 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
205 } 205 }
206 206
207 lpszParamSep = _tcschr( lpszParsed, _T(')') ); 207 lpszParamSep = _tcschr( lpszParsed, _T(')') );
208 if ( lpszParamSep != NULL ) 208 if ( lpszParamSep != nullptr )
209 { 209 {
210 *lpszParamSep = _T('\0'); 210 *lpszParamSep = _T('\0');
211 211
@@ -248,7 +248,7 @@ static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
248 PCSTR2LPTSTR( lineInfo.FileName, lpszFileName ); 248 PCSTR2LPTSTR( lineInfo.FileName, lpszFileName );
249 TCHAR fname[_MAX_FNAME]; 249 TCHAR fname[_MAX_FNAME];
250 TCHAR ext[_MAX_EXT]; 250 TCHAR ext[_MAX_EXT];
251 _tsplitpath(lpszFileName, NULL, NULL, fname, ext); 251 _tsplitpath(lpszFileName, nullptr, nullptr, fname, ext);
252 _stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber ); 252 _stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber );
253 ret = TRUE; 253 ret = TRUE;
254 } 254 }
@@ -332,11 +332,11 @@ void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
332 hProcess, 332 hProcess,
333 hThread, 333 hThread,
334 &callStack, 334 &callStack,
335 NULL, 335 nullptr,
336 NULL, 336 nullptr,
337 SymFunctionTableAccess, 337 SymFunctionTableAccess,
338 SymGetModuleBase, 338 SymGetModuleBase,
339 NULL); 339 nullptr);
340 340
341 if ( index == 0 ) 341 if ( index == 0 )
342 continue; 342 continue;
@@ -389,11 +389,11 @@ void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip,
389 hProcess, 389 hProcess,
390 hThread, 390 hThread,
391 &callStack, 391 &callStack,
392 NULL, 392 nullptr,
393 NULL, 393 nullptr,
394 SymFunctionTableAccess, 394 SymFunctionTableAccess,
395 SymGetModuleBase, 395 SymGetModuleBase,
396 NULL); 396 nullptr);
397 397
398 if ( index == 0 ) 398 if ( index == 0 )
399 continue; 399 continue;
diff --git a/src/common/fifo_queue.h b/src/common/fifo_queue.h
index 2c18285d4..b426e6596 100644
--- a/src/common/fifo_queue.h
+++ b/src/common/fifo_queue.h
@@ -57,7 +57,7 @@ public:
57 // advance the read pointer 57 // advance the read pointer
58 m_read_ptr = m_read_ptr->next; 58 m_read_ptr = m_read_ptr->next;
59 // set the next element to NULL to stop the recursive deletion 59 // set the next element to NULL to stop the recursive deletion
60 tmpptr->next = NULL; 60 tmpptr->next = nullptr;
61 delete tmpptr; // this also deletes the element 61 delete tmpptr; // this also deletes the element
62 } 62 }
63 63
@@ -86,7 +86,7 @@ private:
86 class ElementPtr 86 class ElementPtr
87 { 87 {
88 public: 88 public:
89 ElementPtr() : current(NULL), next(NULL) {} 89 ElementPtr() : current(nullptr), next(nullptr) {}
90 90
91 ~ElementPtr() 91 ~ElementPtr()
92 { 92 {
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index b6dec838c..6c4860503 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -140,7 +140,7 @@ bool CreateDir(const std::string &path)
140{ 140{
141 INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str()); 141 INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
142#ifdef _WIN32 142#ifdef _WIN32
143 if (::CreateDirectory(Common::UTF8ToTStr(path).c_str(), NULL)) 143 if (::CreateDirectory(Common::UTF8ToTStr(path).c_str(), nullptr))
144 return true; 144 return true;
145 DWORD error = GetLastError(); 145 DWORD error = GetLastError();
146 if (error == ERROR_ALREADY_EXISTS) 146 if (error == ERROR_ALREADY_EXISTS)
@@ -423,7 +423,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
423 FSTEntry entry; 423 FSTEntry entry;
424 const std::string virtualName(Common::TStrToUTF8(ffd.cFileName)); 424 const std::string virtualName(Common::TStrToUTF8(ffd.cFileName));
425#else 425#else
426 struct dirent dirent, *result = NULL; 426 struct dirent dirent, *result = nullptr;
427 427
428 DIR *dirp = opendir(directory.c_str()); 428 DIR *dirp = opendir(directory.c_str());
429 if (!dirp) 429 if (!dirp)
@@ -491,7 +491,7 @@ bool DeleteDirRecursively(const std::string &directory)
491 { 491 {
492 const std::string virtualName(Common::TStrToUTF8(ffd.cFileName)); 492 const std::string virtualName(Common::TStrToUTF8(ffd.cFileName));
493#else 493#else
494 struct dirent dirent, *result = NULL; 494 struct dirent dirent, *result = nullptr;
495 DIR *dirp = opendir(directory.c_str()); 495 DIR *dirp = opendir(directory.c_str());
496 if (!dirp) 496 if (!dirp)
497 return false; 497 return false;
@@ -552,7 +552,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path)
552 if (!FileUtil::Exists(source_path)) return; 552 if (!FileUtil::Exists(source_path)) return;
553 if (!FileUtil::Exists(dest_path)) FileUtil::CreateFullPath(dest_path); 553 if (!FileUtil::Exists(dest_path)) FileUtil::CreateFullPath(dest_path);
554 554
555 struct dirent dirent, *result = NULL; 555 struct dirent dirent, *result = nullptr;
556 DIR *dirp = opendir(source_path.c_str()); 556 DIR *dirp = opendir(source_path.c_str());
557 if (!dirp) return; 557 if (!dirp) return;
558 558
@@ -586,11 +586,11 @@ std::string GetCurrentDir()
586{ 586{
587 char *dir; 587 char *dir;
588 // Get the current working directory (getcwd uses malloc) 588 // Get the current working directory (getcwd uses malloc)
589 if (!(dir = __getcwd(NULL, 0))) { 589 if (!(dir = __getcwd(nullptr, 0))) {
590 590
591 ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s", 591 ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
592 GetLastErrorMsg()); 592 GetLastErrorMsg());
593 return NULL; 593 return nullptr;
594 } 594 }
595 std::string strDir = dir; 595 std::string strDir = dir;
596 free(dir); 596 free(dir);
@@ -626,7 +626,7 @@ std::string& GetExeDirectory()
626 if (DolphinPath.empty()) 626 if (DolphinPath.empty())
627 { 627 {
628 TCHAR Dolphin_exe_Path[2048]; 628 TCHAR Dolphin_exe_Path[2048];
629 GetModuleFileName(NULL, Dolphin_exe_Path, 2048); 629 GetModuleFileName(nullptr, Dolphin_exe_Path, 2048);
630 DolphinPath = Common::TStrToUTF8(Dolphin_exe_Path); 630 DolphinPath = Common::TStrToUTF8(Dolphin_exe_Path);
631 DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\')); 631 DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
632 } 632 }
@@ -826,7 +826,7 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
826} 826}
827 827
828IOFile::IOFile() 828IOFile::IOFile()
829 : m_file(NULL), m_good(true) 829 : m_file(nullptr), m_good(true)
830{} 830{}
831 831
832IOFile::IOFile(std::FILE* file) 832IOFile::IOFile(std::FILE* file)
@@ -834,7 +834,7 @@ IOFile::IOFile(std::FILE* file)
834{} 834{}
835 835
836IOFile::IOFile(const std::string& filename, const char openmode[]) 836IOFile::IOFile(const std::string& filename, const char openmode[])
837 : m_file(NULL), m_good(true) 837 : m_file(nullptr), m_good(true)
838{ 838{
839 Open(filename, openmode); 839 Open(filename, openmode);
840} 840}
@@ -845,7 +845,7 @@ IOFile::~IOFile()
845} 845}
846 846
847IOFile::IOFile(IOFile&& other) 847IOFile::IOFile(IOFile&& other)
848 : m_file(NULL), m_good(true) 848 : m_file(nullptr), m_good(true)
849{ 849{
850 Swap(other); 850 Swap(other);
851} 851}
@@ -880,14 +880,14 @@ bool IOFile::Close()
880 if (!IsOpen() || 0 != std::fclose(m_file)) 880 if (!IsOpen() || 0 != std::fclose(m_file))
881 m_good = false; 881 m_good = false;
882 882
883 m_file = NULL; 883 m_file = nullptr;
884 return m_good; 884 return m_good;
885} 885}
886 886
887std::FILE* IOFile::ReleaseHandle() 887std::FILE* IOFile::ReleaseHandle()
888{ 888{
889 std::FILE* const ret = m_file; 889 std::FILE* const ret = m_file;
890 m_file = NULL; 890 m_file = nullptr;
891 return ret; 891 return ret;
892} 892}
893 893
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 72b80be8a..beaf7174a 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -202,11 +202,11 @@ public:
202 return WriteArray(reinterpret_cast<const char*>(data), length); 202 return WriteArray(reinterpret_cast<const char*>(data), length);
203 } 203 }
204 204
205 bool IsOpen() { return NULL != m_file; } 205 bool IsOpen() { return nullptr != m_file; }
206 206
207 // m_good is set to false when a read, write or other function fails 207 // m_good is set to false when a read, write or other function fails
208 bool IsGood() { return m_good; } 208 bool IsGood() { return m_good; }
209 operator void*() { return m_good ? m_file : NULL; } 209 operator void*() { return m_good ? m_file : nullptr; }
210 210
211 std::FILE* ReleaseHandle(); 211 std::FILE* ReleaseHandle();
212 212
diff --git a/src/common/linear_disk_cache.h b/src/common/linear_disk_cache.h
index f4263f72a..bb1b5174f 100644
--- a/src/common/linear_disk_cache.h
+++ b/src/common/linear_disk_cache.h
@@ -70,7 +70,7 @@ public:
70 // good header, read some key/value pairs 70 // good header, read some key/value pairs
71 K key; 71 K key;
72 72
73 V *value = NULL; 73 V *value = nullptr;
74 u32 value_size; 74 u32 value_size;
75 u32 entry_number; 75 u32 entry_number;
76 76
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp
index 38c681ee0..39b1924c7 100644
--- a/src/common/log_manager.cpp
+++ b/src/common/log_manager.cpp
@@ -7,7 +7,6 @@
7#include "common/log_manager.h" 7#include "common/log_manager.h"
8#include "common/console_listener.h" 8#include "common/console_listener.h"
9#include "common/timer.h" 9#include "common/timer.h"
10#include "common/thread.h"
11 10
12void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, 11void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
13 const char* function, const char* fmt, ...) 12 const char* function, const char* fmt, ...)
@@ -22,7 +21,7 @@ void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char*
22 va_end(args); 21 va_end(args);
23} 22}
24 23
25LogManager *LogManager::m_logManager = NULL; 24LogManager *LogManager::m_logManager = nullptr;
26 25
27LogManager::LogManager() 26LogManager::LogManager()
28{ 27{
@@ -142,7 +141,7 @@ void LogManager::Init()
142void LogManager::Shutdown() 141void LogManager::Shutdown()
143{ 142{
144 delete m_logManager; 143 delete m_logManager;
145 m_logManager = NULL; 144 m_logManager = nullptr;
146} 145}
147 146
148LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable) 147LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable)
diff --git a/src/common/mem_arena.cpp b/src/common/mem_arena.cpp
index 67dbaf509..7d4fda0e2 100644
--- a/src/common/mem_arena.cpp
+++ b/src/common/mem_arena.cpp
@@ -30,7 +30,7 @@
30#endif 30#endif
31 31
32#ifdef IOS 32#ifdef IOS
33void* globalbase = NULL; 33void* globalbase = nullptr;
34#endif 34#endif
35 35
36#ifdef ANDROID 36#ifdef ANDROID
@@ -121,7 +121,7 @@ void MemArena::GrabLowMemSpace(size_t size)
121{ 121{
122#ifdef _WIN32 122#ifdef _WIN32
123#ifndef _XBOX 123#ifndef _XBOX
124 hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL); 124 hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, (DWORD)(size), nullptr);
125 GetSystemInfo(&sysInfo); 125 GetSystemInfo(&sysInfo);
126#endif 126#endif
127#elif defined(ANDROID) 127#elif defined(ANDROID)
@@ -178,7 +178,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base)
178#ifdef _XBOX 178#ifdef _XBOX
179 size = roundup(size); 179 size = roundup(size);
180 // use 64kb pages 180 // use 64kb pages
181 void * ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); 181 void * ptr = VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
182 return ptr; 182 return ptr;
183#else 183#else
184 size = roundup(size); 184 size = roundup(size);
@@ -243,8 +243,8 @@ u8* MemArena::Find4GBBase()
243 return base; 243 return base;
244#else 244#else
245#ifdef IOS 245#ifdef IOS
246 void* base = NULL; 246 void* base = nullptr;
247 if (globalbase == NULL){ 247 if (globalbase == nullptr){
248 base = mmap(0, 0x08000000, PROT_READ | PROT_WRITE, 248 base = mmap(0, 0x08000000, PROT_READ | PROT_WRITE,
249 MAP_ANON | MAP_SHARED, -1, 0); 249 MAP_ANON | MAP_SHARED, -1, 0);
250 if (base == MAP_FAILED) { 250 if (base == MAP_FAILED) {
@@ -357,7 +357,7 @@ bail:
357 if (views[j].out_ptr_low && *views[j].out_ptr_low) 357 if (views[j].out_ptr_low && *views[j].out_ptr_low)
358 { 358 {
359 arena->ReleaseView(*views[j].out_ptr_low, views[j].size); 359 arena->ReleaseView(*views[j].out_ptr_low, views[j].size);
360 *views[j].out_ptr_low = NULL; 360 *views[j].out_ptr_low = nullptr;
361 } 361 }
362 if (*views[j].out_ptr) 362 if (*views[j].out_ptr)
363 { 363 {
@@ -369,7 +369,7 @@ bail:
369 arena->ReleaseView(*views[j].out_ptr, views[j].size); 369 arena->ReleaseView(*views[j].out_ptr, views[j].size);
370 } 370 }
371#endif 371#endif
372 *views[j].out_ptr = NULL; 372 *views[j].out_ptr = nullptr;
373 } 373 }
374 } 374 }
375 return false; 375 return false;
@@ -415,7 +415,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
415#elif defined(_WIN32) 415#elif defined(_WIN32)
416 // Try a whole range of possible bases. Return once we got a valid one. 416 // Try a whole range of possible bases. Return once we got a valid one.
417 u32 max_base_addr = 0x7FFF0000 - 0x10000000; 417 u32 max_base_addr = 0x7FFF0000 - 0x10000000;
418 u8 *base = NULL; 418 u8 *base = nullptr;
419 419
420 for (u32 base_addr = 0x01000000; base_addr < max_base_addr; base_addr += 0x400000) 420 for (u32 base_addr = 0x01000000; base_addr < max_base_addr; base_addr += 0x400000)
421 { 421 {
@@ -463,8 +463,8 @@ void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemAr
463 arena->ReleaseView(*views[i].out_ptr_low, views[i].size); 463 arena->ReleaseView(*views[i].out_ptr_low, views[i].size);
464 if (*views[i].out_ptr && (views[i].out_ptr_low && *views[i].out_ptr != *views[i].out_ptr_low)) 464 if (*views[i].out_ptr && (views[i].out_ptr_low && *views[i].out_ptr != *views[i].out_ptr_low))
465 arena->ReleaseView(*views[i].out_ptr, views[i].size); 465 arena->ReleaseView(*views[i].out_ptr, views[i].size);
466 *views[i].out_ptr = NULL; 466 *views[i].out_ptr = nullptr;
467 if (views[i].out_ptr_low) 467 if (views[i].out_ptr_low)
468 *views[i].out_ptr_low = NULL; 468 *views[i].out_ptr_low = nullptr;
469 } 469 }
470} 470}
diff --git a/src/common/memory_util.cpp b/src/common/memory_util.cpp
index b6f66e4e1..93da5500b 100644
--- a/src/common/memory_util.cpp
+++ b/src/common/memory_util.cpp
@@ -93,7 +93,7 @@ void* AllocateMemoryPages(size_t size)
93 // printf("Mapped memory at %p (size %ld)\n", ptr, 93 // printf("Mapped memory at %p (size %ld)\n", ptr,
94 // (unsigned long)size); 94 // (unsigned long)size);
95 95
96 if (ptr == NULL) 96 if (ptr == nullptr)
97 PanicAlert("Failed to allocate raw memory"); 97 PanicAlert("Failed to allocate raw memory");
98 98
99 return ptr; 99 return ptr;
@@ -104,7 +104,7 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
104#ifdef _WIN32 104#ifdef _WIN32
105 void* ptr = _aligned_malloc(size,alignment); 105 void* ptr = _aligned_malloc(size,alignment);
106#else 106#else
107 void* ptr = NULL; 107 void* ptr = nullptr;
108#ifdef ANDROID 108#ifdef ANDROID
109 ptr = memalign(alignment, size); 109 ptr = memalign(alignment, size);
110#else 110#else
@@ -116,7 +116,7 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
116 // printf("Mapped memory at %p (size %ld)\n", ptr, 116 // printf("Mapped memory at %p (size %ld)\n", ptr,
117 // (unsigned long)size); 117 // (unsigned long)size);
118 118
119 if (ptr == NULL) 119 if (ptr == nullptr)
120 PanicAlert("Failed to allocate aligned memory"); 120 PanicAlert("Failed to allocate aligned memory");
121 121
122 return ptr; 122 return ptr;
@@ -130,7 +130,7 @@ void FreeMemoryPages(void* ptr, size_t size)
130 130
131 if (!VirtualFree(ptr, 0, MEM_RELEASE)) 131 if (!VirtualFree(ptr, 0, MEM_RELEASE))
132 PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg()); 132 PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
133 ptr = NULL; // Is this our responsibility? 133 ptr = nullptr; // Is this our responsibility?
134 134
135#else 135#else
136 munmap(ptr, size); 136 munmap(ptr, size);
@@ -184,7 +184,7 @@ std::string MemUsage()
184 // Print information about the memory usage of the process. 184 // Print information about the memory usage of the process.
185 185
186 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); 186 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
187 if (NULL == hProcess) return "MemUsage Error"; 187 if (nullptr == hProcess) return "MemUsage Error";
188 188
189 if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) 189 if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
190 Ret = Common::StringFromFormat("%s K", Common::ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str()); 190 Ret = Common::StringFromFormat("%s K", Common::ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
diff --git a/src/common/misc.cpp b/src/common/misc.cpp
index cf6df44e8..bc9d26188 100644
--- a/src/common/misc.cpp
+++ b/src/common/misc.cpp
@@ -23,9 +23,9 @@ const char* GetLastErrorMsg()
23#ifdef _WIN32 23#ifdef _WIN32
24 static __declspec(thread) char err_str[buff_size] = {}; 24 static __declspec(thread) char err_str[buff_size] = {};
25 25
26 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 26 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(),
27 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 27 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
28 err_str, buff_size, NULL); 28 err_str, buff_size, nullptr);
29#else 29#else
30 static __thread char err_str[buff_size] = {}; 30 static __thread char err_str[buff_size] = {};
31 31
diff --git a/src/common/platform.h b/src/common/platform.h
index d9f095433..53d98fe74 100644
--- a/src/common/platform.h
+++ b/src/common/platform.h
@@ -77,7 +77,7 @@
77inline struct tm* localtime_r(const time_t *clock, struct tm *result) { 77inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
78 if (localtime_s(result, clock) == 0) 78 if (localtime_s(result, clock) == 0)
79 return result; 79 return result;
80 return NULL; 80 return nullptr;
81} 81}
82 82
83#else 83#else
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index dcec9275f..7fb7ede5e 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -31,7 +31,7 @@ std::string ToUpper(std::string str) {
31// faster than sscanf 31// faster than sscanf
32bool AsciiToHex(const char* _szValue, u32& result) 32bool AsciiToHex(const char* _szValue, u32& result)
33{ 33{
34 char *endptr = NULL; 34 char *endptr = nullptr;
35 const u32 value = strtoul(_szValue, &endptr, 16); 35 const u32 value = strtoul(_szValue, &endptr, 16);
36 36
37 if (!endptr || *endptr) 37 if (!endptr || *endptr)
@@ -69,7 +69,7 @@ bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list ar
69 // will be present in the middle of a multibyte sequence. 69 // will be present in the middle of a multibyte sequence.
70 // 70 //
71 // This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l. 71 // This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l.
72 static locale_t c_locale = NULL; 72 static locale_t c_locale = nullptr;
73 if (!c_locale) 73 if (!c_locale)
74 c_locale = _create_locale(LC_ALL, ".1252"); 74 c_locale = _create_locale(LC_ALL, ".1252");
75 writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args); 75 writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args);
@@ -92,7 +92,7 @@ bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list ar
92std::string StringFromFormat(const char* format, ...) 92std::string StringFromFormat(const char* format, ...)
93{ 93{
94 va_list args; 94 va_list args;
95 char *buf = NULL; 95 char *buf = nullptr;
96#ifdef _WIN32 96#ifdef _WIN32
97 int required = 0; 97 int required = 0;
98 98
@@ -162,7 +162,7 @@ std::string StripQuotes(const std::string& s)
162 162
163bool TryParse(const std::string &str, u32 *const output) 163bool TryParse(const std::string &str, u32 *const output)
164{ 164{
165 char *endptr = NULL; 165 char *endptr = nullptr;
166 166
167 // Reset errno to a value other than ERANGE 167 // Reset errno to a value other than ERANGE
168 errno = 0; 168 errno = 0;
diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h
index 59efbce4c..7e3b620c7 100644
--- a/src/common/thread_queue_list.h
+++ b/src/common/thread_queue_list.h
@@ -37,7 +37,7 @@ struct ThreadQueueList {
37 ~ThreadQueueList() { 37 ~ThreadQueueList() {
38 for (int i = 0; i < NUM_QUEUES; ++i) 38 for (int i = 0; i < NUM_QUEUES; ++i)
39 { 39 {
40 if (queues[i].data != NULL) 40 if (queues[i].data != nullptr)
41 free(queues[i].data); 41 free(queues[i].data);
42 } 42 }
43 } 43 }
@@ -46,7 +46,7 @@ struct ThreadQueueList {
46 int contains(const IdType uid) { 46 int contains(const IdType uid) {
47 for (int i = 0; i < NUM_QUEUES; ++i) 47 for (int i = 0; i < NUM_QUEUES; ++i)
48 { 48 {
49 if (queues[i].data == NULL) 49 if (queues[i].data == nullptr)
50 continue; 50 continue;
51 51
52 Queue *cur = &queues[i]; 52 Queue *cur = &queues[i];
@@ -133,7 +133,7 @@ struct ThreadQueueList {
133 inline void clear() { 133 inline void clear() {
134 for (int i = 0; i < NUM_QUEUES; ++i) 134 for (int i = 0; i < NUM_QUEUES; ++i)
135 { 135 {
136 if (queues[i].data != NULL) 136 if (queues[i].data != nullptr)
137 free(queues[i].data); 137 free(queues[i].data);
138 } 138 }
139 memset(queues, 0, sizeof(queues)); 139 memset(queues, 0, sizeof(queues));
@@ -147,7 +147,7 @@ struct ThreadQueueList {
147 147
148 inline void prepare(u32 priority) { 148 inline void prepare(u32 priority) {
149 Queue *cur = &queues[priority]; 149 Queue *cur = &queues[priority];
150 if (cur->next == NULL) 150 if (cur->next == nullptr)
151 link(priority, INITIAL_CAPACITY); 151 link(priority, INITIAL_CAPACITY);
152 } 152 }
153 153
@@ -176,7 +176,7 @@ private:
176 176
177 for (int i = (int) priority - 1; i >= 0; --i) 177 for (int i = (int) priority - 1; i >= 0; --i)
178 { 178 {
179 if (queues[i].next != NULL) 179 if (queues[i].next != nullptr)
180 { 180 {
181 cur->next = queues[i].next; 181 cur->next = queues[i].next;
182 queues[i].next = cur; 182 queues[i].next = cur;
@@ -193,7 +193,7 @@ private:
193 int size = cur->end - cur->first; 193 int size = cur->end - cur->first;
194 if (size >= cur->capacity - 2) { 194 if (size >= cur->capacity - 2) {
195 IdType *new_data = (IdType *)realloc(cur->data, cur->capacity * 2 * sizeof(IdType)); 195 IdType *new_data = (IdType *)realloc(cur->data, cur->capacity * 2 * sizeof(IdType));
196 if (new_data != NULL) { 196 if (new_data != nullptr) {
197 cur->capacity *= 2; 197 cur->capacity *= 2;
198 cur->data = new_data; 198 cur->data = new_data;
199 } 199 }
diff --git a/src/common/timer.cpp b/src/common/timer.cpp
index ded4a344e..4a797f751 100644
--- a/src/common/timer.cpp
+++ b/src/common/timer.cpp
@@ -25,7 +25,7 @@ u32 Timer::GetTimeMs()
25 return timeGetTime(); 25 return timeGetTime();
26#else 26#else
27 struct timeval t; 27 struct timeval t;
28 (void)gettimeofday(&t, NULL); 28 (void)gettimeofday(&t, nullptr);
29 return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000)); 29 return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000));
30#endif 30#endif
31} 31}
@@ -183,7 +183,7 @@ std::string Timer::GetTimeFormatted()
183 return StringFromFormat("%s:%03i", tmp, tp.millitm); 183 return StringFromFormat("%s:%03i", tmp, tp.millitm);
184#else 184#else
185 struct timeval t; 185 struct timeval t;
186 (void)gettimeofday(&t, NULL); 186 (void)gettimeofday(&t, nullptr);
187 return StringFromFormat("%s:%03d", tmp, (int)(t.tv_usec / 1000)); 187 return StringFromFormat("%s:%03d", tmp, (int)(t.tv_usec / 1000));
188#endif 188#endif
189} 189}
@@ -197,7 +197,7 @@ double Timer::GetDoubleTime()
197 (void)::ftime(&tp); 197 (void)::ftime(&tp);
198#else 198#else
199 struct timeval t; 199 struct timeval t;
200 (void)gettimeofday(&t, NULL); 200 (void)gettimeofday(&t, nullptr);
201#endif 201#endif
202 // Get continuous timestamp 202 // Get continuous timestamp
203 u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970(); 203 u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970();
diff --git a/src/common/utf8.cpp b/src/common/utf8.cpp
index be4ebc855..66a2f6339 100644
--- a/src/common/utf8.cpp
+++ b/src/common/utf8.cpp
@@ -281,28 +281,28 @@ int u8_read_escape_sequence(const char *str, u32 *dest)
281 do { 281 do {
282 digs[dno++] = str[i++]; 282 digs[dno++] = str[i++];
283 } while (octal_digit(str[i]) && dno < 3); 283 } while (octal_digit(str[i]) && dno < 3);
284 ch = strtol(digs, NULL, 8); 284 ch = strtol(digs, nullptr, 8);
285 } 285 }
286 else if (str[0] == 'x') { 286 else if (str[0] == 'x') {
287 while (hex_digit(str[i]) && dno < 2) { 287 while (hex_digit(str[i]) && dno < 2) {
288 digs[dno++] = str[i++]; 288 digs[dno++] = str[i++];
289 } 289 }
290 if (dno > 0) 290 if (dno > 0)
291 ch = strtol(digs, NULL, 16); 291 ch = strtol(digs, nullptr, 16);
292 } 292 }
293 else if (str[0] == 'u') { 293 else if (str[0] == 'u') {
294 while (hex_digit(str[i]) && dno < 4) { 294 while (hex_digit(str[i]) && dno < 4) {
295 digs[dno++] = str[i++]; 295 digs[dno++] = str[i++];
296 } 296 }
297 if (dno > 0) 297 if (dno > 0)
298 ch = strtol(digs, NULL, 16); 298 ch = strtol(digs, nullptr, 16);
299 } 299 }
300 else if (str[0] == 'U') { 300 else if (str[0] == 'U') {
301 while (hex_digit(str[i]) && dno < 8) { 301 while (hex_digit(str[i]) && dno < 8) {
302 digs[dno++] = str[i++]; 302 digs[dno++] = str[i++];
303 } 303 }
304 if (dno > 0) 304 if (dno > 0)
305 ch = strtol(digs, NULL, 16); 305 ch = strtol(digs, nullptr, 16);
306 } 306 }
307 *dest = ch; 307 *dest = ch;
308 308
@@ -353,7 +353,7 @@ const char *u8_strchr(const char *s, u32 ch, int *charn)
353 lasti = i; 353 lasti = i;
354 (*charn)++; 354 (*charn)++;
355 } 355 }
356 return NULL; 356 return nullptr;
357} 357}
358 358
359const char *u8_memchr(const char *s, u32 ch, size_t sz, int *charn) 359const char *u8_memchr(const char *s, u32 ch, size_t sz, int *charn)
@@ -378,7 +378,7 @@ const char *u8_memchr(const char *s, u32 ch, size_t sz, int *charn)
378 lasti = i; 378 lasti = i;
379 (*charn)++; 379 (*charn)++;
380 } 380 }
381 return NULL; 381 return nullptr;
382} 382}
383 383
384int u8_is_locale_utf8(const char *locale) 384int u8_is_locale_utf8(const char *locale)
@@ -419,35 +419,35 @@ bool UTF8StringHasNonASCII(const char *utf8string) {
419 419
420std::string ConvertWStringToUTF8(const wchar_t *wstr) { 420std::string ConvertWStringToUTF8(const wchar_t *wstr) {
421 int len = (int)wcslen(wstr); 421 int len = (int)wcslen(wstr);
422 int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, NULL, NULL); 422 int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, nullptr, nullptr);
423 std::string s; 423 std::string s;
424 s.resize(size); 424 s.resize(size);
425 if (size > 0) { 425 if (size > 0) {
426 WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, NULL, NULL); 426 WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, nullptr, nullptr);
427 } 427 }
428 return s; 428 return s;
429} 429}
430 430
431std::string ConvertWStringToUTF8(const std::wstring &wstr) { 431std::string ConvertWStringToUTF8(const std::wstring &wstr) {
432 int len = (int)wstr.size(); 432 int len = (int)wstr.size();
433 int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL); 433 int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, nullptr, nullptr);
434 std::string s; 434 std::string s;
435 s.resize(size); 435 s.resize(size);
436 if (size > 0) { 436 if (size > 0) {
437 WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, NULL, NULL); 437 WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, nullptr, nullptr);
438 } 438 }
439 return s; 439 return s;
440} 440}
441 441
442void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) { 442void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) {
443 int len = (int)source.size(); 443 int len = (int)source.size();
444 int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0); 444 int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0);
445 MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size)); 445 MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size));
446} 446}
447 447
448std::wstring ConvertUTF8ToWString(const std::string &source) { 448std::wstring ConvertUTF8ToWString(const std::string &source) {
449 int len = (int)source.size(); 449 int len = (int)source.size();
450 int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0); 450 int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0);
451 std::wstring str; 451 std::wstring str;
452 str.resize(size); 452 str.resize(size);
453 if (size > 0) { 453 if (size > 0) {
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 48241c3d4..f3d7dca9e 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -63,6 +63,7 @@ set(SRCS
63 loader/elf.cpp 63 loader/elf.cpp
64 loader/loader.cpp 64 loader/loader.cpp
65 loader/ncch.cpp 65 loader/ncch.cpp
66 loader/3dsx.cpp
66 core.cpp 67 core.cpp
67 core_timing.cpp 68 core_timing.cpp
68 mem_map.cpp 69 mem_map.cpp
@@ -143,6 +144,7 @@ set(HEADERS
143 loader/elf.h 144 loader/elf.h
144 loader/loader.h 145 loader/loader.h
145 loader/ncch.h 146 loader/ncch.h
147 loader/3dsx.h
146 core.h 148 core.h
147 core_timing.h 149 core_timing.h
148 mem_map.h 150 mem_map.h
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index f899e2e8a..233cd3e3a 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -26,7 +26,7 @@
26#define CITRA_IGNORE_EXIT(x) 26#define CITRA_IGNORE_EXIT(x)
27 27
28#include <algorithm> 28#include <algorithm>
29#include <map> 29#include <unordered_map>
30#include <stdio.h> 30#include <stdio.h>
31#include <assert.h> 31#include <assert.h>
32#include <cstdio> 32#include <cstdio>
@@ -94,9 +94,8 @@ typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper);
94 94
95/* exclusive memory access */ 95/* exclusive memory access */
96static int exclusive_detect(ARMul_State* state, ARMword addr){ 96static int exclusive_detect(ARMul_State* state, ARMword addr){
97 int i;
98 #if 0 97 #if 0
99 for(i = 0; i < 128; i++){ 98 for(int i = 0; i < 128; i++){
100 if(state->exclusive_tag_array[i] == addr) 99 if(state->exclusive_tag_array[i] == addr)
101 return 0; 100 return 0;
102 } 101 }
@@ -108,9 +107,8 @@ static int exclusive_detect(ARMul_State* state, ARMword addr){
108} 107}
109 108
110static void add_exclusive_addr(ARMul_State* state, ARMword addr){ 109static void add_exclusive_addr(ARMul_State* state, ARMword addr){
111 int i;
112 #if 0 110 #if 0
113 for(i = 0; i < 128; i++){ 111 for(int i = 0; i < 128; i++){
114 if(state->exclusive_tag_array[i] == 0xffffffff){ 112 if(state->exclusive_tag_array[i] == 0xffffffff){
115 state->exclusive_tag_array[i] = addr; 113 state->exclusive_tag_array[i] = addr;
116 //DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr); 114 //DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr);
@@ -3309,9 +3307,8 @@ const transop_fp_t arm_instruction_trans[] = {
3309 INTERPRETER_TRANSLATE(blx_1_thumb) 3307 INTERPRETER_TRANSLATE(blx_1_thumb)
3310}; 3308};
3311 3309
3312typedef map<unsigned int, int> bb_map; 3310typedef std::unordered_map<u32, int> bb_map;
3313bb_map CreamCache[65536]; 3311bb_map CreamCache;
3314bb_map ProfileCache[65536];
3315 3312
3316//#define USE_DUMMY_CACHE 3313//#define USE_DUMMY_CACHE
3317 3314
@@ -3319,14 +3316,12 @@ bb_map ProfileCache[65536];
3319unsigned int DummyCache[0x100000]; 3316unsigned int DummyCache[0x100000];
3320#endif 3317#endif
3321 3318
3322#define HASH(x) ((x + (x << 3) + (x >> 6)) % 65536)
3323void insert_bb(unsigned int addr, int start) 3319void insert_bb(unsigned int addr, int start)
3324{ 3320{
3325#ifdef USE_DUMMY_CACHE 3321#ifdef USE_DUMMY_CACHE
3326 DummyCache[addr] = start; 3322 DummyCache[addr] = start;
3327#else 3323#else
3328// CreamCache[addr] = start; 3324 CreamCache[addr] = start;
3329 CreamCache[HASH(addr)][addr] = start;
3330#endif 3325#endif
3331} 3326}
3332 3327
@@ -3341,8 +3336,8 @@ int find_bb(unsigned int addr, int &start)
3341 } else 3336 } else
3342 ret = -1; 3337 ret = -1;
3343#else 3338#else
3344 bb_map::const_iterator it = CreamCache[HASH(addr)].find(addr); 3339 bb_map::const_iterator it = CreamCache.find(addr);
3345 if (it != CreamCache[HASH(addr)].end()) { 3340 if (it != CreamCache.end()) {
3346 start = static_cast<int>(it->second); 3341 start = static_cast<int>(it->second);
3347 ret = 0; 3342 ret = 0;
3348#if HYBRID_MODE 3343#if HYBRID_MODE
@@ -3473,30 +3468,15 @@ void flush_bb(uint32_t addr)
3473 uint32_t start; 3468 uint32_t start;
3474 3469
3475 addr &= 0xfffff000; 3470 addr &= 0xfffff000;
3476 for (int i = 0; i < 65536; i ++) { 3471 for (it = CreamCache.begin(); it != CreamCache.end(); ) {
3477 for (it = CreamCache[i].begin(); it != CreamCache[i].end(); ) { 3472 start = static_cast<uint32_t>(it->first);
3478 start = static_cast<uint32_t>(it->first); 3473 //start = (start >> 12) << 12;
3479 //start = (start >> 12) << 12; 3474 start &= 0xfffff000;
3480 start &= 0xfffff000; 3475 if (start == addr) {
3481 if (start == addr) { 3476 //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
3482 //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first)); 3477 CreamCache.erase(it++);
3483 CreamCache[i].erase(it ++); 3478 } else
3484 } else 3479 ++it;
3485 ++it;
3486 }
3487 }
3488
3489 for (int i = 0; i < 65536; i ++) {
3490 for (it = ProfileCache[i].begin(); it != ProfileCache[i].end(); ) {
3491 start = static_cast<uint32_t>(it->first);
3492 //start = (start >> 12) << 12;
3493 start &= 0xfffff000;
3494 if (start == addr) {
3495 //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
3496 ProfileCache[i].erase(it ++);
3497 } else
3498 ++it;
3499 }
3500 } 3480 }
3501 3481
3502 //DEBUG_LOG(ARM11, "flush bb @ %x\n", addr); 3482 //DEBUG_LOG(ARM11, "flush bb @ %x\n", addr);
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 73223874e..d717bd2c8 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -5724,7 +5724,7 @@ L_stm_s_takeabort:
5724 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 5724 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5725 s16 b1 = (state->Reg[src2] & 0xFFFF); 5725 s16 b1 = (state->Reg[src2] & 0xFFFF);
5726 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); 5726 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5727 state->Reg[tar] = (a1 - a2)&0xFFFF | (((b1 - b2)&0xFFFF)<< 0x10); 5727 state->Reg[tar] = ((a1 - a2) & 0xFFFF) | (((b1 - b2)&0xFFFF)<< 0x10);
5728 return 1; 5728 return 1;
5729 } 5729 }
5730 else if ((instr & 0xFF0) == 0xf10)//sadd16 5730 else if ((instr & 0xFF0) == 0xf10)//sadd16
@@ -5736,7 +5736,7 @@ L_stm_s_takeabort:
5736 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 5736 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5737 s16 b1 = (state->Reg[src2] & 0xFFFF); 5737 s16 b1 = (state->Reg[src2] & 0xFFFF);
5738 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); 5738 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5739 state->Reg[tar] = (a1 + a2)&0xFFFF | (((b1 + b2)&0xFFFF)<< 0x10); 5739 state->Reg[tar] = ((a1 + a2) & 0xFFFF) | (((b1 + b2)&0xFFFF)<< 0x10);
5740 return 1; 5740 return 1;
5741 } 5741 }
5742 else if ((instr & 0xFF0) == 0xf50)//ssax 5742 else if ((instr & 0xFF0) == 0xf50)//ssax
@@ -5748,7 +5748,7 @@ L_stm_s_takeabort:
5748 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 5748 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5749 s16 b1 = (state->Reg[src2] & 0xFFFF); 5749 s16 b1 = (state->Reg[src2] & 0xFFFF);
5750 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); 5750 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5751 state->Reg[tar] = (a1 - b2) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10); 5751 state->Reg[tar] = ((a1 + b2) & 0xFFFF) | (((a2 - b1) & 0xFFFF) << 0x10);
5752 return 1; 5752 return 1;
5753 } 5753 }
5754 else if ((instr & 0xFF0) == 0xf30)//sasx 5754 else if ((instr & 0xFF0) == 0xf30)//sasx
@@ -5760,7 +5760,7 @@ L_stm_s_takeabort:
5760 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 5760 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5761 s16 b1 = (state->Reg[src2] & 0xFFFF); 5761 s16 b1 = (state->Reg[src2] & 0xFFFF);
5762 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); 5762 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5763 state->Reg[tar] = (a2 - b1) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10); 5763 state->Reg[tar] = ((a1 - b2) & 0xFFFF) | (((a2 + b1) & 0xFFFF) << 0x10);
5764 return 1; 5764 return 1;
5765 } 5765 }
5766 else printf ("Unhandled v6 insn: sadd/ssub\n"); 5766 else printf ("Unhandled v6 insn: sadd/ssub\n");
diff --git a/src/core/arm/skyeye_common/armcpu.h b/src/core/arm/skyeye_common/armcpu.h
index 3a029f0e7..2b756c5bc 100644
--- a/src/core/arm/skyeye_common/armcpu.h
+++ b/src/core/arm/skyeye_common/armcpu.h
@@ -24,8 +24,6 @@
24#include <stddef.h> 24#include <stddef.h>
25#include <stdio.h> 25#include <stdio.h>
26 26
27#include "common/thread.h"
28
29#include "core/arm/skyeye_common/armdefs.h" 27#include "core/arm/skyeye_common/armdefs.h"
30 28
31typedef struct ARM_CPU_State_s { 29typedef struct ARM_CPU_State_s {
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 558c6cbf7..bf8acf41f 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -67,7 +67,7 @@ s64 idledCycles;
67static std::recursive_mutex externalEventSection; 67static std::recursive_mutex externalEventSection;
68 68
69// Warning: not included in save state. 69// Warning: not included in save state.
70void(*advanceCallback)(int cyclesExecuted) = NULL; 70void(*advanceCallback)(int cyclesExecuted) = nullptr;
71 71
72void SetClockFrequencyMHz(int cpuMhz) 72void SetClockFrequencyMHz(int cpuMhz)
73{ 73{
@@ -231,7 +231,7 @@ void ClearPendingEvents()
231 231
232void AddEventToQueue(Event* ne) 232void AddEventToQueue(Event* ne)
233{ 233{
234 Event* prev = NULL; 234 Event* prev = nullptr;
235 Event** pNext = &first; 235 Event** pNext = &first;
236 for (;;) 236 for (;;)
237 { 237 {
@@ -327,7 +327,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata)
327 } 327 }
328 if (!tsFirst) 328 if (!tsFirst)
329 { 329 {
330 tsLast = NULL; 330 tsLast = nullptr;
331 return result; 331 return result;
332 } 332 }
333 333
@@ -433,7 +433,7 @@ void RemoveThreadsafeEvent(int event_type)
433 } 433 }
434 if (!tsFirst) 434 if (!tsFirst)
435 { 435 {
436 tsLast = NULL; 436 tsLast = nullptr;
437 return; 437 return;
438 } 438 }
439 Event *prev = tsFirst; 439 Event *prev = tsFirst;
@@ -495,7 +495,7 @@ void MoveEvents()
495 AddEventToQueue(tsFirst); 495 AddEventToQueue(tsFirst);
496 tsFirst = next; 496 tsFirst = next;
497 } 497 }
498 tsLast = NULL; 498 tsLast = nullptr;
499 499
500 // Move free events to threadsafe pool 500 // Move free events to threadsafe pool
501 while (allocatedTsEvents > 0 && eventPool) 501 while (allocatedTsEvents > 0 && eventPool)
@@ -614,7 +614,7 @@ void DoState(PointerWrap &p)
614 // These (should) be filled in later by the modules. 614 // These (should) be filled in later by the modules.
615 event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT")); 615 event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT"));
616 616
617 p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **)NULL); 617 p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **)nullptr);
618 p.DoLinkedList<BaseEvent, GetNewTsEvent, FreeTsEvent, Event_DoState>(tsFirst, &tsLast); 618 p.DoLinkedList<BaseEvent, GetNewTsEvent, FreeTsEvent, Event_DoState>(tsFirst, &tsLast);
619 619
620 p.Do(g_clock_rate_arm11); 620 p.Do(g_clock_rate_arm11);
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h
index 2e79bb883..f3cb11133 100644
--- a/src/core/file_sys/archive.h
+++ b/src/core/file_sys/archive.h
@@ -67,6 +67,8 @@ public:
67 u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. 67 u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated.
68 break; 68 break;
69 } 69 }
70 default:
71 break;
70 } 72 }
71 } 73 }
72 74
@@ -192,6 +194,14 @@ public:
192 virtual bool DeleteFile(const FileSys::Path& path) const = 0; 194 virtual bool DeleteFile(const FileSys::Path& path) const = 0;
193 195
194 /** 196 /**
197 * Rename a File specified by its path
198 * @param src_path Source path relative to the archive
199 * @param dest_path Destination path relative to the archive
200 * @return Whether rename succeeded
201 */
202 virtual bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0;
203
204 /**
195 * Delete a directory specified by its path 205 * Delete a directory specified by its path
196 * @param path Path relative to the archive 206 * @param path Path relative to the archive
197 * @return Whether the directory could be deleted 207 * @return Whether the directory could be deleted
@@ -206,6 +216,14 @@ public:
206 virtual bool CreateDirectory(const Path& path) const = 0; 216 virtual bool CreateDirectory(const Path& path) const = 0;
207 217
208 /** 218 /**
219 * Rename a Directory specified by its path
220 * @param src_path Source path relative to the archive
221 * @param dest_path Destination path relative to the archive
222 * @return Whether rename succeeded
223 */
224 virtual bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0;
225
226 /**
209 * Open a directory specified by its path 227 * Open a directory specified by its path
210 * @param path Path relative to the archive 228 * @param path Path relative to the archive
211 * @return Opened directory, or nullptr 229 * @return Opened directory, or nullptr
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index 53dc57954..8c2dbeda5 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -43,6 +43,11 @@ bool Archive_RomFS::DeleteFile(const FileSys::Path& path) const {
43 return false; 43 return false;
44} 44}
45 45
46bool Archive_RomFS::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
47 ERROR_LOG(FILESYS, "Attempted to rename a file within ROMFS.");
48 return false;
49}
50
46/** 51/**
47 * Delete a directory specified by its path 52 * Delete a directory specified by its path
48 * @param path Path relative to the archive 53 * @param path Path relative to the archive
@@ -63,6 +68,11 @@ bool Archive_RomFS::CreateDirectory(const Path& path) const {
63 return false; 68 return false;
64} 69}
65 70
71bool Archive_RomFS::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
72 ERROR_LOG(FILESYS, "Attempted to rename a file within ROMFS.");
73 return false;
74}
75
66/** 76/**
67 * Open a directory specified by its path 77 * Open a directory specified by its path
68 * @param path Path relative to the archive 78 * @param path Path relative to the archive
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index 0649dde99..222bdc356 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -44,6 +44,14 @@ public:
44 bool DeleteFile(const FileSys::Path& path) const override; 44 bool DeleteFile(const FileSys::Path& path) const override;
45 45
46 /** 46 /**
47 * Rename a File specified by its path
48 * @param src_path Source path relative to the archive
49 * @param dest_path Destination path relative to the archive
50 * @return Whether rename succeeded
51 */
52 bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
53
54 /**
47 * Delete a directory specified by its path 55 * Delete a directory specified by its path
48 * @param path Path relative to the archive 56 * @param path Path relative to the archive
49 * @return Whether the directory could be deleted 57 * @return Whether the directory could be deleted
@@ -58,6 +66,14 @@ public:
58 bool CreateDirectory(const Path& path) const override; 66 bool CreateDirectory(const Path& path) const override;
59 67
60 /** 68 /**
69 * Rename a Directory specified by its path
70 * @param src_path Source path relative to the archive
71 * @param dest_path Destination path relative to the archive
72 * @return Whether rename succeeded
73 */
74 bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
75
76 /**
61 * Open a directory specified by its path 77 * Open a directory specified by its path
62 * @param path Path relative to the archive 78 * @param path Path relative to the archive
63 * @return Opened directory, or nullptr 79 * @return Opened directory, or nullptr
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index c2ffcd40d..fc0b9b72d 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -50,7 +50,7 @@ bool Archive_SDMC::Initialize() {
50 * @return Opened file, or nullptr 50 * @return Opened file, or nullptr
51 */ 51 */
52std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { 52std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const {
53 DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.DebugStr().c_str(), mode); 53 DEBUG_LOG(FILESYS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex);
54 File_SDMC* file = new File_SDMC(this, path, mode); 54 File_SDMC* file = new File_SDMC(this, path, mode);
55 if (!file->Open()) 55 if (!file->Open())
56 return nullptr; 56 return nullptr;
@@ -66,6 +66,10 @@ bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const {
66 return FileUtil::Delete(GetMountPoint() + path.AsString()); 66 return FileUtil::Delete(GetMountPoint() + path.AsString());
67} 67}
68 68
69bool Archive_SDMC::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
70 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
71}
72
69/** 73/**
70 * Delete a directory specified by its path 74 * Delete a directory specified by its path
71 * @param path Path relative to the archive 75 * @param path Path relative to the archive
@@ -84,6 +88,10 @@ bool Archive_SDMC::CreateDirectory(const Path& path) const {
84 return FileUtil::CreateDir(GetMountPoint() + path.AsString()); 88 return FileUtil::CreateDir(GetMountPoint() + path.AsString());
85} 89}
86 90
91bool Archive_SDMC::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
92 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
93}
94
87/** 95/**
88 * Open a directory specified by its path 96 * Open a directory specified by its path
89 * @param path Path relative to the archive 97 * @param path Path relative to the archive
@@ -92,6 +100,8 @@ bool Archive_SDMC::CreateDirectory(const Path& path) const {
92std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const { 100std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const {
93 DEBUG_LOG(FILESYS, "called path=%s", path.DebugStr().c_str()); 101 DEBUG_LOG(FILESYS, "called path=%s", path.DebugStr().c_str());
94 Directory_SDMC* directory = new Directory_SDMC(this, path); 102 Directory_SDMC* directory = new Directory_SDMC(this, path);
103 if (!directory->Open())
104 return nullptr;
95 return std::unique_ptr<Directory>(directory); 105 return std::unique_ptr<Directory>(directory);
96} 106}
97 107
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 74ce29c0d..19f563a62 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -48,6 +48,14 @@ public:
48 bool DeleteFile(const FileSys::Path& path) const override; 48 bool DeleteFile(const FileSys::Path& path) const override;
49 49
50 /** 50 /**
51 * Rename a File specified by its path
52 * @param src_path Source path relative to the archive
53 * @param dest_path Destination path relative to the archive
54 * @return Whether rename succeeded
55 */
56 bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
57
58 /**
51 * Delete a directory specified by its path 59 * Delete a directory specified by its path
52 * @param path Path relative to the archive 60 * @param path Path relative to the archive
53 * @return Whether the directory could be deleted 61 * @return Whether the directory could be deleted
@@ -62,6 +70,14 @@ public:
62 bool CreateDirectory(const Path& path) const override; 70 bool CreateDirectory(const Path& path) const override;
63 71
64 /** 72 /**
73 * Rename a Directory specified by its path
74 * @param src_path Source path relative to the archive
75 * @param dest_path Destination path relative to the archive
76 * @return Whether rename succeeded
77 */
78 bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
79
80 /**
65 * Open a directory specified by its path 81 * Open a directory specified by its path
66 * @param path Path relative to the archive 82 * @param path Path relative to the archive
67 * @return Opened directory, or nullptr 83 * @return Opened directory, or nullptr
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h
index e10431337..1bb4101d6 100644
--- a/src/core/file_sys/directory.h
+++ b/src/core/file_sys/directory.h
@@ -42,6 +42,12 @@ public:
42 virtual ~Directory() { } 42 virtual ~Directory() { }
43 43
44 /** 44 /**
45 * Open the directory
46 * @return true if the directory opened correctly
47 */
48 virtual bool Open() = 0;
49
50 /**
45 * List files contained in the directory 51 * List files contained in the directory
46 * @param count Number of entries to return at once in entries 52 * @param count Number of entries to return at once in entries
47 * @param entries Buffer to read data into 53 * @param entries Buffer to read data into
diff --git a/src/core/file_sys/directory_romfs.cpp b/src/core/file_sys/directory_romfs.cpp
index 4e8f4c04d..e6d571391 100644
--- a/src/core/file_sys/directory_romfs.cpp
+++ b/src/core/file_sys/directory_romfs.cpp
@@ -17,6 +17,10 @@ Directory_RomFS::Directory_RomFS() {
17Directory_RomFS::~Directory_RomFS() { 17Directory_RomFS::~Directory_RomFS() {
18} 18}
19 19
20bool Directory_RomFS::Open() {
21 return false;
22}
23
20/** 24/**
21 * List files contained in the directory 25 * List files contained in the directory
22 * @param count Number of entries to return at once in entries 26 * @param count Number of entries to return at once in entries
diff --git a/src/core/file_sys/directory_romfs.h b/src/core/file_sys/directory_romfs.h
index 4b71c4b13..e2944099e 100644
--- a/src/core/file_sys/directory_romfs.h
+++ b/src/core/file_sys/directory_romfs.h
@@ -20,6 +20,12 @@ public:
20 ~Directory_RomFS() override; 20 ~Directory_RomFS() override;
21 21
22 /** 22 /**
23 * Open the directory
24 * @return true if the directory opened correctly
25 */
26 bool Open() override;
27
28 /**
23 * List files contained in the directory 29 * List files contained in the directory
24 * @param count Number of entries to return at once in entries 30 * @param count Number of entries to return at once in entries
25 * @param entries Buffer to read data into 31 * @param entries Buffer to read data into
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp
index 60a197ce9..0f156a127 100644
--- a/src/core/file_sys/directory_sdmc.cpp
+++ b/src/core/file_sys/directory_sdmc.cpp
@@ -19,15 +19,22 @@ Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const Path& path) {
19 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass 19 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
20 // the root directory we set while opening the archive. 20 // the root directory we set while opening the archive.
21 // For example, opening /../../usr/bin can give the emulated program your installed programs. 21 // For example, opening /../../usr/bin can give the emulated program your installed programs.
22 std::string absolute_path = archive->GetMountPoint() + path.AsString(); 22 this->path = archive->GetMountPoint() + path.AsString();
23 FileUtil::ScanDirectoryTree(absolute_path, directory); 23
24 children_iterator = directory.children.begin();
25} 24}
26 25
27Directory_SDMC::~Directory_SDMC() { 26Directory_SDMC::~Directory_SDMC() {
28 Close(); 27 Close();
29} 28}
30 29
30bool Directory_SDMC::Open() {
31 if (!FileUtil::IsDirectory(path))
32 return false;
33 FileUtil::ScanDirectoryTree(path, directory);
34 children_iterator = directory.children.begin();
35 return true;
36}
37
31/** 38/**
32 * List files contained in the directory 39 * List files contained in the directory
33 * @param count Number of entries to return at once in entries 40 * @param count Number of entries to return at once in entries
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h
index 4520d0401..4c08b0d61 100644
--- a/src/core/file_sys/directory_sdmc.h
+++ b/src/core/file_sys/directory_sdmc.h
@@ -23,6 +23,12 @@ public:
23 ~Directory_SDMC() override; 23 ~Directory_SDMC() override;
24 24
25 /** 25 /**
26 * Open the directory
27 * @return true if the directory opened correctly
28 */
29 bool Open() override;
30
31 /**
26 * List files contained in the directory 32 * List files contained in the directory
27 * @param count Number of entries to return at once in entries 33 * @param count Number of entries to return at once in entries
28 * @param entries Buffer to read data into 34 * @param entries Buffer to read data into
@@ -37,6 +43,7 @@ public:
37 bool Close() const override; 43 bool Close() const override;
38 44
39private: 45private:
46 std::string path;
40 u32 total_entries_in_directory; 47 u32 total_entries_in_directory;
41 FileUtil::FSTEntry directory; 48 FileUtil::FSTEntry directory;
42 49
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp
index a4b90670a..b01d96e3d 100644
--- a/src/core/file_sys/file_sdmc.cpp
+++ b/src/core/file_sys/file_sdmc.cpp
@@ -38,12 +38,15 @@ bool File_SDMC::Open() {
38 } 38 }
39 39
40 std::string mode_string; 40 std::string mode_string;
41 if (mode.read_flag && mode.write_flag) 41 if (mode.create_flag)
42 mode_string = "w+"; 42 mode_string = "w+";
43 else if (mode.write_flag)
44 mode_string = "r+"; // Files opened with Write access can be read from
43 else if (mode.read_flag) 45 else if (mode.read_flag)
44 mode_string = "r"; 46 mode_string = "r";
45 else if (mode.write_flag) 47
46 mode_string = "w"; 48 // Open the file in binary mode, to avoid problems with CR/LF on Windows systems
49 mode_string += "b";
47 50
48 file = new FileUtil::IOFile(path, mode_string.c_str()); 51 file = new FileUtil::IOFile(path, mode_string.c_str());
49 return true; 52 return true;
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index db571b895..ce4f3c854 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -53,7 +53,7 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3
53 // Wait current thread (acquire the arbiter)... 53 // Wait current thread (acquire the arbiter)...
54 case ArbitrationType::WaitIfLessThan: 54 case ArbitrationType::WaitIfLessThan:
55 if ((s32)Memory::Read32(address) <= value) { 55 if ((s32)Memory::Read32(address) <= value) {
56 Kernel::WaitCurrentThread(WAITTYPE_ARB, handle); 56 Kernel::WaitCurrentThread(WAITTYPE_ARB, handle, address);
57 HLE::Reschedule(__func__); 57 HLE::Reschedule(__func__);
58 } 58 }
59 break; 59 break;
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
index e273444c9..a875fa7ff 100644
--- a/src/core/hle/kernel/archive.cpp
+++ b/src/core/hle/kernel/archive.cpp
@@ -340,49 +340,68 @@ ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path
340 return MakeResult<Handle>(handle); 340 return MakeResult<Handle>(handle);
341} 341}
342 342
343/** 343ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) {
344 * Delete a File from an Archive
345 * @param archive_handle Handle to an open Archive object
346 * @param path Path to the File inside of the Archive
347 * @return Whether deletion succeeded
348 */
349Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) {
350 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 344 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
351 if (archive == nullptr) 345 if (archive == nullptr)
352 return -1; 346 return InvalidHandle(ErrorModule::FS);
353 if (archive->backend->DeleteFile(path)) 347 if (archive->backend->DeleteFile(path))
354 return 0; 348 return RESULT_SUCCESS;
355 return -1; 349 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
350 ErrorSummary::Canceled, ErrorLevel::Status);
356} 351}
357 352
358/** 353ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
359 * Delete a Directory from an Archive 354 Handle dest_archive_handle, const FileSys::Path& dest_path) {
360 * @param archive_handle Handle to an open Archive object 355 Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle);
361 * @param path Path to the Directory inside of the Archive 356 Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle);
362 * @return Whether deletion succeeded 357 if (src_archive == nullptr || dest_archive == nullptr)
363 */ 358 return InvalidHandle(ErrorModule::FS);
364Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { 359 if (src_archive == dest_archive) {
360 if (src_archive->backend->RenameFile(src_path, dest_path))
361 return RESULT_SUCCESS;
362 } else {
363 // TODO: Implement renaming across archives
364 return UnimplementedFunction(ErrorModule::FS);
365 }
366 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
367 ErrorSummary::NothingHappened, ErrorLevel::Status);
368}
369
370ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
365 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 371 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
366 if (archive == nullptr) 372 if (archive == nullptr)
367 return -1; 373 return InvalidHandle(ErrorModule::FS);
368 if (archive->backend->DeleteDirectory(path)) 374 if (archive->backend->DeleteDirectory(path))
369 return 0; 375 return RESULT_SUCCESS;
370 return -1; 376 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
377 ErrorSummary::Canceled, ErrorLevel::Status);
371} 378}
372 379
373/** 380ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
374 * Create a Directory from an Archive
375 * @param archive_handle Handle to an open Archive object
376 * @param path Path to the Directory inside of the Archive
377 * @return Whether creation succeeded
378 */
379Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
380 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 381 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
381 if (archive == nullptr) 382 if (archive == nullptr)
382 return -1; 383 return InvalidHandle(ErrorModule::FS);
383 if (archive->backend->CreateDirectory(path)) 384 if (archive->backend->CreateDirectory(path))
384 return 0; 385 return RESULT_SUCCESS;
385 return -1; 386 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
387 ErrorSummary::Canceled, ErrorLevel::Status);
388}
389
390ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
391 Handle dest_archive_handle, const FileSys::Path& dest_path) {
392 Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle);
393 Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle);
394 if (src_archive == nullptr || dest_archive == nullptr)
395 return InvalidHandle(ErrorModule::FS);
396 if (src_archive == dest_archive) {
397 if (src_archive->backend->RenameDirectory(src_path, dest_path))
398 return RESULT_SUCCESS;
399 } else {
400 // TODO: Implement renaming across archives
401 return UnimplementedFunction(ErrorModule::FS);
402 }
403 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
404 ErrorSummary::NothingHappened, ErrorLevel::Status);
386} 405}
387 406
388/** 407/**
@@ -402,6 +421,11 @@ ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys:
402 directory->path = path; 421 directory->path = path;
403 directory->backend = archive->backend->OpenDirectory(path); 422 directory->backend = archive->backend->OpenDirectory(path);
404 423
424 if (!directory->backend) {
425 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
426 ErrorSummary::NotFound, ErrorLevel::Permanent);
427 }
428
405 return MakeResult<Handle>(handle); 429 return MakeResult<Handle>(handle);
406} 430}
407 431
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h
index 6fc4f0f25..b50833a2b 100644
--- a/src/core/hle/kernel/archive.h
+++ b/src/core/hle/kernel/archive.h
@@ -50,7 +50,18 @@ ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path
50 * @param path Path to the File inside of the Archive 50 * @param path Path to the File inside of the Archive
51 * @return Whether deletion succeeded 51 * @return Whether deletion succeeded
52 */ 52 */
53Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path); 53ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
54
55/**
56 * Rename a File between two Archives
57 * @param src_archive_handle Handle to the source Archive object
58 * @param src_path Path to the File inside of the source Archive
59 * @param dest_archive_handle Handle to the destination Archive object
60 * @param dest_path Path to the File inside of the destination Archive
61 * @return Whether rename succeeded
62 */
63ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
64 Handle dest_archive_handle, const FileSys::Path& dest_path);
54 65
55/** 66/**
56 * Delete a Directory from an Archive 67 * Delete a Directory from an Archive
@@ -58,7 +69,7 @@ Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
58 * @param path Path to the Directory inside of the Archive 69 * @param path Path to the Directory inside of the Archive
59 * @return Whether deletion succeeded 70 * @return Whether deletion succeeded
60 */ 71 */
61Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 72ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
62 73
63/** 74/**
64 * Create a Directory from an Archive 75 * Create a Directory from an Archive
@@ -66,7 +77,18 @@ Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa
66 * @param path Path to the Directory inside of the Archive 77 * @param path Path to the Directory inside of the Archive
67 * @return Whether creation of directory succeeded 78 * @return Whether creation of directory succeeded
68 */ 79 */
69Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 80ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
81
82/**
83 * Rename a Directory between two Archives
84 * @param src_archive_handle Handle to the source Archive object
85 * @param src_path Path to the Directory inside of the source Archive
86 * @param dest_archive_handle Handle to the destination Archive object
87 * @param dest_path Path to the Directory inside of the destination Archive
88 * @return Whether rename succeeded
89 */
90ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
91 Handle dest_archive_handle, const FileSys::Path& dest_path);
70 92
71/** 93/**
72 * Open a Directory from an Archive 94 * Open a Directory from an Archive
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 018000abd..80a34c2d5 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 2// Licensed under GPLv2
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6
5#include "common/common.h" 7#include "common/common.h"
6 8
7#include "core/core.h" 9#include "core/core.h"
@@ -37,7 +39,7 @@ Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) {
37 return 0; 39 return 0;
38} 40}
39 41
40bool ObjectPool::IsValid(Handle handle) { 42bool ObjectPool::IsValid(Handle handle) const {
41 int index = handle - HANDLE_OFFSET; 43 int index = handle - HANDLE_OFFSET;
42 if (index < 0) 44 if (index < 0)
43 return false; 45 return false;
@@ -75,13 +77,8 @@ void ObjectPool::List() {
75 } 77 }
76} 78}
77 79
78int ObjectPool::GetCount() { 80int ObjectPool::GetCount() const {
79 int count = 0; 81 return std::count(occupied.begin(), occupied.end(), true);
80 for (int i = 0; i < MAX_COUNT; i++) {
81 if (occupied[i])
82 count++;
83 }
84 return count;
85} 82}
86 83
87Object* ObjectPool::CreateByIDType(int type) { 84Object* ObjectPool::CreateByIDType(int type) {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 8d3937ce8..00a2228bf 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -86,7 +86,7 @@ public:
86 } 86 }
87 } 87 }
88 88
89 bool IsValid(Handle handle); 89 bool IsValid(Handle handle) const;
90 90
91 template <class T> 91 template <class T>
92 T* Get(Handle handle) { 92 T* Get(Handle handle) {
@@ -142,7 +142,7 @@ public:
142 Object* &operator [](Handle handle); 142 Object* &operator [](Handle handle);
143 void List(); 143 void List();
144 void Clear(); 144 void Clear();
145 int GetCount(); 145 int GetCount() const;
146 146
147private: 147private:
148 148
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index b303ba128..d07e9761b 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -88,20 +88,19 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) {
88 88
89bool ReleaseMutex(Mutex* mutex) { 89bool ReleaseMutex(Mutex* mutex) {
90 MutexEraseLock(mutex); 90 MutexEraseLock(mutex);
91 bool woke_threads = false;
92 91
93 // Find the next waiting thread for the mutex... 92 // Find the next waiting thread for the mutex...
94 while (!woke_threads && !mutex->waiting_threads.empty()) { 93 while (!mutex->waiting_threads.empty()) {
95 std::vector<Handle>::iterator iter = mutex->waiting_threads.begin(); 94 std::vector<Handle>::iterator iter = mutex->waiting_threads.begin();
96 woke_threads |= ReleaseMutexForThread(mutex, *iter); 95 ReleaseMutexForThread(mutex, *iter);
97 mutex->waiting_threads.erase(iter); 96 mutex->waiting_threads.erase(iter);
98 } 97 }
98
99 // Reset mutex lock thread handle, nothing is waiting 99 // Reset mutex lock thread handle, nothing is waiting
100 if (!woke_threads) { 100 mutex->locked = false;
101 mutex->locked = false; 101 mutex->lock_thread = -1;
102 mutex->lock_thread = -1; 102
103 } 103 return true;
104 return woke_threads;
105} 104}
106 105
107/** 106/**
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f3f54a4e9..1e879b45a 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -49,6 +49,8 @@ public:
49 49
50 ThreadContext context; 50 ThreadContext context;
51 51
52 u32 thread_id;
53
52 u32 status; 54 u32 status;
53 u32 entry_point; 55 u32 entry_point;
54 u32 stack_top; 56 u32 stack_top;
@@ -61,6 +63,7 @@ public:
61 63
62 WaitType wait_type; 64 WaitType wait_type;
63 Handle wait_handle; 65 Handle wait_handle;
66 VAddr wait_address;
64 67
65 std::vector<Handle> waiting_threads; 68 std::vector<Handle> waiting_threads;
66 69
@@ -76,6 +79,9 @@ static Common::ThreadQueueList<Handle> thread_ready_queue;
76static Handle current_thread_handle; 79static Handle current_thread_handle;
77static Thread* current_thread; 80static Thread* current_thread;
78 81
82static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
83static u32 next_thread_id; ///< The next available thread id
84
79/// Gets the current thread 85/// Gets the current thread
80inline Thread* GetCurrentThread() { 86inline Thread* GetCurrentThread() {
81 return current_thread; 87 return current_thread;
@@ -121,6 +127,7 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) {
121 } 127 }
122 t->wait_type = WAITTYPE_NONE; 128 t->wait_type = WAITTYPE_NONE;
123 t->wait_handle = 0; 129 t->wait_handle = 0;
130 t->wait_address = 0;
124} 131}
125 132
126/// Change a thread to "ready" state 133/// Change a thread to "ready" state
@@ -141,9 +148,15 @@ void ChangeReadyState(Thread* t, bool ready) {
141} 148}
142 149
143/// Verify that a thread has not been released from waiting 150/// Verify that a thread has not been released from waiting
144inline bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) { 151static bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) {
145 _dbg_assert_(KERNEL, thread != nullptr); 152 _dbg_assert_(KERNEL, thread != nullptr);
146 return type == thread->wait_type && wait_handle == thread->wait_handle; 153 return (type == thread->wait_type) && (wait_handle == thread->wait_handle) && (thread->IsWaiting());
154}
155
156/// Verify that a thread has not been released from waiting (with wait address)
157static bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle, VAddr wait_address) {
158 _dbg_assert_(KERNEL, thread != nullptr);
159 return VerifyWait(thread, type, wait_handle) && (wait_address == thread->wait_address);
147} 160}
148 161
149/// Stops the current thread 162/// Stops the current thread
@@ -164,6 +177,7 @@ ResultCode StopThread(Handle handle, const char* reason) {
164 // Stopped threads are never waiting. 177 // Stopped threads are never waiting.
165 thread->wait_type = WAITTYPE_NONE; 178 thread->wait_type = WAITTYPE_NONE;
166 thread->wait_handle = 0; 179 thread->wait_handle = 0;
180 thread->wait_address = 0;
167 181
168 return RESULT_SUCCESS; 182 return RESULT_SUCCESS;
169} 183}
@@ -192,12 +206,12 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
192 for (Handle handle : thread_queue) { 206 for (Handle handle : thread_queue) {
193 Thread* thread = g_object_pool.Get<Thread>(handle); 207 Thread* thread = g_object_pool.Get<Thread>(handle);
194 208
195 // TODO(bunnei): Verify arbiter address... 209 if (!VerifyWait(thread, WAITTYPE_ARB, arbiter, address))
196 if (!VerifyWait(thread, WAITTYPE_ARB, arbiter))
197 continue; 210 continue;
198 211
199 if (thread == nullptr) 212 if (thread == nullptr)
200 continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. 213 continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
214
201 if(thread->current_priority <= priority) { 215 if(thread->current_priority <= priority) {
202 highest_priority_thread = handle; 216 highest_priority_thread = handle;
203 priority = thread->current_priority; 217 priority = thread->current_priority;
@@ -217,8 +231,7 @@ void ArbitrateAllThreads(u32 arbiter, u32 address) {
217 for (Handle handle : thread_queue) { 231 for (Handle handle : thread_queue) {
218 Thread* thread = g_object_pool.Get<Thread>(handle); 232 Thread* thread = g_object_pool.Get<Thread>(handle);
219 233
220 // TODO(bunnei): Verify arbiter address... 234 if (VerifyWait(thread, WAITTYPE_ARB, arbiter, address))
221 if (VerifyWait(thread, WAITTYPE_ARB, arbiter))
222 ResumeThreadFromWait(handle); 235 ResumeThreadFromWait(handle);
223 } 236 }
224} 237}
@@ -272,11 +285,6 @@ Thread* NextThread() {
272 return Kernel::g_object_pool.Get<Thread>(next); 285 return Kernel::g_object_pool.Get<Thread>(next);
273} 286}
274 287
275/**
276 * Puts the current thread in the wait state for the given type
277 * @param wait_type Type of wait
278 * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread
279 */
280void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { 288void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
281 Thread* thread = GetCurrentThread(); 289 Thread* thread = GetCurrentThread();
282 thread->wait_type = wait_type; 290 thread->wait_type = wait_type;
@@ -284,6 +292,11 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
284 ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); 292 ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
285} 293}
286 294
295void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_address) {
296 WaitCurrentThread(wait_type, wait_handle);
297 GetCurrentThread()->wait_address = wait_address;
298}
299
287/// Resumes a thread from waiting by marking it as "ready" 300/// Resumes a thread from waiting by marking it as "ready"
288void ResumeThreadFromWait(Handle handle) { 301void ResumeThreadFromWait(Handle handle) {
289 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); 302 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle);
@@ -325,6 +338,7 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
325 thread_queue.push_back(handle); 338 thread_queue.push_back(handle);
326 thread_ready_queue.prepare(priority); 339 thread_ready_queue.prepare(priority);
327 340
341 thread->thread_id = next_thread_id++;
328 thread->status = THREADSTATUS_DORMANT; 342 thread->status = THREADSTATUS_DORMANT;
329 thread->entry_point = entry_point; 343 thread->entry_point = entry_point;
330 thread->stack_top = stack_top; 344 thread->stack_top = stack_top;
@@ -333,6 +347,7 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
333 thread->processor_id = processor_id; 347 thread->processor_id = processor_id;
334 thread->wait_type = WAITTYPE_NONE; 348 thread->wait_type = WAITTYPE_NONE;
335 thread->wait_handle = 0; 349 thread->wait_handle = 0;
350 thread->wait_address = 0;
336 thread->name = name; 351 thread->name = name;
337 352
338 return thread; 353 return thread;
@@ -465,9 +480,21 @@ void Reschedule() {
465 } 480 }
466} 481}
467 482
483ResultCode GetThreadId(u32* thread_id, Handle handle) {
484 Thread* thread = g_object_pool.Get<Thread>(handle);
485 if (thread == nullptr)
486 return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS,
487 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
488
489 *thread_id = thread->thread_id;
490
491 return RESULT_SUCCESS;
492}
493
468//////////////////////////////////////////////////////////////////////////////////////////////////// 494////////////////////////////////////////////////////////////////////////////////////////////////////
469 495
470void ThreadingInit() { 496void ThreadingInit() {
497 next_thread_id = INITIAL_THREAD_ID;
471} 498}
472 499
473void ThreadingShutdown() { 500void ThreadingShutdown() {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index ce63a70d3..be7adface 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -5,6 +5,9 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8
9#include "core/mem_map.h"
10
8#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
9#include "core/hle/result.h" 12#include "core/hle/result.h"
10 13
@@ -58,6 +61,14 @@ void Reschedule();
58/// Stops the current thread 61/// Stops the current thread
59ResultCode StopThread(Handle thread, const char* reason); 62ResultCode StopThread(Handle thread, const char* reason);
60 63
64/**
65 * Retrieves the ID of the specified thread handle
66 * @param thread_id Will contain the output thread id
67 * @param handle Handle to the thread we want
68 * @return Whether the function was successful or not
69 */
70ResultCode GetThreadId(u32* thread_id, Handle handle);
71
61/// Resumes a thread from waiting by marking it as "ready" 72/// Resumes a thread from waiting by marking it as "ready"
62void ResumeThreadFromWait(Handle handle); 73void ResumeThreadFromWait(Handle handle);
63 74
@@ -77,6 +88,14 @@ Handle GetCurrentThreadHandle();
77 */ 88 */
78void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle()); 89void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle());
79 90
91/**
92 * Puts the current thread in the wait state for the given type
93 * @param wait_type Type of wait
94 * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread
95 * @param wait_address Arbitration address used to resume from wait
96 */
97void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_address);
98
80/// Put current thread in a wait state - on WaitSynchronization 99/// Put current thread in a wait state - on WaitSynchronization
81void WaitThread_Synchronization(); 100void WaitThread_Synchronization();
82 101
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 9af96f6b8..46aee40d6 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -11,6 +11,24 @@
11 11
12namespace AC_U { 12namespace AC_U {
13 13
14/**
15 * AC_U::GetWifiStatus service function
16 * Outputs:
17 * 1 : Result of function, 0 on success, otherwise error code
18 * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet.
19 */
20void GetWifiStatus(Service::Interface* self) {
21 u32* cmd_buff = Service::GetCommandBuffer();
22
23 // TODO(purpasmart96): This function is only a stub,
24 // it returns a valid result without implementing full functionality.
25
26 cmd_buff[1] = 0; // No error
27 cmd_buff[2] = 0; // Connection type set to none
28
29 WARN_LOG(KERNEL, "(STUBBED) called");
30}
31
14const Interface::FunctionInfo FunctionTable[] = { 32const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010000, nullptr, "CreateDefaultConfig"}, 33 {0x00010000, nullptr, "CreateDefaultConfig"},
16 {0x00040006, nullptr, "ConnectAsync"}, 34 {0x00040006, nullptr, "ConnectAsync"},
@@ -18,7 +36,7 @@ const Interface::FunctionInfo FunctionTable[] = {
18 {0x00080004, nullptr, "CloseAsync"}, 36 {0x00080004, nullptr, "CloseAsync"},
19 {0x00090002, nullptr, "GetCloseResult"}, 37 {0x00090002, nullptr, "GetCloseResult"},
20 {0x000A0000, nullptr, "GetLastErrorCode"}, 38 {0x000A0000, nullptr, "GetLastErrorCode"},
21 {0x000D0000, nullptr, "GetWifiStatus"}, 39 {0x000D0000, GetWifiStatus, "GetWifiStatus"},
22 {0x000E0042, nullptr, "GetCurrentAPInfo"}, 40 {0x000E0042, nullptr, "GetCurrentAPInfo"},
23 {0x00100042, nullptr, "GetCurrentNZoneInfo"}, 41 {0x00100042, nullptr, "GetCurrentNZoneInfo"},
24 {0x00110042, nullptr, "GetNZoneApNumService"}, 42 {0x00110042, nullptr, "GetNZoneApNumService"},
diff --git a/src/core/hle/service/cfg_u.cpp b/src/core/hle/service/cfg_u.cpp
index 822b0e2b8..d6b586ea0 100644
--- a/src/core/hle/service/cfg_u.cpp
+++ b/src/core/hle/service/cfg_u.cpp
@@ -11,6 +11,90 @@
11 11
12namespace CFG_U { 12namespace CFG_U {
13 13
14static const std::array<const char*, 187> country_codes = {
15 nullptr, "JP", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 0-7
16 "AI", "AG", "AR", "AW", "BS", "BB", "BZ", "BO", // 8-15
17 "BR", "VG", "CA", "KY", "CL", "CO", "CR", "DM", // 16-23
18 "DO", "EC", "SV", "GF", "GD", "GP", "GT", "GY", // 24-31
19 "HT", "HN", "JM", "MQ", "MX", "MS", "AN", "NI", // 32-39
20 "PA", "PY", "PE", "KN", "LC", "VC", "SR", "TT", // 40-47
21 "TC", "US", "UY", "VI", "VE", nullptr, nullptr, nullptr, // 48-55
22 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 56-63
23 "AL", "AU", "AT", "BE", "BA", "BW", "BG", "HR", // 64-71
24 "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", // 72-79
25 "HU", "IS", "IE", "IT", "LV", "LS", "LI", "LT", // 80-87
26 "LU", "MK", "MT", "ME", "MZ", "NA", "NL", "NZ", // 88-95
27 "NO", "PL", "PT", "RO", "RU", "RS", "SK", "SI", // 96-103
28 "ZA", "ES", "SZ", "SE", "CH", "TR", "GB", "ZM", // 104-111
29 "ZW", "AZ", "MR", "ML", "NE", "TD", "SD", "ER", // 112-119
30 "DJ", "SO", "AD", "GI", "GG", "IM", "JE", "MC", // 120-127
31 "TW", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 128-135
32 "KR", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 136-143
33 "HK", "MO", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 144-151
34 "ID", "SG", "TH", "PH", "MY", nullptr, nullptr, nullptr, // 152-159
35 "CN", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 160-167
36 "AE", "IN", "EG", "OM", "QA", "KW", "SA", "SY", // 168-175
37 "BH", "JO", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 176-183
38 "SM", "VA", "BM", // 184-186
39};
40
41/**
42 * CFG_User::GetCountryCodeString service function
43 * Inputs:
44 * 1 : Country Code ID
45 * Outputs:
46 * 1 : Result of function, 0 on success, otherwise error code
47 * 2 : Country's 2-char string
48 */
49static void GetCountryCodeString(Service::Interface* self) {
50 u32* cmd_buffer = Service::GetCommandBuffer();
51 u32 country_code_id = cmd_buffer[1];
52
53 if (country_code_id >= country_codes.size()) {
54 ERROR_LOG(KERNEL, "requested country code id=%d is invalid", country_code_id);
55 cmd_buffer[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw;
56 return;
57 }
58
59 const char* code = country_codes[country_code_id];
60 if (code != nullptr) {
61 cmd_buffer[1] = 0;
62 cmd_buffer[2] = code[0] | (code[1] << 8);
63 } else {
64 cmd_buffer[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw;
65 DEBUG_LOG(KERNEL, "requested country code id=%d is not set", country_code_id);
66 }
67}
68
69/**
70 * CFG_User::GetCountryCodeID service function
71 * Inputs:
72 * 1 : Country Code 2-char string
73 * Outputs:
74 * 1 : Result of function, 0 on success, otherwise error code
75 * 2 : Country Code ID
76 */
77static void GetCountryCodeID(Service::Interface* self) {
78 u32* cmd_buffer = Service::GetCommandBuffer();
79 u16 country_code = cmd_buffer[1];
80 u16 country_code_id = -1;
81
82 for (u32 i = 0; i < country_codes.size(); ++i) {
83 const char* code_string = country_codes[i];
84
85 if (code_string != nullptr) {
86 u16 code = code_string[0] | (code_string[1] << 8);
87 if (code == country_code) {
88 country_code_id = i;
89 break;
90 }
91 }
92 }
93
94 cmd_buffer[1] = 0;
95 cmd_buffer[2] = country_code_id;
96}
97
14const Interface::FunctionInfo FunctionTable[] = { 98const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010082, nullptr, "GetConfigInfoBlk2"}, 99 {0x00010082, nullptr, "GetConfigInfoBlk2"},
16 {0x00020000, nullptr, "SecureInfoGetRegion"}, 100 {0x00020000, nullptr, "SecureInfoGetRegion"},
@@ -20,8 +104,8 @@ const Interface::FunctionInfo FunctionTable[] = {
20 {0x00060000, nullptr, "GetModelNintendo2DS"}, 104 {0x00060000, nullptr, "GetModelNintendo2DS"},
21 {0x00070040, nullptr, "unknown"}, 105 {0x00070040, nullptr, "unknown"},
22 {0x00080080, nullptr, "unknown"}, 106 {0x00080080, nullptr, "unknown"},
23 {0x00090080, nullptr, "GetCountryCodeString"}, 107 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
24 {0x000A0040, nullptr, "GetCountryCodeID"}, 108 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
25}; 109};
26//////////////////////////////////////////////////////////////////////////////////////////////////// 110////////////////////////////////////////////////////////////////////////////////////////////////////
27// Interface class 111// Interface class
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index bbcf26f61..72be4c817 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -4,6 +4,7 @@
4 4
5#include "common/log.h" 5#include "common/log.h"
6#include "core/hle/hle.h" 6#include "core/hle/hle.h"
7#include "core/hle/kernel/event.h"
7#include "core/hle/service/dsp_dsp.h" 8#include "core/hle/service/dsp_dsp.h"
8 9
9//////////////////////////////////////////////////////////////////////////////////////////////////// 10////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -11,38 +12,137 @@
11 12
12namespace DSP_DSP { 13namespace DSP_DSP {
13 14
15static Handle semaphore_event;
16static Handle interrupt_event;
17
18/**
19 * DSP_DSP::ConvertProcessAddressFromDspDram service function
20 * Inputs:
21 * 1 : Address
22 * Outputs:
23 * 1 : Result of function, 0 on success, otherwise error code
24 * 2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address)
25 */
26void ConvertProcessAddressFromDspDram(Service::Interface* self) {
27 u32* cmd_buff = Service::GetCommandBuffer();
28
29 u32 addr = cmd_buff[1];
30
31 cmd_buff[1] = 0; // No error
32 cmd_buff[2] = (addr << 1) + (Memory::DSP_MEMORY_VADDR + 0x40000);
33
34 DEBUG_LOG(KERNEL, "(STUBBED) called with address %u", addr);
35}
36
37/**
38 * DSP_DSP::LoadComponent service function
39 * Inputs:
40 * 1 : Size
41 * 2 : Unknown (observed only half word used)
42 * 3 : Unknown (observed only half word used)
43 * 4 : (size << 4) | 0xA
44 * 5 : Buffer address
45 * Outputs:
46 * 1 : Result of function, 0 on success, otherwise error code
47 * 2 : Component loaded, 0 on not loaded, 1 on loaded
48 */
49void LoadComponent(Service::Interface* self) {
50 u32* cmd_buff = Service::GetCommandBuffer();
51
52 cmd_buff[1] = 0; // No error
53 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
54
55 // TODO(bunnei): Implement real DSP firmware loading
56
57 DEBUG_LOG(KERNEL, "(STUBBED) called");
58}
59
60/**
61 * DSP_DSP::GetSemaphoreEventHandle service function
62 * Outputs:
63 * 1 : Result of function, 0 on success, otherwise error code
64 * 3 : Semaphore event handle
65 */
66void GetSemaphoreEventHandle(Service::Interface* self) {
67 u32* cmd_buff = Service::GetCommandBuffer();
68
69 cmd_buff[1] = 0; // No error
70 cmd_buff[3] = semaphore_event; // Event handle
71
72 DEBUG_LOG(KERNEL, "(STUBBED) called");
73}
74
75/**
76 * DSP_DSP::RegisterInterruptEvents service function
77 * Inputs:
78 * 1 : Parameter 0 (purpose unknown)
79 * 2 : Parameter 1 (purpose unknown)
80 * 4 : Interrupt event handle
81 * Outputs:
82 * 1 : Result of function, 0 on success, otherwise error code
83 */
84void RegisterInterruptEvents(Service::Interface* self) {
85 u32* cmd_buff = Service::GetCommandBuffer();
86
87 interrupt_event = static_cast<Handle>(cmd_buff[4]);
88
89 cmd_buff[1] = 0; // No error
90
91 DEBUG_LOG(KERNEL, "(STUBBED) called");
92}
93
94/**
95 * DSP_DSP::WriteReg0x10 service function
96 * Inputs:
97 * 1 : Unknown (observed only half word used)
98 * Outputs:
99 * 1 : Result of function, 0 on success, otherwise error code
100 */
101void WriteReg0x10(Service::Interface* self) {
102 u32* cmd_buff = Service::GetCommandBuffer();
103
104 Kernel::SignalEvent(interrupt_event);
105
106 cmd_buff[1] = 0; // No error
107
108 DEBUG_LOG(KERNEL, "(STUBBED) called");
109}
110
14const Interface::FunctionInfo FunctionTable[] = { 111const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010040, nullptr, "RecvData"}, 112 {0x00010040, nullptr, "RecvData"},
16 {0x00020040, nullptr, "RecvDataIsReady"}, 113 {0x00020040, nullptr, "RecvDataIsReady"},
17 {0x00030080, nullptr, "SendData"}, 114 {0x00030080, nullptr, "SendData"},
18 {0x00040040, nullptr, "SendDataIsEmpty"}, 115 {0x00040040, nullptr, "SendDataIsEmpty"},
19 {0x00070040, nullptr, "WriteReg0x10"}, 116 {0x00070040, WriteReg0x10, "WriteReg0x10"},
20 {0x00080000, nullptr, "GetSemaphore"}, 117 {0x00080000, nullptr, "GetSemaphore"},
21 {0x00090040, nullptr, "ClearSemaphore"}, 118 {0x00090040, nullptr, "ClearSemaphore"},
22 {0x000B0000, nullptr, "CheckSemaphoreRequest"}, 119 {0x000B0000, nullptr, "CheckSemaphoreRequest"},
23 {0x000C0040, nullptr, "ConvertProcessAddressFromDspDram"}, 120 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
24 {0x000D0082, nullptr, "WriteProcessPipe"}, 121 {0x000D0082, nullptr, "WriteProcessPipe"},
25 {0x001000C0, nullptr, "ReadPipeIfPossible"}, 122 {0x001000C0, nullptr, "ReadPipeIfPossible"},
26 {0x001100C2, nullptr, "LoadComponent"}, 123 {0x001100C2, LoadComponent, "LoadComponent"},
27 {0x00120000, nullptr, "UnloadComponent"}, 124 {0x00120000, nullptr, "UnloadComponent"},
28 {0x00130082, nullptr, "FlushDataCache"}, 125 {0x00130082, nullptr, "FlushDataCache"},
29 {0x00140082, nullptr, "InvalidateDCache"}, 126 {0x00140082, nullptr, "InvalidateDCache"},
30 {0x00150082, nullptr, "RegisterInterruptEvents"}, 127 {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"},
31 {0x00160000, nullptr, "GetSemaphoreEventHandle"}, 128 {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"},
32 {0x00170040, nullptr, "SetSemaphoreMask"}, 129 {0x00170040, nullptr, "SetSemaphoreMask"},
33 {0x00180040, nullptr, "GetPhysicalAddress"}, 130 {0x00180040, nullptr, "GetPhysicalAddress"},
34 {0x00190040, nullptr, "GetVirtualAddress"}, 131 {0x00190040, nullptr, "GetVirtualAddress"},
35 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, 132 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
36 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, 133 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
37 {0x001C0082, nullptr, "SetIirFilterEQ"}, 134 {0x001C0082, nullptr, "SetIirFilterEQ"},
38 {0x001F0000, nullptr, "GetHeadphoneStatus"}, 135 {0x001F0000, nullptr, "GetHeadphoneStatus"},
39 {0x00210000, nullptr, "GetIsDspOccupied"}, 136 {0x00210000, nullptr, "GetIsDspOccupied"},
40}; 137};
41 138
42//////////////////////////////////////////////////////////////////////////////////////////////////// 139////////////////////////////////////////////////////////////////////////////////////////////////////
43// Interface class 140// Interface class
44 141
45Interface::Interface() { 142Interface::Interface() {
143 semaphore_event = Kernel::CreateEvent(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
144 interrupt_event = 0;
145
46 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 146 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
47} 147}
48 148
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h
index c4ce44245..9431b62f6 100644
--- a/src/core/hle/service/dsp_dsp.h
+++ b/src/core/hle/service/dsp_dsp.h
@@ -20,7 +20,7 @@ public:
20 * @return Port name of service 20 * @return Port name of service
21 */ 21 */
22 std::string GetPortName() const override { 22 std::string GetPortName() const override {
23 return "dsp:DSP"; 23 return "dsp::DSP";
24 } 24 }
25}; 25};
26 26
diff --git a/src/core/hle/service/fs_user.cpp b/src/core/hle/service/fs_user.cpp
index 435be5b5d..51e8b579e 100644
--- a/src/core/hle/service/fs_user.cpp
+++ b/src/core/hle/service/fs_user.cpp
@@ -55,7 +55,7 @@ static void OpenFile(Service::Interface* self) {
55 u32 filename_ptr = cmd_buff[9]; 55 u32 filename_ptr = cmd_buff[9];
56 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 56 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
57 57
58 DEBUG_LOG(KERNEL, "path=%s, mode=%d attrs=%d", file_path.DebugStr().c_str(), mode, attributes); 58 DEBUG_LOG(KERNEL, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
59 59
60 ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode); 60 ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode);
61 cmd_buff[1] = handle.Code().raw; 61 cmd_buff[1] = handle.Code().raw;
@@ -102,8 +102,8 @@ static void OpenFileDirectly(Service::Interface* self) {
102 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 102 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
103 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 103 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
104 104
105 DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%d attributes=%d", 105 DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%u attributes=%d",
106 archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode, attributes); 106 archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes);
107 107
108 if (archive_path.GetType() != FileSys::Empty) { 108 if (archive_path.GetType() != FileSys::Empty) {
109 ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); 109 ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported");
@@ -159,7 +159,49 @@ void DeleteFile(Service::Interface* self) {
159 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", 159 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
160 filename_type, filename_size, file_path.DebugStr().c_str()); 160 filename_type, filename_size, file_path.DebugStr().c_str());
161 161
162 cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path); 162 cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path).raw;
163
164 DEBUG_LOG(KERNEL, "called");
165}
166
167/*
168 * FS_User::RenameFile service function
169 * Inputs:
170 * 2 : Source archive handle lower word
171 * 3 : Source archive handle upper word
172 * 4 : Source file path type
173 * 5 : Source file path size
174 * 6 : Dest archive handle lower word
175 * 7 : Dest archive handle upper word
176 * 8 : Dest file path type
177 * 9 : Dest file path size
178 * 11: Source file path string data
179 * 13: Dest file path string
180 * Outputs:
181 * 1 : Result of function, 0 on success, otherwise error code
182 */
183void RenameFile(Service::Interface* self) {
184 u32* cmd_buff = Service::GetCommandBuffer();
185
186 // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
187 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
188 Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
189 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
190 u32 src_filename_size = cmd_buff[5];
191 Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]);
192 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
193 u32 dest_filename_size = cmd_buff[9];
194 u32 src_filename_ptr = cmd_buff[11];
195 u32 dest_filename_ptr = cmd_buff[13];
196
197 FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr);
198 FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr);
199
200 DEBUG_LOG(KERNEL, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
201 src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(),
202 dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
203
204 cmd_buff[1] = Kernel::RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw;
163 205
164 DEBUG_LOG(KERNEL, "called"); 206 DEBUG_LOG(KERNEL, "called");
165} 207}
@@ -190,7 +232,7 @@ void DeleteDirectory(Service::Interface* self) {
190 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", 232 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
191 dirname_type, dirname_size, dir_path.DebugStr().c_str()); 233 dirname_type, dirname_size, dir_path.DebugStr().c_str());
192 234
193 cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path); 235 cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
194 236
195 DEBUG_LOG(KERNEL, "called"); 237 DEBUG_LOG(KERNEL, "called");
196} 238}
@@ -220,11 +262,53 @@ static void CreateDirectory(Service::Interface* self) {
220 262
221 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 263 DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
222 264
223 cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path); 265 cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path).raw;
224 266
225 DEBUG_LOG(KERNEL, "called"); 267 DEBUG_LOG(KERNEL, "called");
226} 268}
227 269
270/*
271 * FS_User::RenameDirectory service function
272 * Inputs:
273 * 2 : Source archive handle lower word
274 * 3 : Source archive handle upper word
275 * 4 : Source dir path type
276 * 5 : Source dir path size
277 * 6 : Dest archive handle lower word
278 * 7 : Dest archive handle upper word
279 * 8 : Dest dir path type
280 * 9 : Dest dir path size
281 * 11: Source dir path string data
282 * 13: Dest dir path string
283 * Outputs:
284 * 1 : Result of function, 0 on success, otherwise error code
285 */
286void RenameDirectory(Service::Interface* self) {
287 u32* cmd_buff = Service::GetCommandBuffer();
288
289 // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
290 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
291 Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
292 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
293 u32 src_dirname_size = cmd_buff[5];
294 Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]);
295 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
296 u32 dest_dirname_size = cmd_buff[9];
297 u32 src_dirname_ptr = cmd_buff[11];
298 u32 dest_dirname_ptr = cmd_buff[13];
299
300 FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr);
301 FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr);
302
303 DEBUG_LOG(KERNEL, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
304 src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(),
305 dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
306
307 cmd_buff[1] = Kernel::RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw;
308
309 DEBUG_LOG(KERNEL, "called");
310}
311
228static void OpenDirectory(Service::Interface* self) { 312static void OpenDirectory(Service::Interface* self) {
229 u32* cmd_buff = Service::GetCommandBuffer(); 313 u32* cmd_buff = Service::GetCommandBuffer();
230 314
@@ -314,12 +398,12 @@ const Interface::FunctionInfo FunctionTable[] = {
314 {0x080201C2, OpenFile, "OpenFile"}, 398 {0x080201C2, OpenFile, "OpenFile"},
315 {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, 399 {0x08030204, OpenFileDirectly, "OpenFileDirectly"},
316 {0x08040142, DeleteFile, "DeleteFile"}, 400 {0x08040142, DeleteFile, "DeleteFile"},
317 {0x08050244, nullptr, "RenameFile"}, 401 {0x08050244, RenameFile, "RenameFile"},
318 {0x08060142, DeleteDirectory, "DeleteDirectory"}, 402 {0x08060142, DeleteDirectory, "DeleteDirectory"},
319 {0x08070142, nullptr, "DeleteDirectoryRecursively"}, 403 {0x08070142, nullptr, "DeleteDirectoryRecursively"},
320 {0x08080202, nullptr, "CreateFile"}, 404 {0x08080202, nullptr, "CreateFile"},
321 {0x08090182, CreateDirectory, "CreateDirectory"}, 405 {0x08090182, CreateDirectory, "CreateDirectory"},
322 {0x080A0244, nullptr, "RenameDirectory"}, 406 {0x080A0244, RenameDirectory, "RenameDirectory"},
323 {0x080B0102, OpenDirectory, "OpenDirectory"}, 407 {0x080B0102, OpenDirectory, "OpenDirectory"},
324 {0x080C00C2, OpenArchive, "OpenArchive"}, 408 {0x080C00C2, OpenArchive, "OpenArchive"},
325 {0x080D0144, nullptr, "ControlArchive"}, 409 {0x080D0144, nullptr, "ControlArchive"},
diff --git a/src/core/hle/service/hid_user.cpp b/src/core/hle/service/hid_user.cpp
index d29de1a52..2abaf0f2f 100644
--- a/src/core/hle/service/hid_user.cpp
+++ b/src/core/hle/service/hid_user.cpp
@@ -55,7 +55,7 @@ static void UpdateNextCirclePadState() {
55/** 55/**
56 * Sets a Pad state (button or button combo) as pressed 56 * Sets a Pad state (button or button combo) as pressed
57 */ 57 */
58void PadButtonPress(PadState pad_state) { 58void PadButtonPress(const PadState& pad_state) {
59 next_state.hex |= pad_state.hex; 59 next_state.hex |= pad_state.hex;
60 UpdateNextCirclePadState(); 60 UpdateNextCirclePadState();
61} 61}
@@ -63,7 +63,7 @@ void PadButtonPress(PadState pad_state) {
63/** 63/**
64 * Sets a Pad state (button or button combo) as released 64 * Sets a Pad state (button or button combo) as released
65 */ 65 */
66void PadButtonRelease(PadState pad_state) { 66void PadButtonRelease(const PadState& pad_state) {
67 next_state.hex &= ~pad_state.hex; 67 next_state.hex &= ~pad_state.hex;
68 UpdateNextCirclePadState(); 68 UpdateNextCirclePadState();
69} 69}
diff --git a/src/core/hle/service/hid_user.h b/src/core/hle/service/hid_user.h
index 5ed97085d..8f53befdb 100644
--- a/src/core/hle/service/hid_user.h
+++ b/src/core/hle/service/hid_user.h
@@ -93,8 +93,8 @@ const PadState PAD_CIRCLE_UP = {{1u << 30}};
93const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; 93const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
94 94
95// Methods for updating the HID module's state 95// Methods for updating the HID module's state
96void PadButtonPress(PadState pad_state); 96void PadButtonPress(const PadState& pad_state);
97void PadButtonRelease(PadState pad_state); 97void PadButtonRelease(const PadState& pad_state);
98void PadUpdateComplete(); 98void PadUpdateComplete();
99 99
100/** 100/**
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp
index d9122dbbc..941df467b 100644
--- a/src/core/hle/service/ptm_u.cpp
+++ b/src/core/hle/service/ptm_u.cpp
@@ -11,15 +11,101 @@
11 11
12namespace PTM_U { 12namespace PTM_U {
13 13
14/// Charge levels used by PTM functions
15enum class ChargeLevels : u32 {
16 CriticalBattery = 1,
17 LowBattery = 2,
18 HalfFull = 3,
19 MostlyFull = 4,
20 CompletelyFull = 5,
21};
22
23static bool shell_open = true;
24
25static bool battery_is_charging = true;
26
27/**
28 * It is unknown if GetAdapterState is the same as GetBatteryChargeState,
29 * it is likely to just be a duplicate function of GetBatteryChargeState
30 * that controls another part of the HW.
31 * PTM_U::GetAdapterState service function
32 * Outputs:
33 * 1 : Result of function, 0 on success, otherwise error code
34 * 2 : Output of function, 0 = not charging, 1 = charging.
35 */
36static void GetAdapterState(Service::Interface* self) {
37 u32* cmd_buff = Service::GetCommandBuffer();
38
39 // TODO(purpasmart96): This function is only a stub,
40 // it returns a valid result without implementing full functionality.
41
42 cmd_buff[1] = 0; // No error
43 cmd_buff[2] = battery_is_charging ? 1 : 0;
44
45 WARN_LOG(KERNEL, "(STUBBED) called");
46}
47
48/*
49 * PTM_User::GetShellState service function.
50 * Outputs:
51 * 1 : Result of function, 0 on success, otherwise error code
52 * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0)
53 */
54static void GetShellState(Service::Interface* self) {
55 u32* cmd_buff = Service::GetCommandBuffer();
56
57 cmd_buff[1] = 0;
58 cmd_buff[2] = shell_open ? 1 : 0;
59
60 DEBUG_LOG(KERNEL, "PTM_U::GetShellState called");
61}
62
63/**
64 * PTM_U::GetBatteryLevel service function
65 * Outputs:
66 * 1 : Result of function, 0 on success, otherwise error code
67 * 2 : Battery level, 5 = completely full battery, 4 = mostly full battery,
68 * 3 = half full battery, 2 = low battery, 1 = critical battery.
69 */
70static void GetBatteryLevel(Service::Interface* self) {
71 u32* cmd_buff = Service::GetCommandBuffer();
72
73 // TODO(purpasmart96): This function is only a stub,
74 // it returns a valid result without implementing full functionality.
75
76 cmd_buff[1] = 0; // No error
77 cmd_buff[2] = static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery
78
79 WARN_LOG(KERNEL, "(STUBBED) called");
80}
81
82/**
83 * PTM_U::GetBatteryChargeState service function
84 * Outputs:
85 * 1 : Result of function, 0 on success, otherwise error code
86 * 2 : Output of function, 0 = not charging, 1 = charging.
87 */
88static void GetBatteryChargeState(Service::Interface* self) {
89 u32* cmd_buff = Service::GetCommandBuffer();
90
91 // TODO(purpasmart96): This function is only a stub,
92 // it returns a valid result without implementing full functionality.
93
94 cmd_buff[1] = 0; // No error
95 cmd_buff[2] = battery_is_charging ? 1 : 0;
96
97 WARN_LOG(KERNEL, "(STUBBED) called");
98}
99
14const Interface::FunctionInfo FunctionTable[] = { 100const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010002, nullptr, "RegisterAlarmClient"}, 101 {0x00010002, nullptr, "RegisterAlarmClient"},
16 {0x00020080, nullptr, "SetRtcAlarm"}, 102 {0x00020080, nullptr, "SetRtcAlarm"},
17 {0x00030000, nullptr, "GetRtcAlarm"}, 103 {0x00030000, nullptr, "GetRtcAlarm"},
18 {0x00040000, nullptr, "CancelRtcAlarm"}, 104 {0x00040000, nullptr, "CancelRtcAlarm"},
19 {0x00050000, nullptr, "GetAdapterState"}, 105 {0x00050000, GetAdapterState, "GetAdapterState"},
20 {0x00060000, nullptr, "GetShellState"}, 106 {0x00060000, GetShellState, "GetShellState"},
21 {0x00070000, nullptr, "GetBatteryLevel"}, 107 {0x00070000, GetBatteryLevel, "GetBatteryLevel"},
22 {0x00080000, nullptr, "GetBatteryChargeState"}, 108 {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"},
23 {0x00090000, nullptr, "GetPedometerState"}, 109 {0x00090000, nullptr, "GetPedometerState"},
24 {0x000A0042, nullptr, "GetStepHistoryEntry"}, 110 {0x000A0042, nullptr, "GetStepHistoryEntry"},
25 {0x000B00C2, nullptr, "GetStepHistory"}, 111 {0x000B00C2, nullptr, "GetStepHistory"},
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 87d768856..a5805ed05 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -189,6 +189,8 @@ static Result CreateAddressArbiter(u32* arbiter) {
189 189
190/// Arbitrate address 190/// Arbitrate address
191static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { 191static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) {
192 DEBUG_LOG(SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter,
193 address, type, value);
192 return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), 194 return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type),
193 address, value).raw; 195 address, value).raw;
194} 196}
@@ -279,10 +281,11 @@ static Result ReleaseMutex(Handle handle) {
279 return res.raw; 281 return res.raw;
280} 282}
281 283
282/// Get current thread ID 284/// Get the ID for the specified thread.
283static Result GetThreadId(u32* thread_id, Handle thread) { 285static Result GetThreadId(u32* thread_id, Handle handle) {
284 ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); 286 DEBUG_LOG(SVC, "called thread=0x%08X", handle);
285 return 0; 287 ResultCode result = Kernel::GetThreadId(thread_id, handle);
288 return result.raw;
286} 289}
287 290
288/// Query memory 291/// Query memory
@@ -331,6 +334,9 @@ static Result ClearEvent(Handle evt) {
331/// Sleep the current thread 334/// Sleep the current thread
332static void SleepThread(s64 nanoseconds) { 335static void SleepThread(s64 nanoseconds) {
333 DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds); 336 DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds);
337
338 // Check for next thread to schedule
339 HLE::Reschedule(__func__);
334} 340}
335 341
336/// This returns the total CPU ticks elapsed since the CPU was powered-on 342/// This returns the total CPU ticks elapsed since the CPU was powered-on
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 3ad801c63..af5e1b39b 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -49,7 +49,7 @@ inline void Write(u32 addr, const T data) {
49 49
50 // Writes other than u32 are untested, so I'd rather have them abort than silently fail 50 // Writes other than u32 are untested, so I'd rather have them abort than silently fail
51 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { 51 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) {
52 ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); 52 ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
53 return; 53 return;
54 } 54 }
55 55
@@ -140,8 +140,8 @@ inline void Write(u32 addr, const T data) {
140 140
141 DEBUG_LOG(GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x", 141 DEBUG_LOG(GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x",
142 config.output_height * config.output_width * 4, 142 config.output_height * config.output_width * 4,
143 config.GetPhysicalInputAddress(), config.input_width, config.input_height, 143 config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height,
144 config.GetPhysicalOutputAddress(), config.output_width, config.output_height, 144 config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height,
145 config.output_format.Value()); 145 config.output_format.Value());
146 } 146 }
147 break; 147 break;
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index 4d0719263..ea001673a 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -68,7 +68,7 @@ inline void Write(u32 addr, const T data) {
68 break; 68 break;
69 69
70 default: 70 default:
71 ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); 71 ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
72 } 72 }
73} 73}
74 74
diff --git a/src/core/hw/ndma.cpp b/src/core/hw/ndma.cpp
index e29a773f1..593e5de30 100644
--- a/src/core/hw/ndma.cpp
+++ b/src/core/hw/ndma.cpp
@@ -15,7 +15,7 @@ inline void Read(T &var, const u32 addr) {
15 15
16template <typename T> 16template <typename T>
17inline void Write(u32 addr, const T data) { 17inline void Write(u32 addr, const T data) {
18 ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); 18 ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
19} 19}
20 20
21// Explicitly instantiate template functions because we aren't defining this in the header: 21// Explicitly instantiate template functions because we aren't defining this in the header:
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
new file mode 100644
index 000000000..7ef146359
--- /dev/null
+++ b/src/core/loader/3dsx.cpp
@@ -0,0 +1,236 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <vector>
7
8#include "core/file_sys/archive_romfs.h"
9#include "core/loader/elf.h"
10#include "core/loader/ncch.h"
11#include "core/hle/kernel/archive.h"
12#include "core/mem_map.h"
13
14#include "3dsx.h"
15
16
17namespace Loader {
18
19
20/**
21 * File layout:
22 * - File header
23 * - Code, rodata and data relocation table headers
24 * - Code segment
25 * - Rodata segment
26 * - Loadable (non-BSS) part of the data segment
27 * - Code relocation table
28 * - Rodata relocation table
29 * - Data relocation table
30 *
31 * Memory layout before relocations are applied:
32 * [0..codeSegSize) -> code segment
33 * [codeSegSize..rodataSegSize) -> rodata segment
34 * [rodataSegSize..dataSegSize) -> data segment
35 *
36 * Memory layout after relocations are applied: well, however the loader sets it up :)
37 * The entrypoint is always the start of the code segment.
38 * The BSS section must be cleared manually by the application.
39 */
40enum THREEDSX_Error {
41 ERROR_NONE = 0,
42 ERROR_READ = 1,
43 ERROR_FILE = 2,
44 ERROR_ALLOC = 3
45};
46static const u32 RELOCBUFSIZE = 512;
47
48// File header
49static const u32 THREEDSX_MAGIC = 0x58534433; // '3DSX'
50#pragma pack(1)
51struct THREEDSX_Header
52{
53 u32 magic;
54 u16 header_size, reloc_hdr_size;
55 u32 format_ver;
56 u32 flags;
57
58 // Sizes of the code, rodata and data segments +
59 // size of the BSS section (uninitialized latter half of the data segment)
60 u32 code_seg_size, rodata_seg_size, data_seg_size, bss_size;
61};
62
63// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
64struct THREEDSX_RelocHdr
65{
66 // # of absolute relocations (that is, fix address to post-relocation memory layout)
67 u32 cross_segment_absolute;
68 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched)
69 u32 cross_segment_relative;
70 // more?
71
72 // Relocations are written in this order:
73 // - Absolute relocations
74 // - Relative relocations
75};
76
77// Relocation entry: from the current pointer, skip X words and patch Y words
78struct THREEDSX_Reloc
79{
80 u16 skip, patch;
81};
82#pragma pack()
83
84struct THREEloadinfo
85{
86 u8* seg_ptrs[3]; // code, rodata & data
87 u32 seg_addrs[3];
88 u32 seg_sizes[3];
89};
90
91class THREEDSXReader {
92public:
93 static int Load3DSXFile(const std::string& filename, u32 base_addr);
94};
95
96static u32 TranslateAddr(u32 addr, THREEloadinfo *loadinfo, u32* offsets)
97{
98 if (addr < offsets[0])
99 return loadinfo->seg_addrs[0] + addr;
100 if (addr < offsets[1])
101 return loadinfo->seg_addrs[1] + addr - offsets[0];
102 return loadinfo->seg_addrs[2] + addr - offsets[1];
103}
104
105int THREEDSXReader::Load3DSXFile(const std::string& filename, u32 base_addr)
106{
107 FileUtil::IOFile file(filename, "rb");
108 if (!file.IsOpen()) {
109 return ERROR_FILE;
110 }
111 THREEDSX_Header hdr;
112 if (file.ReadBytes(&hdr, sizeof(hdr)) != sizeof(hdr))
113 return ERROR_READ;
114
115 THREEloadinfo loadinfo;
116 //loadinfo segments must be a multiple of 0x1000
117 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) &~0xFFF;
118 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF;
119 loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF;
120 u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] };
121 u32 data_load_size = (hdr.data_seg_size - hdr.bss_size + 0xFFF) &~0xFFF;
122 u32 bss_load_size = loadinfo.seg_sizes[2] - data_load_size;
123 u32 n_reloc_tables = hdr.reloc_hdr_size / 4;
124 std::vector<u8> all_mem(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2] + 3 * n_reloc_tables);
125
126 loadinfo.seg_addrs[0] = base_addr;
127 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0];
128 loadinfo.seg_addrs[2] = loadinfo.seg_addrs[1] + loadinfo.seg_sizes[1];
129 loadinfo.seg_ptrs[0] = &all_mem[0];
130 loadinfo.seg_ptrs[1] = loadinfo.seg_ptrs[0] + loadinfo.seg_sizes[0];
131 loadinfo.seg_ptrs[2] = loadinfo.seg_ptrs[1] + loadinfo.seg_sizes[1];
132
133 // Skip header for future compatibility
134 file.Seek(hdr.header_size, SEEK_SET);
135
136 // Read the relocation headers
137 u32* relocs = (u32*)(loadinfo.seg_ptrs[2] + hdr.data_seg_size);
138
139 for (u32 current_segment = 0; current_segment < 3; current_segment++) {
140 if (file.ReadBytes(&relocs[current_segment*n_reloc_tables], n_reloc_tables * 4) != n_reloc_tables * 4)
141 return ERROR_READ;
142 }
143
144 // Read the segments
145 if (file.ReadBytes(loadinfo.seg_ptrs[0], hdr.code_seg_size) != hdr.code_seg_size)
146 return ERROR_READ;
147 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size)
148 return ERROR_READ;
149 if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) != hdr.data_seg_size - hdr.bss_size)
150 return ERROR_READ;
151
152 // BSS clear
153 memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size);
154
155 // Relocate the segments
156 for (u32 current_segment = 0; current_segment < 3; current_segment++) {
157 for (u32 current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) {
158 u32 n_relocs = relocs[current_segment*n_reloc_tables + current_segment_reloc_table];
159 if (current_segment_reloc_table >= 2) {
160 // We are not using this table - ignore it because we don't know what it dose
161 file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR);
162 continue;
163 }
164 static THREEDSX_Reloc reloc_table[RELOCBUFSIZE];
165
166 u32* pos = (u32*)loadinfo.seg_ptrs[current_segment];
167 u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4);
168
169 while (n_relocs) {
170 u32 remaining = std::min(RELOCBUFSIZE, n_relocs);
171 n_relocs -= remaining;
172
173 if (file.ReadBytes(reloc_table, remaining*sizeof(THREEDSX_Reloc)) != remaining*sizeof(THREEDSX_Reloc))
174 return ERROR_READ;
175
176 for (u32 current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) {
177 DEBUG_LOG(LOADER, "(t=%d,skip=%u,patch=%u)\n",
178 current_segment_reloc_table, (u32)reloc_table[current_inprogress].skip, (u32)reloc_table[current_inprogress].patch);
179 pos += reloc_table[current_inprogress].skip;
180 s32 num_patches = reloc_table[current_inprogress].patch;
181 while (0 < num_patches && pos < end_pos) {
182 u32 in_addr = (char*)pos - (char*)&all_mem[0];
183 u32 addr = TranslateAddr(*pos, &loadinfo, offsets);
184 DEBUG_LOG(LOADER, "Patching %08X <-- rel(%08X,%d) (%08X)\n",
185 base_addr + in_addr, addr, current_segment_reloc_table, *pos);
186 switch (current_segment_reloc_table) {
187 case 0: *pos = (addr); break;
188 case 1: *pos = (addr - in_addr); break;
189 default: break; //this should never happen
190 }
191 pos++;
192 num_patches--;
193 }
194 }
195 }
196 }
197 }
198
199 // Write the data
200 memcpy(Memory::GetPointer(base_addr), &all_mem[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]);
201
202 DEBUG_LOG(LOADER, "CODE: %u pages\n", loadinfo.seg_sizes[0] / 0x1000);
203 DEBUG_LOG(LOADER, "RODATA: %u pages\n", loadinfo.seg_sizes[1] / 0x1000);
204 DEBUG_LOG(LOADER, "DATA: %u pages\n", data_load_size / 0x1000);
205 DEBUG_LOG(LOADER, "BSS: %u pages\n", bss_load_size / 0x1000);
206
207 return ERROR_NONE;
208}
209
210 /// AppLoader_DSX constructor
211 AppLoader_THREEDSX::AppLoader_THREEDSX(const std::string& filename) : filename(filename) {
212 }
213
214 /// AppLoader_DSX destructor
215 AppLoader_THREEDSX::~AppLoader_THREEDSX() {
216 }
217
218 /**
219 * Loads a 3DSX file
220 * @return Success on success, otherwise Error
221 */
222 ResultStatus AppLoader_THREEDSX::Load() {
223 INFO_LOG(LOADER, "Loading 3DSX file %s...", filename.c_str());
224 FileUtil::IOFile file(filename, "rb");
225 if (file.IsOpen()) {
226
227 THREEDSXReader reader;
228 reader.Load3DSXFile(filename, 0x00100000);
229 Kernel::LoadExec(0x00100000);
230 } else {
231 return ResultStatus::Error;
232 }
233 return ResultStatus::Success;
234 }
235
236} // namespace Loader
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h
new file mode 100644
index 000000000..848d3ef8a
--- /dev/null
+++ b/src/core/loader/3dsx.h
@@ -0,0 +1,32 @@
1// Copyright 2014 Dolphin Emulator Project / Citra Emulator Project
2// Licensed under GPLv2+
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "core/loader/loader.h"
9
10////////////////////////////////////////////////////////////////////////////////////////////////////
11// Loader namespace
12
13namespace Loader {
14
15/// Loads an 3DSX file
16class AppLoader_THREEDSX final : public AppLoader {
17public:
18 AppLoader_THREEDSX(const std::string& filename);
19 ~AppLoader_THREEDSX() override;
20
21 /**
22 * Load the bootable file
23 * @return ResultStatus result of function
24 */
25 ResultStatus Load() override;
26
27private:
28 std::string filename;
29 bool is_loaded;
30};
31
32} // namespace Loader
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index a268e021a..174397b05 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -5,6 +5,7 @@
5#include <memory> 5#include <memory>
6 6
7#include "core/file_sys/archive_romfs.h" 7#include "core/file_sys/archive_romfs.h"
8#include "core/loader/3dsx.h"
8#include "core/loader/elf.h" 9#include "core/loader/elf.h"
9#include "core/loader/ncch.h" 10#include "core/loader/ncch.h"
10#include "core/hle/kernel/archive.h" 11#include "core/hle/kernel/archive.h"
@@ -42,6 +43,8 @@ FileType IdentifyFile(const std::string &filename) {
42 return FileType::CCI; 43 return FileType::CCI;
43 } else if (extension == ".bin") { 44 } else if (extension == ".bin") {
44 return FileType::BIN; 45 return FileType::BIN;
46 } else if (extension == ".3dsx") {
47 return FileType::THREEDSX;
45 } 48 }
46 return FileType::Unknown; 49 return FileType::Unknown;
47} 50}
@@ -56,6 +59,10 @@ ResultStatus LoadFile(const std::string& filename) {
56 59
57 switch (IdentifyFile(filename)) { 60 switch (IdentifyFile(filename)) {
58 61
62 //3DSX file format...
63 case FileType::THREEDSX:
64 return AppLoader_THREEDSX(filename).Load();
65
59 // Standard ELF file format... 66 // Standard ELF file format...
60 case FileType::ELF: 67 case FileType::ELF:
61 return AppLoader_ELF(filename).Load(); 68 return AppLoader_ELF(filename).Load();
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 68f843005..0f836d285 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -22,6 +22,7 @@ enum class FileType {
22 CIA, 22 CIA,
23 ELF, 23 ELF,
24 BIN, 24 BIN,
25 THREEDSX, //3DSX
25}; 26};
26 27
27/// Return type for functions in Loader namespace 28/// Return type for functions in Loader namespace
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index a58c59244..f17afb60d 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -16,10 +16,9 @@ typedef u32 PAddr; ///< Represents a pointer in the physical address space.
16 16
17//////////////////////////////////////////////////////////////////////////////////////////////////// 17////////////////////////////////////////////////////////////////////////////////////////////////////
18 18
19enum { 19enum : u32 {
20 BOOTROM_SIZE = 0x00010000, ///< Bootrom (super secret code/data @ 0x8000) size 20 BOOTROM_SIZE = 0x00010000, ///< Bootrom (super secret code/data @ 0x8000) size
21 MPCORE_PRIV_SIZE = 0x00002000, ///< MPCore private memory region size 21 MPCORE_PRIV_SIZE = 0x00002000, ///< MPCore private memory region size
22 DSP_SIZE = 0x00080000, ///< DSP memory size
23 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size 22 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size
24 23
25 FCRAM_SIZE = 0x08000000, ///< FCRAM size 24 FCRAM_SIZE = 0x08000000, ///< FCRAM size
@@ -27,47 +26,42 @@ enum {
27 FCRAM_PADDR_END = (FCRAM_PADDR + FCRAM_SIZE), ///< FCRAM end of physical space 26 FCRAM_PADDR_END = (FCRAM_PADDR + FCRAM_SIZE), ///< FCRAM end of physical space
28 FCRAM_VADDR = 0x08000000, ///< FCRAM virtual address 27 FCRAM_VADDR = 0x08000000, ///< FCRAM virtual address
29 FCRAM_VADDR_END = (FCRAM_VADDR + FCRAM_SIZE), ///< FCRAM end of virtual space 28 FCRAM_VADDR_END = (FCRAM_VADDR + FCRAM_SIZE), ///< FCRAM end of virtual space
30 FCRAM_MASK = (FCRAM_SIZE - 1), ///< FCRAM mask
31 29
32 SHARED_MEMORY_SIZE = 0x04000000, ///< Shared memory size 30 SHARED_MEMORY_SIZE = 0x04000000, ///< Shared memory size
33 SHARED_MEMORY_VADDR = 0x10000000, ///< Shared memory 31 SHARED_MEMORY_VADDR = 0x10000000, ///< Shared memory
34 SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE), 32 SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE),
35 SHARED_MEMORY_MASK = (SHARED_MEMORY_SIZE - 1), 33
34 DSP_MEMORY_SIZE = 0x00080000, ///< DSP memory size
35 DSP_MEMORY_VADDR = 0x1FF00000, ///< DSP memory virtual address
36 36
37 CONFIG_MEMORY_SIZE = 0x00001000, ///< Configuration memory size 37 CONFIG_MEMORY_SIZE = 0x00001000, ///< Configuration memory size
38 CONFIG_MEMORY_VADDR = 0x1FF80000, ///< Configuration memory virtual address 38 CONFIG_MEMORY_VADDR = 0x1FF80000, ///< Configuration memory virtual address
39 CONFIG_MEMORY_VADDR_END = (CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE), 39 CONFIG_MEMORY_VADDR_END = (CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE),
40 CONFIG_MEMORY_MASK = (CONFIG_MEMORY_SIZE - 1),
41 40
42 KERNEL_MEMORY_SIZE = 0x00001000, ///< Kernel memory size 41 KERNEL_MEMORY_SIZE = 0x00001000, ///< Kernel memory size
43 KERNEL_MEMORY_VADDR = 0xFFFF0000, ///< Kernel memory where the kthread objects etc are 42 KERNEL_MEMORY_VADDR = 0xFFFF0000, ///< Kernel memory where the kthread objects etc are
44 KERNEL_MEMORY_VADDR_END = (KERNEL_MEMORY_VADDR + KERNEL_MEMORY_SIZE), 43 KERNEL_MEMORY_VADDR_END = (KERNEL_MEMORY_VADDR + KERNEL_MEMORY_SIZE),
45 KERNEL_MEMORY_MASK = (KERNEL_MEMORY_SIZE - 1),
46 44
47 EXEFS_CODE_SIZE = 0x03F00000, 45 EXEFS_CODE_SIZE = 0x03F00000,
48 EXEFS_CODE_VADDR = 0x00100000, ///< ExeFS:/.code is loaded here 46 EXEFS_CODE_VADDR = 0x00100000, ///< ExeFS:/.code is loaded here
49 EXEFS_CODE_VADDR_END = (EXEFS_CODE_VADDR + EXEFS_CODE_SIZE), 47 EXEFS_CODE_VADDR_END = (EXEFS_CODE_VADDR + EXEFS_CODE_SIZE),
50 EXEFS_CODE_MASK = 0x03FFFFFF,
51 48
52 // Region of FCRAM used by system 49 // Region of FCRAM used by system
53 SYSTEM_MEMORY_SIZE = 0x02C00000, ///< 44MB 50 SYSTEM_MEMORY_SIZE = 0x02C00000, ///< 44MB
54 SYSTEM_MEMORY_VADDR = 0x04000000, 51 SYSTEM_MEMORY_VADDR = 0x04000000,
55 SYSTEM_MEMORY_VADDR_END = (SYSTEM_MEMORY_VADDR + SYSTEM_MEMORY_SIZE), 52 SYSTEM_MEMORY_VADDR_END = (SYSTEM_MEMORY_VADDR + SYSTEM_MEMORY_SIZE),
56 SYSTEM_MEMORY_MASK = 0x03FFFFFF,
57 53
58 HEAP_SIZE = FCRAM_SIZE, ///< Application heap size 54 HEAP_SIZE = FCRAM_SIZE, ///< Application heap size
59 //HEAP_PADDR = HEAP_GSP_SIZE, 55 //HEAP_PADDR = HEAP_GSP_SIZE,
60 //HEAP_PADDR_END = (HEAP_PADDR + HEAP_SIZE), 56 //HEAP_PADDR_END = (HEAP_PADDR + HEAP_SIZE),
61 HEAP_VADDR = 0x08000000, 57 HEAP_VADDR = 0x08000000,
62 HEAP_VADDR_END = (HEAP_VADDR + HEAP_SIZE), 58 HEAP_VADDR_END = (HEAP_VADDR + HEAP_SIZE),
63 HEAP_MASK = (HEAP_SIZE - 1),
64 59
65 HEAP_GSP_SIZE = 0x02000000, ///< GSP heap size... TODO: Define correctly? 60 HEAP_GSP_SIZE = 0x02000000, ///< GSP heap size... TODO: Define correctly?
66 HEAP_GSP_VADDR = 0x14000000, 61 HEAP_GSP_VADDR = 0x14000000,
67 HEAP_GSP_VADDR_END = (HEAP_GSP_VADDR + HEAP_GSP_SIZE), 62 HEAP_GSP_VADDR_END = (HEAP_GSP_VADDR + HEAP_GSP_SIZE),
68 HEAP_GSP_PADDR = 0x00000000, 63 HEAP_GSP_PADDR = 0x00000000,
69 HEAP_GSP_PADDR_END = (HEAP_GSP_PADDR + HEAP_GSP_SIZE), 64 HEAP_GSP_PADDR_END = (HEAP_GSP_PADDR + HEAP_GSP_SIZE),
70 HEAP_GSP_MASK = (HEAP_GSP_SIZE - 1),
71 65
72 HARDWARE_IO_SIZE = 0x01000000, 66 HARDWARE_IO_SIZE = 0x01000000,
73 HARDWARE_IO_PADDR = 0x10000000, ///< IO physical address start 67 HARDWARE_IO_PADDR = 0x10000000, ///< IO physical address start
@@ -80,12 +74,10 @@ enum {
80 VRAM_VADDR = 0x1F000000, 74 VRAM_VADDR = 0x1F000000,
81 VRAM_PADDR_END = (VRAM_PADDR + VRAM_SIZE), 75 VRAM_PADDR_END = (VRAM_PADDR + VRAM_SIZE),
82 VRAM_VADDR_END = (VRAM_VADDR + VRAM_SIZE), 76 VRAM_VADDR_END = (VRAM_VADDR + VRAM_SIZE),
83 VRAM_MASK = 0x007FFFFF,
84 77
85 SCRATCHPAD_SIZE = 0x00004000, ///< Typical stack size - TODO: Read from exheader 78 SCRATCHPAD_SIZE = 0x00004000, ///< Typical stack size - TODO: Read from exheader
86 SCRATCHPAD_VADDR_END = 0x10000000, 79 SCRATCHPAD_VADDR_END = 0x10000000,
87 SCRATCHPAD_VADDR = (SCRATCHPAD_VADDR_END - SCRATCHPAD_SIZE), ///< Stack space 80 SCRATCHPAD_VADDR = (SCRATCHPAD_VADDR_END - SCRATCHPAD_SIZE), ///< Stack space
88 SCRATCHPAD_MASK = (SCRATCHPAD_SIZE - 1), ///< Scratchpad memory mask
89}; 81};
90 82
91//////////////////////////////////////////////////////////////////////////////////////////////////// 83////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 443d5ad7e..1887bcedb 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -56,7 +56,7 @@ inline void Read(T &var, const VAddr vaddr) {
56 56
57 // Kernel memory command buffer 57 // Kernel memory command buffer
58 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { 58 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
59 var = *((const T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK]); 59 var = *((const T*)&g_kernel_mem[vaddr - KERNEL_MEMORY_VADDR]);
60 60
61 // Hardware I/O register reads 61 // Hardware I/O register reads
62 // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space 62 // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
@@ -65,23 +65,23 @@ inline void Read(T &var, const VAddr vaddr) {
65 65
66 // ExeFS:/.code is loaded here 66 // ExeFS:/.code is loaded here
67 } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) { 67 } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
68 var = *((const T*)&g_exefs_code[vaddr & EXEFS_CODE_MASK]); 68 var = *((const T*)&g_exefs_code[vaddr - EXEFS_CODE_VADDR]);
69 69
70 // FCRAM - GSP heap 70 // FCRAM - GSP heap
71 } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) { 71 } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
72 var = *((const T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK]); 72 var = *((const T*)&g_heap_gsp[vaddr - HEAP_GSP_VADDR]);
73 73
74 // FCRAM - application heap 74 // FCRAM - application heap
75 } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) { 75 } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
76 var = *((const T*)&g_heap[vaddr & HEAP_MASK]); 76 var = *((const T*)&g_heap[vaddr - HEAP_VADDR]);
77 77
78 // Shared memory 78 // Shared memory
79 } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) { 79 } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
80 var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]); 80 var = *((const T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR]);
81 81
82 // System memory 82 // System memory
83 } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) { 83 } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
84 var = *((const T*)&g_system_mem[vaddr & SYSTEM_MEMORY_MASK]); 84 var = *((const T*)&g_system_mem[vaddr - SYSTEM_MEMORY_VADDR]);
85 85
86 // Config memory 86 // Config memory
87 } else if ((vaddr >= CONFIG_MEMORY_VADDR) && (vaddr < CONFIG_MEMORY_VADDR_END)) { 87 } else if ((vaddr >= CONFIG_MEMORY_VADDR) && (vaddr < CONFIG_MEMORY_VADDR_END)) {
@@ -89,10 +89,10 @@ inline void Read(T &var, const VAddr vaddr) {
89 89
90 // VRAM 90 // VRAM
91 } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { 91 } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
92 var = *((const T*)&g_vram[vaddr & VRAM_MASK]); 92 var = *((const T*)&g_vram[vaddr - VRAM_VADDR]);
93 93
94 } else { 94 } else {
95 ERROR_LOG(MEMMAP, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr); 95 ERROR_LOG(MEMMAP, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, vaddr);
96 } 96 }
97} 97}
98 98
@@ -101,7 +101,7 @@ inline void Write(const VAddr vaddr, const T data) {
101 101
102 // Kernel memory command buffer 102 // Kernel memory command buffer
103 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { 103 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
104 *(T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK] = data; 104 *(T*)&g_kernel_mem[vaddr - KERNEL_MEMORY_VADDR] = data;
105 105
106 // Hardware I/O register writes 106 // Hardware I/O register writes
107 // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space 107 // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
@@ -110,27 +110,27 @@ inline void Write(const VAddr vaddr, const T data) {
110 110
111 // ExeFS:/.code is loaded here 111 // ExeFS:/.code is loaded here
112 } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) { 112 } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
113 *(T*)&g_exefs_code[vaddr & EXEFS_CODE_MASK] = data; 113 *(T*)&g_exefs_code[vaddr - EXEFS_CODE_VADDR] = data;
114 114
115 // FCRAM - GSP heap 115 // FCRAM - GSP heap
116 } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) { 116 } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
117 *(T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK] = data; 117 *(T*)&g_heap_gsp[vaddr - HEAP_GSP_VADDR] = data;
118 118
119 // FCRAM - application heap 119 // FCRAM - application heap
120 } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) { 120 } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
121 *(T*)&g_heap[vaddr & HEAP_MASK] = data; 121 *(T*)&g_heap[vaddr - HEAP_VADDR] = data;
122 122
123 // Shared memory 123 // Shared memory
124 } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) { 124 } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
125 *(T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK] = data; 125 *(T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR] = data;
126 126
127 // System memory 127 // System memory
128 } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) { 128 } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
129 *(T*)&g_system_mem[vaddr & SYSTEM_MEMORY_MASK] = data; 129 *(T*)&g_system_mem[vaddr - SYSTEM_MEMORY_VADDR] = data;
130 130
131 // VRAM 131 // VRAM
132 } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { 132 } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
133 *(T*)&g_vram[vaddr & VRAM_MASK] = data; 133 *(T*)&g_vram[vaddr - VRAM_VADDR] = data;
134 134
135 //} else if ((vaddr & 0xFFF00000) == 0x1FF00000) { 135 //} else if ((vaddr & 0xFFF00000) == 0x1FF00000) {
136 // _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory"); 136 // _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory");
@@ -141,38 +141,38 @@ inline void Write(const VAddr vaddr, const T data) {
141 141
142 // Error out... 142 // Error out...
143 } else { 143 } else {
144 ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr); 144 ERROR_LOG(MEMMAP, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, vaddr);
145 } 145 }
146} 146}
147 147
148u8 *GetPointer(const VAddr vaddr) { 148u8 *GetPointer(const VAddr vaddr) {
149 // Kernel memory command buffer 149 // Kernel memory command buffer
150 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { 150 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
151 return g_kernel_mem + (vaddr & KERNEL_MEMORY_MASK); 151 return g_kernel_mem + (vaddr - KERNEL_MEMORY_VADDR);
152 152
153 // ExeFS:/.code is loaded here 153 // ExeFS:/.code is loaded here
154 } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) { 154 } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
155 return g_exefs_code + (vaddr & EXEFS_CODE_MASK); 155 return g_exefs_code + (vaddr - EXEFS_CODE_VADDR);
156 156
157 // FCRAM - GSP heap 157 // FCRAM - GSP heap
158 } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) { 158 } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
159 return g_heap_gsp + (vaddr & HEAP_GSP_MASK); 159 return g_heap_gsp + (vaddr - HEAP_GSP_VADDR);
160 160
161 // FCRAM - application heap 161 // FCRAM - application heap
162 } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) { 162 } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
163 return g_heap + (vaddr & HEAP_MASK); 163 return g_heap + (vaddr - HEAP_VADDR);
164 164
165 // Shared memory 165 // Shared memory
166 } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) { 166 } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
167 return g_shared_mem + (vaddr & SHARED_MEMORY_MASK); 167 return g_shared_mem + (vaddr - SHARED_MEMORY_VADDR);
168 168
169 // System memory 169 // System memory
170 } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) { 170 } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
171 return g_system_mem + (vaddr & SYSTEM_MEMORY_MASK); 171 return g_system_mem + (vaddr - SYSTEM_MEMORY_VADDR);
172 172
173 // VRAM 173 // VRAM
174 } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { 174 } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
175 return g_vram + (vaddr & VRAM_MASK); 175 return g_vram + (vaddr - VRAM_VADDR);
176 176
177 } else { 177 } else {
178 ERROR_LOG(MEMMAP, "unknown GetPointer @ 0x%08x", vaddr); 178 ERROR_LOG(MEMMAP, "unknown GetPointer @ 0x%08x", vaddr);
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 1ec727698..8a6ba2560 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -60,7 +60,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
60 const u8* load_address = base_address + loader_config.data_offset; 60 const u8* load_address = base_address + loader_config.data_offset;
61 61
62 // TODO: What happens if a loader overwrites a previous one's data? 62 // TODO: What happens if a loader overwrites a previous one's data?
63 for (int component = 0; component < loader_config.component_count; ++component) { 63 for (unsigned component = 0; component < loader_config.component_count; ++component) {
64 u32 attribute_index = loader_config.GetComponent(component); 64 u32 attribute_index = loader_config.GetComponent(component);
65 vertex_attribute_sources[attribute_index] = load_address; 65 vertex_attribute_sources[attribute_index] = load_address;
66 vertex_attribute_strides[attribute_index] = static_cast<u32>(loader_config.byte_count); 66 vertex_attribute_strides[attribute_index] = static_cast<u32>(loader_config.byte_count);
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 275b06b7c..8a5f11424 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -155,7 +155,7 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data
155 155
156 // This is put into a try-catch block to make sure we notice unknown configurations. 156 // This is put into a try-catch block to make sure we notice unknown configurations.
157 std::vector<OutputRegisterInfo> output_info_table; 157 std::vector<OutputRegisterInfo> output_info_table;
158 for (int i = 0; i < 7; ++i) { 158 for (unsigned i = 0; i < 7; ++i) {
159 using OutputAttributes = Pica::Regs::VSOutputAttributes; 159 using OutputAttributes = Pica::Regs::VSOutputAttributes;
160 160
161 // TODO: It's still unclear how the attribute components map to the register! 161 // TODO: It's still unclear how the attribute components map to the register!
@@ -375,8 +375,8 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
375 png_write_info(png_ptr, info_ptr); 375 png_write_info(png_ptr, info_ptr);
376 376
377 buf = new u8[row_stride * texture_config.height]; 377 buf = new u8[row_stride * texture_config.height];
378 for (int y = 0; y < texture_config.height; ++y) { 378 for (unsigned y = 0; y < texture_config.height; ++y) {
379 for (int x = 0; x < texture_config.width; ++x) { 379 for (unsigned x = 0; x < texture_config.width; ++x) {
380 // Cf. rasterizer code for an explanation of this algorithm. 380 // Cf. rasterizer code for an explanation of this algorithm.
381 int texel_index_within_tile = 0; 381 int texel_index_within_tile = 0;
382 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) { 382 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) {
@@ -402,7 +402,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
402 } 402 }
403 403
404 // Write image data 404 // Write image data
405 for (auto y = 0; y < texture_config.height; ++y) 405 for (unsigned y = 0; y < texture_config.height; ++y)
406 { 406 {
407 u8* row_ptr = (u8*)buf + y * row_stride; 407 u8* row_ptr = (u8*)buf + y * row_stride;
408 u8* ptr = row_ptr; 408 u8* ptr = row_ptr;
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp
index a0eb0418c..fdac9ae1a 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_util.cpp
@@ -22,7 +22,7 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
22 // Compile Vertex Shader 22 // Compile Vertex Shader
23 DEBUG_LOG(GPU, "Compiling vertex shader."); 23 DEBUG_LOG(GPU, "Compiling vertex shader.");
24 24
25 glShaderSource(vertex_shader_id, 1, &vertex_shader, NULL); 25 glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr);
26 glCompileShader(vertex_shader_id); 26 glCompileShader(vertex_shader_id);
27 27
28 // Check Vertex Shader 28 // Check Vertex Shader
@@ -31,14 +31,14 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
31 31
32 if (info_log_length > 1) { 32 if (info_log_length > 1) {
33 std::vector<char> vertex_shader_error(info_log_length); 33 std::vector<char> vertex_shader_error(info_log_length);
34 glGetShaderInfoLog(vertex_shader_id, info_log_length, NULL, &vertex_shader_error[0]); 34 glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]);
35 DEBUG_LOG(GPU, "%s", &vertex_shader_error[0]); 35 DEBUG_LOG(GPU, "%s", &vertex_shader_error[0]);
36 } 36 }
37 37
38 // Compile Fragment Shader 38 // Compile Fragment Shader
39 DEBUG_LOG(GPU, "Compiling fragment shader."); 39 DEBUG_LOG(GPU, "Compiling fragment shader.");
40 40
41 glShaderSource(fragment_shader_id, 1, &fragment_shader, NULL); 41 glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr);
42 glCompileShader(fragment_shader_id); 42 glCompileShader(fragment_shader_id);
43 43
44 // Check Fragment Shader 44 // Check Fragment Shader
@@ -47,7 +47,7 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
47 47
48 if (info_log_length > 1) { 48 if (info_log_length > 1) {
49 std::vector<char> fragment_shader_error(info_log_length); 49 std::vector<char> fragment_shader_error(info_log_length);
50 glGetShaderInfoLog(fragment_shader_id, info_log_length, NULL, &fragment_shader_error[0]); 50 glGetShaderInfoLog(fragment_shader_id, info_log_length, nullptr, &fragment_shader_error[0]);
51 DEBUG_LOG(GPU, "%s", &fragment_shader_error[0]); 51 DEBUG_LOG(GPU, "%s", &fragment_shader_error[0]);
52 } 52 }
53 53
@@ -65,7 +65,7 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
65 65
66 if (info_log_length > 1) { 66 if (info_log_length > 1) {
67 std::vector<char> program_error(info_log_length); 67 std::vector<char> program_error(info_log_length);
68 glGetProgramInfoLog(program_id, info_log_length, NULL, &program_error[0]); 68 glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]);
69 DEBUG_LOG(GPU, "%s", &program_error[0]); 69 DEBUG_LOG(GPU, "%s", &program_error[0]);
70 } 70 }
71 71
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index abbb4c2cb..06de6afbd 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -61,7 +61,7 @@ void RendererOpenGL::SwapBuffers() {
61 for(int i : {0, 1}) { 61 for(int i : {0, 1}) {
62 const auto& framebuffer = GPU::g_regs.framebuffer_config[i]; 62 const auto& framebuffer = GPU::g_regs.framebuffer_config[i];
63 63
64 if (textures[i].width != framebuffer.width || textures[i].height != framebuffer.height) { 64 if (textures[i].width != (GLsizei)framebuffer.width || textures[i].height != (GLsizei)framebuffer.height) {
65 // Reallocate texture if the framebuffer size has changed. 65 // Reallocate texture if the framebuffer size has changed.
66 // This is expected to not happen very often and hence should not be a 66 // This is expected to not happen very often and hence should not be a
67 // performance problem. 67 // performance problem.
@@ -240,14 +240,14 @@ MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() {
240 MathUtil::Rectangle<unsigned> viewport_extent; 240 MathUtil::Rectangle<unsigned> viewport_extent;
241 if (window_aspect_ratio > emulation_aspect_ratio) { 241 if (window_aspect_ratio > emulation_aspect_ratio) {
242 // Window is narrower than the emulation content => apply borders to the top and bottom 242 // Window is narrower than the emulation content => apply borders to the top and bottom
243 unsigned viewport_height = emulation_aspect_ratio * framebuffer_width; 243 unsigned viewport_height = std::round(emulation_aspect_ratio * framebuffer_width);
244 viewport_extent.left = 0; 244 viewport_extent.left = 0;
245 viewport_extent.top = (framebuffer_height - viewport_height) / 2; 245 viewport_extent.top = (framebuffer_height - viewport_height) / 2;
246 viewport_extent.right = viewport_extent.left + framebuffer_width; 246 viewport_extent.right = viewport_extent.left + framebuffer_width;
247 viewport_extent.bottom = viewport_extent.top + viewport_height; 247 viewport_extent.bottom = viewport_extent.top + viewport_height;
248 } else { 248 } else {
249 // Otherwise, apply borders to the left and right sides of the window. 249 // Otherwise, apply borders to the left and right sides of the window.
250 unsigned viewport_width = framebuffer_height / emulation_aspect_ratio; 250 unsigned viewport_width = std::round(framebuffer_height / emulation_aspect_ratio);
251 viewport_extent.left = (framebuffer_width - viewport_width) / 2; 251 viewport_extent.left = (framebuffer_width - viewport_width) / 2;
252 viewport_extent.top = 0; 252 viewport_extent.top = 0;
253 viewport_extent.right = viewport_extent.left + viewport_width; 253 viewport_extent.right = viewport_extent.left + viewport_width;
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index c779771c5..b581ff4da 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -17,8 +17,8 @@
17 17
18namespace VideoCore { 18namespace VideoCore {
19 19
20EmuWindow* g_emu_window = NULL; ///< Frontend emulator window 20EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window
21RendererBase* g_renderer = NULL; ///< Renderer plugin 21RendererBase* g_renderer = nullptr; ///< Renderer plugin
22int g_current_frame = 0; 22int g_current_frame = 0;
23 23
24/// Initialize the video core 24/// Initialize the video core