summaryrefslogtreecommitdiffstats
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)
else()
# Silence deprecation warnings
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
+ # set up output paths for executable binaries (.exe-files, and .dll-files on DLL-capable platforms)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
add_definitions(-DSINGLETHREADED)
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
### Comments
* For regular comments, use C++ style (`//`) comments, even for multi-line ones.
* For doc-comments (Doxygen comments), use `/// ` if it's a single line, else use the `/**` `*/` style featured in the example. Start the text on the second line, not the first containing `/**`.
+* 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.
```cpp
namespace 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&
return true;
}
-void Config::ReadControls() {
+void Config::ReadValues() {
+ // Controls
Settings::values.pad_a_key = glfw_config->GetInteger("Controls", "pad_a", GLFW_KEY_A);
Settings::values.pad_b_key = glfw_config->GetInteger("Controls", "pad_b", GLFW_KEY_S);
Settings::values.pad_x_key = glfw_config->GetInteger("Controls", "pad_x", GLFW_KEY_Z);
@@ -54,27 +55,21 @@ void Config::ReadControls() {
Settings::values.pad_sdown_key = glfw_config->GetInteger("Controls", "pad_sdown", GLFW_KEY_DOWN);
Settings::values.pad_sleft_key = glfw_config->GetInteger("Controls", "pad_sleft", GLFW_KEY_LEFT);
Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT);
-}
-void Config::ReadCore() {
+ // Core
Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter);
Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 60);
-}
-void Config::ReadData() {
+ // Data Storage
Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true);
-}
-void Config::ReadMiscellaneous() {
+ // Miscellaneous
Settings::values.enable_log = glfw_config->GetBoolean("Miscellaneous", "enable_log", true);
}
void Config::Reload() {
LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file);
- ReadControls();
- ReadCore();
- ReadData();
- ReadMiscellaneous();
+ ReadValues();
}
Config::~Config() {
diff --git a/src/citra/config.h b/src/citra/config.h
index 19bb83700..2b46fa8aa 100644
--- a/src/citra/config.h
+++ b/src/citra/config.h
@@ -15,10 +15,7 @@ class Config {
std::string glfw_config_loc;
bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true);
- void ReadControls();
- void ReadCore();
- void ReadData();
- void ReadMiscellaneous();
+ void ReadValues();
public:
Config();
~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() {
ReloadSetKeymaps();
+ glfwSetErrorCallback([](int error, const char *desc){
+ ERROR_LOG(GUI, "GLFW 0x%08x: %s", error, desc);
+ });
+
// Initialize the window
if(glfwInit() != GL_TRUE) {
- printf("Failed to initialize GLFW! Exiting...");
+ ERROR_LOG(GUI, "Failed to initialize GLFW! Exiting...");
exit(1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
@@ -72,10 +76,10 @@ EmuWindow_GLFW::EmuWindow_GLFW() {
std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth,
(VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight),
- window_title.c_str(), NULL, NULL);
+ window_title.c_str(), nullptr, nullptr);
- if (m_render_window == NULL) {
- printf("Failed to create GLFW window! Exiting...");
+ if (m_render_window == nullptr) {
+ ERROR_LOG(GUI, "Failed to create GLFW window! Exiting...");
exit(1);
}
@@ -119,7 +123,7 @@ void EmuWindow_GLFW::MakeCurrent() {
/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
void EmuWindow_GLFW::DoneCurrent() {
- glfwMakeContextCurrent(NULL);
+ glfwMakeContextCurrent(nullptr);
}
void 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()
{
// If we are a top-level widget, store the current geometry
// otherwise, store the last backup
- if (parent() == NULL)
+ if (parent() == nullptr)
return ((QGLWidget*)this)->saveGeometry();
else
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() {
Reload();
}
-void Config::ReadControls() {
+void Config::ReadValues() {
qt_config->beginGroup("Controls");
Settings::values.pad_a_key = qt_config->value("pad_a", Qt::Key_A).toInt();
Settings::values.pad_b_key = qt_config->value("pad_b", Qt::Key_S).toInt();
@@ -41,9 +41,22 @@ void Config::ReadControls() {
Settings::values.pad_sleft_key = qt_config->value("pad_sleft", Qt::Key_Left).toInt();
Settings::values.pad_sright_key = qt_config->value("pad_sright", Qt::Key_Right).toInt();
qt_config->endGroup();
+
+ qt_config->beginGroup("Core");
+ Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt();
+ Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 60).toInt();
+ qt_config->endGroup();
+
+ qt_config->beginGroup("Data Storage");
+ Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
+ qt_config->endGroup();
+
+ qt_config->beginGroup("Miscellaneous");
+ Settings::values.enable_log = qt_config->value("enable_log", true).toBool();
+ qt_config->endGroup();
}
-void Config::SaveControls() {
+void Config::SaveValues() {
qt_config->beginGroup("Controls");
qt_config->setValue("pad_a", Settings::values.pad_a_key);
qt_config->setValue("pad_b", Settings::values.pad_b_key);
@@ -63,58 +76,27 @@ void Config::SaveControls() {
qt_config->setValue("pad_sleft", Settings::values.pad_sleft_key);
qt_config->setValue("pad_sright", Settings::values.pad_sright_key);
qt_config->endGroup();
-}
-
-void Config::ReadCore() {
- qt_config->beginGroup("Core");
- Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt();
- Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 60).toInt();
- qt_config->endGroup();
-}
-void Config::SaveCore() {
qt_config->beginGroup("Core");
qt_config->setValue("cpu_core", Settings::values.cpu_core);
qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate);
qt_config->endGroup();
-}
-
-void Config::ReadData() {
- qt_config->beginGroup("Data Storage");
- Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
- qt_config->endGroup();
-}
-void Config::SaveData() {
qt_config->beginGroup("Data Storage");
qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
qt_config->endGroup();
-}
-
-void Config::ReadMiscellaneous() {
- qt_config->beginGroup("Miscellaneous");
- Settings::values.enable_log = qt_config->value("enable_log", true).toBool();
- qt_config->endGroup();
-}
-void Config::SaveMiscellaneous() {
qt_config->beginGroup("Miscellaneous");
qt_config->setValue("enable_log", Settings::values.enable_log);
qt_config->endGroup();
}
void Config::Reload() {
- ReadControls();
- ReadCore();
- ReadData();
- ReadMiscellaneous();
+ ReadValues();
}
void Config::Save() {
- SaveControls();
- SaveCore();
- SaveData();
- SaveMiscellaneous();
+ SaveValues();
}
Config::~Config() {
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h
index 8c6568cb2..4c95d0cb9 100644
--- a/src/citra_qt/config.h
+++ b/src/citra_qt/config.h
@@ -12,15 +12,8 @@ class Config {
QSettings* qt_config;
std::string qt_config_loc;
- void ReadControls();
- void SaveControls();
- void ReadCore();
- void SaveCore();
- void ReadData();
- void SaveData();
-
- void ReadMiscellaneous();
- void SaveMiscellaneous();
+ void ReadValues();
+ void SaveValues();
public:
Config();
~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 @@
struct Hotkey
{
- Hotkey() : shortcut(NULL), context(Qt::WindowShortcut) {}
+ Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) {}
QKeySequence keyseq;
QShortcut* shortcut;
@@ -81,7 +81,7 @@ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widge
Hotkey& hk = hotkey_groups[group][action];
if (!hk.shortcut)
- hk.shortcut = new QShortcut(hk.keyseq, widget, NULL, NULL, hk.context);
+ hk.shortcut = new QShortcut(hk.keyseq, widget, nullptr, nullptr, hk.context);
return hk.shortcut;
}
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()
GMainWindow::~GMainWindow()
{
// will get automatically deleted otherwise
- if (render_window->parent() == NULL)
+ if (render_window->parent() == nullptr)
delete render_window;
}
@@ -164,7 +164,7 @@ void GMainWindow::BootGame(std::string filename)
void GMainWindow::OnMenuLoadFile()
{
- QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS executable (*.elf *.axf *.bin *.cci *.cxi)"));
+ QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS executable (*.3dsx *.elf *.axf *.bin *.cci *.cxi)"));
if (filename.size())
BootGame(filename.toLatin1().data());
}
@@ -213,14 +213,14 @@ void GMainWindow::OnOpenHotkeysDialog()
void GMainWindow::ToggleWindowMode()
{
bool enable = ui.action_Popout_Window_Mode->isChecked();
- if (enable && render_window->parent() != NULL)
+ if (enable && render_window->parent() != nullptr)
{
ui.horizontalLayout->removeWidget(render_window);
- render_window->setParent(NULL);
+ render_window->setParent(nullptr);
render_window->setVisible(true);
render_window->RestoreGeometry();
}
- else if (!enable && render_window->parent() == NULL)
+ else if (!enable && render_window->parent() == nullptr)
{
render_window->BackupGeometry();
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:
{
for (auto it = x.begin(), end = x.end(); it != end; ++it)
{
- if (it->second != NULL)
+ if (it->second != nullptr)
delete it->second;
}
}
- T *dv = NULL;
+ T *dv = nullptr;
DoMap(x, dv);
}
@@ -264,11 +264,11 @@ public:
{
for (auto it = x.begin(), end = x.end(); it != end; ++it)
{
- if (it->second != NULL)
+ if (it->second != nullptr)
delete it->second;
}
}
- T *dv = NULL;
+ T *dv = nullptr;
DoMultimap(x, dv);
}
@@ -320,7 +320,7 @@ public:
template<class T>
void Do(std::vector<T *> &x)
{
- T *dv = NULL;
+ T *dv = nullptr;
DoVector(x, dv);
}
@@ -369,7 +369,7 @@ public:
template<class T>
void Do(std::deque<T *> &x)
{
- T *dv = NULL;
+ T *dv = nullptr;
DoDeque(x, dv);
}
@@ -395,7 +395,7 @@ public:
template<class T>
void Do(std::list<T *> &x)
{
- T *dv = NULL;
+ T *dv = nullptr;
Do(x, dv);
}
@@ -433,7 +433,7 @@ public:
{
for (auto it = x.begin(), end = x.end(); it != end; ++it)
{
- if (*it != NULL)
+ if (*it != nullptr)
delete *it;
}
}
@@ -518,7 +518,7 @@ public:
void DoClass(T *&x) {
if (mode == MODE_READ)
{
- if (x != NULL)
+ if (x != nullptr)
delete x;
x = new T();
}
@@ -567,7 +567,7 @@ public:
{
if (mode == MODE_READ)
{
- cur->next = 0;
+ cur->next = nullptr;
list_cur = cur;
if (prev)
prev->next = cur;
@@ -586,13 +586,13 @@ public:
if (mode == MODE_READ)
{
if (prev)
- prev->next = 0;
+ prev->next = nullptr;
if (list_end)
*list_end = prev;
if (list_cur)
{
if (list_start == list_cur)
- list_start = 0;
+ list_start = nullptr;
do
{
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){
// Restore the global locale
_configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
}
- else if(new_locale != NULL)
+ else if(new_locale != nullptr)
{
// Configure the thread to set the locale only for this thread
_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 @@
ConsoleListener::ConsoleListener()
{
#ifdef _WIN32
- hConsole = NULL;
+ hConsole = nullptr;
bUseColor = true;
#else
bUseColor = isatty(fileno(stdout));
@@ -66,19 +66,19 @@ void ConsoleListener::UpdateHandle()
void ConsoleListener::Close()
{
#ifdef _WIN32
- if (hConsole == NULL)
+ if (hConsole == nullptr)
return;
FreeConsole();
- hConsole = NULL;
+ hConsole = nullptr;
#else
- fflush(NULL);
+ fflush(nullptr);
#endif
}
bool ConsoleListener::IsOpen()
{
#ifdef _WIN32
- return (hConsole != NULL);
+ return (hConsole != nullptr);
#else
return true;
#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 )
}
// Add user defined path
- if ( lpszIniPath != NULL )
+ if ( lpszIniPath != nullptr )
if ( lpszIniPath[0] != '\0' )
{
strcat( lpszSymbolPath, ";" );
@@ -138,7 +138,7 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
DWORD dwSymSize = 10000;
TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?");
CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?";
- LPTSTR lpszParamSep = NULL;
+ LPTSTR lpszParamSep = nullptr;
LPTSTR lpszParsed = lpszUnDSymbol;
PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize );
@@ -187,13 +187,13 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
// Let's go through the stack, and modify the function prototype, and insert the actual
// parameter values from the stack
- if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == NULL && _tcsstr( lpszUnDSymbol, _T("()") ) == NULL)
+ if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == nullptr && _tcsstr( lpszUnDSymbol, _T("()") ) == nullptr)
{
ULONG index = 0;
for( ; ; index++ )
{
lpszParamSep = _tcschr( lpszParsed, _T(',') );
- if ( lpszParamSep == NULL )
+ if ( lpszParamSep == nullptr )
break;
*lpszParamSep = _T('\0');
@@ -205,7 +205,7 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
}
lpszParamSep = _tcschr( lpszParsed, _T(')') );
- if ( lpszParamSep != NULL )
+ if ( lpszParamSep != nullptr )
{
*lpszParamSep = _T('\0');
@@ -248,7 +248,7 @@ static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
PCSTR2LPTSTR( lineInfo.FileName, lpszFileName );
TCHAR fname[_MAX_FNAME];
TCHAR ext[_MAX_EXT];
- _tsplitpath(lpszFileName, NULL, NULL, fname, ext);
+ _tsplitpath(lpszFileName, nullptr, nullptr, fname, ext);
_stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber );
ret = TRUE;
}
@@ -332,11 +332,11 @@ void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
hProcess,
hThread,
&callStack,
- NULL,
- NULL,
+ nullptr,
+ nullptr,
SymFunctionTableAccess,
SymGetModuleBase,
- NULL);
+ nullptr);
if ( index == 0 )
continue;
@@ -389,11 +389,11 @@ void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip,
hProcess,
hThread,
&callStack,
- NULL,
- NULL,
+ nullptr,
+ nullptr,
SymFunctionTableAccess,
SymGetModuleBase,
- NULL);
+ nullptr);
if ( index == 0 )
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:
// advance the read pointer
m_read_ptr = m_read_ptr->next;
// set the next element to NULL to stop the recursive deletion
- tmpptr->next = NULL;
+ tmpptr->next = nullptr;
delete tmpptr; // this also deletes the element
}
@@ -86,7 +86,7 @@ private:
class ElementPtr
{
public:
- ElementPtr() : current(NULL), next(NULL) {}
+ ElementPtr() : current(nullptr), next(nullptr) {}
~ElementPtr()
{
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)
{
INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
#ifdef _WIN32
- if (::CreateDirectory(Common::UTF8ToTStr(path).c_str(), NULL))
+ if (::CreateDirectory(Common::UTF8ToTStr(path).c_str(), nullptr))
return true;
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
@@ -423,7 +423,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
FSTEntry entry;
const std::string virtualName(Common::TStrToUTF8(ffd.cFileName));
#else
- struct dirent dirent, *result = NULL;
+ struct dirent dirent, *result = nullptr;
DIR *dirp = opendir(directory.c_str());
if (!dirp)
@@ -491,7 +491,7 @@ bool DeleteDirRecursively(const std::string &directory)
{
const std::string virtualName(Common::TStrToUTF8(ffd.cFileName));
#else
- struct dirent dirent, *result = NULL;
+ struct dirent dirent, *result = nullptr;
DIR *dirp = opendir(directory.c_str());
if (!dirp)
return false;
@@ -552,7 +552,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path)
if (!FileUtil::Exists(source_path)) return;
if (!FileUtil::Exists(dest_path)) FileUtil::CreateFullPath(dest_path);
- struct dirent dirent, *result = NULL;
+ struct dirent dirent, *result = nullptr;
DIR *dirp = opendir(source_path.c_str());
if (!dirp) return;
@@ -586,11 +586,11 @@ std::string GetCurrentDir()
{
char *dir;
// Get the current working directory (getcwd uses malloc)
- if (!(dir = __getcwd(NULL, 0))) {
+ if (!(dir = __getcwd(nullptr, 0))) {
ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
GetLastErrorMsg());
- return NULL;
+ return nullptr;
}
std::string strDir = dir;
free(dir);
@@ -626,7 +626,7 @@ std::string& GetExeDirectory()
if (DolphinPath.empty())
{
TCHAR Dolphin_exe_Path[2048];
- GetModuleFileName(NULL, Dolphin_exe_Path, 2048);
+ GetModuleFileName(nullptr, Dolphin_exe_Path, 2048);
DolphinPath = Common::TStrToUTF8(Dolphin_exe_Path);
DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
}
@@ -826,7 +826,7 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
}
IOFile::IOFile()
- : m_file(NULL), m_good(true)
+ : m_file(nullptr), m_good(true)
{}
IOFile::IOFile(std::FILE* file)
@@ -834,7 +834,7 @@ IOFile::IOFile(std::FILE* file)
{}
IOFile::IOFile(const std::string& filename, const char openmode[])
- : m_file(NULL), m_good(true)
+ : m_file(nullptr), m_good(true)
{
Open(filename, openmode);
}
@@ -845,7 +845,7 @@ IOFile::~IOFile()
}
IOFile::IOFile(IOFile&& other)
- : m_file(NULL), m_good(true)
+ : m_file(nullptr), m_good(true)
{
Swap(other);
}
@@ -880,14 +880,14 @@ bool IOFile::Close()
if (!IsOpen() || 0 != std::fclose(m_file))
m_good = false;
- m_file = NULL;
+ m_file = nullptr;
return m_good;
}
std::FILE* IOFile::ReleaseHandle()
{
std::FILE* const ret = m_file;
- m_file = NULL;
+ m_file = nullptr;
return ret;
}
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:
return WriteArray(reinterpret_cast<const char*>(data), length);
}
- bool IsOpen() { return NULL != m_file; }
+ bool IsOpen() { return nullptr != m_file; }
// m_good is set to false when a read, write or other function fails
bool IsGood() { return m_good; }
- operator void*() { return m_good ? m_file : NULL; }
+ operator void*() { return m_good ? m_file : nullptr; }
std::FILE* ReleaseHandle();
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:
// good header, read some key/value pairs
K key;
- V *value = NULL;
+ V *value = nullptr;
u32 value_size;
u32 entry_number;
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 @@
#include "common/log_manager.h"
#include "common/console_listener.h"
#include "common/timer.h"
-#include "common/thread.h"
void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
const char* function, const char* fmt, ...)
@@ -22,7 +21,7 @@ void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char*
va_end(args);
}
-LogManager *LogManager::m_logManager = NULL;
+LogManager *LogManager::m_logManager = nullptr;
LogManager::LogManager()
{
@@ -142,7 +141,7 @@ void LogManager::Init()
void LogManager::Shutdown()
{
delete m_logManager;
- m_logManager = NULL;
+ m_logManager = nullptr;
}
LogContainer::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 @@
#endif
#ifdef IOS
-void* globalbase = NULL;
+void* globalbase = nullptr;
#endif
#ifdef ANDROID
@@ -121,7 +121,7 @@ void MemArena::GrabLowMemSpace(size_t size)
{
#ifdef _WIN32
#ifndef _XBOX
- hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL);
+ hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, (DWORD)(size), nullptr);
GetSystemInfo(&sysInfo);
#endif
#elif defined(ANDROID)
@@ -178,7 +178,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base)
#ifdef _XBOX
size = roundup(size);
// use 64kb pages
- void * ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
+ void * ptr = VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
return ptr;
#else
size = roundup(size);
@@ -243,8 +243,8 @@ u8* MemArena::Find4GBBase()
return base;
#else
#ifdef IOS
- void* base = NULL;
- if (globalbase == NULL){
+ void* base = nullptr;
+ if (globalbase == nullptr){
base = mmap(0, 0x08000000, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_SHARED, -1, 0);
if (base == MAP_FAILED) {
@@ -357,7 +357,7 @@ bail:
if (views[j].out_ptr_low && *views[j].out_ptr_low)
{
arena->ReleaseView(*views[j].out_ptr_low, views[j].size);
- *views[j].out_ptr_low = NULL;
+ *views[j].out_ptr_low = nullptr;
}
if (*views[j].out_ptr)
{
@@ -369,7 +369,7 @@ bail:
arena->ReleaseView(*views[j].out_ptr, views[j].size);
}
#endif
- *views[j].out_ptr = NULL;
+ *views[j].out_ptr = nullptr;
}
}
return false;
@@ -415,7 +415,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
#elif defined(_WIN32)
// Try a whole range of possible bases. Return once we got a valid one.
u32 max_base_addr = 0x7FFF0000 - 0x10000000;
- u8 *base = NULL;
+ u8 *base = nullptr;
for (u32 base_addr = 0x01000000; base_addr < max_base_addr; base_addr += 0x400000)
{
@@ -463,8 +463,8 @@ void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemAr
arena->ReleaseView(*views[i].out_ptr_low, views[i].size);
if (*views[i].out_ptr && (views[i].out_ptr_low && *views[i].out_ptr != *views[i].out_ptr_low))
arena->ReleaseView(*views[i].out_ptr, views[i].size);
- *views[i].out_ptr = NULL;
+ *views[i].out_ptr = nullptr;
if (views[i].out_ptr_low)
- *views[i].out_ptr_low = NULL;
+ *views[i].out_ptr_low = nullptr;
}
}
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)
// printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
- if (ptr == NULL)
+ if (ptr == nullptr)
PanicAlert("Failed to allocate raw memory");
return ptr;
@@ -104,7 +104,7 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
#ifdef _WIN32
void* ptr = _aligned_malloc(size,alignment);
#else
- void* ptr = NULL;
+ void* ptr = nullptr;
#ifdef ANDROID
ptr = memalign(alignment, size);
#else
@@ -116,7 +116,7 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
// printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
- if (ptr == NULL)
+ if (ptr == nullptr)
PanicAlert("Failed to allocate aligned memory");
return ptr;
@@ -130,7 +130,7 @@ void FreeMemoryPages(void* ptr, size_t size)
if (!VirtualFree(ptr, 0, MEM_RELEASE))
PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
- ptr = NULL; // Is this our responsibility?
+ ptr = nullptr; // Is this our responsibility?
#else
munmap(ptr, size);
@@ -184,7 +184,7 @@ std::string MemUsage()
// Print information about the memory usage of the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
- if (NULL == hProcess) return "MemUsage Error";
+ if (nullptr == hProcess) return "MemUsage Error";
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
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()
#ifdef _WIN32
static __declspec(thread) char err_str[buff_size] = {};
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- err_str, buff_size, NULL);
+ err_str, buff_size, nullptr);
#else
static __thread char err_str[buff_size] = {};
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 @@
inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
if (localtime_s(result, clock) == 0)
return result;
- return NULL;
+ return nullptr;
}
#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) {
// faster than sscanf
bool AsciiToHex(const char* _szValue, u32& result)
{
- char *endptr = NULL;
+ char *endptr = nullptr;
const u32 value = strtoul(_szValue, &endptr, 16);
if (!endptr || *endptr)
@@ -69,7 +69,7 @@ bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list ar
// will be present in the middle of a multibyte sequence.
//
// This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l.
- static locale_t c_locale = NULL;
+ static locale_t c_locale = nullptr;
if (!c_locale)
c_locale = _create_locale(LC_ALL, ".1252");
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
std::string StringFromFormat(const char* format, ...)
{
va_list args;
- char *buf = NULL;
+ char *buf = nullptr;
#ifdef _WIN32
int required = 0;
@@ -162,7 +162,7 @@ std::string StripQuotes(const std::string& s)
bool TryParse(const std::string &str, u32 *const output)
{
- char *endptr = NULL;
+ char *endptr = nullptr;
// Reset errno to a value other than ERANGE
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 {
~ThreadQueueList() {
for (int i = 0; i < NUM_QUEUES; ++i)
{
- if (queues[i].data != NULL)
+ if (queues[i].data != nullptr)
free(queues[i].data);
}
}
@@ -46,7 +46,7 @@ struct ThreadQueueList {
int contains(const IdType uid) {
for (int i = 0; i < NUM_QUEUES; ++i)
{
- if (queues[i].data == NULL)
+ if (queues[i].data == nullptr)
continue;
Queue *cur = &queues[i];
@@ -133,7 +133,7 @@ struct ThreadQueueList {
inline void clear() {
for (int i = 0; i < NUM_QUEUES; ++i)
{
- if (queues[i].data != NULL)
+ if (queues[i].data != nullptr)
free(queues[i].data);
}
memset(queues, 0, sizeof(queues));
@@ -147,7 +147,7 @@ struct ThreadQueueList {
inline void prepare(u32 priority) {
Queue *cur = &queues[priority];
- if (cur->next == NULL)
+ if (cur->next == nullptr)
link(priority, INITIAL_CAPACITY);
}
@@ -176,7 +176,7 @@ private:
for (int i = (int) priority - 1; i >= 0; --i)
{
- if (queues[i].next != NULL)
+ if (queues[i].next != nullptr)
{
cur->next = queues[i].next;
queues[i].next = cur;
@@ -193,7 +193,7 @@ private:
int size = cur->end - cur->first;
if (size >= cur->capacity - 2) {
IdType *new_data = (IdType *)realloc(cur->data, cur->capacity * 2 * sizeof(IdType));
- if (new_data != NULL) {
+ if (new_data != nullptr) {
cur->capacity *= 2;
cur->data = new_data;
}
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()
return timeGetTime();
#else
struct timeval t;
- (void)gettimeofday(&t, NULL);
+ (void)gettimeofday(&t, nullptr);
return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000));
#endif
}
@@ -183,7 +183,7 @@ std::string Timer::GetTimeFormatted()
return StringFromFormat("%s:%03i", tmp, tp.millitm);
#else
struct timeval t;
- (void)gettimeofday(&t, NULL);
+ (void)gettimeofday(&t, nullptr);
return StringFromFormat("%s:%03d", tmp, (int)(t.tv_usec / 1000));
#endif
}
@@ -197,7 +197,7 @@ double Timer::GetDoubleTime()
(void)::ftime(&tp);
#else
struct timeval t;
- (void)gettimeofday(&t, NULL);
+ (void)gettimeofday(&t, nullptr);
#endif
// Get continuous timestamp
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)
do {
digs[dno++] = str[i++];
} while (octal_digit(str[i]) && dno < 3);
- ch = strtol(digs, NULL, 8);
+ ch = strtol(digs, nullptr, 8);
}
else if (str[0] == 'x') {
while (hex_digit(str[i]) && dno < 2) {
digs[dno++] = str[i++];
}
if (dno > 0)
- ch = strtol(digs, NULL, 16);
+ ch = strtol(digs, nullptr, 16);
}
else if (str[0] == 'u') {
while (hex_digit(str[i]) && dno < 4) {
digs[dno++] = str[i++];
}
if (dno > 0)
- ch = strtol(digs, NULL, 16);
+ ch = strtol(digs, nullptr, 16);
}
else if (str[0] == 'U') {
while (hex_digit(str[i]) && dno < 8) {
digs[dno++] = str[i++];
}
if (dno > 0)
- ch = strtol(digs, NULL, 16);
+ ch = strtol(digs, nullptr, 16);
}
*dest = ch;
@@ -353,7 +353,7 @@ const char *u8_strchr(const char *s, u32 ch, int *charn)
lasti = i;
(*charn)++;
}
- return NULL;
+ return nullptr;
}
const 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)
lasti = i;
(*charn)++;
}
- return NULL;
+ return nullptr;
}
int u8_is_locale_utf8(const char *locale)
@@ -419,35 +419,35 @@ bool UTF8StringHasNonASCII(const char *utf8string) {
std::string ConvertWStringToUTF8(const wchar_t *wstr) {
int len = (int)wcslen(wstr);
- int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, NULL, NULL);
+ int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, nullptr, nullptr);
std::string s;
s.resize(size);
if (size > 0) {
- WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, nullptr, nullptr);
}
return s;
}
std::string ConvertWStringToUTF8(const std::wstring &wstr) {
int len = (int)wstr.size();
- int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL);
+ int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, nullptr, nullptr);
std::string s;
s.resize(size);
if (size > 0) {
- WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, nullptr, nullptr);
}
return s;
}
void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) {
int len = (int)source.size();
- int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
+ int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0);
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size));
}
std::wstring ConvertUTF8ToWString(const std::string &source) {
int len = (int)source.size();
- int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
+ int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0);
std::wstring str;
str.resize(size);
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
loader/elf.cpp
loader/loader.cpp
loader/ncch.cpp
+ loader/3dsx.cpp
core.cpp
core_timing.cpp
mem_map.cpp
@@ -143,6 +144,7 @@ set(HEADERS
loader/elf.h
loader/loader.h
loader/ncch.h
+ loader/3dsx.h
core.h
core_timing.h
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 @@
#define CITRA_IGNORE_EXIT(x)
#include <algorithm>
-#include <map>
+#include <unordered_map>
#include <stdio.h>
#include <assert.h>
#include <cstdio>
@@ -94,9 +94,8 @@ typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper);
/* exclusive memory access */
static int exclusive_detect(ARMul_State* state, ARMword addr){
- int i;
#if 0
- for(i = 0; i < 128; i++){
+ for(int i = 0; i < 128; i++){
if(state->exclusive_tag_array[i] == addr)
return 0;
}
@@ -108,9 +107,8 @@ static int exclusive_detect(ARMul_State* state, ARMword addr){
}
static void add_exclusive_addr(ARMul_State* state, ARMword addr){
- int i;
#if 0
- for(i = 0; i < 128; i++){
+ for(int i = 0; i < 128; i++){
if(state->exclusive_tag_array[i] == 0xffffffff){
state->exclusive_tag_array[i] = addr;
//DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr);
@@ -3309,9 +3307,8 @@ const transop_fp_t arm_instruction_trans[] = {
INTERPRETER_TRANSLATE(blx_1_thumb)
};
-typedef map<unsigned int, int> bb_map;
-bb_map CreamCache[65536];
-bb_map ProfileCache[65536];
+typedef std::unordered_map<u32, int> bb_map;
+bb_map CreamCache;
//#define USE_DUMMY_CACHE
@@ -3319,14 +3316,12 @@ bb_map ProfileCache[65536];
unsigned int DummyCache[0x100000];
#endif
-#define HASH(x) ((x + (x << 3) + (x >> 6)) % 65536)
void insert_bb(unsigned int addr, int start)
{
#ifdef USE_DUMMY_CACHE
DummyCache[addr] = start;
#else
-// CreamCache[addr] = start;
- CreamCache[HASH(addr)][addr] = start;
+ CreamCache[addr] = start;
#endif
}
@@ -3341,8 +3336,8 @@ int find_bb(unsigned int addr, int &start)
} else
ret = -1;
#else
- bb_map::const_iterator it = CreamCache[HASH(addr)].find(addr);
- if (it != CreamCache[HASH(addr)].end()) {
+ bb_map::const_iterator it = CreamCache.find(addr);
+ if (it != CreamCache.end()) {
start = static_cast<int>(it->second);
ret = 0;
#if HYBRID_MODE
@@ -3473,30 +3468,15 @@ void flush_bb(uint32_t addr)
uint32_t start;
addr &= 0xfffff000;
- for (int i = 0; i < 65536; i ++) {
- for (it = CreamCache[i].begin(); it != CreamCache[i].end(); ) {
- start = static_cast<uint32_t>(it->first);
- //start = (start >> 12) << 12;
- start &= 0xfffff000;
- if (start == addr) {
- //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
- CreamCache[i].erase(it ++);
- } else
- ++it;
- }
- }
-
- for (int i = 0; i < 65536; i ++) {
- for (it = ProfileCache[i].begin(); it != ProfileCache[i].end(); ) {
- start = static_cast<uint32_t>(it->first);
- //start = (start >> 12) << 12;
- start &= 0xfffff000;
- if (start == addr) {
- //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
- ProfileCache[i].erase(it ++);
- } else
- ++it;
- }
+ for (it = CreamCache.begin(); it != CreamCache.end(); ) {
+ start = static_cast<uint32_t>(it->first);
+ //start = (start >> 12) << 12;
+ start &= 0xfffff000;
+ if (start == addr) {
+ //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first));
+ CreamCache.erase(it++);
+ } else
+ ++it;
}
//DEBUG_LOG(ARM11, "flush bb @ %x\n", addr);
diff --git a/src/core/arm/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:
s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
s16 b1 = (state->Reg[src2] & 0xFFFF);
s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = (a1 - a2)&0xFFFF | (((b1 - b2)&0xFFFF)<< 0x10);
+ state->Reg[tar] = ((a1 - a2) & 0xFFFF) | (((b1 - b2)&0xFFFF)<< 0x10);
return 1;
}
else if ((instr & 0xFF0) == 0xf10)//sadd16
@@ -5736,7 +5736,7 @@ L_stm_s_takeabort:
s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
s16 b1 = (state->Reg[src2] & 0xFFFF);
s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = (a1 + a2)&0xFFFF | (((b1 + b2)&0xFFFF)<< 0x10);
+ state->Reg[tar] = ((a1 + a2) & 0xFFFF) | (((b1 + b2)&0xFFFF)<< 0x10);
return 1;
}
else if ((instr & 0xFF0) == 0xf50)//ssax
@@ -5748,7 +5748,7 @@ L_stm_s_takeabort:
s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
s16 b1 = (state->Reg[src2] & 0xFFFF);
s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = (a1 - b2) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10);
+ state->Reg[tar] = ((a1 + b2) & 0xFFFF) | (((a2 - b1) & 0xFFFF) << 0x10);
return 1;
}
else if ((instr & 0xFF0) == 0xf30)//sasx
@@ -5760,7 +5760,7 @@ L_stm_s_takeabort:
s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
s16 b1 = (state->Reg[src2] & 0xFFFF);
s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = (a2 - b1) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10);
+ state->Reg[tar] = ((a1 - b2) & 0xFFFF) | (((a2 + b1) & 0xFFFF) << 0x10);
return 1;
}
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 @@
#include <stddef.h>
#include <stdio.h>
-#include "common/thread.h"
-
#include "core/arm/skyeye_common/armdefs.h"
typedef struct ARM_CPU_State_s {
diff --git a/src/core/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;
static std::recursive_mutex externalEventSection;
// Warning: not included in save state.
-void(*advanceCallback)(int cyclesExecuted) = NULL;
+void(*advanceCallback)(int cyclesExecuted) = nullptr;
void SetClockFrequencyMHz(int cpuMhz)
{
@@ -231,7 +231,7 @@ void ClearPendingEvents()
void AddEventToQueue(Event* ne)
{
- Event* prev = NULL;
+ Event* prev = nullptr;
Event** pNext = &first;
for (;;)
{
@@ -327,7 +327,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata)
}
if (!tsFirst)
{
- tsLast = NULL;
+ tsLast = nullptr;
return result;
}
@@ -433,7 +433,7 @@ void RemoveThreadsafeEvent(int event_type)
}
if (!tsFirst)
{
- tsLast = NULL;
+ tsLast = nullptr;
return;
}
Event *prev = tsFirst;
@@ -495,7 +495,7 @@ void MoveEvents()
AddEventToQueue(tsFirst);
tsFirst = next;
}
- tsLast = NULL;
+ tsLast = nullptr;
// Move free events to threadsafe pool
while (allocatedTsEvents > 0 && eventPool)
@@ -614,7 +614,7 @@ void DoState(PointerWrap &p)
// These (should) be filled in later by the modules.
event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT"));
- p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **)NULL);
+ p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **)nullptr);
p.DoLinkedList<BaseEvent, GetNewTsEvent, FreeTsEvent, Event_DoState>(tsFirst, &tsLast);
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:
u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated.
break;
}
+ default:
+ break;
}
}
@@ -192,6 +194,14 @@ public:
virtual bool DeleteFile(const FileSys::Path& path) const = 0;
/**
+ * Rename a File specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ virtual bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0;
+
+ /**
* Delete a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be deleted
@@ -206,6 +216,14 @@ public:
virtual bool CreateDirectory(const Path& path) const = 0;
/**
+ * Rename a Directory specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ virtual bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0;
+
+ /**
* Open a directory specified by its path
* @param path Path relative to the archive
* @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 {
return false;
}
+bool Archive_RomFS::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
+ ERROR_LOG(FILESYS, "Attempted to rename a file within ROMFS.");
+ return false;
+}
+
/**
* Delete a directory specified by its path
* @param path Path relative to the archive
@@ -63,6 +68,11 @@ bool Archive_RomFS::CreateDirectory(const Path& path) const {
return false;
}
+bool Archive_RomFS::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
+ ERROR_LOG(FILESYS, "Attempted to rename a file within ROMFS.");
+ return false;
+}
+
/**
* Open a directory specified by its path
* @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:
bool DeleteFile(const FileSys::Path& path) const override;
/**
+ * Rename a File specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
+
+ /**
* Delete a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be deleted
@@ -58,6 +66,14 @@ public:
bool CreateDirectory(const Path& path) const override;
/**
+ * Rename a Directory specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
+
+ /**
* Open a directory specified by its path
* @param path Path relative to the archive
* @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() {
* @return Opened file, or nullptr
*/
std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const {
- DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.DebugStr().c_str(), mode);
+ DEBUG_LOG(FILESYS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex);
File_SDMC* file = new File_SDMC(this, path, mode);
if (!file->Open())
return nullptr;
@@ -66,6 +66,10 @@ bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const {
return FileUtil::Delete(GetMountPoint() + path.AsString());
}
+bool Archive_SDMC::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
+ return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
+}
+
/**
* Delete a directory specified by its path
* @param path Path relative to the archive
@@ -84,6 +88,10 @@ bool Archive_SDMC::CreateDirectory(const Path& path) const {
return FileUtil::CreateDir(GetMountPoint() + path.AsString());
}
+bool Archive_SDMC::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
+ return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
+}
+
/**
* Open a directory specified by its path
* @param path Path relative to the archive
@@ -92,6 +100,8 @@ bool Archive_SDMC::CreateDirectory(const Path& path) const {
std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const {
DEBUG_LOG(FILESYS, "called path=%s", path.DebugStr().c_str());
Directory_SDMC* directory = new Directory_SDMC(this, path);
+ if (!directory->Open())
+ return nullptr;
return std::unique_ptr<Directory>(directory);
}
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 74ce29c0d..19f563a62 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -48,6 +48,14 @@ public:
bool DeleteFile(const FileSys::Path& path) const override;
/**
+ * Rename a File specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
+
+ /**
* Delete a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be deleted
@@ -62,6 +70,14 @@ public:
bool CreateDirectory(const Path& path) const override;
/**
+ * Rename a Directory specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
+
+ /**
* Open a directory specified by its path
* @param path Path relative to the archive
* @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:
virtual ~Directory() { }
/**
+ * Open the directory
+ * @return true if the directory opened correctly
+ */
+ virtual bool Open() = 0;
+
+ /**
* List files contained in the directory
* @param count Number of entries to return at once in entries
* @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() {
Directory_RomFS::~Directory_RomFS() {
}
+bool Directory_RomFS::Open() {
+ return false;
+}
+
/**
* List files contained in the directory
* @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:
~Directory_RomFS() override;
/**
+ * Open the directory
+ * @return true if the directory opened correctly
+ */
+ bool Open() override;
+
+ /**
* List files contained in the directory
* @param count Number of entries to return at once in entries
* @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) {
// TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
// the root directory we set while opening the archive.
// For example, opening /../../usr/bin can give the emulated program your installed programs.
- std::string absolute_path = archive->GetMountPoint() + path.AsString();
- FileUtil::ScanDirectoryTree(absolute_path, directory);
- children_iterator = directory.children.begin();
+ this->path = archive->GetMountPoint() + path.AsString();
+
}
Directory_SDMC::~Directory_SDMC() {
Close();
}
+bool Directory_SDMC::Open() {
+ if (!FileUtil::IsDirectory(path))
+ return false;
+ FileUtil::ScanDirectoryTree(path, directory);
+ children_iterator = directory.children.begin();
+ return true;
+}
+
/**
* List files contained in the directory
* @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:
~Directory_SDMC() override;
/**
+ * Open the directory
+ * @return true if the directory opened correctly
+ */
+ bool Open() override;
+
+ /**
* List files contained in the directory
* @param count Number of entries to return at once in entries
* @param entries Buffer to read data into
@@ -37,6 +43,7 @@ public:
bool Close() const override;
private:
+ std::string path;
u32 total_entries_in_directory;
FileUtil::FSTEntry directory;
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() {
}
std::string mode_string;
- if (mode.read_flag && mode.write_flag)
+ if (mode.create_flag)
mode_string = "w+";
+ else if (mode.write_flag)
+ mode_string = "r+"; // Files opened with Write access can be read from
else if (mode.read_flag)
mode_string = "r";
- else if (mode.write_flag)
- mode_string = "w";
+
+ // Open the file in binary mode, to avoid problems with CR/LF on Windows systems
+ mode_string += "b";
file = new FileUtil::IOFile(path, mode_string.c_str());
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
// Wait current thread (acquire the arbiter)...
case ArbitrationType::WaitIfLessThan:
if ((s32)Memory::Read32(address) <= value) {
- Kernel::WaitCurrentThread(WAITTYPE_ARB, handle);
+ Kernel::WaitCurrentThread(WAITTYPE_ARB, handle, address);
HLE::Reschedule(__func__);
}
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
return MakeResult<Handle>(handle);
}
-/**
- * Delete a File from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the File inside of the Archive
- * @return Whether deletion succeeded
- */
-Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) {
+ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) {
Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
if (archive == nullptr)
- return -1;
+ return InvalidHandle(ErrorModule::FS);
if (archive->backend->DeleteFile(path))
- return 0;
- return -1;
+ return RESULT_SUCCESS;
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::Canceled, ErrorLevel::Status);
}
-/**
- * Delete a Directory from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the Directory inside of the Archive
- * @return Whether deletion succeeded
- */
-Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
+ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
+ Handle dest_archive_handle, const FileSys::Path& dest_path) {
+ Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle);
+ Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle);
+ if (src_archive == nullptr || dest_archive == nullptr)
+ return InvalidHandle(ErrorModule::FS);
+ if (src_archive == dest_archive) {
+ if (src_archive->backend->RenameFile(src_path, dest_path))
+ return RESULT_SUCCESS;
+ } else {
+ // TODO: Implement renaming across archives
+ return UnimplementedFunction(ErrorModule::FS);
+ }
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::NothingHappened, ErrorLevel::Status);
+}
+
+ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
if (archive == nullptr)
- return -1;
+ return InvalidHandle(ErrorModule::FS);
if (archive->backend->DeleteDirectory(path))
- return 0;
- return -1;
+ return RESULT_SUCCESS;
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::Canceled, ErrorLevel::Status);
}
-/**
- * Create a Directory from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the Directory inside of the Archive
- * @return Whether creation succeeded
- */
-Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
+ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
if (archive == nullptr)
- return -1;
+ return InvalidHandle(ErrorModule::FS);
if (archive->backend->CreateDirectory(path))
- return 0;
- return -1;
+ return RESULT_SUCCESS;
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::Canceled, ErrorLevel::Status);
+}
+
+ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
+ Handle dest_archive_handle, const FileSys::Path& dest_path) {
+ Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle);
+ Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle);
+ if (src_archive == nullptr || dest_archive == nullptr)
+ return InvalidHandle(ErrorModule::FS);
+ if (src_archive == dest_archive) {
+ if (src_archive->backend->RenameDirectory(src_path, dest_path))
+ return RESULT_SUCCESS;
+ } else {
+ // TODO: Implement renaming across archives
+ return UnimplementedFunction(ErrorModule::FS);
+ }
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::NothingHappened, ErrorLevel::Status);
}
/**
@@ -402,6 +421,11 @@ ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys:
directory->path = path;
directory->backend = archive->backend->OpenDirectory(path);
+ if (!directory->backend) {
+ return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
+ ErrorSummary::NotFound, ErrorLevel::Permanent);
+ }
+
return MakeResult<Handle>(handle);
}
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
* @param path Path to the File inside of the Archive
* @return Whether deletion succeeded
*/
-Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
+ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
+
+/**
+ * Rename a File between two Archives
+ * @param src_archive_handle Handle to the source Archive object
+ * @param src_path Path to the File inside of the source Archive
+ * @param dest_archive_handle Handle to the destination Archive object
+ * @param dest_path Path to the File inside of the destination Archive
+ * @return Whether rename succeeded
+ */
+ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
+ Handle dest_archive_handle, const FileSys::Path& dest_path);
/**
* Delete a Directory from an Archive
@@ -58,7 +69,7 @@ Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
* @param path Path to the Directory inside of the Archive
* @return Whether deletion succeeded
*/
-Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
+ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
/**
* Create a Directory from an Archive
@@ -66,7 +77,18 @@ Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa
* @param path Path to the Directory inside of the Archive
* @return Whether creation of directory succeeded
*/
-Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
+ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
+
+/**
+ * Rename a Directory between two Archives
+ * @param src_archive_handle Handle to the source Archive object
+ * @param src_path Path to the Directory inside of the source Archive
+ * @param dest_archive_handle Handle to the destination Archive object
+ * @param dest_path Path to the Directory inside of the destination Archive
+ * @return Whether rename succeeded
+ */
+ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
+ Handle dest_archive_handle, const FileSys::Path& dest_path);
/**
* 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 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
+#include <algorithm>
+
#include "common/common.h"
#include "core/core.h"
@@ -37,7 +39,7 @@ Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) {
return 0;
}
-bool ObjectPool::IsValid(Handle handle) {
+bool ObjectPool::IsValid(Handle handle) const {
int index = handle - HANDLE_OFFSET;
if (index < 0)
return false;
@@ -75,13 +77,8 @@ void ObjectPool::List() {
}
}
-int ObjectPool::GetCount() {
- int count = 0;
- for (int i = 0; i < MAX_COUNT; i++) {
- if (occupied[i])
- count++;
- }
- return count;
+int ObjectPool::GetCount() const {
+ return std::count(occupied.begin(), occupied.end(), true);
}
Object* 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:
}
}
- bool IsValid(Handle handle);
+ bool IsValid(Handle handle) const;
template <class T>
T* Get(Handle handle) {
@@ -142,7 +142,7 @@ public:
Object* &operator [](Handle handle);
void List();
void Clear();
- int GetCount();
+ int GetCount() const;
private:
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) {
bool ReleaseMutex(Mutex* mutex) {
MutexEraseLock(mutex);
- bool woke_threads = false;
// Find the next waiting thread for the mutex...
- while (!woke_threads && !mutex->waiting_threads.empty()) {
+ while (!mutex->waiting_threads.empty()) {
std::vector<Handle>::iterator iter = mutex->waiting_threads.begin();
- woke_threads |= ReleaseMutexForThread(mutex, *iter);
+ ReleaseMutexForThread(mutex, *iter);
mutex->waiting_threads.erase(iter);
}
+
// Reset mutex lock thread handle, nothing is waiting
- if (!woke_threads) {
- mutex->locked = false;
- mutex->lock_thread = -1;
- }
- return woke_threads;
+ mutex->locked = false;
+ mutex->lock_thread = -1;
+
+ return true;
}
/**
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:
ThreadContext context;
+ u32 thread_id;
+
u32 status;
u32 entry_point;
u32 stack_top;
@@ -61,6 +63,7 @@ public:
WaitType wait_type;
Handle wait_handle;
+ VAddr wait_address;
std::vector<Handle> waiting_threads;
@@ -76,6 +79,9 @@ static Common::ThreadQueueList<Handle> thread_ready_queue;
static Handle current_thread_handle;
static Thread* current_thread;
+static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
+static u32 next_thread_id; ///< The next available thread id
+
/// Gets the current thread
inline Thread* GetCurrentThread() {
return current_thread;
@@ -121,6 +127,7 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) {
}
t->wait_type = WAITTYPE_NONE;
t->wait_handle = 0;
+ t->wait_address = 0;
}
/// Change a thread to "ready" state
@@ -141,9 +148,15 @@ void ChangeReadyState(Thread* t, bool ready) {
}
/// Verify that a thread has not been released from waiting
-inline bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) {
+static bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) {
_dbg_assert_(KERNEL, thread != nullptr);
- return type == thread->wait_type && wait_handle == thread->wait_handle;
+ return (type == thread->wait_type) && (wait_handle == thread->wait_handle) && (thread->IsWaiting());
+}
+
+/// Verify that a thread has not been released from waiting (with wait address)
+static bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle, VAddr wait_address) {
+ _dbg_assert_(KERNEL, thread != nullptr);
+ return VerifyWait(thread, type, wait_handle) && (wait_address == thread->wait_address);
}
/// Stops the current thread
@@ -164,6 +177,7 @@ ResultCode StopThread(Handle handle, const char* reason) {
// Stopped threads are never waiting.
thread->wait_type = WAITTYPE_NONE;
thread->wait_handle = 0;
+ thread->wait_address = 0;
return RESULT_SUCCESS;
}
@@ -192,12 +206,12 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
for (Handle handle : thread_queue) {
Thread* thread = g_object_pool.Get<Thread>(handle);
- // TODO(bunnei): Verify arbiter address...
- if (!VerifyWait(thread, WAITTYPE_ARB, arbiter))
+ if (!VerifyWait(thread, WAITTYPE_ARB, arbiter, address))
continue;
if (thread == nullptr)
continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
+
if(thread->current_priority <= priority) {
highest_priority_thread = handle;
priority = thread->current_priority;
@@ -217,8 +231,7 @@ void ArbitrateAllThreads(u32 arbiter, u32 address) {
for (Handle handle : thread_queue) {
Thread* thread = g_object_pool.Get<Thread>(handle);
- // TODO(bunnei): Verify arbiter address...
- if (VerifyWait(thread, WAITTYPE_ARB, arbiter))
+ if (VerifyWait(thread, WAITTYPE_ARB, arbiter, address))
ResumeThreadFromWait(handle);
}
}
@@ -272,11 +285,6 @@ Thread* NextThread() {
return Kernel::g_object_pool.Get<Thread>(next);
}
-/**
- * Puts the current thread in the wait state for the given type
- * @param wait_type Type of wait
- * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread
- */
void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
Thread* thread = GetCurrentThread();
thread->wait_type = wait_type;
@@ -284,6 +292,11 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
}
+void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_address) {
+ WaitCurrentThread(wait_type, wait_handle);
+ GetCurrentThread()->wait_address = wait_address;
+}
+
/// Resumes a thread from waiting by marking it as "ready"
void ResumeThreadFromWait(Handle handle) {
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
thread_queue.push_back(handle);
thread_ready_queue.prepare(priority);
+ thread->thread_id = next_thread_id++;
thread->status = THREADSTATUS_DORMANT;
thread->entry_point = entry_point;
thread->stack_top = stack_top;
@@ -333,6 +347,7 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
thread->processor_id = processor_id;
thread->wait_type = WAITTYPE_NONE;
thread->wait_handle = 0;
+ thread->wait_address = 0;
thread->name = name;
return thread;
@@ -465,9 +480,21 @@ void Reschedule() {
}
}
+ResultCode GetThreadId(u32* thread_id, Handle handle) {
+ Thread* thread = g_object_pool.Get<Thread>(handle);
+ if (thread == nullptr)
+ return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS,
+ ErrorSummary::WrongArgument, ErrorLevel::Permanent);
+
+ *thread_id = thread->thread_id;
+
+ return RESULT_SUCCESS;
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
void ThreadingInit() {
+ next_thread_id = INITIAL_THREAD_ID;
}
void 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 @@
#pragma once
#include "common/common_types.h"
+
+#include "core/mem_map.h"
+
#include "core/hle/kernel/kernel.h"
#include "core/hle/result.h"
@@ -58,6 +61,14 @@ void Reschedule();
/// Stops the current thread
ResultCode StopThread(Handle thread, const char* reason);
+/**
+ * Retrieves the ID of the specified thread handle
+ * @param thread_id Will contain the output thread id
+ * @param handle Handle to the thread we want
+ * @return Whether the function was successful or not
+ */
+ResultCode GetThreadId(u32* thread_id, Handle handle);
+
/// Resumes a thread from waiting by marking it as "ready"
void ResumeThreadFromWait(Handle handle);
@@ -77,6 +88,14 @@ Handle GetCurrentThreadHandle();
*/
void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle());
+/**
+ * Puts the current thread in the wait state for the given type
+ * @param wait_type Type of wait
+ * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread
+ * @param wait_address Arbitration address used to resume from wait
+ */
+void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_address);
+
/// Put current thread in a wait state - on WaitSynchronization
void WaitThread_Synchronization();
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 @@
namespace AC_U {
+/**
+ * AC_U::GetWifiStatus service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet.
+ */
+void GetWifiStatus(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(purpasmart96): This function is only a stub,
+ // it returns a valid result without implementing full functionality.
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = 0; // Connection type set to none
+
+ WARN_LOG(KERNEL, "(STUBBED) called");
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010000, nullptr, "CreateDefaultConfig"},
{0x00040006, nullptr, "ConnectAsync"},
@@ -18,7 +36,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00080004, nullptr, "CloseAsync"},
{0x00090002, nullptr, "GetCloseResult"},
{0x000A0000, nullptr, "GetLastErrorCode"},
- {0x000D0000, nullptr, "GetWifiStatus"},
+ {0x000D0000, GetWifiStatus, "GetWifiStatus"},
{0x000E0042, nullptr, "GetCurrentAPInfo"},
{0x00100042, nullptr, "GetCurrentNZoneInfo"},
{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 @@
namespace CFG_U {
+static const std::array<const char*, 187> country_codes = {
+ nullptr, "JP", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 0-7
+ "AI", "AG", "AR", "AW", "BS", "BB", "BZ", "BO", // 8-15
+ "BR", "VG", "CA", "KY", "CL", "CO", "CR", "DM", // 16-23
+ "DO", "EC", "SV", "GF", "GD", "GP", "GT", "GY", // 24-31
+ "HT", "HN", "JM", "MQ", "MX", "MS", "AN", "NI", // 32-39
+ "PA", "PY", "PE", "KN", "LC", "VC", "SR", "TT", // 40-47
+ "TC", "US", "UY", "VI", "VE", nullptr, nullptr, nullptr, // 48-55
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 56-63
+ "AL", "AU", "AT", "BE", "BA", "BW", "BG", "HR", // 64-71
+ "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", // 72-79
+ "HU", "IS", "IE", "IT", "LV", "LS", "LI", "LT", // 80-87
+ "LU", "MK", "MT", "ME", "MZ", "NA", "NL", "NZ", // 88-95
+ "NO", "PL", "PT", "RO", "RU", "RS", "SK", "SI", // 96-103
+ "ZA", "ES", "SZ", "SE", "CH", "TR", "GB", "ZM", // 104-111
+ "ZW", "AZ", "MR", "ML", "NE", "TD", "SD", "ER", // 112-119
+ "DJ", "SO", "AD", "GI", "GG", "IM", "JE", "MC", // 120-127
+ "TW", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 128-135
+ "KR", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 136-143
+ "HK", "MO", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 144-151
+ "ID", "SG", "TH", "PH", "MY", nullptr, nullptr, nullptr, // 152-159
+ "CN", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 160-167
+ "AE", "IN", "EG", "OM", "QA", "KW", "SA", "SY", // 168-175
+ "BH", "JO", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // 176-183
+ "SM", "VA", "BM", // 184-186
+};
+
+/**
+ * CFG_User::GetCountryCodeString service function
+ * Inputs:
+ * 1 : Country Code ID
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Country's 2-char string
+ */
+static void GetCountryCodeString(Service::Interface* self) {
+ u32* cmd_buffer = Service::GetCommandBuffer();
+ u32 country_code_id = cmd_buffer[1];
+
+ if (country_code_id >= country_codes.size()) {
+ ERROR_LOG(KERNEL, "requested country code id=%d is invalid", country_code_id);
+ cmd_buffer[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw;
+ return;
+ }
+
+ const char* code = country_codes[country_code_id];
+ if (code != nullptr) {
+ cmd_buffer[1] = 0;
+ cmd_buffer[2] = code[0] | (code[1] << 8);
+ } else {
+ cmd_buffer[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw;
+ DEBUG_LOG(KERNEL, "requested country code id=%d is not set", country_code_id);
+ }
+}
+
+/**
+ * CFG_User::GetCountryCodeID service function
+ * Inputs:
+ * 1 : Country Code 2-char string
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Country Code ID
+ */
+static void GetCountryCodeID(Service::Interface* self) {
+ u32* cmd_buffer = Service::GetCommandBuffer();
+ u16 country_code = cmd_buffer[1];
+ u16 country_code_id = -1;
+
+ for (u32 i = 0; i < country_codes.size(); ++i) {
+ const char* code_string = country_codes[i];
+
+ if (code_string != nullptr) {
+ u16 code = code_string[0] | (code_string[1] << 8);
+ if (code == country_code) {
+ country_code_id = i;
+ break;
+ }
+ }
+ }
+
+ cmd_buffer[1] = 0;
+ cmd_buffer[2] = country_code_id;
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010082, nullptr, "GetConfigInfoBlk2"},
{0x00020000, nullptr, "SecureInfoGetRegion"},
@@ -20,8 +104,8 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00060000, nullptr, "GetModelNintendo2DS"},
{0x00070040, nullptr, "unknown"},
{0x00080080, nullptr, "unknown"},
- {0x00090080, nullptr, "GetCountryCodeString"},
- {0x000A0040, nullptr, "GetCountryCodeID"},
+ {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
+ {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// 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 @@
#include "common/log.h"
#include "core/hle/hle.h"
+#include "core/hle/kernel/event.h"
#include "core/hle/service/dsp_dsp.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -11,38 +12,137 @@
namespace DSP_DSP {
+static Handle semaphore_event;
+static Handle interrupt_event;
+
+/**
+ * DSP_DSP::ConvertProcessAddressFromDspDram service function
+ * Inputs:
+ * 1 : Address
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address)
+ */
+void ConvertProcessAddressFromDspDram(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ u32 addr = cmd_buff[1];
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = (addr << 1) + (Memory::DSP_MEMORY_VADDR + 0x40000);
+
+ DEBUG_LOG(KERNEL, "(STUBBED) called with address %u", addr);
+}
+
+/**
+ * DSP_DSP::LoadComponent service function
+ * Inputs:
+ * 1 : Size
+ * 2 : Unknown (observed only half word used)
+ * 3 : Unknown (observed only half word used)
+ * 4 : (size << 4) | 0xA
+ * 5 : Buffer address
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Component loaded, 0 on not loaded, 1 on loaded
+ */
+void LoadComponent(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
+
+ // TODO(bunnei): Implement real DSP firmware loading
+
+ DEBUG_LOG(KERNEL, "(STUBBED) called");
+}
+
+/**
+ * DSP_DSP::GetSemaphoreEventHandle service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 3 : Semaphore event handle
+ */
+void GetSemaphoreEventHandle(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[3] = semaphore_event; // Event handle
+
+ DEBUG_LOG(KERNEL, "(STUBBED) called");
+}
+
+/**
+ * DSP_DSP::RegisterInterruptEvents service function
+ * Inputs:
+ * 1 : Parameter 0 (purpose unknown)
+ * 2 : Parameter 1 (purpose unknown)
+ * 4 : Interrupt event handle
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void RegisterInterruptEvents(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ interrupt_event = static_cast<Handle>(cmd_buff[4]);
+
+ cmd_buff[1] = 0; // No error
+
+ DEBUG_LOG(KERNEL, "(STUBBED) called");
+}
+
+/**
+ * DSP_DSP::WriteReg0x10 service function
+ * Inputs:
+ * 1 : Unknown (observed only half word used)
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void WriteReg0x10(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ Kernel::SignalEvent(interrupt_event);
+
+ cmd_buff[1] = 0; // No error
+
+ DEBUG_LOG(KERNEL, "(STUBBED) called");
+}
+
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010040, nullptr, "RecvData"},
- {0x00020040, nullptr, "RecvDataIsReady"},
- {0x00030080, nullptr, "SendData"},
- {0x00040040, nullptr, "SendDataIsEmpty"},
- {0x00070040, nullptr, "WriteReg0x10"},
- {0x00080000, nullptr, "GetSemaphore"},
- {0x00090040, nullptr, "ClearSemaphore"},
- {0x000B0000, nullptr, "CheckSemaphoreRequest"},
- {0x000C0040, nullptr, "ConvertProcessAddressFromDspDram"},
- {0x000D0082, nullptr, "WriteProcessPipe"},
- {0x001000C0, nullptr, "ReadPipeIfPossible"},
- {0x001100C2, nullptr, "LoadComponent"},
- {0x00120000, nullptr, "UnloadComponent"},
- {0x00130082, nullptr, "FlushDataCache"},
- {0x00140082, nullptr, "InvalidateDCache"},
- {0x00150082, nullptr, "RegisterInterruptEvents"},
- {0x00160000, nullptr, "GetSemaphoreEventHandle"},
- {0x00170040, nullptr, "SetSemaphoreMask"},
- {0x00180040, nullptr, "GetPhysicalAddress"},
- {0x00190040, nullptr, "GetVirtualAddress"},
- {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
- {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
- {0x001C0082, nullptr, "SetIirFilterEQ"},
- {0x001F0000, nullptr, "GetHeadphoneStatus"},
- {0x00210000, nullptr, "GetIsDspOccupied"},
+ {0x00010040, nullptr, "RecvData"},
+ {0x00020040, nullptr, "RecvDataIsReady"},
+ {0x00030080, nullptr, "SendData"},
+ {0x00040040, nullptr, "SendDataIsEmpty"},
+ {0x00070040, WriteReg0x10, "WriteReg0x10"},
+ {0x00080000, nullptr, "GetSemaphore"},
+ {0x00090040, nullptr, "ClearSemaphore"},
+ {0x000B0000, nullptr, "CheckSemaphoreRequest"},
+ {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
+ {0x000D0082, nullptr, "WriteProcessPipe"},
+ {0x001000C0, nullptr, "ReadPipeIfPossible"},
+ {0x001100C2, LoadComponent, "LoadComponent"},
+ {0x00120000, nullptr, "UnloadComponent"},
+ {0x00130082, nullptr, "FlushDataCache"},
+ {0x00140082, nullptr, "InvalidateDCache"},
+ {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"},
+ {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"},
+ {0x00170040, nullptr, "SetSemaphoreMask"},
+ {0x00180040, nullptr, "GetPhysicalAddress"},
+ {0x00190040, nullptr, "GetVirtualAddress"},
+ {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
+ {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
+ {0x001C0082, nullptr, "SetIirFilterEQ"},
+ {0x001F0000, nullptr, "GetHeadphoneStatus"},
+ {0x00210000, nullptr, "GetIsDspOccupied"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Interface class
Interface::Interface() {
+ semaphore_event = Kernel::CreateEvent(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
+ interrupt_event = 0;
+
Register(FunctionTable, ARRAY_SIZE(FunctionTable));
}
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:
* @return Port name of service
*/
std::string GetPortName() const override {
- return "dsp:DSP";
+ return "dsp::DSP";
}
};
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) {
u32 filename_ptr = cmd_buff[9];
FileSys::Path file_path(filename_type, filename_size, filename_ptr);
- DEBUG_LOG(KERNEL, "path=%s, mode=%d attrs=%d", file_path.DebugStr().c_str(), mode, attributes);
+ DEBUG_LOG(KERNEL, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode);
cmd_buff[1] = handle.Code().raw;
@@ -102,8 +102,8 @@ static void OpenFileDirectly(Service::Interface* self) {
FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
FileSys::Path file_path(filename_type, filename_size, filename_ptr);
- DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%d attributes=%d",
- archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode, attributes);
+ DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%u attributes=%d",
+ archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes);
if (archive_path.GetType() != FileSys::Empty) {
ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported");
@@ -159,7 +159,49 @@ void DeleteFile(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
filename_type, filename_size, file_path.DebugStr().c_str());
- cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path);
+ cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path).raw;
+
+ DEBUG_LOG(KERNEL, "called");
+}
+
+/*
+ * FS_User::RenameFile service function
+ * Inputs:
+ * 2 : Source archive handle lower word
+ * 3 : Source archive handle upper word
+ * 4 : Source file path type
+ * 5 : Source file path size
+ * 6 : Dest archive handle lower word
+ * 7 : Dest archive handle upper word
+ * 8 : Dest file path type
+ * 9 : Dest file path size
+ * 11: Source file path string data
+ * 13: Dest file path string
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void RenameFile(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
+ // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
+ Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
+ auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
+ u32 src_filename_size = cmd_buff[5];
+ Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]);
+ auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
+ u32 dest_filename_size = cmd_buff[9];
+ u32 src_filename_ptr = cmd_buff[11];
+ u32 dest_filename_ptr = cmd_buff[13];
+
+ FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr);
+ FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr);
+
+ DEBUG_LOG(KERNEL, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
+ src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(),
+ dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
+
+ cmd_buff[1] = Kernel::RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw;
DEBUG_LOG(KERNEL, "called");
}
@@ -190,7 +232,7 @@ void DeleteDirectory(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
dirname_type, dirname_size, dir_path.DebugStr().c_str());
- cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path);
+ cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
DEBUG_LOG(KERNEL, "called");
}
@@ -220,11 +262,53 @@ static void CreateDirectory(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
- cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path);
+ cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path).raw;
DEBUG_LOG(KERNEL, "called");
}
+/*
+ * FS_User::RenameDirectory service function
+ * Inputs:
+ * 2 : Source archive handle lower word
+ * 3 : Source archive handle upper word
+ * 4 : Source dir path type
+ * 5 : Source dir path size
+ * 6 : Dest archive handle lower word
+ * 7 : Dest archive handle upper word
+ * 8 : Dest dir path type
+ * 9 : Dest dir path size
+ * 11: Source dir path string data
+ * 13: Dest dir path string
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void RenameDirectory(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
+ // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
+ Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
+ auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
+ u32 src_dirname_size = cmd_buff[5];
+ Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]);
+ auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
+ u32 dest_dirname_size = cmd_buff[9];
+ u32 src_dirname_ptr = cmd_buff[11];
+ u32 dest_dirname_ptr = cmd_buff[13];
+
+ FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr);
+ FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr);
+
+ DEBUG_LOG(KERNEL, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
+ src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(),
+ dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
+
+ cmd_buff[1] = Kernel::RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw;
+
+ DEBUG_LOG(KERNEL, "called");
+}
+
static void OpenDirectory(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
@@ -314,12 +398,12 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x080201C2, OpenFile, "OpenFile"},
{0x08030204, OpenFileDirectly, "OpenFileDirectly"},
{0x08040142, DeleteFile, "DeleteFile"},
- {0x08050244, nullptr, "RenameFile"},
+ {0x08050244, RenameFile, "RenameFile"},
{0x08060142, DeleteDirectory, "DeleteDirectory"},
{0x08070142, nullptr, "DeleteDirectoryRecursively"},
{0x08080202, nullptr, "CreateFile"},
{0x08090182, CreateDirectory, "CreateDirectory"},
- {0x080A0244, nullptr, "RenameDirectory"},
+ {0x080A0244, RenameDirectory, "RenameDirectory"},
{0x080B0102, OpenDirectory, "OpenDirectory"},
{0x080C00C2, OpenArchive, "OpenArchive"},
{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() {
/**
* Sets a Pad state (button or button combo) as pressed
*/
-void PadButtonPress(PadState pad_state) {
+void PadButtonPress(const PadState& pad_state) {
next_state.hex |= pad_state.hex;
UpdateNextCirclePadState();
}
@@ -63,7 +63,7 @@ void PadButtonPress(PadState pad_state) {
/**
* Sets a Pad state (button or button combo) as released
*/
-void PadButtonRelease(PadState pad_state) {
+void PadButtonRelease(const PadState& pad_state) {
next_state.hex &= ~pad_state.hex;
UpdateNextCirclePadState();
}
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}};
const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
// Methods for updating the HID module's state
-void PadButtonPress(PadState pad_state);
-void PadButtonRelease(PadState pad_state);
+void PadButtonPress(const PadState& pad_state);
+void PadButtonRelease(const PadState& pad_state);
void PadUpdateComplete();
/**
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 @@
namespace PTM_U {
+/// Charge levels used by PTM functions
+enum class ChargeLevels : u32 {
+ CriticalBattery = 1,
+ LowBattery = 2,
+ HalfFull = 3,
+ MostlyFull = 4,
+ CompletelyFull = 5,
+};
+
+static bool shell_open = true;
+
+static bool battery_is_charging = true;
+
+/**
+ * It is unknown if GetAdapterState is the same as GetBatteryChargeState,
+ * it is likely to just be a duplicate function of GetBatteryChargeState
+ * that controls another part of the HW.
+ * PTM_U::GetAdapterState service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Output of function, 0 = not charging, 1 = charging.
+ */
+static void GetAdapterState(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(purpasmart96): This function is only a stub,
+ // it returns a valid result without implementing full functionality.
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = battery_is_charging ? 1 : 0;
+
+ WARN_LOG(KERNEL, "(STUBBED) called");
+}
+
+/*
+ * PTM_User::GetShellState service function.
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0)
+ */
+static void GetShellState(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ cmd_buff[1] = 0;
+ cmd_buff[2] = shell_open ? 1 : 0;
+
+ DEBUG_LOG(KERNEL, "PTM_U::GetShellState called");
+}
+
+/**
+ * PTM_U::GetBatteryLevel service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Battery level, 5 = completely full battery, 4 = mostly full battery,
+ * 3 = half full battery, 2 = low battery, 1 = critical battery.
+ */
+static void GetBatteryLevel(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(purpasmart96): This function is only a stub,
+ // it returns a valid result without implementing full functionality.
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery
+
+ WARN_LOG(KERNEL, "(STUBBED) called");
+}
+
+/**
+ * PTM_U::GetBatteryChargeState service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Output of function, 0 = not charging, 1 = charging.
+ */
+static void GetBatteryChargeState(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(purpasmart96): This function is only a stub,
+ // it returns a valid result without implementing full functionality.
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = battery_is_charging ? 1 : 0;
+
+ WARN_LOG(KERNEL, "(STUBBED) called");
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010002, nullptr, "RegisterAlarmClient"},
{0x00020080, nullptr, "SetRtcAlarm"},
{0x00030000, nullptr, "GetRtcAlarm"},
{0x00040000, nullptr, "CancelRtcAlarm"},
- {0x00050000, nullptr, "GetAdapterState"},
- {0x00060000, nullptr, "GetShellState"},
- {0x00070000, nullptr, "GetBatteryLevel"},
- {0x00080000, nullptr, "GetBatteryChargeState"},
+ {0x00050000, GetAdapterState, "GetAdapterState"},
+ {0x00060000, GetShellState, "GetShellState"},
+ {0x00070000, GetBatteryLevel, "GetBatteryLevel"},
+ {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"},
{0x00090000, nullptr, "GetPedometerState"},
{0x000A0042, nullptr, "GetStepHistoryEntry"},
{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) {
/// Arbitrate address
static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) {
+ DEBUG_LOG(SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter,
+ address, type, value);
return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type),
address, value).raw;
}
@@ -279,10 +281,11 @@ static Result ReleaseMutex(Handle handle) {
return res.raw;
}
-/// Get current thread ID
-static Result GetThreadId(u32* thread_id, Handle thread) {
- ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread);
- return 0;
+/// Get the ID for the specified thread.
+static Result GetThreadId(u32* thread_id, Handle handle) {
+ DEBUG_LOG(SVC, "called thread=0x%08X", handle);
+ ResultCode result = Kernel::GetThreadId(thread_id, handle);
+ return result.raw;
}
/// Query memory
@@ -331,6 +334,9 @@ static Result ClearEvent(Handle evt) {
/// Sleep the current thread
static void SleepThread(s64 nanoseconds) {
DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds);
+
+ // Check for next thread to schedule
+ HLE::Reschedule(__func__);
}
/// This returns the total CPU ticks elapsed since the CPU was powered-on
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) {
// Writes other than u32 are untested, so I'd rather have them abort than silently fail
if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) {
- ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
+ ERROR_LOG(GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
return;
}
@@ -140,8 +140,8 @@ inline void Write(u32 addr, const T data) {
DEBUG_LOG(GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x",
config.output_height * config.output_width * 4,
- config.GetPhysicalInputAddress(), config.input_width, config.input_height,
- config.GetPhysicalOutputAddress(), config.output_width, config.output_height,
+ config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height,
+ config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height,
config.output_format.Value());
}
break;
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index 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) {
break;
default:
- ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
+ ERROR_LOG(HW, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
}
}
diff --git a/src/core/hw/ndma.cpp b/src/core/hw/ndma.cpp
index 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) {
template <typename T>
inline void Write(u32 addr, const T data) {
- ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr);
+ ERROR_LOG(NDMA, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
}
// Explicitly instantiate template functions because we aren't defining this in the header:
diff --git a/src/core/loader/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 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <vector>
+
+#include "core/file_sys/archive_romfs.h"
+#include "core/loader/elf.h"
+#include "core/loader/ncch.h"
+#include "core/hle/kernel/archive.h"
+#include "core/mem_map.h"
+
+#include "3dsx.h"
+
+
+namespace Loader {
+
+
+/**
+ * File layout:
+ * - File header
+ * - Code, rodata and data relocation table headers
+ * - Code segment
+ * - Rodata segment
+ * - Loadable (non-BSS) part of the data segment
+ * - Code relocation table
+ * - Rodata relocation table
+ * - Data relocation table
+ *
+ * Memory layout before relocations are applied:
+ * [0..codeSegSize) -> code segment
+ * [codeSegSize..rodataSegSize) -> rodata segment
+ * [rodataSegSize..dataSegSize) -> data segment
+ *
+ * Memory layout after relocations are applied: well, however the loader sets it up :)
+ * The entrypoint is always the start of the code segment.
+ * The BSS section must be cleared manually by the application.
+ */
+enum THREEDSX_Error {
+ ERROR_NONE = 0,
+ ERROR_READ = 1,
+ ERROR_FILE = 2,
+ ERROR_ALLOC = 3
+};
+static const u32 RELOCBUFSIZE = 512;
+
+// File header
+static const u32 THREEDSX_MAGIC = 0x58534433; // '3DSX'
+#pragma pack(1)
+struct THREEDSX_Header
+{
+ u32 magic;
+ u16 header_size, reloc_hdr_size;
+ u32 format_ver;
+ u32 flags;
+
+ // Sizes of the code, rodata and data segments +
+ // size of the BSS section (uninitialized latter half of the data segment)
+ u32 code_seg_size, rodata_seg_size, data_seg_size, bss_size;
+};
+
+// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
+struct THREEDSX_RelocHdr
+{
+ // # of absolute relocations (that is, fix address to post-relocation memory layout)
+ u32 cross_segment_absolute;
+ // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched)
+ u32 cross_segment_relative;
+ // more?
+
+ // Relocations are written in this order:
+ // - Absolute relocations
+ // - Relative relocations
+};
+
+// Relocation entry: from the current pointer, skip X words and patch Y words
+struct THREEDSX_Reloc
+{
+ u16 skip, patch;
+};
+#pragma pack()
+
+struct THREEloadinfo
+{
+ u8* seg_ptrs[3]; // code, rodata & data
+ u32 seg_addrs[3];
+ u32 seg_sizes[3];
+};
+
+class THREEDSXReader {
+public:
+ static int Load3DSXFile(const std::string& filename, u32 base_addr);
+};
+
+static u32 TranslateAddr(u32 addr, THREEloadinfo *loadinfo, u32* offsets)
+{
+ if (addr < offsets[0])
+ return loadinfo->seg_addrs[0] + addr;
+ if (addr < offsets[1])
+ return loadinfo->seg_addrs[1] + addr - offsets[0];
+ return loadinfo->seg_addrs[2] + addr - offsets[1];
+}
+
+int THREEDSXReader::Load3DSXFile(const std::string& filename, u32 base_addr)
+{
+ FileUtil::IOFile file(filename, "rb");
+ if (!file.IsOpen()) {
+ return ERROR_FILE;
+ }
+ THREEDSX_Header hdr;
+ if (file.ReadBytes(&hdr, sizeof(hdr)) != sizeof(hdr))
+ return ERROR_READ;
+
+ THREEloadinfo loadinfo;
+ //loadinfo segments must be a multiple of 0x1000
+ loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) &~0xFFF;
+ loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF;
+ loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF;
+ u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] };
+ u32 data_load_size = (hdr.data_seg_size - hdr.bss_size + 0xFFF) &~0xFFF;
+ u32 bss_load_size = loadinfo.seg_sizes[2] - data_load_size;
+ u32 n_reloc_tables = hdr.reloc_hdr_size / 4;
+ std::vector<u8> all_mem(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2] + 3 * n_reloc_tables);
+
+ loadinfo.seg_addrs[0] = base_addr;
+ loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0];
+ loadinfo.seg_addrs[2] = loadinfo.seg_addrs[1] + loadinfo.seg_sizes[1];
+ loadinfo.seg_ptrs[0] = &all_mem[0];
+ loadinfo.seg_ptrs[1] = loadinfo.seg_ptrs[0] + loadinfo.seg_sizes[0];
+ loadinfo.seg_ptrs[2] = loadinfo.seg_ptrs[1] + loadinfo.seg_sizes[1];
+
+ // Skip header for future compatibility
+ file.Seek(hdr.header_size, SEEK_SET);
+
+ // Read the relocation headers
+ u32* relocs = (u32*)(loadinfo.seg_ptrs[2] + hdr.data_seg_size);
+
+ for (u32 current_segment = 0; current_segment < 3; current_segment++) {
+ if (file.ReadBytes(&relocs[current_segment*n_reloc_tables], n_reloc_tables * 4) != n_reloc_tables * 4)
+ return ERROR_READ;
+ }
+
+ // Read the segments
+ if (file.ReadBytes(loadinfo.seg_ptrs[0], hdr.code_seg_size) != hdr.code_seg_size)
+ return ERROR_READ;
+ if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size)
+ return ERROR_READ;
+ if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) != hdr.data_seg_size - hdr.bss_size)
+ return ERROR_READ;
+
+ // BSS clear
+ memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size);
+
+ // Relocate the segments
+ for (u32 current_segment = 0; current_segment < 3; current_segment++) {
+ for (u32 current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) {
+ u32 n_relocs = relocs[current_segment*n_reloc_tables + current_segment_reloc_table];
+ if (current_segment_reloc_table >= 2) {
+ // We are not using this table - ignore it because we don't know what it dose
+ file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR);
+ continue;
+ }
+ static THREEDSX_Reloc reloc_table[RELOCBUFSIZE];
+
+ u32* pos = (u32*)loadinfo.seg_ptrs[current_segment];
+ u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4);
+
+ while (n_relocs) {
+ u32 remaining = std::min(RELOCBUFSIZE, n_relocs);
+ n_relocs -= remaining;
+
+ if (file.ReadBytes(reloc_table, remaining*sizeof(THREEDSX_Reloc)) != remaining*sizeof(THREEDSX_Reloc))
+ return ERROR_READ;
+
+ for (u32 current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) {
+ DEBUG_LOG(LOADER, "(t=%d,skip=%u,patch=%u)\n",
+ current_segment_reloc_table, (u32)reloc_table[current_inprogress].skip, (u32)reloc_table[current_inprogress].patch);
+ pos += reloc_table[current_inprogress].skip;
+ s32 num_patches = reloc_table[current_inprogress].patch;
+ while (0 < num_patches && pos < end_pos) {
+ u32 in_addr = (char*)pos - (char*)&all_mem[0];
+ u32 addr = TranslateAddr(*pos, &loadinfo, offsets);
+ DEBUG_LOG(LOADER, "Patching %08X <-- rel(%08X,%d) (%08X)\n",
+ base_addr + in_addr, addr, current_segment_reloc_table, *pos);
+ switch (current_segment_reloc_table) {
+ case 0: *pos = (addr); break;
+ case 1: *pos = (addr - in_addr); break;
+ default: break; //this should never happen
+ }
+ pos++;
+ num_patches--;
+ }
+ }
+ }
+ }
+ }
+
+ // Write the data
+ memcpy(Memory::GetPointer(base_addr), &all_mem[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]);
+
+ DEBUG_LOG(LOADER, "CODE: %u pages\n", loadinfo.seg_sizes[0] / 0x1000);
+ DEBUG_LOG(LOADER, "RODATA: %u pages\n", loadinfo.seg_sizes[1] / 0x1000);
+ DEBUG_LOG(LOADER, "DATA: %u pages\n", data_load_size / 0x1000);
+ DEBUG_LOG(LOADER, "BSS: %u pages\n", bss_load_size / 0x1000);
+
+ return ERROR_NONE;
+}
+
+ /// AppLoader_DSX constructor
+ AppLoader_THREEDSX::AppLoader_THREEDSX(const std::string& filename) : filename(filename) {
+ }
+
+ /// AppLoader_DSX destructor
+ AppLoader_THREEDSX::~AppLoader_THREEDSX() {
+ }
+
+ /**
+ * Loads a 3DSX file
+ * @return Success on success, otherwise Error
+ */
+ ResultStatus AppLoader_THREEDSX::Load() {
+ INFO_LOG(LOADER, "Loading 3DSX file %s...", filename.c_str());
+ FileUtil::IOFile file(filename, "rb");
+ if (file.IsOpen()) {
+
+ THREEDSXReader reader;
+ reader.Load3DSXFile(filename, 0x00100000);
+ Kernel::LoadExec(0x00100000);
+ } else {
+ return ResultStatus::Error;
+ }
+ return ResultStatus::Success;
+ }
+
+} // 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 @@
+// Copyright 2014 Dolphin Emulator Project / Citra Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+#include "core/loader/loader.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Loader namespace
+
+namespace Loader {
+
+/// Loads an 3DSX file
+class AppLoader_THREEDSX final : public AppLoader {
+public:
+ AppLoader_THREEDSX(const std::string& filename);
+ ~AppLoader_THREEDSX() override;
+
+ /**
+ * Load the bootable file
+ * @return ResultStatus result of function
+ */
+ ResultStatus Load() override;
+
+private:
+ std::string filename;
+ bool is_loaded;
+};
+
+} // 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 @@
#include <memory>
#include "core/file_sys/archive_romfs.h"
+#include "core/loader/3dsx.h"
#include "core/loader/elf.h"
#include "core/loader/ncch.h"
#include "core/hle/kernel/archive.h"
@@ -42,6 +43,8 @@ FileType IdentifyFile(const std::string &filename) {
return FileType::CCI;
} else if (extension == ".bin") {
return FileType::BIN;
+ } else if (extension == ".3dsx") {
+ return FileType::THREEDSX;
}
return FileType::Unknown;
}
@@ -56,6 +59,10 @@ ResultStatus LoadFile(const std::string& filename) {
switch (IdentifyFile(filename)) {
+ //3DSX file format...
+ case FileType::THREEDSX:
+ return AppLoader_THREEDSX(filename).Load();
+
// Standard ELF file format...
case FileType::ELF:
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 {
CIA,
ELF,
BIN,
+ THREEDSX, //3DSX
};
/// 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.
////////////////////////////////////////////////////////////////////////////////////////////////////
-enum {
+enum : u32 {
BOOTROM_SIZE = 0x00010000, ///< Bootrom (super secret code/data @ 0x8000) size
MPCORE_PRIV_SIZE = 0x00002000, ///< MPCore private memory region size
- DSP_SIZE = 0x00080000, ///< DSP memory size
AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size
FCRAM_SIZE = 0x08000000, ///< FCRAM size
@@ -27,47 +26,42 @@ enum {
FCRAM_PADDR_END = (FCRAM_PADDR + FCRAM_SIZE), ///< FCRAM end of physical space
FCRAM_VADDR = 0x08000000, ///< FCRAM virtual address
FCRAM_VADDR_END = (FCRAM_VADDR + FCRAM_SIZE), ///< FCRAM end of virtual space
- FCRAM_MASK = (FCRAM_SIZE - 1), ///< FCRAM mask
SHARED_MEMORY_SIZE = 0x04000000, ///< Shared memory size
SHARED_MEMORY_VADDR = 0x10000000, ///< Shared memory
SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE),
- SHARED_MEMORY_MASK = (SHARED_MEMORY_SIZE - 1),
+
+ DSP_MEMORY_SIZE = 0x00080000, ///< DSP memory size
+ DSP_MEMORY_VADDR = 0x1FF00000, ///< DSP memory virtual address
CONFIG_MEMORY_SIZE = 0x00001000, ///< Configuration memory size
CONFIG_MEMORY_VADDR = 0x1FF80000, ///< Configuration memory virtual address
CONFIG_MEMORY_VADDR_END = (CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE),
- CONFIG_MEMORY_MASK = (CONFIG_MEMORY_SIZE - 1),
KERNEL_MEMORY_SIZE = 0x00001000, ///< Kernel memory size
KERNEL_MEMORY_VADDR = 0xFFFF0000, ///< Kernel memory where the kthread objects etc are
KERNEL_MEMORY_VADDR_END = (KERNEL_MEMORY_VADDR + KERNEL_MEMORY_SIZE),
- KERNEL_MEMORY_MASK = (KERNEL_MEMORY_SIZE - 1),
EXEFS_CODE_SIZE = 0x03F00000,
EXEFS_CODE_VADDR = 0x00100000, ///< ExeFS:/.code is loaded here
EXEFS_CODE_VADDR_END = (EXEFS_CODE_VADDR + EXEFS_CODE_SIZE),
- EXEFS_CODE_MASK = 0x03FFFFFF,
// Region of FCRAM used by system
SYSTEM_MEMORY_SIZE = 0x02C00000, ///< 44MB
SYSTEM_MEMORY_VADDR = 0x04000000,
SYSTEM_MEMORY_VADDR_END = (SYSTEM_MEMORY_VADDR + SYSTEM_MEMORY_SIZE),
- SYSTEM_MEMORY_MASK = 0x03FFFFFF,
HEAP_SIZE = FCRAM_SIZE, ///< Application heap size
//HEAP_PADDR = HEAP_GSP_SIZE,
//HEAP_PADDR_END = (HEAP_PADDR + HEAP_SIZE),
HEAP_VADDR = 0x08000000,
HEAP_VADDR_END = (HEAP_VADDR + HEAP_SIZE),
- HEAP_MASK = (HEAP_SIZE - 1),
HEAP_GSP_SIZE = 0x02000000, ///< GSP heap size... TODO: Define correctly?
HEAP_GSP_VADDR = 0x14000000,
HEAP_GSP_VADDR_END = (HEAP_GSP_VADDR + HEAP_GSP_SIZE),
HEAP_GSP_PADDR = 0x00000000,
HEAP_GSP_PADDR_END = (HEAP_GSP_PADDR + HEAP_GSP_SIZE),
- HEAP_GSP_MASK = (HEAP_GSP_SIZE - 1),
HARDWARE_IO_SIZE = 0x01000000,
HARDWARE_IO_PADDR = 0x10000000, ///< IO physical address start
@@ -80,12 +74,10 @@ enum {
VRAM_VADDR = 0x1F000000,
VRAM_PADDR_END = (VRAM_PADDR + VRAM_SIZE),
VRAM_VADDR_END = (VRAM_VADDR + VRAM_SIZE),
- VRAM_MASK = 0x007FFFFF,
SCRATCHPAD_SIZE = 0x00004000, ///< Typical stack size - TODO: Read from exheader
SCRATCHPAD_VADDR_END = 0x10000000,
SCRATCHPAD_VADDR = (SCRATCHPAD_VADDR_END - SCRATCHPAD_SIZE), ///< Stack space
- SCRATCHPAD_MASK = (SCRATCHPAD_SIZE - 1), ///< Scratchpad memory mask
};
////////////////////////////////////////////////////////////////////////////////////////////////////
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) {
// Kernel memory command buffer
if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
- var = *((const T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK]);
+ var = *((const T*)&g_kernel_mem[vaddr - KERNEL_MEMORY_VADDR]);
// Hardware I/O register reads
// 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
@@ -65,23 +65,23 @@ inline void Read(T &var, const VAddr vaddr) {
// ExeFS:/.code is loaded here
} else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
- var = *((const T*)&g_exefs_code[vaddr & EXEFS_CODE_MASK]);
+ var = *((const T*)&g_exefs_code[vaddr - EXEFS_CODE_VADDR]);
// FCRAM - GSP heap
} else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
- var = *((const T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK]);
+ var = *((const T*)&g_heap_gsp[vaddr - HEAP_GSP_VADDR]);
// FCRAM - application heap
} else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
- var = *((const T*)&g_heap[vaddr & HEAP_MASK]);
+ var = *((const T*)&g_heap[vaddr - HEAP_VADDR]);
// Shared memory
} else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
- var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
+ var = *((const T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR]);
// System memory
} else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
- var = *((const T*)&g_system_mem[vaddr & SYSTEM_MEMORY_MASK]);
+ var = *((const T*)&g_system_mem[vaddr - SYSTEM_MEMORY_VADDR]);
// Config memory
} else if ((vaddr >= CONFIG_MEMORY_VADDR) && (vaddr < CONFIG_MEMORY_VADDR_END)) {
@@ -89,10 +89,10 @@ inline void Read(T &var, const VAddr vaddr) {
// VRAM
} else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
- var = *((const T*)&g_vram[vaddr & VRAM_MASK]);
+ var = *((const T*)&g_vram[vaddr - VRAM_VADDR]);
} else {
- ERROR_LOG(MEMMAP, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
+ ERROR_LOG(MEMMAP, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, vaddr);
}
}
@@ -101,7 +101,7 @@ inline void Write(const VAddr vaddr, const T data) {
// Kernel memory command buffer
if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
- *(T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK] = data;
+ *(T*)&g_kernel_mem[vaddr - KERNEL_MEMORY_VADDR] = data;
// Hardware I/O register writes
// 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
@@ -110,27 +110,27 @@ inline void Write(const VAddr vaddr, const T data) {
// ExeFS:/.code is loaded here
} else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
- *(T*)&g_exefs_code[vaddr & EXEFS_CODE_MASK] = data;
+ *(T*)&g_exefs_code[vaddr - EXEFS_CODE_VADDR] = data;
// FCRAM - GSP heap
} else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
- *(T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK] = data;
+ *(T*)&g_heap_gsp[vaddr - HEAP_GSP_VADDR] = data;
// FCRAM - application heap
} else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
- *(T*)&g_heap[vaddr & HEAP_MASK] = data;
+ *(T*)&g_heap[vaddr - HEAP_VADDR] = data;
// Shared memory
} else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
- *(T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK] = data;
+ *(T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR] = data;
// System memory
} else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
- *(T*)&g_system_mem[vaddr & SYSTEM_MEMORY_MASK] = data;
+ *(T*)&g_system_mem[vaddr - SYSTEM_MEMORY_VADDR] = data;
// VRAM
} else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
- *(T*)&g_vram[vaddr & VRAM_MASK] = data;
+ *(T*)&g_vram[vaddr - VRAM_VADDR] = data;
//} else if ((vaddr & 0xFFF00000) == 0x1FF00000) {
// _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory");
@@ -141,38 +141,38 @@ inline void Write(const VAddr vaddr, const T data) {
// Error out...
} else {
- ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr);
+ ERROR_LOG(MEMMAP, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, vaddr);
}
}
u8 *GetPointer(const VAddr vaddr) {
// Kernel memory command buffer
if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
- return g_kernel_mem + (vaddr & KERNEL_MEMORY_MASK);
+ return g_kernel_mem + (vaddr - KERNEL_MEMORY_VADDR);
// ExeFS:/.code is loaded here
} else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
- return g_exefs_code + (vaddr & EXEFS_CODE_MASK);
+ return g_exefs_code + (vaddr - EXEFS_CODE_VADDR);
// FCRAM - GSP heap
} else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
- return g_heap_gsp + (vaddr & HEAP_GSP_MASK);
+ return g_heap_gsp + (vaddr - HEAP_GSP_VADDR);
// FCRAM - application heap
} else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
- return g_heap + (vaddr & HEAP_MASK);
+ return g_heap + (vaddr - HEAP_VADDR);
// Shared memory
} else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
- return g_shared_mem + (vaddr & SHARED_MEMORY_MASK);
+ return g_shared_mem + (vaddr - SHARED_MEMORY_VADDR);
// System memory
} else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
- return g_system_mem + (vaddr & SYSTEM_MEMORY_MASK);
+ return g_system_mem + (vaddr - SYSTEM_MEMORY_VADDR);
// VRAM
} else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
- return g_vram + (vaddr & VRAM_MASK);
+ return g_vram + (vaddr - VRAM_VADDR);
} else {
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) {
const u8* load_address = base_address + loader_config.data_offset;
// TODO: What happens if a loader overwrites a previous one's data?
- for (int component = 0; component < loader_config.component_count; ++component) {
+ for (unsigned component = 0; component < loader_config.component_count; ++component) {
u32 attribute_index = loader_config.GetComponent(component);
vertex_attribute_sources[attribute_index] = load_address;
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
// This is put into a try-catch block to make sure we notice unknown configurations.
std::vector<OutputRegisterInfo> output_info_table;
- for (int i = 0; i < 7; ++i) {
+ for (unsigned i = 0; i < 7; ++i) {
using OutputAttributes = Pica::Regs::VSOutputAttributes;
// 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) {
png_write_info(png_ptr, info_ptr);
buf = new u8[row_stride * texture_config.height];
- for (int y = 0; y < texture_config.height; ++y) {
- for (int x = 0; x < texture_config.width; ++x) {
+ for (unsigned y = 0; y < texture_config.height; ++y) {
+ for (unsigned x = 0; x < texture_config.width; ++x) {
// Cf. rasterizer code for an explanation of this algorithm.
int texel_index_within_tile = 0;
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) {
}
// Write image data
- for (auto y = 0; y < texture_config.height; ++y)
+ for (unsigned y = 0; y < texture_config.height; ++y)
{
u8* row_ptr = (u8*)buf + y * row_stride;
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) {
// Compile Vertex Shader
DEBUG_LOG(GPU, "Compiling vertex shader.");
- glShaderSource(vertex_shader_id, 1, &vertex_shader, NULL);
+ glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr);
glCompileShader(vertex_shader_id);
// Check Vertex Shader
@@ -31,14 +31,14 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> vertex_shader_error(info_log_length);
- glGetShaderInfoLog(vertex_shader_id, info_log_length, NULL, &vertex_shader_error[0]);
+ glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]);
DEBUG_LOG(GPU, "%s", &vertex_shader_error[0]);
}
// Compile Fragment Shader
DEBUG_LOG(GPU, "Compiling fragment shader.");
- glShaderSource(fragment_shader_id, 1, &fragment_shader, NULL);
+ glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr);
glCompileShader(fragment_shader_id);
// Check Fragment Shader
@@ -47,7 +47,7 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> fragment_shader_error(info_log_length);
- glGetShaderInfoLog(fragment_shader_id, info_log_length, NULL, &fragment_shader_error[0]);
+ glGetShaderInfoLog(fragment_shader_id, info_log_length, nullptr, &fragment_shader_error[0]);
DEBUG_LOG(GPU, "%s", &fragment_shader_error[0]);
}
@@ -65,7 +65,7 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> program_error(info_log_length);
- glGetProgramInfoLog(program_id, info_log_length, NULL, &program_error[0]);
+ glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]);
DEBUG_LOG(GPU, "%s", &program_error[0]);
}
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() {
for(int i : {0, 1}) {
const auto& framebuffer = GPU::g_regs.framebuffer_config[i];
- if (textures[i].width != framebuffer.width || textures[i].height != framebuffer.height) {
+ if (textures[i].width != (GLsizei)framebuffer.width || textures[i].height != (GLsizei)framebuffer.height) {
// Reallocate texture if the framebuffer size has changed.
// This is expected to not happen very often and hence should not be a
// performance problem.
@@ -240,14 +240,14 @@ MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() {
MathUtil::Rectangle<unsigned> viewport_extent;
if (window_aspect_ratio > emulation_aspect_ratio) {
// Window is narrower than the emulation content => apply borders to the top and bottom
- unsigned viewport_height = emulation_aspect_ratio * framebuffer_width;
+ unsigned viewport_height = std::round(emulation_aspect_ratio * framebuffer_width);
viewport_extent.left = 0;
viewport_extent.top = (framebuffer_height - viewport_height) / 2;
viewport_extent.right = viewport_extent.left + framebuffer_width;
viewport_extent.bottom = viewport_extent.top + viewport_height;
} else {
// Otherwise, apply borders to the left and right sides of the window.
- unsigned viewport_width = framebuffer_height / emulation_aspect_ratio;
+ unsigned viewport_width = std::round(framebuffer_height / emulation_aspect_ratio);
viewport_extent.left = (framebuffer_width - viewport_width) / 2;
viewport_extent.top = 0;
viewport_extent.right = viewport_extent.left + viewport_width;
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 @@
namespace VideoCore {
-EmuWindow* g_emu_window = NULL; ///< Frontend emulator window
-RendererBase* g_renderer = NULL; ///< Renderer plugin
+EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window
+RendererBase* g_renderer = nullptr; ///< Renderer plugin
int g_current_frame = 0;
/// Initialize the video core