aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--CONTRIBUTING.md1
-rw-r--r--src/citra/emu_window/emu_window_glfw.cpp6
-rw-r--r--src/citra_qt/bootmanager.cpp2
-rw-r--r--src/citra_qt/hotkeys.cpp4
-rw-r--r--src/citra_qt/main.cpp10
-rw-r--r--src/common/chunk_file.h24
-rw-r--r--src/common/common_funcs.h2
-rw-r--r--src/common/console_listener.cpp10
-rw-r--r--src/common/extended_trace.cpp24
-rw-r--r--src/common/fifo_queue.h4
-rw-r--r--src/common/file_util.cpp24
-rw-r--r--src/common/file_util.h4
-rw-r--r--src/common/linear_disk_cache.h2
-rw-r--r--src/common/log_manager.cpp4
-rw-r--r--src/common/mem_arena.cpp20
-rw-r--r--src/common/memory_util.cpp10
-rw-r--r--src/common/misc.cpp4
-rw-r--r--src/common/platform.h2
-rw-r--r--src/common/string_util.cpp8
-rw-r--r--src/common/thread_queue_list.h12
-rw-r--r--src/common/timer.cpp6
-rw-r--r--src/common/utf8.cpp24
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/interpreter/armemu.cpp8
-rw-r--r--src/core/core_timing.cpp12
-rw-r--r--src/core/file_sys/archive.h16
-rw-r--r--src/core/file_sys/archive_romfs.cpp10
-rw-r--r--src/core/file_sys/archive_romfs.h16
-rw-r--r--src/core/file_sys/archive_sdmc.cpp10
-rw-r--r--src/core/file_sys/archive_sdmc.h16
-rw-r--r--src/core/file_sys/directory.h6
-rw-r--r--src/core/file_sys/directory_romfs.cpp4
-rw-r--r--src/core/file_sys/directory_romfs.h6
-rw-r--r--src/core/file_sys/directory_sdmc.cpp13
-rw-r--r--src/core/file_sys/directory_sdmc.h7
-rw-r--r--src/core/file_sys/file_sdmc.cpp9
-rw-r--r--src/core/hle/kernel/archive.cpp84
-rw-r--r--src/core/hle/kernel/archive.h28
-rw-r--r--src/core/hle/kernel/kernel.cpp13
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/thread.cpp18
-rw-r--r--src/core/hle/kernel/thread.h8
-rw-r--r--src/core/hle/service/ac_u.cpp20
-rw-r--r--src/core/hle/service/dsp_dsp.cpp69
-rw-r--r--src/core/hle/service/fs_user.cpp94
-rw-r--r--src/core/hle/service/hid_user.cpp4
-rw-r--r--src/core/hle/service/hid_user.h4
-rw-r--r--src/core/hle/service/ptm_u.cpp94
-rw-r--r--src/core/hle/svc.cpp9
-rw-r--r--src/core/loader/3dsx.cpp236
-rw-r--r--src/core/loader/3dsx.h32
-rw-r--r--src/core/loader/loader.cpp7
-rw-r--r--src/core/loader/loader.h1
-rw-r--r--src/core/mem_map.h6
-rw-r--r--src/video_core/command_processor.cpp2
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp10
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp2
-rw-r--r--src/video_core/video_core.cpp4
60 files changed, 881 insertions, 220 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bbe9f76c..05a56040 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,6 +9,8 @@ if (NOT MSVC)
else()
# Silence deprecation warnings
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
+ # set up output paths for executable binaries (.exe-files, and .dll-files on DLL-capable platforms)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
add_definitions(-DSINGLETHREADED)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 82b66be7..c8c8e388 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -27,6 +27,7 @@ Follow the indentation/whitespace style shown below. Do not use tabs, use 4-spac
### Comments
* For regular comments, use C++ style (`//`) comments, even for multi-line ones.
* For doc-comments (Doxygen comments), use `/// ` if it's a single line, else use the `/**` `*/` style featured in the example. Start the text on the second line, not the first containing `/**`.
+* For items that are both defined and declared in two separate files, put the doc-comment only next to the associated declaration. (In a header file, usually.) Otherwise, put it next to the implementation. Never duplicate doc-comments in both places.
```cpp
namespace Example {
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp
index 697bf469..98261912 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 9bf07991..9a29f974 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 bbaa4a8d..5d0b52e4 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 d5554d91..0701dece 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -131,7 +131,7 @@ GMainWindow::GMainWindow()
GMainWindow::~GMainWindow()
{
// will get automatically deleted otherwise
- if (render_window->parent() == NULL)
+ if (render_window->parent() == nullptr)
delete render_window;
}
@@ -164,7 +164,7 @@ void GMainWindow::BootGame(std::string filename)
void GMainWindow::OnMenuLoadFile()
{
- QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS executable (*.elf *.axf *.bin *.cci *.cxi)"));
+ QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS executable (*.3dsx *.elf *.axf *.bin *.cci *.cxi)"));
if (filename.size())
BootGame(filename.toLatin1().data());
}
@@ -213,14 +213,14 @@ void GMainWindow::OnOpenHotkeysDialog()
void GMainWindow::ToggleWindowMode()
{
bool enable = ui.action_Popout_Window_Mode->isChecked();
- if (enable && render_window->parent() != NULL)
+ if (enable && render_window->parent() != nullptr)
{
ui.horizontalLayout->removeWidget(render_window);
- render_window->setParent(NULL);
+ render_window->setParent(nullptr);
render_window->setVisible(true);
render_window->RestoreGeometry();
}
- else if (!enable && render_window->parent() == NULL)
+ else if (!enable && render_window->parent() == nullptr)
{
render_window->BackupGeometry();
ui.horizontalLayout->addWidget(render_window);
diff --git a/src/common/chunk_file.h b/src/common/chunk_file.h
index 60978407..32af7459 100644
--- a/src/common/chunk_file.h
+++ b/src/common/chunk_file.h
@@ -204,11 +204,11 @@ public:
{
for (auto it = x.begin(), end = x.end(); it != end; ++it)
{
- if (it->second != NULL)
+ if (it->second != nullptr)
delete it->second;
}
}
- T *dv = NULL;
+ T *dv = nullptr;
DoMap(x, dv);
}
@@ -264,11 +264,11 @@ public:
{
for (auto it = x.begin(), end = x.end(); it != end; ++it)
{
- if (it->second != NULL)
+ if (it->second != nullptr)
delete it->second;
}
}
- T *dv = NULL;
+ T *dv = nullptr;
DoMultimap(x, dv);
}
@@ -320,7 +320,7 @@ public:
template<class T>
void Do(std::vector<T *> &x)
{
- T *dv = NULL;
+ T *dv = nullptr;
DoVector(x, dv);
}
@@ -369,7 +369,7 @@ public:
template<class T>
void Do(std::deque<T *> &x)
{
- T *dv = NULL;
+ T *dv = nullptr;
DoDeque(x, dv);
}
@@ -395,7 +395,7 @@ public:
template<class T>
void Do(std::list<T *> &x)
{
- T *dv = NULL;
+ T *dv = nullptr;
Do(x, dv);
}
@@ -433,7 +433,7 @@ public:
{
for (auto it = x.begin(), end = x.end(); it != end; ++it)
{
- if (*it != NULL)
+ if (*it != nullptr)
delete *it;
}
}
@@ -518,7 +518,7 @@ public:
void DoClass(T *&x) {
if (mode == MODE_READ)
{
- if (x != NULL)
+ if (x != nullptr)
delete x;
x = new T();
}
@@ -567,7 +567,7 @@ public:
{
if (mode == MODE_READ)
{
- cur->next = 0;
+ cur->next = nullptr;
list_cur = cur;
if (prev)
prev->next = cur;
@@ -586,13 +586,13 @@ public:
if (mode == MODE_READ)
{
if (prev)
- prev->next = 0;
+ prev->next = nullptr;
if (list_end)
*list_end = prev;
if (list_cur)
{
if (list_start == list_cur)
- list_start = 0;
+ list_start = nullptr;
do
{
LinkedListItem<T>* next = list_cur->next;
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index d84ec4c4..1139dc3b 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 d7f27c35..b6042796 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 bf61ac1d..cf7c346d 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 2c18285d..b426e659 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 b6dec838..6c486050 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -140,7 +140,7 @@ bool CreateDir(const std::string &path)
{
INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
#ifdef _WIN32
- if (::CreateDirectory(Common::UTF8ToTStr(path).c_str(), NULL))
+ if (::CreateDirectory(Common::UTF8ToTStr(path).c_str(), nullptr))
return true;
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
@@ -423,7 +423,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
FSTEntry entry;
const std::string virtualName(Common::TStrToUTF8(ffd.cFileName));
#else
- struct dirent dirent, *result = NULL;
+ struct dirent dirent, *result = nullptr;
DIR *dirp = opendir(directory.c_str());
if (!dirp)
@@ -491,7 +491,7 @@ bool DeleteDirRecursively(const std::string &directory)
{
const std::string virtualName(Common::TStrToUTF8(ffd.cFileName));
#else
- struct dirent dirent, *result = NULL;
+ struct dirent dirent, *result = nullptr;
DIR *dirp = opendir(directory.c_str());
if (!dirp)
return false;
@@ -552,7 +552,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path)
if (!FileUtil::Exists(source_path)) return;
if (!FileUtil::Exists(dest_path)) FileUtil::CreateFullPath(dest_path);
- struct dirent dirent, *result = NULL;
+ struct dirent dirent, *result = nullptr;
DIR *dirp = opendir(source_path.c_str());
if (!dirp) return;
@@ -586,11 +586,11 @@ std::string GetCurrentDir()
{
char *dir;
// Get the current working directory (getcwd uses malloc)
- if (!(dir = __getcwd(NULL, 0))) {
+ if (!(dir = __getcwd(nullptr, 0))) {
ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
GetLastErrorMsg());
- return NULL;
+ return nullptr;
}
std::string strDir = dir;
free(dir);
@@ -626,7 +626,7 @@ std::string& GetExeDirectory()
if (DolphinPath.empty())
{
TCHAR Dolphin_exe_Path[2048];
- GetModuleFileName(NULL, Dolphin_exe_Path, 2048);
+ GetModuleFileName(nullptr, Dolphin_exe_Path, 2048);
DolphinPath = Common::TStrToUTF8(Dolphin_exe_Path);
DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
}
@@ -826,7 +826,7 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
}
IOFile::IOFile()
- : m_file(NULL), m_good(true)
+ : m_file(nullptr), m_good(true)
{}
IOFile::IOFile(std::FILE* file)
@@ -834,7 +834,7 @@ IOFile::IOFile(std::FILE* file)
{}
IOFile::IOFile(const std::string& filename, const char openmode[])
- : m_file(NULL), m_good(true)
+ : m_file(nullptr), m_good(true)
{
Open(filename, openmode);
}
@@ -845,7 +845,7 @@ IOFile::~IOFile()
}
IOFile::IOFile(IOFile&& other)
- : m_file(NULL), m_good(true)
+ : m_file(nullptr), m_good(true)
{
Swap(other);
}
@@ -880,14 +880,14 @@ bool IOFile::Close()
if (!IsOpen() || 0 != std::fclose(m_file))
m_good = false;
- m_file = NULL;
+ m_file = nullptr;
return m_good;
}
std::FILE* IOFile::ReleaseHandle()
{
std::FILE* const ret = m_file;
- m_file = NULL;
+ m_file = nullptr;
return ret;
}
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 72b80be8..beaf7174 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -202,11 +202,11 @@ public:
return WriteArray(reinterpret_cast<const char*>(data), length);
}
- bool IsOpen() { return NULL != m_file; }
+ bool IsOpen() { return nullptr != m_file; }
// m_good is set to false when a read, write or other function fails
bool IsGood() { return m_good; }
- operator void*() { return m_good ? m_file : NULL; }
+ operator void*() { return m_good ? m_file : nullptr; }
std::FILE* ReleaseHandle();
diff --git a/src/common/linear_disk_cache.h b/src/common/linear_disk_cache.h
index f4263f72..bb1b5174 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 2ef7d98c..39b1924c 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 67dbaf50..7d4fda0e 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 b6f66e4e..93da5500 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 cf6df44e..bc9d2618 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 d9f09543..53d98fe7 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 dcec9275..7fb7ede5 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 59efbce4..7e3b620c 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 ded4a344..4a797f75 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 be4ebc85..66a2f633 100644
--- a/src/common/utf8.cpp
+++ b/src/common/utf8.cpp
@@ -281,28 +281,28 @@ int u8_read_escape_sequence(const char *str, u32 *dest)
do {
digs[dno++] = str[i++];
} while (octal_digit(str[i]) && dno < 3);
- ch = strtol(digs, NULL, 8);
+ ch = strtol(digs, nullptr, 8);
}
else if (str[0] == 'x') {
while (hex_digit(str[i]) && dno < 2) {
digs[dno++] = str[i++];
}
if (dno > 0)
- ch = strtol(digs, NULL, 16);
+ ch = strtol(digs, nullptr, 16);
}
else if (str[0] == 'u') {
while (hex_digit(str[i]) && dno < 4) {
digs[dno++] = str[i++];
}
if (dno > 0)
- ch = strtol(digs, NULL, 16);
+ ch = strtol(digs, nullptr, 16);
}
else if (str[0] == 'U') {
while (hex_digit(str[i]) && dno < 8) {
digs[dno++] = str[i++];
}
if (dno > 0)
- ch = strtol(digs, NULL, 16);
+ ch = strtol(digs, nullptr, 16);
}
*dest = ch;
@@ -353,7 +353,7 @@ const char *u8_strchr(const char *s, u32 ch, int *charn)
lasti = i;
(*charn)++;
}
- return NULL;
+ return nullptr;
}
const char *u8_memchr(const char *s, u32 ch, size_t sz, int *charn)
@@ -378,7 +378,7 @@ const char *u8_memchr(const char *s, u32 ch, size_t sz, int *charn)
lasti = i;
(*charn)++;
}
- return NULL;
+ return nullptr;
}
int u8_is_locale_utf8(const char *locale)
@@ -419,35 +419,35 @@ bool UTF8StringHasNonASCII(const char *utf8string) {
std::string ConvertWStringToUTF8(const wchar_t *wstr) {
int len = (int)wcslen(wstr);
- int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, NULL, NULL);
+ int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, nullptr, nullptr);
std::string s;
s.resize(size);
if (size > 0) {
- WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, nullptr, nullptr);
}
return s;
}
std::string ConvertWStringToUTF8(const std::wstring &wstr) {
int len = (int)wstr.size();
- int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL);
+ int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, nullptr, nullptr);
std::string s;
s.resize(size);
if (size > 0) {
- WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, nullptr, nullptr);
}
return s;
}
void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) {
int len = (int)source.size();
- int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
+ int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0);
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size));
}
std::wstring ConvertUTF8ToWString(const std::string &source) {
int len = (int)source.size();
- int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
+ int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0);
std::wstring str;
str.resize(size);
if (size > 0) {
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 48241c3d..f3d7dca9 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -63,6 +63,7 @@ set(SRCS
loader/elf.cpp
loader/loader.cpp
loader/ncch.cpp
+ loader/3dsx.cpp
core.cpp
core_timing.cpp
mem_map.cpp
@@ -143,6 +144,7 @@ set(HEADERS
loader/elf.h
loader/loader.h
loader/ncch.h
+ loader/3dsx.h
core.h
core_timing.h
mem_map.h
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 73223874..d717bd2c 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -5724,7 +5724,7 @@ L_stm_s_takeabort:
s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
s16 b1 = (state->Reg[src2] & 0xFFFF);
s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = (a1 - a2)&0xFFFF | (((b1 - b2)&0xFFFF)<< 0x10);
+ state->Reg[tar] = ((a1 - a2) & 0xFFFF) | (((b1 - b2)&0xFFFF)<< 0x10);
return 1;
}
else if ((instr & 0xFF0) == 0xf10)//sadd16
@@ -5736,7 +5736,7 @@ L_stm_s_takeabort:
s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
s16 b1 = (state->Reg[src2] & 0xFFFF);
s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = (a1 + a2)&0xFFFF | (((b1 + b2)&0xFFFF)<< 0x10);
+ state->Reg[tar] = ((a1 + a2) & 0xFFFF) | (((b1 + b2)&0xFFFF)<< 0x10);
return 1;
}
else if ((instr & 0xFF0) == 0xf50)//ssax
@@ -5748,7 +5748,7 @@ L_stm_s_takeabort:
s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
s16 b1 = (state->Reg[src2] & 0xFFFF);
s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = (a1 - b2) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10);
+ state->Reg[tar] = ((a1 + b2) & 0xFFFF) | (((a2 - b1) & 0xFFFF) << 0x10);
return 1;
}
else if ((instr & 0xFF0) == 0xf30)//sasx
@@ -5760,7 +5760,7 @@ L_stm_s_takeabort:
s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
s16 b1 = (state->Reg[src2] & 0xFFFF);
s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
- state->Reg[tar] = (a2 - b1) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10);
+ state->Reg[tar] = ((a1 - b2) & 0xFFFF) | (((a2 + b1) & 0xFFFF) << 0x10);
return 1;
}
else printf ("Unhandled v6 insn: sadd/ssub\n");
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 558c6cbf..bf8acf41 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -67,7 +67,7 @@ s64 idledCycles;
static std::recursive_mutex externalEventSection;
// Warning: not included in save state.
-void(*advanceCallback)(int cyclesExecuted) = NULL;
+void(*advanceCallback)(int cyclesExecuted) = nullptr;
void SetClockFrequencyMHz(int cpuMhz)
{
@@ -231,7 +231,7 @@ void ClearPendingEvents()
void AddEventToQueue(Event* ne)
{
- Event* prev = NULL;
+ Event* prev = nullptr;
Event** pNext = &first;
for (;;)
{
@@ -327,7 +327,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata)
}
if (!tsFirst)
{
- tsLast = NULL;
+ tsLast = nullptr;
return result;
}
@@ -433,7 +433,7 @@ void RemoveThreadsafeEvent(int event_type)
}
if (!tsFirst)
{
- tsLast = NULL;
+ tsLast = nullptr;
return;
}
Event *prev = tsFirst;
@@ -495,7 +495,7 @@ void MoveEvents()
AddEventToQueue(tsFirst);
tsFirst = next;
}
- tsLast = NULL;
+ tsLast = nullptr;
// Move free events to threadsafe pool
while (allocatedTsEvents > 0 && eventPool)
@@ -614,7 +614,7 @@ void DoState(PointerWrap &p)
// These (should) be filled in later by the modules.
event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT"));
- p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **)NULL);
+ p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **)nullptr);
p.DoLinkedList<BaseEvent, GetNewTsEvent, FreeTsEvent, Event_DoState>(tsFirst, &tsLast);
p.Do(g_clock_rate_arm11);
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h
index c2426a15..f3cb1113 100644
--- a/src/core/file_sys/archive.h
+++ b/src/core/file_sys/archive.h
@@ -194,6 +194,14 @@ public:
virtual bool DeleteFile(const FileSys::Path& path) const = 0;
/**
+ * Rename a File specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ virtual bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0;
+
+ /**
* Delete a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be deleted
@@ -208,6 +216,14 @@ public:
virtual bool CreateDirectory(const Path& path) const = 0;
/**
+ * Rename a Directory specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ virtual bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0;
+
+ /**
* Open a directory specified by its path
* @param path Path relative to the archive
* @return Opened directory, or nullptr
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index 53dc5795..8c2dbeda 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -43,6 +43,11 @@ bool Archive_RomFS::DeleteFile(const FileSys::Path& path) const {
return false;
}
+bool Archive_RomFS::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
+ ERROR_LOG(FILESYS, "Attempted to rename a file within ROMFS.");
+ return false;
+}
+
/**
* Delete a directory specified by its path
* @param path Path relative to the archive
@@ -63,6 +68,11 @@ bool Archive_RomFS::CreateDirectory(const Path& path) const {
return false;
}
+bool Archive_RomFS::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
+ ERROR_LOG(FILESYS, "Attempted to rename a file within ROMFS.");
+ return false;
+}
+
/**
* Open a directory specified by its path
* @param path Path relative to the archive
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index 0649dde9..222bdc35 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -44,6 +44,14 @@ public:
bool DeleteFile(const FileSys::Path& path) const override;
/**
+ * Rename a File specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
+
+ /**
* Delete a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be deleted
@@ -58,6 +66,14 @@ public:
bool CreateDirectory(const Path& path) const override;
/**
+ * Rename a Directory specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
+
+ /**
* Open a directory specified by its path
* @param path Path relative to the archive
* @return Opened directory, or nullptr
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 789212b1..fc0b9b72 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -66,6 +66,10 @@ bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const {
return FileUtil::Delete(GetMountPoint() + path.AsString());
}
+bool Archive_SDMC::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
+ return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
+}
+
/**
* Delete a directory specified by its path
* @param path Path relative to the archive
@@ -84,6 +88,10 @@ bool Archive_SDMC::CreateDirectory(const Path& path) const {
return FileUtil::CreateDir(GetMountPoint() + path.AsString());
}
+bool Archive_SDMC::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
+ return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
+}
+
/**
* Open a directory specified by its path
* @param path Path relative to the archive
@@ -92,6 +100,8 @@ bool Archive_SDMC::CreateDirectory(const Path& path) const {
std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const {
DEBUG_LOG(FILESYS, "called path=%s", path.DebugStr().c_str());
Directory_SDMC* directory = new Directory_SDMC(this, path);
+ if (!directory->Open())
+ return nullptr;
return std::unique_ptr<Directory>(directory);
}
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 74ce29c0..19f563a6 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -48,6 +48,14 @@ public:
bool DeleteFile(const FileSys::Path& path) const override;
/**
+ * Rename a File specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
+
+ /**
* Delete a directory specified by its path
* @param path Path relative to the archive
* @return Whether the directory could be deleted
@@ -62,6 +70,14 @@ public:
bool CreateDirectory(const Path& path) const override;
/**
+ * Rename a Directory specified by its path
+ * @param src_path Source path relative to the archive
+ * @param dest_path Destination path relative to the archive
+ * @return Whether rename succeeded
+ */
+ bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
+
+ /**
* Open a directory specified by its path
* @param path Path relative to the archive
* @return Opened directory, or nullptr
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h
index e1043133..1bb4101d 100644
--- a/src/core/file_sys/directory.h
+++ b/src/core/file_sys/directory.h
@@ -42,6 +42,12 @@ public:
virtual ~Directory() { }
/**
+ * Open the directory
+ * @return true if the directory opened correctly
+ */
+ virtual bool Open() = 0;
+
+ /**
* List files contained in the directory
* @param count Number of entries to return at once in entries
* @param entries Buffer to read data into
diff --git a/src/core/file_sys/directory_romfs.cpp b/src/core/file_sys/directory_romfs.cpp
index 4e8f4c04..e6d57139 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 4b71c4b1..e2944099 100644
--- a/src/core/file_sys/directory_romfs.h
+++ b/src/core/file_sys/directory_romfs.h
@@ -20,6 +20,12 @@ public:
~Directory_RomFS() override;
/**
+ * Open the directory
+ * @return true if the directory opened correctly
+ */
+ bool Open() override;
+
+ /**
* List files contained in the directory
* @param count Number of entries to return at once in entries
* @param entries Buffer to read data into
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp
index 60a197ce..0f156a12 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 4520d040..4c08b0d6 100644
--- a/src/core/file_sys/directory_sdmc.h
+++ b/src/core/file_sys/directory_sdmc.h
@@ -23,6 +23,12 @@ public:
~Directory_SDMC() override;
/**
+ * Open the directory
+ * @return true if the directory opened correctly
+ */
+ bool Open() override;
+
+ /**
* List files contained in the directory
* @param count Number of entries to return at once in entries
* @param entries Buffer to read data into
@@ -37,6 +43,7 @@ public:
bool Close() const override;
private:
+ std::string path;
u32 total_entries_in_directory;
FileUtil::FSTEntry directory;
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp
index a4b90670..b01d96e3 100644
--- a/src/core/file_sys/file_sdmc.cpp
+++ b/src/core/file_sys/file_sdmc.cpp
@@ -38,12 +38,15 @@ bool File_SDMC::Open() {
}
std::string mode_string;
- if (mode.read_flag && mode.write_flag)
+ if (mode.create_flag)
mode_string = "w+";
+ else if (mode.write_flag)
+ mode_string = "r+"; // Files opened with Write access can be read from
else if (mode.read_flag)
mode_string = "r";
- else if (mode.write_flag)
- mode_string = "w";
+
+ // Open the file in binary mode, to avoid problems with CR/LF on Windows systems
+ mode_string += "b";
file = new FileUtil::IOFile(path, mode_string.c_str());
return true;
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
index e273444c..a875fa7f 100644
--- a/src/core/hle/kernel/archive.cpp
+++ b/src/core/hle/kernel/archive.cpp
@@ -340,49 +340,68 @@ ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path
return MakeResult<Handle>(handle);
}
-/**
- * Delete a File from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the File inside of the Archive
- * @return Whether deletion succeeded
- */
-Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) {
+ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) {
Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
if (archive == nullptr)
- return -1;
+ return InvalidHandle(ErrorModule::FS);
if (archive->backend->DeleteFile(path))
- return 0;
- return -1;
+ return RESULT_SUCCESS;
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::Canceled, ErrorLevel::Status);
}
-/**
- * Delete a Directory from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the Directory inside of the Archive
- * @return Whether deletion succeeded
- */
-Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
+ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
+ Handle dest_archive_handle, const FileSys::Path& dest_path) {
+ Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle);
+ Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle);
+ if (src_archive == nullptr || dest_archive == nullptr)
+ return InvalidHandle(ErrorModule::FS);
+ if (src_archive == dest_archive) {
+ if (src_archive->backend->RenameFile(src_path, dest_path))
+ return RESULT_SUCCESS;
+ } else {
+ // TODO: Implement renaming across archives
+ return UnimplementedFunction(ErrorModule::FS);
+ }
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::NothingHappened, ErrorLevel::Status);
+}
+
+ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
if (archive == nullptr)
- return -1;
+ return InvalidHandle(ErrorModule::FS);
if (archive->backend->DeleteDirectory(path))
- return 0;
- return -1;
+ return RESULT_SUCCESS;
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::Canceled, ErrorLevel::Status);
}
-/**
- * Create a Directory from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the Directory inside of the Archive
- * @return Whether creation succeeded
- */
-Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
+ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
if (archive == nullptr)
- return -1;
+ return InvalidHandle(ErrorModule::FS);
if (archive->backend->CreateDirectory(path))
- return 0;
- return -1;
+ return RESULT_SUCCESS;
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::Canceled, ErrorLevel::Status);
+}
+
+ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
+ Handle dest_archive_handle, const FileSys::Path& dest_path) {
+ Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle);
+ Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle);
+ if (src_archive == nullptr || dest_archive == nullptr)
+ return InvalidHandle(ErrorModule::FS);
+ if (src_archive == dest_archive) {
+ if (src_archive->backend->RenameDirectory(src_path, dest_path))
+ return RESULT_SUCCESS;
+ } else {
+ // TODO: Implement renaming across archives
+ return UnimplementedFunction(ErrorModule::FS);
+ }
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
+ ErrorSummary::NothingHappened, ErrorLevel::Status);
}
/**
@@ -402,6 +421,11 @@ ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys:
directory->path = path;
directory->backend = archive->backend->OpenDirectory(path);
+ if (!directory->backend) {
+ return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
+ ErrorSummary::NotFound, ErrorLevel::Permanent);
+ }
+
return MakeResult<Handle>(handle);
}
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h
index 6fc4f0f2..b50833a2 100644
--- a/src/core/hle/kernel/archive.h
+++ b/src/core/hle/kernel/archive.h
@@ -50,7 +50,18 @@ ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path
* @param path Path to the File inside of the Archive
* @return Whether deletion succeeded
*/
-Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
+ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
+
+/**
+ * Rename a File between two Archives
+ * @param src_archive_handle Handle to the source Archive object
+ * @param src_path Path to the File inside of the source Archive
+ * @param dest_archive_handle Handle to the destination Archive object
+ * @param dest_path Path to the File inside of the destination Archive
+ * @return Whether rename succeeded
+ */
+ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
+ Handle dest_archive_handle, const FileSys::Path& dest_path);
/**
* Delete a Directory from an Archive
@@ -58,7 +69,7 @@ Result DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path);
* @param path Path to the Directory inside of the Archive
* @return Whether deletion succeeded
*/
-Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
+ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
/**
* Create a Directory from an Archive
@@ -66,7 +77,18 @@ Result DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa
* @param path Path to the Directory inside of the Archive
* @return Whether creation of directory succeeded
*/
-Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
+ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
+
+/**
+ * Rename a Directory between two Archives
+ * @param src_archive_handle Handle to the source Archive object
+ * @param src_path Path to the Directory inside of the source Archive
+ * @param dest_archive_handle Handle to the destination Archive object
+ * @param dest_path Path to the Directory inside of the destination Archive
+ * @return Whether rename succeeded
+ */
+ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
+ Handle dest_archive_handle, const FileSys::Path& dest_path);
/**
* Open a Directory from an Archive
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 018000ab..80a34c2d 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
+#include <algorithm>
+
#include "common/common.h"
#include "core/core.h"
@@ -37,7 +39,7 @@ Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) {
return 0;
}
-bool ObjectPool::IsValid(Handle handle) {
+bool ObjectPool::IsValid(Handle handle) const {
int index = handle - HANDLE_OFFSET;
if (index < 0)
return false;
@@ -75,13 +77,8 @@ void ObjectPool::List() {
}
}
-int ObjectPool::GetCount() {
- int count = 0;
- for (int i = 0; i < MAX_COUNT; i++) {
- if (occupied[i])
- count++;
- }
- return count;
+int ObjectPool::GetCount() const {
+ return std::count(occupied.begin(), occupied.end(), true);
}
Object* ObjectPool::CreateByIDType(int type) {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 8d3937ce..00a2228b 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -86,7 +86,7 @@ public:
}
}
- bool IsValid(Handle handle);
+ bool IsValid(Handle handle) const;
template <class T>
T* Get(Handle handle) {
@@ -142,7 +142,7 @@ public:
Object* &operator [](Handle handle);
void List();
void Clear();
- int GetCount();
+ int GetCount() const;
private:
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f5979590..8d65dc84 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;
@@ -76,6 +78,9 @@ static Common::ThreadQueueList<Handle> thread_ready_queue;
static Handle current_thread_handle;
static Thread* current_thread;
+static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
+static u32 next_thread_id; ///< The next available thread id
+
/// Gets the current thread
inline Thread* GetCurrentThread() {
return current_thread;
@@ -325,6 +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 = next_thread_id++;
thread->status = THREADSTATUS_DORMANT;
thread->entry_point = entry_point;
thread->stack_top = stack_top;
@@ -465,9 +471,21 @@ void Reschedule() {
}
}
+ResultCode GetThreadId(u32* thread_id, Handle handle) {
+ Thread* thread = g_object_pool.Get<Thread>(handle);
+ if (thread == nullptr)
+ return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS,
+ ErrorSummary::WrongArgument, ErrorLevel::Permanent);
+
+ *thread_id = thread->thread_id;
+
+ return RESULT_SUCCESS;
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
void ThreadingInit() {
+ next_thread_id = INITIAL_THREAD_ID;
}
void ThreadingShutdown() {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index ce63a70d..53a19d77 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -58,6 +58,14 @@ void Reschedule();
/// Stops the current thread
ResultCode StopThread(Handle thread, const char* reason);
+/**
+ * Retrieves the ID of the specified thread handle
+ * @param thread_id Will contain the output thread id
+ * @param handle Handle to the thread we want
+ * @return Whether the function was successful or not
+ */
+ResultCode GetThreadId(u32* thread_id, Handle handle);
+
/// Resumes a thread from waiting by marking it as "ready"
void ResumeThreadFromWait(Handle handle);
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 9af96f6b..46aee40d 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -11,6 +11,24 @@
namespace AC_U {
+/**
+ * AC_U::GetWifiStatus service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet.
+ */
+void GetWifiStatus(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(purpasmart96): This function is only a stub,
+ // it returns a valid result without implementing full functionality.
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = 0; // Connection type set to none
+
+ WARN_LOG(KERNEL, "(STUBBED) called");
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010000, nullptr, "CreateDefaultConfig"},
{0x00040006, nullptr, "ConnectAsync"},
@@ -18,7 +36,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00080004, nullptr, "CloseAsync"},
{0x00090002, nullptr, "GetCloseResult"},
{0x000A0000, nullptr, "GetLastErrorCode"},
- {0x000D0000, nullptr, "GetWifiStatus"},
+ {0x000D0000, GetWifiStatus, "GetWifiStatus"},
{0x000E0042, nullptr, "GetCurrentAPInfo"},
{0x00100042, nullptr, "GetCurrentNZoneInfo"},
{0x00110042, nullptr, "GetNZoneApNumService"},
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index a2b68cac..72be4c81 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -16,6 +16,25 @@ static Handle semaphore_event;
static Handle interrupt_event;
/**
+ * DSP_DSP::ConvertProcessAddressFromDspDram service function
+ * Inputs:
+ * 1 : Address
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address)
+ */
+void ConvertProcessAddressFromDspDram(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ u32 addr = cmd_buff[1];
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = (addr << 1) + (Memory::DSP_MEMORY_VADDR + 0x40000);
+
+ DEBUG_LOG(KERNEL, "(STUBBED) called with address %u", addr);
+}
+
+/**
* DSP_DSP::LoadComponent service function
* Inputs:
* 1 : Size
@@ -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/hle/service/fs_user.cpp b/src/core/hle/service/fs_user.cpp
index 34af78cb..51e8b579 100644
--- a/src/core/hle/service/fs_user.cpp
+++ b/src/core/hle/service/fs_user.cpp
@@ -159,7 +159,49 @@ void DeleteFile(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
filename_type, filename_size, file_path.DebugStr().c_str());
- cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path);
+ cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path).raw;
+
+ DEBUG_LOG(KERNEL, "called");
+}
+
+/*
+ * FS_User::RenameFile service function
+ * Inputs:
+ * 2 : Source archive handle lower word
+ * 3 : Source archive handle upper word
+ * 4 : Source file path type
+ * 5 : Source file path size
+ * 6 : Dest archive handle lower word
+ * 7 : Dest archive handle upper word
+ * 8 : Dest file path type
+ * 9 : Dest file path size
+ * 11: Source file path string data
+ * 13: Dest file path string
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void RenameFile(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
+ // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
+ Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
+ auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
+ u32 src_filename_size = cmd_buff[5];
+ Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]);
+ auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
+ u32 dest_filename_size = cmd_buff[9];
+ u32 src_filename_ptr = cmd_buff[11];
+ u32 dest_filename_ptr = cmd_buff[13];
+
+ FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr);
+ FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr);
+
+ DEBUG_LOG(KERNEL, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
+ src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(),
+ dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
+
+ cmd_buff[1] = Kernel::RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw;
DEBUG_LOG(KERNEL, "called");
}
@@ -190,7 +232,7 @@ void DeleteDirectory(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
dirname_type, dirname_size, dir_path.DebugStr().c_str());
- cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path);
+ cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
DEBUG_LOG(KERNEL, "called");
}
@@ -220,11 +262,53 @@ static void CreateDirectory(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
- cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path);
+ cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path).raw;
DEBUG_LOG(KERNEL, "called");
}
+/*
+ * FS_User::RenameDirectory service function
+ * Inputs:
+ * 2 : Source archive handle lower word
+ * 3 : Source archive handle upper word
+ * 4 : Source dir path type
+ * 5 : Source dir path size
+ * 6 : Dest archive handle lower word
+ * 7 : Dest archive handle upper word
+ * 8 : Dest dir path type
+ * 9 : Dest dir path size
+ * 11: Source dir path string data
+ * 13: Dest dir path string
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void RenameDirectory(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
+ // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
+ Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
+ auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
+ u32 src_dirname_size = cmd_buff[5];
+ Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]);
+ auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
+ u32 dest_dirname_size = cmd_buff[9];
+ u32 src_dirname_ptr = cmd_buff[11];
+ u32 dest_dirname_ptr = cmd_buff[13];
+
+ FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr);
+ FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr);
+
+ DEBUG_LOG(KERNEL, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
+ src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(),
+ dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
+
+ cmd_buff[1] = Kernel::RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw;
+
+ DEBUG_LOG(KERNEL, "called");
+}
+
static void OpenDirectory(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
@@ -314,12 +398,12 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x080201C2, OpenFile, "OpenFile"},
{0x08030204, OpenFileDirectly, "OpenFileDirectly"},
{0x08040142, DeleteFile, "DeleteFile"},
- {0x08050244, nullptr, "RenameFile"},
+ {0x08050244, RenameFile, "RenameFile"},
{0x08060142, DeleteDirectory, "DeleteDirectory"},
{0x08070142, nullptr, "DeleteDirectoryRecursively"},
{0x08080202, nullptr, "CreateFile"},
{0x08090182, CreateDirectory, "CreateDirectory"},
- {0x080A0244, nullptr, "RenameDirectory"},
+ {0x080A0244, RenameDirectory, "RenameDirectory"},
{0x080B0102, OpenDirectory, "OpenDirectory"},
{0x080C00C2, OpenArchive, "OpenArchive"},
{0x080D0144, nullptr, "ControlArchive"},
diff --git a/src/core/hle/service/hid_user.cpp b/src/core/hle/service/hid_user.cpp
index d29de1a5..2abaf0f2 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 5ed97085..8f53befd 100644
--- a/src/core/hle/service/hid_user.h
+++ b/src/core/hle/service/hid_user.h
@@ -93,8 +93,8 @@ const PadState PAD_CIRCLE_UP = {{1u << 30}};
const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
// Methods for updating the HID module's state
-void PadButtonPress(PadState pad_state);
-void PadButtonRelease(PadState pad_state);
+void PadButtonPress(const PadState& pad_state);
+void PadButtonRelease(const PadState& pad_state);
void PadUpdateComplete();
/**
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp
index d9122dbb..941df467 100644
--- a/src/core/hle/service/ptm_u.cpp
+++ b/src/core/hle/service/ptm_u.cpp
@@ -11,15 +11,101 @@
namespace PTM_U {
+/// Charge levels used by PTM functions
+enum class ChargeLevels : u32 {
+ CriticalBattery = 1,
+ LowBattery = 2,
+ HalfFull = 3,
+ MostlyFull = 4,
+ CompletelyFull = 5,
+};
+
+static bool shell_open = true;
+
+static bool battery_is_charging = true;
+
+/**
+ * It is unknown if GetAdapterState is the same as GetBatteryChargeState,
+ * it is likely to just be a duplicate function of GetBatteryChargeState
+ * that controls another part of the HW.
+ * PTM_U::GetAdapterState service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Output of function, 0 = not charging, 1 = charging.
+ */
+static void GetAdapterState(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(purpasmart96): This function is only a stub,
+ // it returns a valid result without implementing full functionality.
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = battery_is_charging ? 1 : 0;
+
+ WARN_LOG(KERNEL, "(STUBBED) called");
+}
+
+/*
+ * PTM_User::GetShellState service function.
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0)
+ */
+static void GetShellState(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ cmd_buff[1] = 0;
+ cmd_buff[2] = shell_open ? 1 : 0;
+
+ DEBUG_LOG(KERNEL, "PTM_U::GetShellState called");
+}
+
+/**
+ * PTM_U::GetBatteryLevel service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Battery level, 5 = completely full battery, 4 = mostly full battery,
+ * 3 = half full battery, 2 = low battery, 1 = critical battery.
+ */
+static void GetBatteryLevel(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(purpasmart96): This function is only a stub,
+ // it returns a valid result without implementing full functionality.
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery
+
+ WARN_LOG(KERNEL, "(STUBBED) called");
+}
+
+/**
+ * PTM_U::GetBatteryChargeState service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Output of function, 0 = not charging, 1 = charging.
+ */
+static void GetBatteryChargeState(Service::Interface* self) {
+ u32* cmd_buff = Service::GetCommandBuffer();
+
+ // TODO(purpasmart96): This function is only a stub,
+ // it returns a valid result without implementing full functionality.
+
+ cmd_buff[1] = 0; // No error
+ cmd_buff[2] = battery_is_charging ? 1 : 0;
+
+ WARN_LOG(KERNEL, "(STUBBED) called");
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010002, nullptr, "RegisterAlarmClient"},
{0x00020080, nullptr, "SetRtcAlarm"},
{0x00030000, nullptr, "GetRtcAlarm"},
{0x00040000, nullptr, "CancelRtcAlarm"},
- {0x00050000, nullptr, "GetAdapterState"},
- {0x00060000, nullptr, "GetShellState"},
- {0x00070000, nullptr, "GetBatteryLevel"},
- {0x00080000, nullptr, "GetBatteryChargeState"},
+ {0x00050000, GetAdapterState, "GetAdapterState"},
+ {0x00060000, GetShellState, "GetShellState"},
+ {0x00070000, GetBatteryLevel, "GetBatteryLevel"},
+ {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"},
{0x00090000, nullptr, "GetPedometerState"},
{0x000A0042, nullptr, "GetStepHistoryEntry"},
{0x000B00C2, nullptr, "GetStepHistory"},
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 43a3cbe0..a5805ed0 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
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
new file mode 100644
index 00000000..7ef14635
--- /dev/null
+++ b/src/core/loader/3dsx.cpp
@@ -0,0 +1,236 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <vector>
+
+#include "core/file_sys/archive_romfs.h"
+#include "core/loader/elf.h"
+#include "core/loader/ncch.h"
+#include "core/hle/kernel/archive.h"
+#include "core/mem_map.h"
+
+#include "3dsx.h"
+
+
+namespace Loader {
+
+
+/**
+ * File layout:
+ * - File header
+ * - Code, rodata and data relocation table headers
+ * - Code segment
+ * - Rodata segment
+ * - Loadable (non-BSS) part of the data segment
+ * - Code relocation table
+ * - Rodata relocation table
+ * - Data relocation table
+ *
+ * Memory layout before relocations are applied:
+ * [0..codeSegSize) -> code segment
+ * [codeSegSize..rodataSegSize) -> rodata segment
+ * [rodataSegSize..dataSegSize) -> data segment
+ *
+ * Memory layout after relocations are applied: well, however the loader sets it up :)
+ * The entrypoint is always the start of the code segment.
+ * The BSS section must be cleared manually by the application.
+ */
+enum THREEDSX_Error {
+ ERROR_NONE = 0,
+ ERROR_READ = 1,
+ ERROR_FILE = 2,
+ ERROR_ALLOC = 3
+};
+static const u32 RELOCBUFSIZE = 512;
+
+// File header
+static const u32 THREEDSX_MAGIC = 0x58534433; // '3DSX'
+#pragma pack(1)
+struct THREEDSX_Header
+{
+ u32 magic;
+ u16 header_size, reloc_hdr_size;
+ u32 format_ver;
+ u32 flags;
+
+ // Sizes of the code, rodata and data segments +
+ // size of the BSS section (uninitialized latter half of the data segment)
+ u32 code_seg_size, rodata_seg_size, data_seg_size, bss_size;
+};
+
+// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
+struct THREEDSX_RelocHdr
+{
+ // # of absolute relocations (that is, fix address to post-relocation memory layout)
+ u32 cross_segment_absolute;
+ // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched)
+ u32 cross_segment_relative;
+ // more?
+
+ // Relocations are written in this order:
+ // - Absolute relocations
+ // - Relative relocations
+};
+
+// Relocation entry: from the current pointer, skip X words and patch Y words
+struct THREEDSX_Reloc
+{
+ u16 skip, patch;
+};
+#pragma pack()
+
+struct THREEloadinfo
+{
+ u8* seg_ptrs[3]; // code, rodata & data
+ u32 seg_addrs[3];
+ u32 seg_sizes[3];
+};
+
+class THREEDSXReader {
+public:
+ static int Load3DSXFile(const std::string& filename, u32 base_addr);
+};
+
+static u32 TranslateAddr(u32 addr, THREEloadinfo *loadinfo, u32* offsets)
+{
+ if (addr < offsets[0])
+ return loadinfo->seg_addrs[0] + addr;
+ if (addr < offsets[1])
+ return loadinfo->seg_addrs[1] + addr - offsets[0];
+ return loadinfo->seg_addrs[2] + addr - offsets[1];
+}
+
+int THREEDSXReader::Load3DSXFile(const std::string& filename, u32 base_addr)
+{
+ FileUtil::IOFile file(filename, "rb");
+ if (!file.IsOpen()) {
+ return ERROR_FILE;
+ }
+ THREEDSX_Header hdr;
+ if (file.ReadBytes(&hdr, sizeof(hdr)) != sizeof(hdr))
+ return ERROR_READ;
+
+ THREEloadinfo loadinfo;
+ //loadinfo segments must be a multiple of 0x1000
+ loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) &~0xFFF;
+ loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF;
+ loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF;
+ u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] };
+ u32 data_load_size = (hdr.data_seg_size - hdr.bss_size + 0xFFF) &~0xFFF;
+ u32 bss_load_size = loadinfo.seg_sizes[2] - data_load_size;
+ u32 n_reloc_tables = hdr.reloc_hdr_size / 4;
+ std::vector<u8> all_mem(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2] + 3 * n_reloc_tables);
+
+ loadinfo.seg_addrs[0] = base_addr;
+ loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0];
+ loadinfo.seg_addrs[2] = loadinfo.seg_addrs[1] + loadinfo.seg_sizes[1];
+ loadinfo.seg_ptrs[0] = &all_mem[0];
+ loadinfo.seg_ptrs[1] = loadinfo.seg_ptrs[0] + loadinfo.seg_sizes[0];
+ loadinfo.seg_ptrs[2] = loadinfo.seg_ptrs[1] + loadinfo.seg_sizes[1];
+
+ // Skip header for future compatibility
+ file.Seek(hdr.header_size, SEEK_SET);
+
+ // Read the relocation headers
+ u32* relocs = (u32*)(loadinfo.seg_ptrs[2] + hdr.data_seg_size);
+
+ for (u32 current_segment = 0; current_segment < 3; current_segment++) {
+ if (file.ReadBytes(&relocs[current_segment*n_reloc_tables], n_reloc_tables * 4) != n_reloc_tables * 4)
+ return ERROR_READ;
+ }
+
+ // Read the segments
+ if (file.ReadBytes(loadinfo.seg_ptrs[0], hdr.code_seg_size) != hdr.code_seg_size)
+ return ERROR_READ;
+ if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size)
+ return ERROR_READ;
+ if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) != hdr.data_seg_size - hdr.bss_size)
+ return ERROR_READ;
+
+ // BSS clear
+ memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size);
+
+ // Relocate the segments
+ for (u32 current_segment = 0; current_segment < 3; current_segment++) {
+ for (u32 current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) {
+ u32 n_relocs = relocs[current_segment*n_reloc_tables + current_segment_reloc_table];
+ if (current_segment_reloc_table >= 2) {
+ // We are not using this table - ignore it because we don't know what it dose
+ file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR);
+ continue;
+ }
+ static THREEDSX_Reloc reloc_table[RELOCBUFSIZE];
+
+ u32* pos = (u32*)loadinfo.seg_ptrs[current_segment];
+ u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4);
+
+ while (n_relocs) {
+ u32 remaining = std::min(RELOCBUFSIZE, n_relocs);
+ n_relocs -= remaining;
+
+ if (file.ReadBytes(reloc_table, remaining*sizeof(THREEDSX_Reloc)) != remaining*sizeof(THREEDSX_Reloc))
+ return ERROR_READ;
+
+ for (u32 current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) {
+ DEBUG_LOG(LOADER, "(t=%d,skip=%u,patch=%u)\n",
+ current_segment_reloc_table, (u32)reloc_table[current_inprogress].skip, (u32)reloc_table[current_inprogress].patch);
+ pos += reloc_table[current_inprogress].skip;
+ s32 num_patches = reloc_table[current_inprogress].patch;
+ while (0 < num_patches && pos < end_pos) {
+ u32 in_addr = (char*)pos - (char*)&all_mem[0];
+ u32 addr = TranslateAddr(*pos, &loadinfo, offsets);
+ DEBUG_LOG(LOADER, "Patching %08X <-- rel(%08X,%d) (%08X)\n",
+ base_addr + in_addr, addr, current_segment_reloc_table, *pos);
+ switch (current_segment_reloc_table) {
+ case 0: *pos = (addr); break;
+ case 1: *pos = (addr - in_addr); break;
+ default: break; //this should never happen
+ }
+ pos++;
+ num_patches--;
+ }
+ }
+ }
+ }
+ }
+
+ // Write the data
+ memcpy(Memory::GetPointer(base_addr), &all_mem[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]);
+
+ DEBUG_LOG(LOADER, "CODE: %u pages\n", loadinfo.seg_sizes[0] / 0x1000);
+ DEBUG_LOG(LOADER, "RODATA: %u pages\n", loadinfo.seg_sizes[1] / 0x1000);
+ DEBUG_LOG(LOADER, "DATA: %u pages\n", data_load_size / 0x1000);
+ DEBUG_LOG(LOADER, "BSS: %u pages\n", bss_load_size / 0x1000);
+
+ return ERROR_NONE;
+}
+
+ /// AppLoader_DSX constructor
+ AppLoader_THREEDSX::AppLoader_THREEDSX(const std::string& filename) : filename(filename) {
+ }
+
+ /// AppLoader_DSX destructor
+ AppLoader_THREEDSX::~AppLoader_THREEDSX() {
+ }
+
+ /**
+ * Loads a 3DSX file
+ * @return Success on success, otherwise Error
+ */
+ ResultStatus AppLoader_THREEDSX::Load() {
+ INFO_LOG(LOADER, "Loading 3DSX file %s...", filename.c_str());
+ FileUtil::IOFile file(filename, "rb");
+ if (file.IsOpen()) {
+
+ THREEDSXReader reader;
+ reader.Load3DSXFile(filename, 0x00100000);
+ Kernel::LoadExec(0x00100000);
+ } else {
+ return ResultStatus::Error;
+ }
+ return ResultStatus::Success;
+ }
+
+} // namespace Loader
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h
new file mode 100644
index 00000000..848d3ef8
--- /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 a268e021..174397b0 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -5,6 +5,7 @@
#include <memory>
#include "core/file_sys/archive_romfs.h"
+#include "core/loader/3dsx.h"
#include "core/loader/elf.h"
#include "core/loader/ncch.h"
#include "core/hle/kernel/archive.h"
@@ -42,6 +43,8 @@ FileType IdentifyFile(const std::string &filename) {
return FileType::CCI;
} else if (extension == ".bin") {
return FileType::BIN;
+ } else if (extension == ".3dsx") {
+ return FileType::THREEDSX;
}
return FileType::Unknown;
}
@@ -56,6 +59,10 @@ ResultStatus LoadFile(const std::string& filename) {
switch (IdentifyFile(filename)) {
+ //3DSX file format...
+ case FileType::THREEDSX:
+ return AppLoader_THREEDSX(filename).Load();
+
// Standard ELF file format...
case FileType::ELF:
return AppLoader_ELF(filename).Load();
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 68f84300..0f836d28 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -22,6 +22,7 @@ enum class FileType {
CIA,
ELF,
BIN,
+ THREEDSX, //3DSX
};
/// Return type for functions in Loader namespace
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 2e2c0bdf..f17afb60 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -16,10 +16,9 @@ typedef u32 PAddr; ///< Represents a pointer in the physical address space.
////////////////////////////////////////////////////////////////////////////////////////////////////
-enum {
+enum : u32 {
BOOTROM_SIZE = 0x00010000, ///< Bootrom (super secret code/data @ 0x8000) size
MPCORE_PRIV_SIZE = 0x00002000, ///< MPCore private memory region size
- DSP_SIZE = 0x00080000, ///< DSP memory size
AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size
FCRAM_SIZE = 0x08000000, ///< FCRAM size
@@ -32,6 +31,9 @@ enum {
SHARED_MEMORY_VADDR = 0x10000000, ///< Shared memory
SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE),
+ 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),
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 1ec72769..8a6ba256 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -60,7 +60,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
const u8* load_address = base_address + loader_config.data_offset;
// TODO: What happens if a loader overwrites a previous one's data?
- for (int component = 0; component < loader_config.component_count; ++component) {
+ for (unsigned component = 0; component < loader_config.component_count; ++component) {
u32 attribute_index = loader_config.GetComponent(component);
vertex_attribute_sources[attribute_index] = load_address;
vertex_attribute_strides[attribute_index] = static_cast<u32>(loader_config.byte_count);
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 275b06b7..8a5f1142 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -155,7 +155,7 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data
// This is put into a try-catch block to make sure we notice unknown configurations.
std::vector<OutputRegisterInfo> output_info_table;
- for (int i = 0; i < 7; ++i) {
+ for (unsigned i = 0; i < 7; ++i) {
using OutputAttributes = Pica::Regs::VSOutputAttributes;
// TODO: It's still unclear how the attribute components map to the register!
@@ -375,8 +375,8 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
png_write_info(png_ptr, info_ptr);
buf = new u8[row_stride * texture_config.height];
- for (int y = 0; y < texture_config.height; ++y) {
- for (int x = 0; x < texture_config.width; ++x) {
+ for (unsigned y = 0; y < texture_config.height; ++y) {
+ for (unsigned x = 0; x < texture_config.width; ++x) {
// Cf. rasterizer code for an explanation of this algorithm.
int texel_index_within_tile = 0;
for (int block_size_index = 0; block_size_index < 3; ++block_size_index) {
@@ -402,7 +402,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
}
// Write image data
- for (auto y = 0; y < texture_config.height; ++y)
+ for (unsigned y = 0; y < texture_config.height; ++y)
{
u8* row_ptr = (u8*)buf + y * row_stride;
u8* ptr = row_ptr;
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp
index a0eb0418..fdac9ae1 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_util.cpp
@@ -22,7 +22,7 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
// Compile Vertex Shader
DEBUG_LOG(GPU, "Compiling vertex shader.");
- glShaderSource(vertex_shader_id, 1, &vertex_shader, NULL);
+ glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr);
glCompileShader(vertex_shader_id);
// Check Vertex Shader
@@ -31,14 +31,14 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> vertex_shader_error(info_log_length);
- glGetShaderInfoLog(vertex_shader_id, info_log_length, NULL, &vertex_shader_error[0]);
+ glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]);
DEBUG_LOG(GPU, "%s", &vertex_shader_error[0]);
}
// Compile Fragment Shader
DEBUG_LOG(GPU, "Compiling fragment shader.");
- glShaderSource(fragment_shader_id, 1, &fragment_shader, NULL);
+ glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr);
glCompileShader(fragment_shader_id);
// Check Fragment Shader
@@ -47,7 +47,7 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> fragment_shader_error(info_log_length);
- glGetShaderInfoLog(fragment_shader_id, info_log_length, NULL, &fragment_shader_error[0]);
+ glGetShaderInfoLog(fragment_shader_id, info_log_length, nullptr, &fragment_shader_error[0]);
DEBUG_LOG(GPU, "%s", &fragment_shader_error[0]);
}
@@ -65,7 +65,7 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
if (info_log_length > 1) {
std::vector<char> program_error(info_log_length);
- glGetProgramInfoLog(program_id, info_log_length, NULL, &program_error[0]);
+ glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]);
DEBUG_LOG(GPU, "%s", &program_error[0]);
}
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index fd44c3f6..06de6afb 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.
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index c779771c..b581ff4d 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