From 45afc15aa6b9b1798a321bc053171deb765d7681 Mon Sep 17 00:00:00 2001 From: archshift Date: Sun, 23 Nov 2014 23:20:04 -0800 Subject: [PATCH 01/27] Implemented RenameFile in FS:USER --- src/core/file_sys/archive.h | 8 ++++++ src/core/file_sys/archive_romfs.cpp | 11 ++++++++ src/core/file_sys/archive_romfs.h | 8 ++++++ src/core/file_sys/archive_sdmc.cpp | 10 +++++++ src/core/file_sys/archive_sdmc.h | 8 ++++++ src/core/hle/kernel/archive.cpp | 24 ++++++++++++++++ src/core/hle/kernel/archive.h | 11 ++++++++ src/core/hle/service/fs_user.cpp | 44 ++++++++++++++++++++++++++++- 8 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h index 2e79bb883..703742a1f 100644 --- a/src/core/file_sys/archive.h +++ b/src/core/file_sys/archive.h @@ -191,6 +191,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 diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index 53dc57954..5594c5910 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp @@ -43,6 +43,17 @@ bool Archive_RomFS::DeleteFile(const FileSys::Path& path) const { return false; } +/** + * 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 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 diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index 0649dde99..d14372a01 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h @@ -43,6 +43,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 diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index c2ffcd40d..24bc43a02 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp @@ -66,6 +66,16 @@ bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const { return FileUtil::Delete(GetMountPoint() + path.AsString()); } +/** + * 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 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 diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 74ce29c0d..0dbed987b 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h @@ -47,6 +47,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 diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index e273444c9..0bf31ea2f 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp @@ -355,6 +355,30 @@ Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) { return -1; } +/** + * 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 + */ +Result 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(src_archive_handle); + Archive* dest_archive = Kernel::g_object_pool.GetFast(dest_archive_handle); + if (src_archive == nullptr || dest_archive == nullptr) + return -1; + if (src_archive == dest_archive) { + if (src_archive->backend->RenameFile(src_path, dest_path)) + return 0; + } else { + // TODO: Implement renaming across archives + return -1; + } + return -1; +} + /** * Delete a Directory from an Archive * @param archive_handle Handle to an open Archive object diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h index 6fc4f0f25..5158fbae8 100644 --- a/src/core/hle/kernel/archive.h +++ b/src/core/hle/kernel/archive.h @@ -52,6 +52,17 @@ ResultVal OpenFileFromArchive(Handle archive_handle, const FileSys::Path */ Result 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 + */ +Result 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 * @param archive_handle Handle to an open Archive object diff --git a/src/core/hle/service/fs_user.cpp b/src/core/hle/service/fs_user.cpp index 435be5b5d..e9756e2eb 100644 --- a/src/core/hle/service/fs_user.cpp +++ b/src/core/hle/service/fs_user.cpp @@ -164,6 +164,48 @@ void DeleteFile(Service::Interface* self) { 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(cmd_buff[3]); + auto src_filename_type = static_cast(cmd_buff[4]); + u32 src_filename_size = cmd_buff[5]; + Handle dest_archive_handle = static_cast(cmd_buff[7]); + auto dest_filename_type = static_cast(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); + + DEBUG_LOG(KERNEL, "called"); +} + /* * FS_User::DeleteDirectory service function * Inputs: @@ -314,7 +356,7 @@ 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"}, From e5ff01c2cde0fe903140f0215461a68d4f489132 Mon Sep 17 00:00:00 2001 From: archshift Date: Mon, 24 Nov 2014 01:12:58 -0800 Subject: [PATCH 02/27] Implemented RenameDirectory in FS:USER --- src/core/file_sys/archive.h | 8 ++++++ src/core/file_sys/archive_romfs.cpp | 11 ++++++++ src/core/file_sys/archive_romfs.h | 8 ++++++ src/core/file_sys/archive_sdmc.cpp | 10 +++++++ src/core/file_sys/archive_sdmc.h | 8 ++++++ src/core/hle/kernel/archive.cpp | 24 ++++++++++++++++ src/core/hle/kernel/archive.h | 11 ++++++++ src/core/hle/service/fs_user.cpp | 44 ++++++++++++++++++++++++++++- 8 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h index 703742a1f..5ea75361e 100644 --- a/src/core/file_sys/archive.h +++ b/src/core/file_sys/archive.h @@ -213,6 +213,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 diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index 5594c5910..d0ca7d380 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp @@ -74,6 +74,17 @@ bool Archive_RomFS::CreateDirectory(const Path& path) const { return false; } +/** + * 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 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 d14372a01..222bdc356 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h @@ -65,6 +65,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 diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 24bc43a02..c8958a0eb 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp @@ -94,6 +94,16 @@ bool Archive_SDMC::CreateDirectory(const Path& path) const { return FileUtil::CreateDir(GetMountPoint() + path.AsString()); } +/** + * 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 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 diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 0dbed987b..19f563a62 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h @@ -69,6 +69,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 diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index 0bf31ea2f..bffe59952 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp @@ -409,6 +409,30 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa return -1; } +/** + * 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 + */ +Result 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(src_archive_handle); + Archive* dest_archive = Kernel::g_object_pool.GetFast(dest_archive_handle); + if (src_archive == nullptr || dest_archive == nullptr) + return -1; + if (src_archive == dest_archive) { + if (src_archive->backend->RenameDirectory(src_path, dest_path)) + return 0; + } else { + // TODO: Implement renaming across archives + return -1; + } + return -1; +} + /** * Open a Directory from an Archive * @param archive_handle Handle to an open Archive object diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h index 5158fbae8..9d071d315 100644 --- a/src/core/hle/kernel/archive.h +++ b/src/core/hle/kernel/archive.h @@ -79,6 +79,17 @@ Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa */ Result 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 + */ +Result 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 * @param archive_handle Handle to an open Archive object diff --git a/src/core/hle/service/fs_user.cpp b/src/core/hle/service/fs_user.cpp index e9756e2eb..f4b1a879c 100644 --- a/src/core/hle/service/fs_user.cpp +++ b/src/core/hle/service/fs_user.cpp @@ -267,6 +267,48 @@ static void CreateDirectory(Service::Interface* self) { 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(cmd_buff[3]); + auto src_dirname_type = static_cast(cmd_buff[4]); + u32 src_dirname_size = cmd_buff[5]; + Handle dest_archive_handle = static_cast(cmd_buff[7]); + auto dest_dirname_type = static_cast(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); + + DEBUG_LOG(KERNEL, "called"); +} + static void OpenDirectory(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); @@ -361,7 +403,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x08070142, nullptr, "DeleteDirectoryRecursively"}, {0x08080202, nullptr, "CreateFile"}, {0x08090182, CreateDirectory, "CreateDirectory"}, - {0x080A0244, nullptr, "RenameDirectory"}, + {0x080A0244, RenameDirectory, "RenameDirectory"}, {0x080B0102, OpenDirectory, "OpenDirectory"}, {0x080C00C2, OpenArchive, "OpenArchive"}, {0x080D0144, nullptr, "ControlArchive"}, From 43a682a10615597befa8584767a8af0b6614c82e Mon Sep 17 00:00:00 2001 From: archshift Date: Sun, 23 Nov 2014 00:22:46 -0800 Subject: [PATCH 03/27] Log the cmd_buff arguments when citra comes across an unimplemented function --- src/core/hle/service/service.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 20e7fb4d3..3a7d6c469 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -10,6 +10,7 @@ #include #include "common/common.h" +#include "common/string_util.h" #include "core/mem_map.h" #include "core/hle/kernel/kernel.h" @@ -79,21 +80,20 @@ public: u32* cmd_buff = GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); - if (itr == m_functions.end()) { - ERROR_LOG(OSHLE, "unknown/unimplemented function: port=%s, command=0x%08X", - GetPortName().c_str(), cmd_buff[0]); + if (itr == m_functions.end() || itr->second.func == nullptr) { + // Number of params == bits 0-5 + bits 6-11 + int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); + + std::string error = "unknown/unimplemented function '%s': port=%s"; + for (int i = 1; i <= num_params; ++i) { + error += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]); + } + + std::string name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; + + ERROR_LOG(OSHLE, error.c_str(), name.c_str(), GetPortName().c_str()); // TODO(bunnei): Hack - ignore error - u32* cmd_buff = Service::GetCommandBuffer(); - cmd_buff[1] = 0; - return MakeResult(false); - } - if (itr->second.func == nullptr) { - ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s", - GetPortName().c_str(), itr->second.name.c_str()); - - // TODO(bunnei): Hack - ignore error - u32* cmd_buff = Service::GetCommandBuffer(); cmd_buff[1] = 0; return MakeResult(false); } From 4cdaac44d300531eaffa29cb826183aaf905ee6f Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 23 Nov 2014 11:06:54 -0500 Subject: [PATCH 04/27] PTM_U: Implemented the GetShellState function. --- src/core/hle/service/ptm_u.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index d9122dbbc..1ce32ee4a 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp @@ -11,13 +11,30 @@ namespace PTM_U { +static bool shell_open = true; + +/* + * 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"); +} + const Interface::FunctionInfo FunctionTable[] = { {0x00010002, nullptr, "RegisterAlarmClient"}, {0x00020080, nullptr, "SetRtcAlarm"}, {0x00030000, nullptr, "GetRtcAlarm"}, {0x00040000, nullptr, "CancelRtcAlarm"}, {0x00050000, nullptr, "GetAdapterState"}, - {0x00060000, nullptr, "GetShellState"}, + {0x00060000, GetShellState, "GetShellState"}, {0x00070000, nullptr, "GetBatteryLevel"}, {0x00080000, nullptr, "GetBatteryChargeState"}, {0x00090000, nullptr, "GetPedometerState"}, From f9b53c3e943c06e982e0abbd2f87245d63c17776 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Sun, 30 Nov 2014 01:44:30 -0600 Subject: [PATCH 05/27] Silence a few -Wsign-compare warnings. --- src/video_core/command_processor.cpp | 2 +- src/video_core/debug_utils/debug_utils.cpp | 8 ++++---- src/video_core/renderer_opengl/renderer_opengl.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) 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(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 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/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index abbb4c2cb..2469d0b01 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. From 8712c9dcd6df69866248328ab37c1e1b986d94bd Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 1 Dec 2014 18:48:27 -0500 Subject: [PATCH 06/27] CMake: Place all the built files in BUILD_DIR/bin/ when compiling with MSVC --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) 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) From 32d420330d6dae46f673a2da49f7add9c3f6fcba Mon Sep 17 00:00:00 2001 From: purpasmart96 Date: Fri, 28 Nov 2014 17:17:55 -0800 Subject: [PATCH 07/27] AC_U: Added a stub for GetWifiStatus --- src/core/hle/service/ac_u.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) 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"}, From e3886adc2246c1f9da65deb4ae5ec6360788c77f Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 3 Dec 2014 01:13:29 -0500 Subject: [PATCH 08/27] MemMap: Updated memory map to subtract base address instead of mask. - More readable, a little less error prone. Conflicts: src/core/mem_map.h src/core/mem_map_funcs.cpp --- src/core/mem_map.h | 10 --------- src/core/mem_map_funcs.cpp | 42 +++++++++++++++++++------------------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/core/mem_map.h b/src/core/mem_map.h index a58c59244..2e2c0bdf7 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h @@ -27,47 +27,39 @@ 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), 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 +72,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 e8747840c..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,7 +89,7 @@ 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%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"); @@ -148,31 +148,31 @@ inline void Write(const VAddr vaddr, const T data) { 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); From 8a624239703c046d89ebeaf3ea13c87af75b550f Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Wed, 3 Dec 2014 12:57:57 -0600 Subject: [PATCH 09/27] Change NULLs to nullptrs. --- src/citra/emu_window/emu_window_glfw.cpp | 6 ++--- src/citra_qt/bootmanager.cpp | 2 +- src/citra_qt/hotkeys.cpp | 4 ++-- src/citra_qt/main.cpp | 8 +++---- src/common/chunk_file.h | 24 +++++++++---------- src/common/common_funcs.h | 2 +- src/common/console_listener.cpp | 10 ++++---- src/common/extended_trace.cpp | 24 +++++++++---------- src/common/fifo_queue.h | 4 ++-- src/common/file_util.cpp | 24 +++++++++---------- src/common/file_util.h | 4 ++-- src/common/linear_disk_cache.h | 2 +- src/common/log_manager.cpp | 4 ++-- src/common/mem_arena.cpp | 20 ++++++++-------- src/common/memory_util.cpp | 10 ++++---- src/common/misc.cpp | 4 ++-- src/common/platform.h | 2 +- src/common/string_util.cpp | 8 +++---- src/common/thread_queue_list.h | 12 +++++----- src/common/timer.cpp | 6 ++--- src/common/utf8.cpp | 24 +++++++++---------- src/core/core_timing.cpp | 12 +++++----- .../renderer_opengl/gl_shader_util.cpp | 10 ++++---- src/video_core/video_core.cpp | 4 ++-- 24 files changed, 115 insertions(+), 115 deletions(-) diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp index 697bf4693..982619126 100644 --- a/src/citra/emu_window/emu_window_glfw.cpp +++ b/src/citra/emu_window/emu_window_glfw.cpp @@ -76,9 +76,9 @@ 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) { + if (m_render_window == nullptr) { ERROR_LOG(GUI, "Failed to create GLFW window! Exiting..."); exit(1); } @@ -123,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/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..430a4ece4 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; } @@ -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 void Do(std::vector &x) { - T *dv = NULL; + T *dv = nullptr; DoVector(x, dv); } @@ -369,7 +369,7 @@ public: template void Do(std::deque &x) { - T *dv = NULL; + T *dv = nullptr; DoDeque(x, dv); } @@ -395,7 +395,7 @@ public: template void Do(std::list &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* 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& 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(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 2ef7d98c0..39b1924c7 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp @@ -21,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() { @@ -141,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/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(first, (Event **)NULL); + p.DoLinkedList(first, (Event **)nullptr); p.DoLinkedList(tsFirst, &tsLast); p.Do(g_clock_rate_arm11); 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 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 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 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/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 From 16fc98af644ba6a5a56b9aa804ed1bec5e064a8e Mon Sep 17 00:00:00 2001 From: purpasmart96 Date: Fri, 28 Nov 2014 16:56:44 -0800 Subject: [PATCH 10/27] PTM_U: Added a stub for GetBatteryLevel & GetBatteryChargeState & GetAdapterState --- src/core/hle/service/ptm_u.cpp | 75 ++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index 1ce32ee4a..941df467b 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp @@ -11,8 +11,40 @@ 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: @@ -28,15 +60,52 @@ static void GetShellState(Service::Interface* self) { 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(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"}, + {0x00050000, GetAdapterState, "GetAdapterState"}, {0x00060000, GetShellState, "GetShellState"}, - {0x00070000, nullptr, "GetBatteryLevel"}, - {0x00080000, nullptr, "GetBatteryChargeState"}, + {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, + {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, {0x00090000, nullptr, "GetPedometerState"}, {0x000A0042, nullptr, "GetStepHistoryEntry"}, {0x000B00C2, nullptr, "GetStepHistory"}, From 7ff8f0d916ae020ed736122a91d91f190afcc95c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 3 Dec 2014 19:33:54 -0500 Subject: [PATCH 11/27] hid_user: Pass by reference with PadButtonPress/PadButtonRelease --- src/core/hle/service/hid_user.cpp | 4 ++-- src/core/hle/service/hid_user.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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(); /** From 9b68d5e07416882526b1d4d444a53f684274ca70 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 3 Dec 2014 19:48:34 -0500 Subject: [PATCH 12/27] kernel: Make some functions const --- src/core/hle/kernel/kernel.cpp | 4 ++-- src/core/hle/kernel/kernel.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 018000abd..2954f9913 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -37,7 +37,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,7 +75,7 @@ void ObjectPool::List() { } } -int ObjectPool::GetCount() { +int ObjectPool::GetCount() const { int count = 0; for (int i = 0; i < MAX_COUNT; i++) { if (occupied[i]) 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 T* Get(Handle handle) { @@ -142,7 +142,7 @@ public: Object* &operator [](Handle handle); void List(); void Clear(); - int GetCount(); + int GetCount() const; private: From 208598dbe28a7b403660e97f8841d5f5f68c7dd2 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 3 Dec 2014 19:55:45 -0500 Subject: [PATCH 13/27] kernel: Shorten GetCount --- src/core/hle/kernel/kernel.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 2954f9913..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 + #include "common/common.h" #include "core/core.h" @@ -76,12 +78,7 @@ void ObjectPool::List() { } int ObjectPool::GetCount() const { - int count = 0; - for (int i = 0; i < MAX_COUNT; i++) { - if (occupied[i]) - count++; - } - return count; + return std::count(occupied.begin(), occupied.end(), true); } Object* ObjectPool::CreateByIDType(int type) { From a404ad527282e37fcd368d29c3b47abe0d3edba1 Mon Sep 17 00:00:00 2001 From: archshift Date: Mon, 1 Dec 2014 00:31:37 -0800 Subject: [PATCH 14/27] Add stub for ConvertProcessFromDspDram Should theoretically push retail stuff further along --- src/core/hle/service/dsp_dsp.cpp | 69 ++++++++++++++++++++------------ src/core/mem_map.h | 4 +- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index a2b68cac8..72be4c817 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -15,6 +15,25 @@ 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: @@ -90,31 +109,31 @@ void WriteReg0x10(Service::Interface* self) { } const Interface::FunctionInfo FunctionTable[] = { - {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, nullptr, "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"}, + {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"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/mem_map.h b/src/core/mem_map.h index a58c59244..da440325f 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h @@ -19,7 +19,6 @@ typedef u32 PAddr; ///< Represents a pointer in the physical address space. enum { 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 @@ -34,6 +33,9 @@ enum { 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), From 3ba32d2b53683c8259c3583ce7c63c077f6c0da1 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 3 Dec 2014 23:34:22 -0500 Subject: [PATCH 15/27] mem_map: Make enum for addresses use u32 as the underlying type --- src/core/mem_map.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/mem_map.h b/src/core/mem_map.h index a58c59244..637cde311 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h @@ -16,7 +16,7 @@ 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 From 029ff9f1fd013ec46f3d61510c5f95f05bca698e Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 3 Dec 2014 23:22:06 -0500 Subject: [PATCH 16/27] SVC: Implemented GetThreadId. For now threads are using their Handle value as their Id, it should not really cause any problems because Handle values are unique in Citra, but it should be changed. I left a ToDo there because this is not correct behavior as per hardware. --- src/core/hle/kernel/thread.cpp | 16 ++++++++++++++++ src/core/hle/kernel/thread.h | 3 +++ src/core/hle/svc.cpp | 9 +++++---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index f59795901..6da238828 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; @@ -325,6 +327,9 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio thread_queue.push_back(handle); thread_ready_queue.prepare(priority); + // TODO(Subv): Assign valid ids to each thread, they are much lower than handle values + // they appear to begin at 276 and continue from there + thread->thread_id = handle; thread->status = THREADSTATUS_DORMANT; thread->entry_point = entry_point; thread->stack_top = stack_top; @@ -465,6 +470,17 @@ void Reschedule() { } } +ResultCode GetThreadId(u32* thread_id, Handle handle) { + Thread* thread = g_object_pool.Get(handle); + if (thread == nullptr) + return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent); + + *thread_id = thread->thread_id; + + return RESULT_SUCCESS; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// void ThreadingInit() { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index ce63a70d3..e87867ac0 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -58,6 +58,9 @@ void Reschedule(); /// Stops the current thread ResultCode StopThread(Handle thread, const char* reason); +// Retrieves the thread id of the specified thread handle +ResultCode GetThreadId(u32* thread_id, Handle handle); + /// Resumes a thread from waiting by marking it as "ready" void ResumeThreadFromWait(Handle handle); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 43a3cbe03..a5805ed05 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -281,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 From 43f7f37d93365dee709c1f54286d9f21ca546eab Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Thu, 4 Dec 2014 04:47:52 -0200 Subject: [PATCH 17/27] Resolve doxycomment duplication debate I believe putting comments in the headers has won by a good margin, with everyone other than me preferring it, so time to enshrine it. --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) 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 { From 139a4d91d9e8482d8ceeef591b08ab20b0f7e8ee Mon Sep 17 00:00:00 2001 From: archshift Date: Mon, 24 Nov 2014 15:45:20 -0800 Subject: [PATCH 18/27] Updated archive.cpp functions for proper error handling --- src/core/file_sys/archive_romfs.cpp | 12 ---- src/core/file_sys/archive_sdmc.cpp | 12 ---- src/core/hle/kernel/archive.cpp | 87 ++++++++++------------------- src/core/hle/kernel/archive.h | 14 ++--- src/core/hle/service/fs_user.cpp | 10 ++-- 5 files changed, 41 insertions(+), 94 deletions(-) diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index d0ca7d380..8c2dbeda5 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp @@ -43,12 +43,6 @@ bool Archive_RomFS::DeleteFile(const FileSys::Path& path) const { return false; } -/** - * 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 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; @@ -74,12 +68,6 @@ bool Archive_RomFS::CreateDirectory(const Path& path) const { return false; } -/** - * 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 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; diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index c8958a0eb..a740a3d59 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp @@ -66,12 +66,6 @@ bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const { return FileUtil::Delete(GetMountPoint() + path.AsString()); } -/** - * 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 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()); } @@ -94,12 +88,6 @@ bool Archive_SDMC::CreateDirectory(const Path& path) const { return FileUtil::CreateDir(GetMountPoint() + path.AsString()); } -/** - * 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 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()); } diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index bffe59952..647f0dea9 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp @@ -340,97 +340,68 @@ ResultVal OpenFileFromArchive(Handle archive_handle, const FileSys::Path return MakeResult(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_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); } -/** - * 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 - */ -Result RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, - Handle dest_archive_handle, const FileSys::Path& dest_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(src_archive_handle); Archive* dest_archive = Kernel::g_object_pool.GetFast(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) - return -1; + return InvalidHandle(ErrorModule::FS); if (src_archive == dest_archive) { if (src_archive->backend->RenameFile(src_path, dest_path)) - return 0; + return RESULT_SUCCESS; } else { // TODO: Implement renaming across archives - return -1; + return UnimplementedFunction(ErrorModule::FS); } - return -1; + return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description + ErrorSummary::NothingHappened, 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 DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { Archive* archive = Kernel::g_object_pool.GetFast(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_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); } -/** - * 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 - */ -Result RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, - Handle dest_archive_handle, const FileSys::Path& dest_path) { +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(src_archive_handle); Archive* dest_archive = Kernel::g_object_pool.GetFast(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) - return -1; + return InvalidHandle(ErrorModule::FS); if (src_archive == dest_archive) { if (src_archive->backend->RenameDirectory(src_path, dest_path)) - return 0; + return RESULT_SUCCESS; } else { // TODO: Implement renaming across archives - return -1; + return UnimplementedFunction(ErrorModule::FS); } - return -1; + return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description + ErrorSummary::NothingHappened, ErrorLevel::Status); } /** diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h index 9d071d315..b50833a2b 100644 --- a/src/core/hle/kernel/archive.h +++ b/src/core/hle/kernel/archive.h @@ -50,7 +50,7 @@ ResultVal 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 @@ -60,8 +60,8 @@ Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path); * @param dest_path Path to the File inside of the destination Archive * @return Whether rename succeeded */ -Result RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, - Handle dest_archive_handle, const FileSys::Path& dest_path); +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 @@ -69,7 +69,7 @@ Result RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::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 @@ -77,7 +77,7 @@ 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 @@ -87,8 +87,8 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa * @param dest_path Path to the Directory inside of the destination Archive * @return Whether rename succeeded */ -Result RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, - Handle dest_archive_handle, const FileSys::Path& dest_path); +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/service/fs_user.cpp b/src/core/hle/service/fs_user.cpp index f4b1a879c..95663b905 100644 --- a/src/core/hle/service/fs_user.cpp +++ b/src/core/hle/service/fs_user.cpp @@ -159,7 +159,7 @@ 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"); } @@ -201,7 +201,7 @@ void RenameFile(Service::Interface* self) { 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); + cmd_buff[1] = Kernel::RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; DEBUG_LOG(KERNEL, "called"); } @@ -232,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"); } @@ -262,7 +262,7 @@ 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"); } @@ -304,7 +304,7 @@ void RenameDirectory(Service::Interface* self) { 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); + cmd_buff[1] = Kernel::RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; DEBUG_LOG(KERNEL, "called"); } From ef1d5cda06deac153582766fa9fc4074cb91f3d5 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 4 Dec 2014 08:13:53 -0500 Subject: [PATCH 19/27] Threads: Implemented a sequential thread id --- src/core/hle/kernel/thread.cpp | 16 +++++++++++++--- src/core/hle/kernel/thread.h | 7 ++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 6da238828..ccb927381 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -78,6 +78,17 @@ static Common::ThreadQueueList 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 next available thread id and increments it + * @return Next available thread id + */ +static u32 NextThreadId() { + return next_thread_id++; +} + /// Gets the current thread inline Thread* GetCurrentThread() { return current_thread; @@ -327,9 +338,7 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio thread_queue.push_back(handle); thread_ready_queue.prepare(priority); - // TODO(Subv): Assign valid ids to each thread, they are much lower than handle values - // they appear to begin at 276 and continue from there - thread->thread_id = handle; + thread->thread_id = NextThreadId(); thread->status = THREADSTATUS_DORMANT; thread->entry_point = entry_point; thread->stack_top = stack_top; @@ -484,6 +493,7 @@ ResultCode GetThreadId(u32* thread_id, Handle handle) { //////////////////////////////////////////////////////////////////////////////////////////////////// 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 e87867ac0..53a19d779 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -58,7 +58,12 @@ void Reschedule(); /// Stops the current thread ResultCode StopThread(Handle thread, const char* reason); -// Retrieves the thread id of the specified thread handle +/** + * 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" From 6fac2bf0ab5fa51c6b2228d6fa64752793f38965 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 4 Dec 2014 14:59:56 -0500 Subject: [PATCH 20/27] Threads: Remove a redundant function. Use the next_thread_id variable directly. --- src/core/hle/kernel/thread.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index ccb927381..8d65dc84d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -81,14 +81,6 @@ 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 next available thread id and increments it - * @return Next available thread id - */ -static u32 NextThreadId() { - return next_thread_id++; -} - /// Gets the current thread inline Thread* GetCurrentThread() { return current_thread; @@ -338,7 +330,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 = NextThreadId(); + thread->thread_id = next_thread_id++; thread->status = THREADSTATUS_DORMANT; thread->entry_point = entry_point; thread->stack_top = stack_top; From 20d2ed09502f41519beb435a1300f2a57995c651 Mon Sep 17 00:00:00 2001 From: archshift Date: Sun, 7 Dec 2014 14:40:27 -0800 Subject: [PATCH 21/27] Make OpenDirectory fail if the directory doesn't exist This is in line with what the hardware itself does. It does this by splitting the initial directory opening into Directory.Open(), which will return false if a stat fails. Then, Archive::OpenDirectory will return nullptr, and archive.cpp will return an error code . --- src/core/file_sys/archive_sdmc.cpp | 2 ++ src/core/file_sys/directory.h | 6 ++++++ src/core/file_sys/directory_romfs.cpp | 4 ++++ src/core/file_sys/directory_romfs.h | 6 ++++++ src/core/file_sys/directory_sdmc.cpp | 13 ++++++++++--- src/core/file_sys/directory_sdmc.h | 7 +++++++ src/core/hle/kernel/archive.cpp | 5 +++++ 7 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 169ab0f1c..fc0b9b72d 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp @@ -100,6 +100,8 @@ bool Archive_SDMC::RenameDirectory(const FileSys::Path& src_path, const FileSys: std::unique_ptr 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); } 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 @@ -41,6 +41,12 @@ public: Directory() { } 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 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 @@ -19,6 +19,12 @@ public: Directory_RomFS(); ~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 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 @@ -22,6 +22,12 @@ public: Directory_SDMC(const Archive_SDMC* archive, const Path& path); ~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 @@ -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/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index 647f0dea9..a875fa7ff 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp @@ -421,6 +421,11 @@ ResultVal 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); } From b4256431aa148148182a00af205dc137b9833e41 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Dec 2014 23:47:26 -0500 Subject: [PATCH 22/27] armemu: Fix parenthesis warnings regarding bitwise ops --- src/core/arm/interpreter/armemu.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index 73223874e..cb7c27030 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] = ((a2 - b1) & 0xFFFF) | (((a2 + b1) & 0xFFFF) << 0x10); return 1; } else printf ("Unhandled v6 insn: sadd/ssub\n"); From 62fd564854b31f7e3203db3fb6f113231c30a3b7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 8 Dec 2014 01:44:37 -0500 Subject: [PATCH 23/27] armemu: Fix SASX --- src/core/arm/interpreter/armemu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index cb7c27030..d327252dc 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -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"); From 1aa969741dabecd3516ca79b2e7d3106cf9d3d9a Mon Sep 17 00:00:00 2001 From: ichfly Date: Sun, 7 Dec 2014 21:47:06 +0100 Subject: [PATCH 24/27] Loader: Add 3DSX support --- src/citra_qt/main.cpp | 2 +- src/core/CMakeLists.txt | 2 + src/core/loader/3dsx.cpp | 236 +++++++++++++++++++++++++++++++++++++ src/core/loader/3dsx.h | 32 +++++ src/core/loader/loader.cpp | 7 ++ src/core/loader/loader.h | 1 + 6 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 src/core/loader/3dsx.cpp create mode 100644 src/core/loader/3dsx.h diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 430a4ece4..0701decef 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -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()); } 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/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 +#include + +#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 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 #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 From 905e3b616a70abfc2a68b519bc05a6b0f38151af Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 8 Dec 2014 15:47:20 -0500 Subject: [PATCH 25/27] armemu: Fix SSAX --- src/core/arm/interpreter/armemu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index d327252dc..d717bd2c8 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -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 From 1d1078fd8b49bd501e11676d0bdb73d3bb515efc Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 8 Dec 2014 17:45:17 -0500 Subject: [PATCH 26/27] Kernel/File: Fixed file read/write hwtests The 3DS allows the user to read from files opened with the Write access modifier, even if he did not specify the Read access modifier. Open the files in binary mode so that we can prevent CR/LF problems in Windows, where a line-end is replaced by these two bytes instead of just 0xA, this was causing problems with the GetSize test --- src/core/file_sys/file_sdmc.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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; From dd203f7068dd3aaf95ff9426629e14b4a86e06d2 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 3 Dec 2014 00:46:34 -0500 Subject: [PATCH 27/27] Thread: Fixed to wait on address when in arbitration. --- src/core/hle/kernel/address_arbiter.cpp | 2 +- src/core/hle/kernel/thread.cpp | 29 ++++++++++++++++--------- src/core/hle/kernel/thread.h | 11 ++++++++++ 3 files changed, 31 insertions(+), 11 deletions(-) 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/thread.cpp b/src/core/hle/kernel/thread.cpp index 8d65dc84d..1e879b45a 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -63,6 +63,7 @@ public: WaitType wait_type; Handle wait_handle; + VAddr wait_address; std::vector waiting_threads; @@ -126,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 @@ -146,11 +148,17 @@ 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) && (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 ResultCode StopThread(Handle handle, const char* reason) { Thread* thread = g_object_pool.Get(handle); @@ -169,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; } @@ -197,12 +206,12 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { for (Handle handle : thread_queue) { Thread* thread = g_object_pool.Get(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; @@ -222,8 +231,7 @@ void ArbitrateAllThreads(u32 arbiter, u32 address) { for (Handle handle : thread_queue) { Thread* thread = g_object_pool.Get(handle); - // TODO(bunnei): Verify arbiter address... - if (VerifyWait(thread, WAITTYPE_ARB, arbiter)) + if (VerifyWait(thread, WAITTYPE_ARB, arbiter, address)) ResumeThreadFromWait(handle); } } @@ -277,11 +285,6 @@ Thread* NextThread() { return Kernel::g_object_pool.Get(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; @@ -289,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(handle); @@ -339,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; diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 53a19d779..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" @@ -85,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();