Fix merge conflicts

This commit is contained in:
darkf 2014-12-29 19:47:41 -08:00
commit 8ba9ac0f74
288 changed files with 17413 additions and 13969 deletions

View file

@ -3,14 +3,15 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOU
set(SRCS
break_points.cpp
console_listener.cpp
emu_window.cpp
extended_trace.cpp
file_search.cpp
file_util.cpp
hash.cpp
key_map.cpp
log_manager.cpp
logging/filter.cpp
logging/text_formatter.cpp
logging/backend.cpp
math_util.cpp
mem_arena.cpp
memory_util.cpp
@ -32,7 +33,7 @@ set(HEADERS
common_funcs.h
common_paths.h
common_types.h
console_listener.h
concurrent_ring_buffer.h
cpu_detect.h
debug_interface.h
emu_window.h
@ -44,13 +45,18 @@ set(HEADERS
key_map.h
linear_disk_cache.h
log.h
log_manager.h
logging/text_formatter.h
logging/filter.h
logging/log.h
logging/backend.h
make_unique.h
math_util.h
mem_arena.h
memory_util.h
msg_handler.h
platform.h
scm_rev.h
scope_exit.h
string_util.h
swap.h
symbols.h

View file

@ -1,4 +1,4 @@
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@ -142,7 +142,7 @@ public:
__forceinline BitField& operator=(T val)
{
storage = (storage & ~GetMask()) | (((StorageType)val << position) & GetMask());
Assign(val);
return *this;
}
@ -151,6 +151,10 @@ public:
return Value();
}
__forceinline void Assign(const T& value) {
storage = (storage & ~GetMask()) | (((StorageType)value << position) & GetMask());
}
__forceinline T Value() const
{
if (std::numeric_limits<T>::is_signed)
@ -164,6 +168,12 @@ public:
}
}
// TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015
__forceinline bool ToBool() const
{
return Value() != 0;
}
private:
// StorageType is T for non-enum types and the underlying type of T if
// T is an enumeration. Note that T is wrapped within an enable_if in the

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/common.h"
@ -180,7 +180,7 @@ void TMemCheck::Action(DebugInterface *debug_interface, u32 iValue, u32 addr,
{
if (Log)
{
INFO_LOG(MEMMAP, "CHK %08x (%s) %s%i %0*x at %08x (%s)",
LOG_DEBUG(Debug_Breakpoint, "CHK %08x (%s) %s%i %0*x at %08x (%s)",
pc, debug_interface->getDescription(pc).c_str(),
write ? "Write" : "Read", size*8, size*2, iValue, addr,
debug_interface->getDescription(addr).c_str()

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -154,7 +154,7 @@ public:
Do(foundVersion);
if (error == ERROR_FAILURE || foundVersion < minVer || foundVersion > ver) {
WARN_LOG(COMMON, "Savestate failure: wrong version %d found for %s", foundVersion, title);
LOG_ERROR(Common, "Savestate failure: wrong version %d found for %s", foundVersion, title);
SetError(ERROR_FAILURE);
return PointerWrapSection(*this, -1, title);
}
@ -178,7 +178,14 @@ public:
case MODE_READ: if (memcmp(data, *ptr, size) != 0) return false; break;
case MODE_WRITE: memcpy(*ptr, data, size); break;
case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything
case MODE_VERIFY: for(int i = 0; i < size; i++) _dbg_assert_msg_(COMMON, ((u8*)data)[i] == (*ptr)[i], "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i], &(*ptr)[i]); break;
case MODE_VERIFY:
for (int i = 0; i < size; i++) {
_dbg_assert_msg_(Common, ((u8*)data)[i] == (*ptr)[i],
"Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i],
(*ptr)[i], (*ptr)[i], &(*ptr)[i]);
}
break;
default: break; // throw an error?
}
(*ptr) += size;
@ -191,7 +198,14 @@ public:
case MODE_READ: memcpy(data, *ptr, size); break;
case MODE_WRITE: memcpy(*ptr, data, size); break;
case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything
case MODE_VERIFY: for(int i = 0; i < size; i++) _dbg_assert_msg_(COMMON, ((u8*)data)[i] == (*ptr)[i], "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i], &(*ptr)[i]); break;
case MODE_VERIFY:
for (int i = 0; i < size; i++) {
_dbg_assert_msg_(Common, ((u8*)data)[i] == (*ptr)[i],
"Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i],
(*ptr)[i], (*ptr)[i], &(*ptr)[i]);
}
break;
default: break; // throw an error?
}
(*ptr) += size;
@ -204,11 +218,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 +278,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 +334,7 @@ public:
template<class T>
void Do(std::vector<T *> &x)
{
T *dv = NULL;
T *dv = nullptr;
DoVector(x, dv);
}
@ -369,7 +383,7 @@ public:
template<class T>
void Do(std::deque<T *> &x)
{
T *dv = NULL;
T *dv = nullptr;
DoDeque(x, dv);
}
@ -395,7 +409,7 @@ public:
template<class T>
void Do(std::list<T *> &x)
{
T *dv = NULL;
T *dv = nullptr;
Do(x, dv);
}
@ -433,7 +447,7 @@ public:
{
for (auto it = x.begin(), end = x.end(); it != end; ++it)
{
if (*it != NULL)
if (*it != nullptr)
delete *it;
}
}
@ -476,7 +490,7 @@ public:
break;
default:
ERROR_LOG(COMMON, "Savestate error: invalid mode %d.", mode);
LOG_ERROR(Common, "Savestate error: invalid mode %d.", mode);
}
}
@ -490,7 +504,12 @@ public:
case MODE_READ: x = (char*)*ptr; break;
case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
case MODE_MEASURE: break;
case MODE_VERIFY: _dbg_assert_msg_(COMMON, !strcmp(x.c_str(), (char*)*ptr), "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (char*)*ptr, ptr); break;
case MODE_VERIFY:
_dbg_assert_msg_(Common,
!strcmp(x.c_str(), (char*)*ptr),
"Savestate verification failure: \"%s\" != \"%s\" (at %p).\n",
x.c_str(), (char*)*ptr, ptr);
break;
}
(*ptr) += stringLen;
}
@ -504,7 +523,11 @@ public:
case MODE_READ: x = (wchar_t*)*ptr; break;
case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
case MODE_MEASURE: break;
case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break;
case MODE_VERIFY:
_dbg_assert_msg_(Common, x == (wchar_t*)*ptr,
"Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n",
x.c_str(), (wchar_t*)*ptr, ptr);
break;
}
(*ptr) += stringLen;
}
@ -518,7 +541,7 @@ public:
void DoClass(T *&x) {
if (mode == MODE_READ)
{
if (x != NULL)
if (x != nullptr)
delete x;
x = new T();
}
@ -567,7 +590,7 @@ public:
{
if (mode == MODE_READ)
{
cur->next = 0;
cur->next = nullptr;
list_cur = cur;
if (prev)
prev->next = cur;
@ -586,13 +609,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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,9 +1,12 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common_types.h"
#include <cstdlib>
#ifdef _WIN32
#define SLEEP(x) Sleep(x)
#else
@ -73,6 +76,8 @@ inline u64 _rotr64(u64 x, unsigned int shift){
}
#else // _MSC_VER
#include <locale.h>
// Function Cross-Compatibility
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
@ -106,7 +111,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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -29,19 +29,6 @@
#endif
#endif
// Shared data dirs (Sys and shared User for linux)
#ifdef _WIN32
#define SYSDATA_DIR "sys"
#else
#ifdef DATA_DIR
#define SYSDATA_DIR DATA_DIR "sys"
#define SHARED_USER_DIR DATA_DIR USERDATA_DIR DIR_SEP
#else
#define SYSDATA_DIR "sys"
#define SHARED_USER_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP
#endif
#endif
// Dirs in both User and Sys
#define EUR_DIR "EUR"
#define USA_DIR "USA"
@ -53,6 +40,9 @@
#define MAPS_DIR "maps"
#define CACHE_DIR "cache"
#define SDMC_DIR "sdmc"
#define SAVEDATA_DIR "savedata"
#define SYSDATA_DIR "sysdata"
#define SYSSAVEDATA_DIR "syssavedata"
#define SHADERCACHE_DIR "shader_cache"
#define STATESAVES_DIR "state_saves"
#define SCREENSHOTS_DIR "screenShots"
@ -70,6 +60,9 @@
#define DEBUGGER_CONFIG "debugger.ini"
#define LOGGER_CONFIG "logger.ini"
// Sys files
#define SHARED_FONT "shared_font.bin"
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
#define MAIN_LOG "emu.log"

View file

@ -41,8 +41,6 @@ typedef std::int64_t s64; ///< 64-bit signed int
typedef float f32; ///< 32-bit floating point
typedef double f64; ///< 64-bit floating point
#include "common/common.h"
/// Union for fast 16-bit type casting
union t16 {
u8 _u8[2]; ///< 8-bit unsigned char(s)

View file

@ -0,0 +1,164 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <condition_variable>
#include <cstdint>
#include <mutex>
#include <thread>
#include "common/common.h" // for NonCopyable
#include "common/log.h" // for _dbg_assert_
namespace Common {
/**
* A MPMC (Multiple-Producer Multiple-Consumer) concurrent ring buffer. This data structure permits
* multiple threads to push and pop from a queue of bounded size.
*/
template <typename T, size_t ArraySize>
class ConcurrentRingBuffer : private NonCopyable {
public:
/// Value returned by the popping functions when the queue has been closed.
static const size_t QUEUE_CLOSED = -1;
ConcurrentRingBuffer() {}
~ConcurrentRingBuffer() {
// If for whatever reason the queue wasn't completely drained, destroy the left over items.
for (size_t i = reader_index, end = writer_index; i != end; i = (i + 1) % ArraySize) {
Data()[i].~T();
}
}
/**
* Pushes a value to the queue. If the queue is full, this method will block. Does nothing if
* the queue is closed.
*/
void Push(T val) {
std::unique_lock<std::mutex> lock(mutex);
if (closed) {
return;
}
// If the buffer is full, wait
writer.wait(lock, [&]{
return (writer_index + 1) % ArraySize != reader_index;
});
T* item = &Data()[writer_index];
new (item) T(std::move(val));
writer_index = (writer_index + 1) % ArraySize;
// Wake up waiting readers
lock.unlock();
reader.notify_one();
}
/**
* Pops up to `dest_len` items from the queue, storing them in `dest`. This function will not
* block, and might return 0 values if there are no elements in the queue when it is called.
*
* @return The number of elements stored in `dest`. If the queue has been closed, returns
* `QUEUE_CLOSED`.
*/
size_t Pop(T* dest, size_t dest_len) {
std::unique_lock<std::mutex> lock(mutex);
if (closed && !CanRead()) {
return QUEUE_CLOSED;
}
return PopInternal(dest, dest_len);
}
/**
* Pops up to `dest_len` items from the queue, storing them in `dest`. This function will block
* if there are no elements in the queue when it is called.
*
* @return The number of elements stored in `dest`. If the queue has been closed, returns
* `QUEUE_CLOSED`.
*/
size_t BlockingPop(T* dest, size_t dest_len) {
std::unique_lock<std::mutex> lock(mutex);
if (closed && !CanRead()) {
return QUEUE_CLOSED;
}
while (!CanRead()) {
reader.wait(lock);
if (closed && !CanRead()) {
return QUEUE_CLOSED;
}
}
_dbg_assert_(Common, CanRead());
return PopInternal(dest, dest_len);
}
/**
* Closes the queue. After calling this method, `Push` operations won't have any effect, and
* `PopMany` and `PopManyBlock` will start returning `QUEUE_CLOSED`. This is intended to allow
* a graceful shutdown of all consumers.
*/
void Close() {
std::unique_lock<std::mutex> lock(mutex);
closed = true;
// We need to wake up any reader that are waiting for an item that will never come.
lock.unlock();
reader.notify_all();
}
/// Returns true if `Close()` has been called.
bool IsClosed() const {
return closed;
}
private:
size_t PopInternal(T* dest, size_t dest_len) {
size_t output_count = 0;
while (output_count < dest_len && CanRead()) {
_dbg_assert_(Common, CanRead());
T* item = &Data()[reader_index];
T out_val = std::move(*item);
item->~T();
size_t prev_index = (reader_index + ArraySize - 1) % ArraySize;
reader_index = (reader_index + 1) % ArraySize;
if (writer_index == prev_index) {
writer.notify_one();
}
dest[output_count++] = std::move(out_val);
}
return output_count;
}
bool CanRead() const {
return reader_index != writer_index;
}
T* Data() {
return static_cast<T*>(static_cast<void*>(&storage));
}
/// Storage for entries
typename std::aligned_storage<ArraySize * sizeof(T),
std::alignment_of<T>::value>::type storage;
/// Data is valid in the half-open interval [reader, writer). If they are `QUEUE_CLOSED` then the
/// queue has been closed.
size_t writer_index = 0, reader_index = 0;
// True if the queue has been closed.
bool closed = false;
/// Mutex that protects the entire data structure.
std::mutex mutex;
/// Signaling wakes up reader which is waiting for storage to be non-empty.
std::condition_variable reader;
/// Signaling wakes up writer which is waiting for storage to be non-full.
std::condition_variable writer;
};
} // namespace

View file

@ -1,319 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <algorithm>
#ifdef _WIN32
#include <windows.h>
#include <array>
#endif
#include "common/common.h"
#include "common/log_manager.h" // Common
#include "common/console_listener.h" // Common
ConsoleListener::ConsoleListener()
{
#ifdef _WIN32
hConsole = NULL;
bUseColor = true;
#else
bUseColor = isatty(fileno(stdout));
#endif
}
ConsoleListener::~ConsoleListener()
{
Close();
}
// 100, 100, "Dolphin Log Console"
// Open console window - width and height is the size of console window
// Name is the window title
void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title)
{
#ifdef _WIN32
if (!GetConsoleWindow())
{
// Open the console window and create the window handle for GetStdHandle()
AllocConsole();
// Hide
if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE);
// Save the window handle that AllocConsole() created
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Set the console window title
SetConsoleTitle(Common::UTF8ToTStr(Title).c_str());
// Set letter space
LetterSpace(80, 4000);
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
}
else
{
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
}
#endif
}
void ConsoleListener::UpdateHandle()
{
#ifdef _WIN32
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
}
// Close the console window and close the eventual file handle
void ConsoleListener::Close()
{
#ifdef _WIN32
if (hConsole == NULL)
return;
FreeConsole();
hConsole = NULL;
#else
fflush(NULL);
#endif
}
bool ConsoleListener::IsOpen()
{
#ifdef _WIN32
return (hConsole != NULL);
#else
return true;
#endif
}
/*
LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are
dependent on each other, that's the reason for the additional checks.
*/
void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst)
{
#ifdef _WIN32
BOOL SB, SW;
if (BufferFirst)
{
// Change screen buffer size
COORD Co = {BufferWidth, BufferHeight};
SB = SetConsoleScreenBufferSize(hConsole, Co);
// Change the screen buffer window size
SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
}
else
{
// Change the screen buffer window size
SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
// Change screen buffer size
COORD Co = {BufferWidth, BufferHeight};
SB = SetConsoleScreenBufferSize(hConsole, Co);
}
#endif
}
void ConsoleListener::LetterSpace(int Width, int Height)
{
#ifdef _WIN32
// Get console info
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
//
int OldBufferWidth = ConInfo.dwSize.X;
int OldBufferHeight = ConInfo.dwSize.Y;
int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left);
int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top);
//
int NewBufferWidth = Width;
int NewBufferHeight = Height;
int NewScreenWidth = NewBufferWidth - 1;
int NewScreenHeight = OldScreenHeight;
// Width
BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1));
// Height
BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1));
// Resize the window too
//MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true);
#endif
}
#ifdef _WIN32
COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
{
COORD Ret = {0, 0};
// Full rows
int Step = (int)floor((float)BytesRead / (float)BufferWidth);
Ret.Y += Step;
// Partial row
Ret.X = BytesRead - (BufferWidth * Step);
return Ret;
}
#endif
void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize)
{
#ifdef _WIN32
// Check size
if (Width < 8 || Height < 12) return;
bool DBef = true;
bool DAft = true;
std::string SLog = "";
const HWND hWnd = GetConsoleWindow();
const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Get console info
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y;
// ---------------------------------------------------------------------
// Save the current text
// ------------------------
DWORD cCharsRead = 0;
COORD coordScreen = { 0, 0 };
static const int MAX_BYTES = 1024 * 16;
std::vector<std::array<TCHAR, MAX_BYTES>> Str;
std::vector<std::array<WORD, MAX_BYTES>> Attr;
// ReadConsoleOutputAttribute seems to have a limit at this level
static const int ReadBufferSize = MAX_BYTES - 32;
DWORD cAttrRead = ReadBufferSize;
DWORD BytesRead = 0;
while (BytesRead < BufferSize)
{
Str.resize(Str.size() + 1);
if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead))
SLog += Common::StringFromFormat("WriteConsoleOutputCharacter error");
Attr.resize(Attr.size() + 1);
if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead))
SLog += Common::StringFromFormat("WriteConsoleOutputAttribute error");
// Break on error
if (cAttrRead == 0) break;
BytesRead += cAttrRead;
coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X);
}
// Letter space
int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f);
int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f);
int LBufWidth = LWidth + 1;
int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth);
// Change screen buffer size
LetterSpace(LBufWidth, LBufHeight);
ClearScreen(true);
coordScreen.Y = 0;
coordScreen.X = 0;
DWORD cCharsWritten = 0;
int BytesWritten = 0;
DWORD cAttrWritten = 0;
for (size_t i = 0; i < Attr.size(); i++)
{
if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten))
SLog += Common::StringFromFormat("WriteConsoleOutputCharacter error");
if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten))
SLog += Common::StringFromFormat("WriteConsoleOutputAttribute error");
BytesWritten += cAttrWritten;
coordScreen = GetCoordinates(BytesWritten, LBufWidth);
}
const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X;
COORD Coo = GetCoordinates(OldCursor, LBufWidth);
SetConsoleCursorPosition(hConsole, Coo);
if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str());
// Resize the window too
if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true);
#endif
}
void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
{
#if defined(_WIN32)
WORD Color;
switch (Level)
{
case OS_LEVEL: // light yellow
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
break;
case NOTICE_LEVEL: // light green
Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
break;
case ERROR_LEVEL: // light red
Color = FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
case WARNING_LEVEL: // light purple
Color = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
break;
case INFO_LEVEL: // cyan
Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
break;
case DEBUG_LEVEL: // gray
Color = FOREGROUND_INTENSITY;
break;
default: // off-white
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
}
SetConsoleTextAttribute(hConsole, Color);
printf(Text);
#else
char ColorAttr[16] = "";
char ResetAttr[16] = "";
if (bUseColor)
{
strcpy(ResetAttr, "\033[0m");
switch (Level)
{
case NOTICE_LEVEL: // light green
strcpy(ColorAttr, "\033[92m");
break;
case ERROR_LEVEL: // light red
strcpy(ColorAttr, "\033[91m");
break;
case WARNING_LEVEL: // light yellow
strcpy(ColorAttr, "\033[93m");
break;
default:
break;
}
}
fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr);
#endif
}
// Clear console screen
void ConsoleListener::ClearScreen(bool Cursor)
{
#if defined(_WIN32)
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
// Write space to the entire console
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
// Reset cursor
if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
#endif
}

