Merge pull request #1 from citra-emu/master

Update codebase 1
This commit is contained in:
danieleplay 2014-12-09 15:52:41 +01:00
commit f5c12d5cda
63 changed files with 946 additions and 275 deletions

View File

@ -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)

View File

@ -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 {

View File

@ -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() {

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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()
{

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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());

View File

@ -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] = {};

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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();

View File

@ -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) {

View File

@ -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

View File

@ -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");

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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) {

View File

@ -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:

View File

@ -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() {

View File

@ -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();

View File

@ -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"},

View File

@ -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"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -159,7 +159,49 @@ void DeleteFile(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
filename_type, filename_size, file_path.DebugStr().c_str());
cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path);
cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path).raw;
DEBUG_LOG(KERNEL, "called");
}
/*
* FS_User::RenameFile service function
* Inputs:
* 2 : Source archive handle lower word
* 3 : Source archive handle upper word
* 4 : Source file path type
* 5 : Source file path size
* 6 : Dest archive handle lower word
* 7 : Dest archive handle upper word
* 8 : Dest file path type
* 9 : Dest file path size
* 11: Source file path string data
* 13: Dest file path string
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void RenameFile(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
// TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
// 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
u32 src_filename_size = cmd_buff[5];
Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]);
auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
u32 dest_filename_size = cmd_buff[9];
u32 src_filename_ptr = cmd_buff[11];
u32 dest_filename_ptr = cmd_buff[13];
FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr);
FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr);
DEBUG_LOG(KERNEL, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(),
dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
cmd_buff[1] = Kernel::RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw;
DEBUG_LOG(KERNEL, "called");
}
@ -190,7 +232,7 @@ void DeleteDirectory(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s",
dirname_type, dirname_size, dir_path.DebugStr().c_str());
cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path);
cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
DEBUG_LOG(KERNEL, "called");
}
@ -220,11 +262,53 @@ static void CreateDirectory(Service::Interface* self) {
DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path);
cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path).raw;
DEBUG_LOG(KERNEL, "called");
}
/*
* FS_User::RenameDirectory service function
* Inputs:
* 2 : Source archive handle lower word
* 3 : Source archive handle upper word
* 4 : Source dir path type
* 5 : Source dir path size
* 6 : Dest archive handle lower word
* 7 : Dest archive handle upper word
* 8 : Dest dir path type
* 9 : Dest dir path size
* 11: Source dir path string data
* 13: Dest dir path string
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void RenameDirectory(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
// TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
// 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
u32 src_dirname_size = cmd_buff[5];
Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]);
auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
u32 dest_dirname_size = cmd_buff[9];
u32 src_dirname_ptr = cmd_buff[11];
u32 dest_dirname_ptr = cmd_buff[13];
FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr);
FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr);
DEBUG_LOG(KERNEL, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(),
dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
cmd_buff[1] = Kernel::RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw;
DEBUG_LOG(KERNEL, "called");
}
static void OpenDirectory(Service::Interface* self) {
u32* cmd_buff = Service::GetCommandBuffer();
@ -314,12 +398,12 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x080201C2, OpenFile, "OpenFile"},
{0x08030204, OpenFileDirectly, "OpenFileDirectly"},
{0x08040142, DeleteFile, "DeleteFile"},
{0x08050244, nullptr, "RenameFile"},
{0x08050244, RenameFile, "RenameFile"},
{0x08060142, DeleteDirectory, "DeleteDirectory"},
{0x08070142, nullptr, "DeleteDirectoryRecursively"},
{0x08080202, nullptr, "CreateFile"},
{0x08090182, CreateDirectory, "CreateDirectory"},
{0x080A0244, nullptr, "RenameDirectory"},
{0x080A0244, RenameDirectory, "RenameDirectory"},
{0x080B0102, OpenDirectory, "OpenDirectory"},
{0x080C00C2, OpenArchive, "OpenArchive"},
{0x080D0144, nullptr, "ControlArchive"},

View File

@ -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();
}

View File

@ -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();
/**

View File

@ -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"},

View File

@ -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);
}

View File

@ -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
View 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
View 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

View File

@ -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();

View File

@ -22,6 +22,7 @@ enum class FileType {
CIA,
ELF,
BIN,
THREEDSX, //3DSX
};
/// Return type for functions in Loader namespace

View File

@ -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
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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]);
}

View File

@ -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.

View File

@ -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