mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 22:30:14 +00:00
commit
f5c12d5cda
@ -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)
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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] = {};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -193,6 +193,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
|
||||
@ -207,6 +215,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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -57,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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -61,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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
||||
|
@ -49,6 +49,8 @@ public:
|
||||
|
||||
ThreadContext context;
|
||||
|
||||
u32 thread_id;
|
||||
|
||||
u32 status;
|
||||
u32 entry_point;
|
||||
u32 stack_top;
|
||||
@ -61,6 +63,7 @@ public:
|
||||
|
||||
WaitType wait_type;
|
||||
Handle wait_handle;
|
||||
VAddr wait_address;
|
||||
|
||||
std::vector<Handle> waiting_threads;
|
||||
|
||||
@ -76,6 +79,9 @@ static Common::ThreadQueueList<Handle> thread_ready_queue;
|
||||
static Handle current_thread_handle;
|
||||
static Thread* current_thread;
|
||||
|
||||
static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
|
||||
static u32 next_thread_id; ///< The next available thread id
|
||||
|
||||
/// Gets the current thread
|
||||
inline Thread* GetCurrentThread() {
|
||||
return current_thread;
|
||||
@ -121,6 +127,7 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) {
|
||||
}
|
||||
t->wait_type = WAITTYPE_NONE;
|
||||
t->wait_handle = 0;
|
||||
t->wait_address = 0;
|
||||
}
|
||||
|
||||
/// Change a thread to "ready" state
|
||||
@ -141,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<Thread>(handle);
|
||||
@ -164,6 +177,7 @@ ResultCode StopThread(Handle handle, const char* reason) {
|
||||
// Stopped threads are never waiting.
|
||||
thread->wait_type = WAITTYPE_NONE;
|
||||
thread->wait_handle = 0;
|
||||
thread->wait_address = 0;
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@ -192,12 +206,12 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
|
||||
for (Handle handle : thread_queue) {
|
||||
Thread* thread = g_object_pool.Get<Thread>(handle);
|
||||
|
||||
// TODO(bunnei): Verify arbiter address...
|
||||
if (!VerifyWait(thread, WAITTYPE_ARB, arbiter))
|
||||
if (!VerifyWait(thread, WAITTYPE_ARB, arbiter, address))
|
||||
continue;
|
||||
|
||||
if (thread == nullptr)
|
||||
continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
|
||||
|
||||
if(thread->current_priority <= priority) {
|
||||
highest_priority_thread = handle;
|
||||
priority = thread->current_priority;
|
||||
@ -217,8 +231,7 @@ void ArbitrateAllThreads(u32 arbiter, u32 address) {
|
||||
for (Handle handle : thread_queue) {
|
||||
Thread* thread = g_object_pool.Get<Thread>(handle);
|
||||
|
||||
// TODO(bunnei): Verify arbiter address...
|
||||
if (VerifyWait(thread, WAITTYPE_ARB, arbiter))
|
||||
if (VerifyWait(thread, WAITTYPE_ARB, arbiter, address))
|
||||
ResumeThreadFromWait(handle);
|
||||
}
|
||||
}
|
||||
@ -272,11 +285,6 @@ Thread* NextThread() {
|
||||
return Kernel::g_object_pool.Get<Thread>(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the current thread in the wait state for the given type
|
||||
* @param wait_type Type of wait
|
||||
* @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread
|
||||
*/
|
||||
void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
|
||||
Thread* thread = GetCurrentThread();
|
||||
thread->wait_type = wait_type;
|
||||
@ -284,6 +292,11 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
|
||||
ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
|
||||
}
|
||||
|
||||
void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_address) {
|
||||
WaitCurrentThread(wait_type, wait_handle);
|
||||
GetCurrentThread()->wait_address = wait_address;
|
||||
}
|
||||
|
||||
/// Resumes a thread from waiting by marking it as "ready"
|
||||
void ResumeThreadFromWait(Handle handle) {
|
||||
Thread* thread = Kernel::g_object_pool.Get<Thread>(handle);
|
||||
@ -325,6 +338,7 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
|
||||
thread_queue.push_back(handle);
|
||||
thread_ready_queue.prepare(priority);
|
||||
|
||||
thread->thread_id = next_thread_id++;
|
||||
thread->status = THREADSTATUS_DORMANT;
|
||||
thread->entry_point = entry_point;
|
||||
thread->stack_top = stack_top;
|
||||
@ -333,6 +347,7 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
|
||||
thread->processor_id = processor_id;
|
||||
thread->wait_type = WAITTYPE_NONE;
|
||||
thread->wait_handle = 0;
|
||||
thread->wait_address = 0;
|
||||
thread->name = name;
|
||||
|
||||
return thread;
|
||||
@ -465,9 +480,21 @@ void Reschedule() {
|
||||
}
|
||||
}
|
||||
|
||||
ResultCode GetThreadId(u32* thread_id, Handle handle) {
|
||||
Thread* thread = g_object_pool.Get<Thread>(handle);
|
||||
if (thread == nullptr)
|
||||
return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS,
|
||||
ErrorSummary::WrongArgument, ErrorLevel::Permanent);
|
||||
|
||||
*thread_id = thread->thread_id;
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ThreadingInit() {
|
||||
next_thread_id = INITIAL_THREAD_ID;
|
||||
}
|
||||
|
||||
void ThreadingShutdown() {
|
||||
|
@ -5,6 +5,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include "core/mem_map.h"
|
||||
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
@ -58,6 +61,14 @@ void Reschedule();
|
||||
/// Stops the current thread
|
||||
ResultCode StopThread(Handle thread, const char* reason);
|
||||
|
||||
/**
|
||||
* Retrieves the ID of the specified thread handle
|
||||
* @param thread_id Will contain the output thread id
|
||||
* @param handle Handle to the thread we want
|
||||
* @return Whether the function was successful or not
|
||||
*/
|
||||
ResultCode GetThreadId(u32* thread_id, Handle handle);
|
||||
|
||||
/// Resumes a thread from waiting by marking it as "ready"
|
||||
void ResumeThreadFromWait(Handle handle);
|
||||
|
||||
@ -77,6 +88,14 @@ Handle GetCurrentThreadHandle();
|
||||
*/
|
||||
void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle());
|
||||
|
||||
/**
|
||||
* Puts the current thread in the wait state for the given type
|
||||
* @param wait_type Type of wait
|
||||
* @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread
|
||||
* @param wait_address Arbitration address used to resume from wait
|
||||
*/
|
||||
void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_address);
|
||||
|
||||
/// Put current thread in a wait state - on WaitSynchronization
|
||||
void WaitThread_Synchronization();
|
||||
|
||||
|
@ -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"},
|
||||
|
@ -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"},
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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,7 +262,49 @@ 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");
|
||||
}
|
||||
@ -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"},
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
/**
|
||||
|
@ -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"},
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
|
||||
#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<bool>(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<bool>(false);
|
||||
}
|
||||
|
@ -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
|
||||
|
236
src/core/loader/3dsx.cpp
Normal file
236
src/core/loader/3dsx.cpp
Normal file
@ -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
|
32
src/core/loader/3dsx.h
Normal file
32
src/core/loader/3dsx.h
Normal file
@ -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
|
@ -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();
|
||||
|
@ -22,6 +22,7 @@ enum class FileType {
|
||||
CIA,
|
||||
ELF,
|
||||
BIN,
|
||||
THREEDSX, //3DSX
|
||||
};
|
||||
|
||||
/// Return type for functions in Loader namespace
|
||||
|
@ -16,10 +16,9 @@ typedef u32 PAddr; ///< Represents a pointer in the physical address space.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum {
|
||||
enum : u32 {
|
||||
BOOTROM_SIZE = 0x00010000, ///< Bootrom (super secret code/data @ 0x8000) size
|
||||
MPCORE_PRIV_SIZE = 0x00002000, ///< MPCore private memory region size
|
||||
DSP_SIZE = 0x00080000, ///< DSP memory size
|
||||
AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size
|
||||
|
||||
FCRAM_SIZE = 0x08000000, ///< FCRAM size
|
||||
@ -27,47 +26,42 @@ enum {
|
||||
FCRAM_PADDR_END = (FCRAM_PADDR + FCRAM_SIZE), ///< FCRAM end of physical space
|
||||
FCRAM_VADDR = 0x08000000, ///< FCRAM virtual address
|
||||
FCRAM_VADDR_END = (FCRAM_VADDR + FCRAM_SIZE), ///< FCRAM end of virtual space
|
||||
FCRAM_MASK = (FCRAM_SIZE - 1), ///< FCRAM mask
|
||||
|
||||
SHARED_MEMORY_SIZE = 0x04000000, ///< Shared memory size
|
||||
SHARED_MEMORY_VADDR = 0x10000000, ///< Shared memory
|
||||
SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE),
|
||||
SHARED_MEMORY_MASK = (SHARED_MEMORY_SIZE - 1),
|
||||
|
||||
DSP_MEMORY_SIZE = 0x00080000, ///< DSP memory size
|
||||
DSP_MEMORY_VADDR = 0x1FF00000, ///< DSP memory virtual address
|
||||
|
||||
CONFIG_MEMORY_SIZE = 0x00001000, ///< Configuration memory size
|
||||
CONFIG_MEMORY_VADDR = 0x1FF80000, ///< Configuration memory virtual address
|
||||
CONFIG_MEMORY_VADDR_END = (CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE),
|
||||
CONFIG_MEMORY_MASK = (CONFIG_MEMORY_SIZE - 1),
|
||||
|
||||
KERNEL_MEMORY_SIZE = 0x00001000, ///< Kernel memory size
|
||||
KERNEL_MEMORY_VADDR = 0xFFFF0000, ///< Kernel memory where the kthread objects etc are
|
||||
KERNEL_MEMORY_VADDR_END = (KERNEL_MEMORY_VADDR + KERNEL_MEMORY_SIZE),
|
||||
KERNEL_MEMORY_MASK = (KERNEL_MEMORY_SIZE - 1),
|
||||
|
||||
EXEFS_CODE_SIZE = 0x03F00000,
|
||||
EXEFS_CODE_VADDR = 0x00100000, ///< ExeFS:/.code is loaded here
|
||||
EXEFS_CODE_VADDR_END = (EXEFS_CODE_VADDR + EXEFS_CODE_SIZE),
|
||||
EXEFS_CODE_MASK = 0x03FFFFFF,
|
||||
|
||||
// Region of FCRAM used by system
|
||||
SYSTEM_MEMORY_SIZE = 0x02C00000, ///< 44MB
|
||||
SYSTEM_MEMORY_VADDR = 0x04000000,
|
||||
SYSTEM_MEMORY_VADDR_END = (SYSTEM_MEMORY_VADDR + SYSTEM_MEMORY_SIZE),
|
||||
SYSTEM_MEMORY_MASK = 0x03FFFFFF,
|
||||
|
||||
HEAP_SIZE = FCRAM_SIZE, ///< Application heap size
|
||||
//HEAP_PADDR = HEAP_GSP_SIZE,
|
||||
//HEAP_PADDR_END = (HEAP_PADDR + HEAP_SIZE),
|
||||
HEAP_VADDR = 0x08000000,
|
||||
HEAP_VADDR_END = (HEAP_VADDR + HEAP_SIZE),
|
||||
HEAP_MASK = (HEAP_SIZE - 1),
|
||||
|
||||
HEAP_GSP_SIZE = 0x02000000, ///< GSP heap size... TODO: Define correctly?
|
||||
HEAP_GSP_VADDR = 0x14000000,
|
||||
HEAP_GSP_VADDR_END = (HEAP_GSP_VADDR + HEAP_GSP_SIZE),
|
||||
HEAP_GSP_PADDR = 0x00000000,
|
||||
HEAP_GSP_PADDR_END = (HEAP_GSP_PADDR + HEAP_GSP_SIZE),
|
||||
HEAP_GSP_MASK = (HEAP_GSP_SIZE - 1),
|
||||
|
||||
HARDWARE_IO_SIZE = 0x01000000,
|
||||
HARDWARE_IO_PADDR = 0x10000000, ///< IO physical address start
|
||||
@ -80,12 +74,10 @@ enum {
|
||||
VRAM_VADDR = 0x1F000000,
|
||||
VRAM_PADDR_END = (VRAM_PADDR + VRAM_SIZE),
|
||||
VRAM_VADDR_END = (VRAM_VADDR + VRAM_SIZE),
|
||||
VRAM_MASK = 0x007FFFFF,
|
||||
|
||||
SCRATCHPAD_SIZE = 0x00004000, ///< Typical stack size - TODO: Read from exheader
|
||||
SCRATCHPAD_VADDR_END = 0x10000000,
|
||||
SCRATCHPAD_VADDR = (SCRATCHPAD_VADDR_END - SCRATCHPAD_SIZE), ///< Stack space
|
||||
SCRATCHPAD_MASK = (SCRATCHPAD_SIZE - 1), ///< Scratchpad memory mask
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user