View file

@ -1,38 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include "common/log_manager.h"
#ifdef _WIN32
#include <windows.h>
#endif
class ConsoleListener : public LogListener
{
public:
ConsoleListener();
~ConsoleListener();
void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console");
void UpdateHandle();
void Close();
bool IsOpen();
void LetterSpace(int Width, int Height);
void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst);
void PixelSpace(int Left, int Top, int Width, int Height, bool);
#ifdef _WIN32
COORD GetCoordinates(int BytesRead, int BufferWidth);
#endif
void Log(LogTypes::LOG_LEVELS, const char *Text) override;
void ClearScreen(bool Cursor = true);
private:
#ifdef _WIN32
HWND GetHwnd(void);
HANDLE hConsole;
#endif
bool bUseColor;
};

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "emu_window.h"

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@ -88,7 +88,7 @@ bool IsDirectory(const std::string &filename)
#endif
if (result < 0) {
WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
LOG_WARNING(Common_Filesystem, "stat failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
@ -100,33 +100,33 @@ bool IsDirectory(const std::string &filename)
// Doesn't supports deleting a directory
bool Delete(const std::string &filename)
{
INFO_LOG(COMMON, "Delete: file %s", filename.c_str());
LOG_INFO(Common_Filesystem, "file %s", filename.c_str());
// Return true because we care about the file no
// being there, not the actual delete.
if (!Exists(filename))
{
WARN_LOG(COMMON, "Delete: %s does not exist", filename.c_str());
LOG_WARNING(Common_Filesystem, "%s does not exist", filename.c_str());
return true;
}
// We can't delete a directory
if (IsDirectory(filename))
{
WARN_LOG(COMMON, "Delete failed: %s is a directory", filename.c_str());
LOG_ERROR(Common_Filesystem, "Failed: %s is a directory", filename.c_str());
return false;
}
#ifdef _WIN32
if (!DeleteFile(Common::UTF8ToTStr(filename).c_str()))
{
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
LOG_ERROR(Common_Filesystem, "DeleteFile failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
#else
if (unlink(filename.c_str()) == -1) {
WARN_LOG(COMMON, "Delete: unlink failed on %s: %s",
LOG_ERROR(Common_Filesystem, "unlink failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
@ -138,17 +138,17 @@ bool Delete(const std::string &filename)
// Returns true if successful, or path already exists.
bool CreateDir(const std::string &path)
{
INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
LOG_TRACE(Common_Filesystem, "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)
{
WARN_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str());
LOG_WARNING(Common_Filesystem, "CreateDirectory failed on %s: already exists", path.c_str());
return true;
}
ERROR_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: %i", path.c_str(), error);
LOG_ERROR(Common_Filesystem, "CreateDirectory failed on %s: %i", path.c_str(), error);
return false;
#else
if (mkdir(path.c_str(), 0755) == 0)
@ -158,11 +158,11 @@ bool CreateDir(const std::string &path)
if (err == EEXIST)
{
WARN_LOG(COMMON, "CreateDir: mkdir failed on %s: already exists", path.c_str());
LOG_WARNING(Common_Filesystem, "mkdir failed on %s: already exists", path.c_str());
return true;
}
ERROR_LOG(COMMON, "CreateDir: mkdir failed on %s: %s", path.c_str(), strerror(err));
LOG_ERROR(Common_Filesystem, "mkdir failed on %s: %s", path.c_str(), strerror(err));
return false;
#endif
}
@ -171,11 +171,11 @@ bool CreateDir(const std::string &path)
bool CreateFullPath(const std::string &fullPath)
{
int panicCounter = 100;
INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str());
LOG_TRACE(Common_Filesystem, "path %s", fullPath.c_str());
if (FileUtil::Exists(fullPath))
{
INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str());
LOG_WARNING(Common_Filesystem, "path exists %s", fullPath.c_str());
return true;
}
@ -192,7 +192,7 @@ bool CreateFullPath(const std::string &fullPath)
// Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
std::string const subPath(fullPath.substr(0, position + 1));
if (!FileUtil::IsDirectory(subPath) && !FileUtil::CreateDir(subPath)) {
ERROR_LOG(COMMON, "CreateFullPath: directory creation failed");
LOG_ERROR(Common, "CreateFullPath: directory creation failed");
return false;
}
@ -200,7 +200,7 @@ bool CreateFullPath(const std::string &fullPath)
panicCounter--;
if (panicCounter <= 0)
{
ERROR_LOG(COMMON, "CreateFullPath: directory structure is too deep");
LOG_ERROR(Common, "CreateFullPath: directory structure is too deep");
return false;
}
position++;
@ -211,12 +211,12 @@ bool CreateFullPath(const std::string &fullPath)
// Deletes a directory filename, returns true on success
bool DeleteDir(const std::string &filename)
{
INFO_LOG(COMMON, "DeleteDir: directory %s", filename.c_str());
LOG_INFO(Common_Filesystem, "directory %s", filename.c_str());
// check if a directory
if (!FileUtil::IsDirectory(filename))
{
ERROR_LOG(COMMON, "DeleteDir: Not a directory %s", filename.c_str());
LOG_ERROR(Common_Filesystem, "Not a directory %s", filename.c_str());
return false;
}
@ -227,7 +227,7 @@ bool DeleteDir(const std::string &filename)
if (rmdir(filename.c_str()) == 0)
return true;
#endif
ERROR_LOG(COMMON, "DeleteDir: %s: %s", filename.c_str(), GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "failed %s: %s", filename.c_str(), GetLastErrorMsg());
return false;
}
@ -235,11 +235,11 @@ bool DeleteDir(const std::string &filename)
// renames file srcFilename to destFilename, returns true on success
bool Rename(const std::string &srcFilename, const std::string &destFilename)
{
INFO_LOG(COMMON, "Rename: %s --> %s",
LOG_TRACE(Common_Filesystem, "%s --> %s",
srcFilename.c_str(), destFilename.c_str());
if (rename(srcFilename.c_str(), destFilename.c_str()) == 0)
return true;
ERROR_LOG(COMMON, "Rename: failed %s --> %s: %s",
LOG_ERROR(Common_Filesystem, "failed %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
return false;
}
@ -247,13 +247,13 @@ bool Rename(const std::string &srcFilename, const std::string &destFilename)
// copies file srcFilename to destFilename, returns true on success
bool Copy(const std::string &srcFilename, const std::string &destFilename)
{
INFO_LOG(COMMON, "Copy: %s --> %s",
LOG_TRACE(Common_Filesystem, "%s --> %s",
srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
if (CopyFile(Common::UTF8ToTStr(srcFilename).c_str(), Common::UTF8ToTStr(destFilename).c_str(), FALSE))
return true;
ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
LOG_ERROR(Common_Filesystem, "failed %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
return false;
#else
@ -267,7 +267,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
FILE *input = fopen(srcFilename.c_str(), "rb");
if (!input)
{
ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s",
LOG_ERROR(Common_Filesystem, "opening input failed %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
return false;
}
@ -277,7 +277,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
if (!output)
{
fclose(input);
ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s",
LOG_ERROR(Common_Filesystem, "opening output failed %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
return false;
}
@ -291,8 +291,8 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
{
if (ferror(input) != 0)
{
ERROR_LOG(COMMON,
"Copy: failed reading from source, %s --> %s: %s",
LOG_ERROR(Common_Filesystem,
"failed reading from source, %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
goto bail;
}
@ -302,8 +302,8 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
int wnum = fwrite(buffer, sizeof(char), rnum, output);
if (wnum != rnum)
{
ERROR_LOG(COMMON,
"Copy: failed writing to output, %s --> %s: %s",
LOG_ERROR(Common_Filesystem,
"failed writing to output, %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
goto bail;
}
@ -326,13 +326,13 @@ u64 GetSize(const std::string &filename)
{
if (!Exists(filename))
{
WARN_LOG(COMMON, "GetSize: failed %s: No such file", filename.c_str());
LOG_ERROR(Common_Filesystem, "failed %s: No such file", filename.c_str());
return 0;
}
if (IsDirectory(filename))
{
WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str());
LOG_ERROR(Common_Filesystem, "failed %s: is a directory", filename.c_str());
return 0;
}
@ -343,12 +343,12 @@ u64 GetSize(const std::string &filename)
if (stat64(filename.c_str(), &buf) == 0)
#endif
{
DEBUG_LOG(COMMON, "GetSize: %s: %lld",
LOG_TRACE(Common_Filesystem, "%s: %lld",
filename.c_str(), (long long)buf.st_size);
return buf.st_size;
}
ERROR_LOG(COMMON, "GetSize: Stat failed %s: %s",
LOG_ERROR(Common_Filesystem, "Stat failed %s: %s",
filename.c_str(), GetLastErrorMsg());
return 0;
}
@ -358,7 +358,7 @@ u64 GetSize(const int fd)
{
struct stat64 buf;
if (fstat64(fd, &buf) != 0) {
ERROR_LOG(COMMON, "GetSize: stat failed %i: %s",
LOG_ERROR(Common_Filesystem, "GetSize: stat failed %i: %s",
fd, GetLastErrorMsg());
return 0;
}
@ -371,13 +371,13 @@ u64 GetSize(FILE *f)
// can't use off_t here because it can be 32-bit
u64 pos = ftello(f);
if (fseeko(f, 0, SEEK_END) != 0) {
ERROR_LOG(COMMON, "GetSize: seek failed %p: %s",
LOG_ERROR(Common_Filesystem, "GetSize: seek failed %p: %s",
f, GetLastErrorMsg());
return 0;
}
u64 size = ftello(f);
if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) {
ERROR_LOG(COMMON, "GetSize: seek failed %p: %s",
LOG_ERROR(Common_Filesystem, "GetSize: seek failed %p: %s",
f, GetLastErrorMsg());
return 0;
}
@ -387,11 +387,11 @@ u64 GetSize(FILE *f)
// creates an empty file filename, returns true on success
bool CreateEmptyFile(const std::string &filename)
{
INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
LOG_TRACE(Common_Filesystem, "%s", filename.c_str());
if (!FileUtil::IOFile(filename, "wb"))
{
ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s",
LOG_ERROR(Common_Filesystem, "failed %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
@ -404,7 +404,7 @@ bool CreateEmptyFile(const std::string &filename)
// results into parentEntry. Returns the number of files+directories found
u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
{
INFO_LOG(COMMON, "ScanDirectoryTree: directory %s", directory.c_str());
LOG_TRACE(Common_Filesystem, "directory %s", directory.c_str());
// How many files + directories we found
u32 foundEntries = 0;
#ifdef _WIN32
@ -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)
@ -474,7 +474,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
// Deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::string &directory)
{
INFO_LOG(COMMON, "DeleteDirRecursively: %s", directory.c_str());
LOG_TRACE(Common_Filesystem, "%s", directory.c_str());
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
@ -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",
LOG_ERROR(Common_Filesystem, "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('\\'));
}
@ -647,7 +647,7 @@ std::string GetSysDirectory()
#endif
sysDir += DIR_SEP;
INFO_LOG(COMMON, "GetSysDirectory: Setting to %s:", sysDir.c_str());
LOG_DEBUG(Common_Filesystem, "Setting to %s:", sysDir.c_str());
return sysDir;
}
@ -676,6 +676,9 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP;
paths[D_SAVEDATA_IDX] = paths[D_USER_IDX] + SAVEDATA_DIR DIR_SEP;
paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP;
paths[D_SYSSAVEDATA_IDX] = paths[D_USER_IDX] + SYSSAVEDATA_DIR DIR_SEP;
paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP;
paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
@ -694,7 +697,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
{
if (!FileUtil::IsDirectory(newPath))
{
WARN_LOG(COMMON, "Invalid path specified %s", newPath.c_str());
LOG_ERROR(Common_Filesystem, "Invalid path specified %s", newPath.c_str());
return paths[DirIDX];
}
else
@ -717,6 +720,8 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP;
paths[D_SAVEDATA_IDX] = paths[D_USER_IDX] + SAVEDATA_DIR DIR_SEP;
paths[D_SYSSAVEDATA_IDX] = paths[D_USER_IDX] + SYSSAVEDATA_DIR DIR_SEP;
paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP;
paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
@ -753,19 +758,6 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
return paths[DirIDX];
}
//std::string GetThemeDir(const std::string& theme_name)
//{
// std::string dir = FileUtil::GetUserPath(D_THEMES_IDX) + theme_name + "/";
//
//#if !defined(_WIN32)
// // If theme does not exist in user's dir load from shared directory
// if (!FileUtil::Exists(dir))
// dir = SHARED_USER_DIR THEMES_DIR "/" + theme_name + "/";
//#endif
//
// return dir;
//}
size_t WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{
return FileUtil::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size());
@ -826,7 +818,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 +826,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 +837,7 @@ IOFile::~IOFile()
}
IOFile::IOFile(IOFile&& other)
: m_file(NULL), m_good(true)
: m_file(nullptr), m_good(true)
{
Swap(other);
}
@ -880,14 +872,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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -27,6 +27,9 @@ enum {
D_STATESAVES_IDX,
D_SCREENSHOTS_IDX,
D_SDMC_IDX,
D_SAVEDATA_IDX,
D_SYSDATA_IDX,
D_SYSSAVEDATA_IDX,
D_HIRESTEXTURES_IDX,
D_DUMP_IDX,
D_DUMPFRAMES_IDX,
@ -202,11 +205,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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "key_map.h"

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -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

@ -1,108 +1,12 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#ifndef LOGGING
#define LOGGING
#endif
enum {
OS_LEVEL, // Printed by the emulated operating system
NOTICE_LEVEL, // VERY important information that is NOT errors. Like startup and OSReports.
ERROR_LEVEL, // Critical errors
WARNING_LEVEL, // Something is suspicious.
INFO_LEVEL, // General information.
DEBUG_LEVEL, // Detailed debugging - might make things slow.
};
namespace LogTypes
{
enum LOG_TYPE {
ACTIONREPLAY,
AUDIO,
AUDIO_INTERFACE,
BOOT,
COMMANDPROCESSOR,
COMMON,
CONSOLE,
CONFIG,
DISCIO,
FILEMON,
DSPHLE,
DSPLLE,
DSP_MAIL,
DSPINTERFACE,
DVDINTERFACE,
DYNA_REC,
EXPANSIONINTERFACE,
GDB_STUB,
ARM11,
GSP,
OSHLE,
MASTER_LOG,
MEMMAP,
MEMCARD_MANAGER,
OSREPORT,
PAD,
PROCESSORINTERFACE,
PIXELENGINE,
SERIALINTERFACE,
SP1,
STREAMINGINTERFACE,
VIDEO,
VIDEOINTERFACE,
LOADER,
FILESYS,
WII_IPC_DVD,
WII_IPC_ES,
WII_IPC_FILEIO,
WII_IPC_HID,
KERNEL,
SVC,
NDMA,
HLE,
RENDER,
GPU,
HW,
TIME,
NETPLAY,
GUI,
NUMBER_OF_LOGS // Must be last
};
// FIXME: should this be removed?
enum LOG_LEVELS {
LOS = OS_LEVEL,
LNOTICE = NOTICE_LEVEL,
LERROR = ERROR_LEVEL,
LWARNING = WARNING_LEVEL,
LINFO = INFO_LEVEL,
LDEBUG = DEBUG_LEVEL,
};
#define LOGTYPES_LEVELS LogTypes::LOG_LEVELS
#define LOGTYPES_TYPE LogTypes::LOG_TYPE
} // namespace
void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int line,
const char* function, const char* fmt, ...)
#ifdef __GNUC__
__attribute__((format(printf, 6, 7)))
#endif
;
#if defined LOGGING || defined _DEBUG || defined DEBUGFAST
#define MAX_LOGLEVEL LDEBUG
#else
#ifndef MAX_LOGLEVEL
#define MAX_LOGLEVEL LWARNING
#endif // loglevel
#endif // logging
#include "common/common_funcs.h"
#include "common/msg_handler.h"
#include "common/logging/log.h"
#ifdef MSVC_VER
#ifndef __func__
@ -110,29 +14,16 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int
#endif
#endif
// Let the compiler optimize this out
#define GENERIC_LOG(t, v, ...) { \
if (v <= LogTypes::MAX_LOGLEVEL) \
GenericLog(v, t, __FILE__, __LINE__, __func__, __VA_ARGS__); \
}
#define OS_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LOS, __VA_ARGS__) } while (0)
#define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (0)
#define WARN_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LWARNING, __VA_ARGS__) } while (0)
#define NOTICE_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LNOTICE, __VA_ARGS__) } while (0)
#define INFO_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LINFO, __VA_ARGS__) } while (0)
#define DEBUG_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LDEBUG, __VA_ARGS__) } while (0)
#if MAX_LOGLEVEL >= DEBUG_LEVEL
#if _DEBUG
#define _dbg_assert_(_t_, _a_) \
if (!(_a_)) {\
ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \
LOG_CRITICAL(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \
__LINE__, __FILE__, __TIME__); \
if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \
}
#define _dbg_assert_msg_(_t_, _a_, ...)\
if (!(_a_)) {\
ERROR_LOG(_t_, __VA_ARGS__); \
LOG_CRITICAL(_t_, __VA_ARGS__); \
if (!PanicYesNo(__VA_ARGS__)) {Crash();} \
}
#define _dbg_update_() Host_UpdateLogDisplay();
@ -144,12 +35,12 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int
#define _dbg_assert_(_t_, _a_) {}
#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) {}
#endif // dbg_assert
#endif // MAX_LOGLEVEL DEBUG
#endif
#define _assert_(_a_) _dbg_assert_(MASTER_LOG, _a_)
#ifndef GEKKO
#ifdef MSVC_VER
#ifdef _WIN32
#define _assert_msg_(_t_, _a_, _fmt_, ...) \
if (!(_a_)) {\
if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \
@ -159,7 +50,7 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int
if (!(_a_)) {\
if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \
}
#endif // MSVC_VER
#endif // _WIN32
#else // GEKKO
#define _assert_msg_(_t_, _a_, _fmt_, ...)
#endif
#endif

View file

@ -1,199 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <algorithm>
#include "common/log_manager.h"
#include "common/console_listener.h"
#include "common/timer.h"
void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
const char* function, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
if (LogManager::GetInstance()) {
LogManager::GetInstance()->Log(level, type,
file, line, function, fmt, args);
}
va_end(args);
}
LogManager *LogManager::m_logManager = NULL;
LogManager::LogManager()
{
// create log files
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
m_Log[LogTypes::CONFIG] = new LogContainer("CONFIG", "Configuration");
m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt");
m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt");
m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap");
m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1");
m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt");
m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface");
m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface");
m_Log[LogTypes::GSP] = new LogContainer("GSP", "GSP");
m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt");
m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub");
m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
m_Log[LogTypes::ARM11] = new LogContainer("ARM11", "ARM11");
m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "JIT");
m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
m_Log[LogTypes::TIME] = new LogContainer("Time", "Core Timing");
m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader");
m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System");
m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
m_Log[LogTypes::KERNEL] = new LogContainer("KERNEL", "KERNEL HLE");
m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD");
m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES");
m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO", "WII IPC FILEIO");
m_Log[LogTypes::RENDER] = new LogContainer("RENDER", "RENDER");
m_Log[LogTypes::GPU] = new LogContainer("GPU", "GPU");
m_Log[LogTypes::SVC] = new LogContainer("SVC", "Supervisor Call HLE");
m_Log[LogTypes::NDMA] = new LogContainer("NDMA", "NDMA");
m_Log[LogTypes::HLE] = new LogContainer("HLE", "High Level Emulation");
m_Log[LogTypes::HW] = new LogContainer("HW", "Hardware");
m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
m_Log[LogTypes::GUI] = new LogContainer("GUI", "GUI");
m_fileLog = new FileLogListener(FileUtil::GetUserPath(F_MAINLOG_IDX).c_str());
m_consoleLog = new ConsoleListener();
m_debuggerLog = new DebuggerLogListener();
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
{
m_Log[i]->SetEnable(true);
m_Log[i]->AddListener(m_fileLog);
m_Log[i]->AddListener(m_consoleLog);
#ifdef _MSC_VER
if (IsDebuggerPresent())
m_Log[i]->AddListener(m_debuggerLog);
#endif
}
m_consoleLog->Open();
}
LogManager::~LogManager()
{
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
{
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog);
}
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
delete m_Log[i];
delete m_fileLog;
delete m_consoleLog;
delete m_debuggerLog;
}
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file,
int line, const char* function, const char *fmt, va_list args)
{
char temp[MAX_MSGLEN];
char msg[MAX_MSGLEN * 2];
LogContainer *log = m_Log[type];
if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners())
return;
Common::CharArrayFromFormatV(temp, MAX_MSGLEN, fmt, args);
static const char level_to_char[7] = "ONEWID";
sprintf(msg, "%s %s:%u %c[%s] %s: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line,
level_to_char[(int)level], log->GetShortName(), function, temp);
#ifdef ANDROID
Host_SysMessage(msg);
#endif
log->Trigger(level, msg);
}
void LogManager::Init()
{
m_logManager = new LogManager();
}
void LogManager::Shutdown()
{
delete m_logManager;
m_logManager = NULL;
}
LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable)
: m_enable(enable)
{
strncpy(m_fullName, fullName, 128);
strncpy(m_shortName, shortName, 32);
m_level = LogTypes::MAX_LOGLEVEL;
}
// LogContainer
void LogContainer::AddListener(LogListener *listener)
{
std::lock_guard<std::mutex> lk(m_listeners_lock);
m_listeners.insert(listener);
}
void LogContainer::RemoveListener(LogListener *listener)
{
std::lock_guard<std::mutex> lk(m_listeners_lock);
m_listeners.erase(listener);
}
void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
{
std::lock_guard<std::mutex> lk(m_listeners_lock);
std::set<LogListener*>::const_iterator i;
for (i = m_listeners.begin(); i != m_listeners.end(); ++i)
{
(*i)->Log(level, msg);
}
}
FileLogListener::FileLogListener(const char *filename)
{
OpenFStream(m_logfile, filename, std::ios::app);
SetEnable(true);
}
void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
{
if (!IsEnabled() || !IsValid())
return;
std::lock_guard<std::mutex> lk(m_log_lock);
m_logfile << msg << std::flush;
}
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
{
#if _MSC_VER
::OutputDebugStringA(msg);
#endif
}

View file

@ -1,166 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include "common/log.h"
#include "common/string_util.h"
#include "common/file_util.h"
#include <cstring>
#include <set>
#include <mutex>
#define MAX_MESSAGES 8000
#define MAX_MSGLEN 1024
// pure virtual interface
class LogListener
{
public:
virtual ~LogListener() {}
virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0;
};
class FileLogListener : public LogListener
{
public:
FileLogListener(const char *filename);
void Log(LogTypes::LOG_LEVELS, const char *msg) override;
bool IsValid() { return !m_logfile.fail(); }
bool IsEnabled() const { return m_enable; }
void SetEnable(bool enable) { m_enable = enable; }
const char* GetName() const { return "file"; }
private:
std::mutex m_log_lock;
std::ofstream m_logfile;
bool m_enable;
};
class DebuggerLogListener : public LogListener
{
public:
void Log(LogTypes::LOG_LEVELS, const char *msg) override;
};
class LogContainer
{
public:
LogContainer(const char* shortName, const char* fullName, bool enable = false);
const char* GetShortName() const { return m_shortName; }
const char* GetFullName() const { return m_fullName; }
void AddListener(LogListener* listener);
void RemoveListener(LogListener* listener);
void Trigger(LogTypes::LOG_LEVELS, const char *msg);
bool IsEnabled() const { return m_enable; }
void SetEnable(bool enable) { m_enable = enable; }
LogTypes::LOG_LEVELS GetLevel() const { return m_level; }
void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; }
bool HasListeners() const { return !m_listeners.empty(); }
private:
char m_fullName[128];
char m_shortName[32];
bool m_enable;
LogTypes::LOG_LEVELS m_level;
std::mutex m_listeners_lock;
std::set<LogListener*> m_listeners;
};
class ConsoleListener;
class LogManager : NonCopyable
{
private:
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
FileLogListener *m_fileLog;
ConsoleListener *m_consoleLog;
DebuggerLogListener *m_debuggerLog;
static LogManager *m_logManager; // Singleton. Ugh.
LogManager();
~LogManager();
public:
static u32 GetMaxLevel() { return LogTypes::MAX_LOGLEVEL; }
void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
const char* function, const char *fmt, va_list args);
void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level)
{
m_Log[type]->SetLevel(level);
}
void SetEnable(LogTypes::LOG_TYPE type, bool enable)
{
m_Log[type]->SetEnable(enable);
}
bool IsEnabled(LogTypes::LOG_TYPE type) const
{
return m_Log[type]->IsEnabled();
}
const char* GetShortName(LogTypes::LOG_TYPE type) const
{
return m_Log[type]->GetShortName();
}
const char* GetFullName(LogTypes::LOG_TYPE type) const
{
return m_Log[type]->GetFullName();
}
void AddListener(LogTypes::LOG_TYPE type, LogListener *listener)
{
m_Log[type]->AddListener(listener);
}
void RemoveListener(LogTypes::LOG_TYPE type, LogListener *listener)
{
m_Log[type]->RemoveListener(listener);
}
FileLogListener *GetFileListener() const
{
return m_fileLog;
}
ConsoleListener *GetConsoleListener() const
{
return m_consoleLog;
}
DebuggerLogListener *GetDebuggerListener() const
{
return m_debuggerLog;
}
static LogManager* GetInstance()
{
return m_logManager;
}
static void SetInstance(LogManager *logManager)
{
m_logManager = logManager;
}
static void Init();
static void Shutdown();
};

View file

@ -0,0 +1,151 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/log.h" // For _dbg_assert_
#include "common/logging/backend.h"
#include "common/logging/log.h"
#include "common/logging/text_formatter.h"
namespace Log {
static std::shared_ptr<Logger> global_logger;
/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this.
#define ALL_LOG_CLASSES() \
CLS(Log) \
CLS(Common) \
SUB(Common, Filesystem) \
SUB(Common, Memory) \
CLS(Core) \
SUB(Core, ARM11) \
CLS(Config) \
CLS(Debug) \
SUB(Debug, Emulated) \
SUB(Debug, GPU) \
SUB(Debug, Breakpoint) \
CLS(Kernel) \
SUB(Kernel, SVC) \
CLS(Service) \
SUB(Service, SRV) \
SUB(Service, FS) \
SUB(Service, APT) \
SUB(Service, GSP) \
SUB(Service, AC) \
SUB(Service, PTM) \
SUB(Service, CFG) \
SUB(Service, DSP) \
SUB(Service, HID) \
CLS(HW) \
SUB(HW, Memory) \
SUB(HW, GPU) \
CLS(Frontend) \
CLS(Render) \
SUB(Render, Software) \
SUB(Render, OpenGL) \
CLS(Loader)
Logger::Logger() {
// Register logging classes so that they can be queried at runtime
size_t parent_class;
all_classes.reserve((size_t)Class::Count);
#define CLS(x) \
all_classes.push_back(Class::x); \
parent_class = all_classes.size() - 1;
#define SUB(x, y) \
all_classes.push_back(Class::x##_##y); \
all_classes[parent_class].num_children += 1;
ALL_LOG_CLASSES()
#undef CLS
#undef SUB
// Ensures that ALL_LOG_CLASSES isn't missing any entries.
_dbg_assert_(Log, all_classes.size() == (size_t)Class::Count);
}
// GetClassName is a macro defined by Windows.h, grrr...
const char* Logger::GetLogClassName(Class log_class) {
switch (log_class) {
#define CLS(x) case Class::x: return #x;
#define SUB(x, y) case Class::x##_##y: return #x "." #y;
ALL_LOG_CLASSES()
#undef CLS
#undef SUB
}
return "Unknown";
}
const char* Logger::GetLevelName(Level log_level) {
#define LVL(x) case Level::x: return #x
switch (log_level) {
LVL(Trace);
LVL(Debug);
LVL(Info);
LVL(Warning);
LVL(Error);
LVL(Critical);
}
return "Unknown";
#undef LVL
}
void Logger::LogMessage(Entry entry) {
ring_buffer.Push(std::move(entry));
}
size_t Logger::GetEntries(Entry* out_buffer, size_t buffer_len) {
return ring_buffer.BlockingPop(out_buffer, buffer_len);
}
std::shared_ptr<Logger> InitGlobalLogger() {
global_logger = std::make_shared<Logger>();
return global_logger;
}
Entry CreateEntry(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
const char* format, va_list args) {
using std::chrono::steady_clock;
using std::chrono::duration_cast;
static steady_clock::time_point time_origin = steady_clock::now();
std::array<char, 4 * 1024> formatting_buffer;
Entry entry;
entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
entry.log_class = log_class;
entry.log_level = log_level;
snprintf(formatting_buffer.data(), formatting_buffer.size(), "%s:%s:%u", filename, function, line_nr);
entry.location = std::string(formatting_buffer.data());
vsnprintf(formatting_buffer.data(), formatting_buffer.size(), format, args);
entry.message = std::string(formatting_buffer.data());
return std::move(entry);
}
void LogMessage(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
const char* format, ...) {
va_list args;
va_start(args, format);
Entry entry = CreateEntry(log_class, log_level,
filename, line_nr, function, format, args);
va_end(args);
if (global_logger != nullptr && !global_logger->IsClosed()) {
global_logger->LogMessage(std::move(entry));
} else {
// Fall back to directly printing to stderr
PrintMessage(entry);
}
}
}

View file

@ -0,0 +1,134 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <cstdarg>
#include <memory>
#include <vector>
#include "common/concurrent_ring_buffer.h"
#include "common/logging/log.h"
namespace Log {
/**
* A log entry. Log entries are store in a structured format to permit more varied output
* formatting on different frontends, as well as facilitating filtering and aggregation.
*/
struct Entry {
std::chrono::microseconds timestamp;
Class log_class;
Level log_level;
std::string location;
std::string message;
Entry() = default;
// TODO(yuriks) Use defaulted move constructors once MSVC supports them
#define MOVE(member) member(std::move(o.member))
Entry(Entry&& o)
: MOVE(timestamp), MOVE(log_class), MOVE(log_level),
MOVE(location), MOVE(message)
{}
#undef MOVE
Entry& operator=(const Entry&& o) {
#define MOVE(member) member = std::move(o.member)
MOVE(timestamp);
MOVE(log_class);
MOVE(log_level);
MOVE(location);
MOVE(message);
#undef MOVE
return *this;
}
};
struct ClassInfo {
Class log_class;
/**
* Total number of (direct or indirect) sub classes this class has. If any, they follow in
* sequence after this class in the class list.
*/
unsigned int num_children = 0;
ClassInfo(Class log_class) : log_class(log_class) {}
};
/**
* Logging management class. This class has the dual purpose of acting as an exchange point between
* the logging clients and the log outputter, as well as containing reflection info about available
* log classes.
*/
class Logger {
private:
using Buffer = Common::ConcurrentRingBuffer<Entry, 16 * 1024 / sizeof(Entry)>;
public:
static const size_t QUEUE_CLOSED = Buffer::QUEUE_CLOSED;
Logger();
/**
* Returns a list of all vector classes and subclasses. The sequence returned is a pre-order of
* classes and subclasses, which together with the `num_children` field in ClassInfo, allows
* you to recover the hierarchy.
*/
const std::vector<ClassInfo>& GetClasses() const { return all_classes; }
/**
* Returns the name of the passed log class as a C-string. Subclasses are separated by periods
* instead of underscores as in the enumeration.
*/
static const char* GetLogClassName(Class log_class);
/**
* Returns the name of the passed log level as a C-string.
*/
static const char* GetLevelName(Level log_level);
/**
* Appends a messages to the log buffer.
* @note This function is thread safe.
*/
void LogMessage(Entry entry);
/**
* Retrieves a batch of messages from the log buffer, blocking until they are available.
* @note This function is thread safe.
*
* @param out_buffer Destination buffer that will receive the log entries.
* @param buffer_len The maximum size of `out_buffer`.
* @return The number of entries stored. In case the logger is shutting down, `QUEUE_CLOSED` is
* returned, no entries are stored and the logger should shutdown.
*/
size_t GetEntries(Entry* out_buffer, size_t buffer_len);
/**
* Initiates a shutdown of the logger. This will indicate to log output clients that they
* should shutdown.
*/
void Close() { ring_buffer.Close(); }
/**
* Returns true if Close() has already been called on the Logger.
*/
bool IsClosed() const { return ring_buffer.IsClosed(); }
private:
Buffer ring_buffer;
std::vector<ClassInfo> all_classes;
};
/// Creates a log entry by formatting the given source location, and message.
Entry CreateEntry(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
const char* format, va_list args);
/// Initializes the default Logger.
std::shared_ptr<Logger> InitGlobalLogger();
}

View file

@ -0,0 +1,132 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/logging/filter.h"
#include "common/logging/backend.h"
#include "common/string_util.h"
namespace Log {
Filter::Filter(Level default_level) {
ResetAll(default_level);
}
void Filter::ResetAll(Level level) {
class_levels.fill(level);
}
void Filter::SetClassLevel(Class log_class, Level level) {
class_levels[static_cast<size_t>(log_class)] = level;
}
void Filter::SetSubclassesLevel(const ClassInfo& log_class, Level level) {
const size_t log_class_i = static_cast<size_t>(log_class.log_class);
const size_t begin = log_class_i + 1;
const size_t end = begin + log_class.num_children;
for (size_t i = begin; begin < end; ++i) {
class_levels[i] = level;
}
}
void Filter::ParseFilterString(const std::string& filter_str) {
auto clause_begin = filter_str.cbegin();
while (clause_begin != filter_str.cend()) {
auto clause_end = std::find(clause_begin, filter_str.cend(), ' ');
// If clause isn't empty
if (clause_end != clause_begin) {
ParseFilterRule(clause_begin, clause_end);
}
if (clause_end != filter_str.cend()) {
// Skip over the whitespace
++clause_end;
}
clause_begin = clause_end;
}
}
template <typename It>
static Level GetLevelByName(const It begin, const It end) {
for (u8 i = 0; i < static_cast<u8>(Level::Count); ++i) {
const char* level_name = Logger::GetLevelName(static_cast<Level>(i));
if (Common::ComparePartialString(begin, end, level_name)) {
return static_cast<Level>(i);
}
}
return Level::Count;
}
template <typename It>
static Class GetClassByName(const It begin, const It end) {
for (ClassType i = 0; i < static_cast<ClassType>(Class::Count); ++i) {
const char* level_name = Logger::GetLogClassName(static_cast<Class>(i));
if (Common::ComparePartialString(begin, end, level_name)) {
return static_cast<Class>(i);
}
}
return Class::Count;
}
template <typename InputIt, typename T>
static InputIt find_last(InputIt begin, const InputIt end, const T& value) {
auto match = end;
while (begin != end) {
auto new_match = std::find(begin, end, value);
if (new_match != end) {
match = new_match;
++new_match;
}
begin = new_match;
}
return match;
}
bool Filter::ParseFilterRule(const std::string::const_iterator begin,
const std::string::const_iterator end) {
auto level_separator = std::find(begin, end, ':');
if (level_separator == end) {
LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: %s",
std::string(begin, end).c_str());
return false;
}
const Level level = GetLevelByName(level_separator + 1, end);
if (level == Level::Count) {
LOG_ERROR(Log, "Unknown log level in filter: %s", std::string(begin, end).c_str());
return false;
}
if (Common::ComparePartialString(begin, level_separator, "*")) {
ResetAll(level);
return true;
}
auto class_name_end = find_last(begin, level_separator, '.');
if (class_name_end != level_separator &&
!Common::ComparePartialString(class_name_end + 1, level_separator, "*")) {
class_name_end = level_separator;
}
const Class log_class = GetClassByName(begin, class_name_end);
if (log_class == Class::Count) {
LOG_ERROR(Log, "Unknown log class in filter: %s", std::string(begin, end).c_str());
return false;
}
if (class_name_end == level_separator) {
SetClassLevel(log_class, level);
}
SetSubclassesLevel(log_class, level);
return true;
}
bool Filter::CheckMessage(Class log_class, Level level) const {
return static_cast<u8>(level) >= static_cast<u8>(class_levels[static_cast<size_t>(log_class)]);
}
}

View file

@ -0,0 +1,63 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <array>
#include <string>
#include "common/logging/log.h"
namespace Log {
struct ClassInfo;
/**
* Implements a log message filter which allows different log classes to have different minimum
* severity levels. The filter can be changed at runtime and can be parsed from a string to allow
* editing via the interface or loading from a configuration file.
*/
class Filter {
public:
/// Initializes the filter with all classes having `default_level` as the minimum level.
Filter(Level default_level);
/// Resets the filter so that all classes have `level` as the minimum displayed level.
void ResetAll(Level level);
/// Sets the minimum level of `log_class` (and not of its subclasses) to `level`.
void SetClassLevel(Class log_class, Level level);
/**
* Sets the minimum level of all of `log_class` subclasses to `level`. The level of `log_class`
* itself is not changed.
*/
void SetSubclassesLevel(const ClassInfo& log_class, Level level);
/**
* Parses a filter string and applies it to this filter.
*
* A filter string consists of a space-separated list of filter rules, each of the format
* `<class>:<level>`. `<class>` is a log class name, with subclasses separated using periods.
* A rule for a given class also affects all of its subclasses. `*` wildcards are allowed and
* can be used to apply a rule to all classes or to all subclasses of a class without affecting
* the parent class. `<level>` a severity level name which will be set as the minimum logging
* level of the matched classes. Rules are applied left to right, with each rule overriding
* previous ones in the sequence.
*
* A few examples of filter rules:
* - `*:Info` -- Resets the level of all classes to Info.
* - `Service:Info` -- Sets the level of Service and all subclasses (Service.FS, Service.APT,
* etc.) to Info.
* - `Service.*:Debug` -- Sets the level of all Service subclasses to Debug, while leaving the
* level of Service unchanged.
* - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace.
*/
void ParseFilterString(const std::string& filter_str);
bool ParseFilterRule(const std::string::const_iterator start, const std::string::const_iterator end);
/// Matches class/level combination against the filter, returning true if it passed.
bool CheckMessage(Class log_class, Level level) const;
private:
std::array<Level, (size_t)Class::Count> class_levels;
};
}

115
src/common/logging/log.h Normal file
View file

@ -0,0 +1,115 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <cassert>
#include <chrono>
#include <string>
#include "common/common_types.h"
namespace Log {
/// Specifies the severity or level of detail of the log message.
enum class Level : u8 {
Trace, ///< Extremely detailed and repetitive debugging information that is likely to
/// pollute logs.
Debug, ///< Less detailed debugging information.
Info, ///< Status information from important points during execution.
Warning, ///< Minor or potential problems found during execution of a task.
Error, ///< Major problems found during execution of a task that prevent it from being
/// completed.
Critical, ///< Major problems during execution that threathen the stability of the entire
/// application.
Count ///< Total number of logging levels
};
typedef u8 ClassType;
/**
* Specifies the sub-system that generated the log message.
*
* @note If you add a new entry here, also add a corresponding one to `ALL_LOG_CLASSES` in log.cpp.
*/
enum class Class : ClassType {
Log, ///< Messages about the log system itself
Common, ///< Library routines
Common_Filesystem, ///< Filesystem interface library
Common_Memory, ///< Memory mapping and management functions
Core, ///< LLE emulation core
Core_ARM11, ///< ARM11 CPU core
Config, ///< Emulator configuration (including commandline)
Debug, ///< Debugging tools
Debug_Emulated, ///< Debug messages from the emulated programs
Debug_GPU, ///< GPU debugging tools
Debug_Breakpoint, ///< Logging breakpoints and watchpoints
Kernel, ///< The HLE implementation of the CTR kernel
Kernel_SVC, ///< Kernel system calls
Service, ///< HLE implementation of system services. Each major service
/// should have its own subclass.
Service_SRV, ///< The SRV (Service Directory) implementation
Service_FS, ///< The FS (Filesystem) service implementation
Service_APT, ///< The APT (Applets) service
Service_GSP, ///< The GSP (GPU control) service
Service_AC, ///< The AC (WiFi status) service
Service_PTM, ///< The PTM (Power status & misc.) service
Service_CFG, ///< The CFG (Configuration) service
Service_DSP, ///< The DSP (DSP control) service
Service_HID, ///< The HID (User input) service
HW, ///< Low-level hardware emulation
HW_Memory, ///< Memory-map and address translation
HW_GPU, ///< GPU control emulation
Frontend, ///< Emulator UI
Render, ///< Emulator video output and hardware acceleration
Render_Software, ///< Software renderer backend
Render_OpenGL, ///< OpenGL backend
Loader, ///< ROM loader
Count ///< Total number of logging classes
};
/**
* Level below which messages are simply discarded without buffering regardless of the display
* settings.
*/
const Level MINIMUM_LEVEL =
#ifdef _DEBUG
Level::Trace;
#else
Level::Debug;
#endif
/**
* Logs a message to the global logger. This proxy exists to avoid exposing the details of the
* Logger class, including the ConcurrentRingBuffer template, to all files that desire to log
* messages, reducing unecessary recompilations.
*/
void LogMessage(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
#ifdef _MSC_VER
_Printf_format_string_
#endif
const char* format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 6, 7)))
#endif
;
} // namespace Log
#define LOG_GENERIC(log_class, log_level, ...) \
do { \
if (::Log::Level::log_level >= ::Log::MINIMUM_LEVEL) \
::Log::LogMessage(::Log::Class::log_class, ::Log::Level::log_level, \
__FILE__, __LINE__, __func__, __VA_ARGS__); \
} while (0)
#define LOG_TRACE( log_class, ...) LOG_GENERIC(log_class, Trace, __VA_ARGS__)
#define LOG_DEBUG( log_class, ...) LOG_GENERIC(log_class, Debug, __VA_ARGS__)
#define LOG_INFO( log_class, ...) LOG_GENERIC(log_class, Info, __VA_ARGS__)
#define LOG_WARNING( log_class, ...) LOG_GENERIC(log_class, Warning, __VA_ARGS__)
#define LOG_ERROR( log_class, ...) LOG_GENERIC(log_class, Error, __VA_ARGS__)
#define LOG_CRITICAL(log_class, ...) LOG_GENERIC(log_class, Critical, __VA_ARGS__)

View file

@ -0,0 +1,136 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <array>
#include <cstdio>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <Windows.h>
#endif
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
#include "common/logging/text_formatter.h"
#include "common/string_util.h"
namespace Log {
// TODO(bunnei): This should be moved to a generic path manipulation library
const char* TrimSourcePath(const char* path, const char* root) {
const char* p = path;
while (*p != '\0') {
const char* next_slash = p;
while (*next_slash != '\0' && *next_slash != '/' && *next_slash != '\\') {
++next_slash;
}
bool is_src = Common::ComparePartialString(p, next_slash, root);
p = next_slash;
if (*p != '\0') {
++p;
}
if (is_src) {
path = p;
}
}
return path;
}
void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len) {
unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000);
unsigned int time_fractional = static_cast<unsigned int>(entry.timestamp.count() % 1000000);
const char* class_name = Logger::GetLogClassName(entry.log_class);
const char* level_name = Logger::GetLevelName(entry.log_level);
snprintf(out_text, text_len, "[%4u.%06u] %s <%s> %s: %s",
time_seconds, time_fractional, class_name, level_name,
TrimSourcePath(entry.location.c_str()), entry.message.c_str());
}
void PrintMessage(const Entry& entry) {
std::array<char, 4 * 1024> format_buffer;
FormatLogMessage(entry, format_buffer.data(), format_buffer.size());
fputs(format_buffer.data(), stderr);
fputc('\n', stderr);
}
void PrintColoredMessage(const Entry& entry) {
#ifdef _WIN32
static HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO original_info = {0};
GetConsoleScreenBufferInfo(console_handle, &original_info);
WORD color = 0;
switch (entry.log_level) {
case Level::Trace: // Grey
color = FOREGROUND_INTENSITY; break;
case Level::Debug: // Cyan
color = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
case Level::Info: // Bright gray
color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
case Level::Warning: // Bright yellow
color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; break;
case Level::Error: // Bright red
color = FOREGROUND_RED | FOREGROUND_INTENSITY; break;
case Level::Critical: // Bright magenta
color = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY; break;
}
SetConsoleTextAttribute(console_handle, color);
#else
# define ESC "\x1b"
const char* color = "";
switch (entry.log_level) {
case Level::Trace: // Grey
color = ESC "[1;30m"; break;
case Level::Debug: // Cyan
color = ESC "[0;36m"; break;
case Level::Info: // Bright gray
color = ESC "[0;37m"; break;
case Level::Warning: // Bright yellow
color = ESC "[1;33m"; break;
case Level::Error: // Bright red
color = ESC "[1;31m"; break;
case Level::Critical: // Bright magenta
color = ESC "[1;35m"; break;
}
fputs(color, stderr);
#endif
PrintMessage(entry);
#ifdef _WIN32
SetConsoleTextAttribute(console_handle, original_info.wAttributes);
#else
fputs(ESC "[0m", stderr);
# undef ESC
#endif
}
void TextLoggingLoop(std::shared_ptr<Logger> logger, const Filter* filter) {
std::array<Entry, 256> entry_buffer;
while (true) {
size_t num_entries = logger->GetEntries(entry_buffer.data(), entry_buffer.size());
if (num_entries == Logger::QUEUE_CLOSED) {
break;
}
for (size_t i = 0; i < num_entries; ++i) {
const Entry& entry = entry_buffer[i];
if (filter->CheckMessage(entry.log_class, entry.log_level)) {
PrintColoredMessage(entry);
}
}
}
}
}

View file

@ -0,0 +1,41 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <cstddef>
#include <memory>
namespace Log {
class Logger;
struct Entry;
class Filter;
/**
* Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's
* intended to be used to strip a system-specific build directory from the `__FILE__` macro,
* leaving only the path relative to the sources root.
*
* @param path The input file path as a null-terminated string
* @param root The name of the root source directory as a null-terminated string. Path up to and
* including the last occurence of this name will be stripped
* @return A pointer to the same string passed as `path`, but starting at the trimmed portion
*/
const char* TrimSourcePath(const char* path, const char* root = "src");
/// Formats a log entry into the provided text buffer.
void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len);
/// Formats and prints a log entry to stderr.
void PrintMessage(const Entry& entry);
/// Prints the same message as `PrintMessage`, but colored acoording to the severity level.
void PrintColoredMessage(const Entry& entry);
/**
* Logging loop that repeatedly reads messages from the provided logger and prints them to the
* console. It is the baseline barebones log outputter.
*/
void TextLoggingLoop(std::shared_ptr<Logger> logger, const Filter* filter);
}

16
src/common/make_unique.h Normal file
View file

@ -0,0 +1,16 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
namespace Common {
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
} // namespace

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -30,7 +30,7 @@
#endif
#ifdef IOS
void* globalbase = NULL;
void* globalbase = nullptr;
#endif
#ifdef ANDROID
@ -71,7 +71,7 @@ int ashmem_create_region(const char *name, size_t size)
return fd;
error:
ERROR_LOG(MEMMAP, "NASTY ASHMEM ERROR: ret = %08x", ret);
LOG_ERROR(Common_Memory, "NASTY ASHMEM ERROR: ret = %08x", ret);
close(fd);
return ret;
}
@ -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)
@ -130,7 +130,7 @@ void MemArena::GrabLowMemSpace(size_t size)
// Note that it appears that ashmem is pinned by default, so no need to pin.
if (fd < 0)
{
ERROR_LOG(MEMMAP, "Failed to grab ashmem space of size: %08x errno: %d", (int)size, (int)(errno));
LOG_ERROR(Common_Memory, "Failed to grab ashmem space of size: %08x errno: %d", (int)size, (int)(errno));
return;
}
#else
@ -148,12 +148,12 @@ void MemArena::GrabLowMemSpace(size_t size)
}
else if (errno != EEXIST)
{
ERROR_LOG(MEMMAP, "shm_open failed: %s", strerror(errno));
LOG_ERROR(Common_Memory, "shm_open failed: %s", strerror(errno));
return;
}
}
if (ftruncate(fd, size) < 0)
ERROR_LOG(MEMMAP, "Failed to allocate low memory space");
LOG_ERROR(Common_Memory, "Failed to allocate low memory space");
#endif
}
@ -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);
@ -197,7 +197,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base)
if (retval == MAP_FAILED)
{
NOTICE_LOG(MEMMAP, "mmap failed");
LOG_ERROR(Common_Memory, "mmap failed");
return nullptr;
}
return retval;
@ -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)
{
@ -423,7 +423,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
base = (u8 *)base_addr;
if (Memory_TryBase(base, views, num_views, flags, arena))
{
INFO_LOG(MEMMAP, "Found valid memory base at %p after %i tries.", base, base_attempts);
LOG_DEBUG(Common_Memory, "Found valid memory base at %p after %i tries.", base, base_attempts);
base_attempts = 0;
break;
}
@ -442,7 +442,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
u8 *base = MemArena::Find4GBBase();
if (!Memory_TryBase(base, views, num_views, flags, arena))
{
ERROR_LOG(MEMMAP, "MemoryMap_Setup: Failed finding a memory base.");
LOG_ERROR(Common_Memory, "MemoryMap_Setup: Failed finding a memory base.");
PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
return 0;
}
@ -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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@ -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,19 +104,19 @@ 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
if (posix_memalign(&ptr, alignment, size) != 0)
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
LOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
#endif
#endif
// 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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/common.h"
@ -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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cstdio>
@ -75,7 +75,7 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
Common::CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args);
va_end(args);
ERROR_LOG(MASTER_LOG, "%s: %s", caption.c_str(), buffer);
LOG_INFO(Common, "%s: %s", caption.c_str(), buffer);
// Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
if (msg_handler && (AlertEnabled || Style == QUESTION || Style == CRITICAL))

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -80,7 +80,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;
}
#endif

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

37
src/common/scope_exit.h Normal file
View file

@ -0,0 +1,37 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
namespace detail {
template <typename Func>
struct ScopeExitHelper {
explicit ScopeExitHelper(Func&& func) : func(std::move(func)) {}
~ScopeExitHelper() { func(); }
Func func;
};
template <typename Func>
ScopeExitHelper<Func> ScopeExit(Func&& func) { return ScopeExitHelper<Func>(std::move(func)); }
}
/**
* This macro allows you to conveniently specify a block of code that will run on scope exit. Handy
* for doing ad-hoc clean-up tasks in a function with multiple returns.
*
* Example usage:
* \code
* const int saved_val = g_foo;
* g_foo = 55;
* SCOPE_EXIT({ g_foo = saved_val; });
*
* if (Bar()) {
* return 0;
* } else {
* return 20;
* }
* \endcode
*/
#define SCOPE_EXIT(body) auto scope_exit_helper_##__LINE__ = detail::ScopeExit([&]() body)

View file

@ -1,8 +1,8 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <boost/range/algorithm.hpp>
#include "common/common.h"
#include "common/string_util.h"
@ -18,20 +18,20 @@ namespace Common {
/// Make a string lowercase
std::string ToLower(std::string str) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
boost::transform(str, str.begin(), ::tolower);
return str;
}
/// Make a string uppercase
std::string ToUpper(std::string str) {
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
boost::transform(str, str.begin(), ::toupper);
return 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;
@ -107,7 +107,7 @@ std::string StringFromFormat(const char* format, ...)
#else
va_start(args, format);
if (vasprintf(&buf, format, args) < 0)
ERROR_LOG(COMMON, "Unable to allocate memory for string");
LOG_ERROR(Common, "Unable to allocate memory for string");
va_end(args);
std::string temp = buf;
@ -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;
@ -475,7 +475,7 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
if ((iconv_t)(-1) == conv_desc)
{
ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
LOG_ERROR(Common, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
iconv_close(conv_desc);
return {};
}
@ -510,7 +510,7 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
}
else
{
ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
LOG_ERROR(Common, "iconv failure [%s]: %s", fromcode, strerror(errno));
break;
}
}
@ -528,10 +528,10 @@ std::u16string UTF8ToUTF16(const std::string& input)
{
std::u16string result;
iconv_t const conv_desc = iconv_open("UTF-16", "UTF-8");
iconv_t const conv_desc = iconv_open("UTF-16LE", "UTF-8");
if ((iconv_t)(-1) == conv_desc)
{
ERROR_LOG(COMMON, "Iconv initialization failure [UTF-8]: %s", strerror(errno));
LOG_ERROR(Common, "Iconv initialization failure [UTF-8]: %s", strerror(errno));
iconv_close(conv_desc);
return {};
}
@ -566,7 +566,7 @@ std::u16string UTF8ToUTF16(const std::string& input)
}
else
{
ERROR_LOG(COMMON, "iconv failure [UTF-8]: %s", strerror(errno));
LOG_ERROR(Common, "iconv failure [UTF-8]: %s", strerror(errno));
break;
}
}
@ -582,7 +582,7 @@ std::u16string UTF8ToUTF16(const std::string& input)
std::string UTF16ToUTF8(const std::u16string& input)
{
return CodeToUTF8("UTF-16", input);
return CodeToUTF8("UTF-16LE", input);
}
std::string CP1252ToUTF8(const std::string& input)

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -115,4 +115,19 @@ inline std::string UTF8ToTStr(const std::string& str)
#endif
/**
* Compares the string defined by the range [`begin`, `end`) to the null-terminated C-string
* `other` for equality.
*/
template <typename InIt>
bool ComparePartialString(InIt begin, InIt end, const char* other) {
for (; begin != end && *other != '\0'; ++begin, ++other) {
if (*begin != *other) {
return false;
}
}
// Only return true if both strings finished at the same point
return (begin == end) == (*other == '\0');
}
}

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/symbols.h"

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/thread.h"

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -21,6 +21,7 @@
//for gettimeofday and struct time(spec|val)
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#endif
namespace Common

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project / PPSSPP Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <time.h>
@ -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

@ -1,5 +1,5 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

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