(view as text)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dade7a6..6b5d555 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -363,7 +363,7 @@ if(NOT ANDROID)
message("bluez NOT found, disabling bluetooth support")
endif(BLUEZ_FOUND)
- check_lib(PULSEAUDIO libpulse-simple QUIET)
+ check_lib(PULSEAUDIO libpulse QUIET)
if(PULSEAUDIO_FOUND)
add_definitions(-DHAVE_PULSEAUDIO=1)
message("PulseAudio found, enabling PulseAudio sound backend")
diff --git a/Source/Core/AudioCommon/PulseAudioStream.cpp b/Source/Core/AudioCommon/PulseAudioStream.cpp
index 13307a8..fe68d0e 100644
--- a/Source/Core/AudioCommon/PulseAudioStream.cpp
+++ b/Source/Core/AudioCommon/PulseAudioStream.cpp
@@ -11,30 +11,28 @@
namespace
{
-const size_t BUFFER_SAMPLES = 512;
+const size_t BUFFER_SAMPLES = 512; // ~10 ms
const size_t CHANNEL_COUNT = 2;
-const size_t BUFFER_SIZE = BUFFER_SAMPLES * CHANNEL_COUNT;
+const size_t BUFFER_SIZE = BUFFER_SAMPLES * CHANNEL_COUNT * sizeof(s16);
}
PulseAudio::PulseAudio(CMixer *mixer)
: SoundStream(mixer)
- , mix_buffer(BUFFER_SIZE)
- , thread()
- , run_thread()
- , pa()
+ , m_thread()
+ , m_run_thread()
{}
bool PulseAudio::Start()
{
- run_thread = true;
- thread = std::thread(std::mem_fun(&PulseAudio::SoundLoop), this);
+ m_run_thread = true;
+ m_thread = std::thread(std::mem_fun(&PulseAudio::SoundLoop), this);
return true;
}
void PulseAudio::Stop()
{
- run_thread = false;
- thread.join();
+ m_run_thread = false;
+ m_thread.join();
}
void PulseAudio::Update()
@@ -49,11 +47,11 @@ void PulseAudio::SoundLoop()
if (PulseInit())
{
- while (run_thread)
- {
- m_mixer->Mix(&mix_buffer[0], mix_buffer.size() / CHANNEL_COUNT);
- Write(&mix_buffer[0], mix_buffer.size() * sizeof(s16));
- }
+ while (m_run_thread.load() && m_pa_connected == 1 && m_pa_error >= 0)
+ m_pa_error = pa_mainloop_iterate(m_pa_ml, 1, NULL);
+
+ if(m_pa_error < 0)
+ ERROR_LOG(AUDIO, "PulseAudio error: %s", pa_strerror(m_pa_error));
PulseShutdown();
}
@@ -61,39 +59,117 @@ void PulseAudio::SoundLoop()
bool PulseAudio::PulseInit()
{
- pa_sample_spec ss = {};
+ m_pa_error = 0;
+ m_pa_connected = 0;
+
+ // create pulseaudio main loop and context
+ // also register the async state callback which is called when the connection to the pa server has changed
+ m_pa_ml = pa_mainloop_new();
+ m_pa_mlapi = pa_mainloop_get_api(m_pa_ml);
+ m_pa_ctx = pa_context_new(m_pa_mlapi, "dolphin-emu");
+ m_pa_error = pa_context_connect(m_pa_ctx, NULL, PA_CONTEXT_NOFLAGS, NULL);
+ pa_context_set_state_callback(m_pa_ctx, StateCallback, this);
+
+ // wait until we're connected to the pulseaudio server
+ while (m_pa_connected == 0 && m_pa_error >= 0)
+ m_pa_error = pa_mainloop_iterate(m_pa_ml, 1, NULL);
+
+ if (m_pa_connected == 2 || m_pa_error < 0)
+ {
+ ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", pa_strerror(m_pa_error));
+ return false;
+ }
+
+ // create a new audio stream with our sample format
+ // also connect the callbacks for this stream
+ pa_sample_spec ss;
ss.format = PA_SAMPLE_S16LE;
ss.channels = 2;
ss.rate = m_mixer->GetSampleRate();
-
- int error;
- pa = pa_simple_new(nullptr, "dolphin-emu", PA_STREAM_PLAYBACK,
- nullptr, "audio", &ss, nullptr, nullptr, &error);
-
- if (!pa)
+ m_pa_s = pa_stream_new(m_pa_ctx, "Playback", &ss, NULL);
+ pa_stream_set_write_callback(m_pa_s, WriteCallback, this);
+ pa_stream_set_underflow_callback(m_pa_s, UnderflowCallback, this);
+
+ // connect this audio stream to the default audio playback
+ // limit buffersize to reduce latency
+ m_pa_ba.fragsize = -1;
+ m_pa_ba.maxlength = -1; // max buffer, so also max latency
+ m_pa_ba.minreq = -1; // don't read every byte, try to group them _a bit_
+ m_pa_ba.prebuf = -1; // start as early as possible
+ m_pa_ba.tlength = BUFFER_SIZE; // designed latency, only change this flag for low latency output
+ pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE);
+ m_pa_error = pa_stream_connect_playback(m_pa_s, NULL, &m_pa_ba, flags, NULL, NULL);
+ if (m_pa_error < 0)
{
- ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s",
- pa_strerror(error));
+ ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", pa_strerror(m_pa_error));
return false;
}
- else
- {
- NOTICE_LOG(AUDIO, "Pulse successfully initialized.");
- return true;
- }
+
+ INFO_LOG(AUDIO, "Pulse successfully initialized");
+ return true;
}
void PulseAudio::PulseShutdown()
{
- pa_simple_free(pa);
+ pa_context_disconnect(m_pa_ctx);
+ pa_context_unref(m_pa_ctx);
+ pa_mainloop_free(m_pa_ml);
}
-void PulseAudio::Write(const void *data, size_t length)
+void PulseAudio::StateCallback(pa_context* c)
{
- int error;
- if (pa_simple_write(pa, data, length, &error) < 0)
+ pa_context_state_t state = pa_context_get_state(c);
+ switch (state)
{
- ERROR_LOG(AUDIO, "PulseAudio failed to write data: %s",
- pa_strerror(error));
+ case PA_CONTEXT_FAILED:
+ case PA_CONTEXT_TERMINATED:
+ m_pa_connected = 2;
+ break;
+ case PA_CONTEXT_READY:
+ m_pa_connected = 1;
+ break;
+ default:
+ break;
}
}
+// on underflow, increase pulseaudio latency in ~10ms steps
+void PulseAudio::UnderflowCallback(pa_stream* s)
+{
+ m_pa_ba.tlength += BUFFER_SIZE;
+ pa_stream_set_buffer_attr(s, &m_pa_ba, NULL, NULL);
+
+ WARN_LOG(AUDIO, "pulseaudio underflow, new latency: %d bytes", m_pa_ba.tlength);
+}
+
+void PulseAudio::WriteCallback(pa_stream* s, size_t length)
+{
+ // fetch dst buffer directly from pulseaudio, so no memcpy is needed
+ void* buffer;
+ m_pa_error = pa_stream_begin_write(s, &buffer, &length);
+
+ if (!buffer || m_pa_error < 0)
+ return; // error will be printed from main loop
+
+ m_mixer->Mix((s16*) buffer, length / sizeof(s16) / CHANNEL_COUNT);
+ m_pa_error = pa_stream_write(s, buffer, length, NULL, 0, PA_SEEK_RELATIVE);
+}
+
+// Callbacks that forward to internal methods (required because PulseAudio is a C API).
+
+void PulseAudio::StateCallback(pa_context* c, void* userdata)
+{
+ PulseAudio* p = (PulseAudio*) userdata;
+ p->StateCallback(c);
+}
+
+void PulseAudio::UnderflowCallback(pa_stream* s, void* userdata)
+{
+ PulseAudio* p = (PulseAudio*) userdata;
+ p->UnderflowCallback(s);
+}
+
+void PulseAudio::WriteCallback(pa_stream* s, size_t length, void* userdata)
+{
+ PulseAudio* p = (PulseAudio*) userdata;
+ p->WriteCallback(s, length);
+}
diff --git a/Source/Core/AudioCommon/PulseAudioStream.h b/Source/Core/AudioCommon/PulseAudioStream.h
index 8be8eae..3164a4e 100644
--- a/Source/Core/AudioCommon/PulseAudioStream.h
+++ b/Source/Core/AudioCommon/PulseAudioStream.h
@@ -6,17 +6,16 @@
#define _PULSE_AUDIO_STREAM_H
#if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO
-#include <pulse/simple.h>
-#include <pulse/error.h>
+#include <pulse/pulseaudio.h>
#endif
+#include <atomic>
+
#include "Common.h"
#include "SoundStream.h"
#include "Thread.h"
-#include <vector>
-
class PulseAudio : public SoundStream
{
#if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO
@@ -32,18 +31,31 @@ public:
virtual void Update();
+ void StateCallback(pa_context *c);
+ void WriteCallback(pa_stream *s, size_t length);
+ void UnderflowCallback(pa_stream *s);
+
private:
virtual void SoundLoop();
bool PulseInit();
void PulseShutdown();
- void Write(const void *data, size_t bytes);
- std::vector<s16> mix_buffer;
- std::thread thread;
- volatile bool run_thread;
+ // wrapper callback functions, last parameter _must_ be PulseAudio*
+ static void StateCallback(pa_context *c, void *userdata);
+ static void WriteCallback(pa_stream *s, size_t length, void *userdata);
+ static void UnderflowCallback(pa_stream *s, void *userdata);
+
+ std::thread m_thread;
+ std::atomic<bool> m_run_thread;
- pa_simple* pa;
+ int m_pa_error;
+ int m_pa_connected;
+ pa_mainloop *m_pa_ml;
+ pa_mainloop_api *m_pa_mlapi;
+ pa_context *m_pa_ctx;
+ pa_stream *m_pa_s;
+ pa_buffer_attr m_pa_ba;
#else
public:
PulseAudio(CMixer *mixer) : SoundStream(mixer) {}
diff --git a/Source/Core/Common/CDUtils.cpp b/Source/Core/Common/CDUtils.cpp
index 569ceb3..705f9a7 100644
--- a/Source/Core/Common/CDUtils.cpp
+++ b/Source/Core/Common/CDUtils.cpp
@@ -2,6 +2,7 @@
#include "CDUtils.h"
#include "Common.h"
+#include "StringUtil.h"
#include <memory> // for std::unique_ptr
#ifdef _WIN32
@@ -150,10 +151,10 @@ static struct
};
// Returns true if a device is a block or char device and not a symbolic link
-bool is_device(const char *source_name)
+bool is_device(const std::string& source_name)
{
struct stat buf;
- if (0 != lstat(source_name, &buf))
+ if (0 != lstat(source_name.c_str(), &buf))
return false;
return ((S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode)) &&
@@ -161,17 +162,15 @@ bool is_device(const char *source_name)
}
// Check a device to see if it is a DVD/CD-ROM drive
-static bool is_cdrom(const char *drive, char *mnttype)
+static bool is_cdrom(const std::string& drive, char *mnttype)
{
- bool is_cd=false;
- int cdfd;
-
// Check if the device exists
if (!is_device(drive))
return(false);
+ bool is_cd=false;
// If it does exist, verify that it is a cdrom/dvd drive
- cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0);
+ int cdfd = open(drive.c_str(), (O_RDONLY|O_NONBLOCK), 0);
if ( cdfd >= 0 )
{
#ifdef __linux__
@@ -186,21 +185,16 @@ static bool is_cdrom(const char *drive, char *mnttype)
// Returns a pointer to an array of strings with the device names
std::vector<std::string> cdio_get_devices ()
{
- unsigned int i;
- char drive[40];
std::vector<std::string> drives;
-
// Scan the system for DVD/CD-ROM drives.
- for ( i=0; checklist[i].format; ++i )
+ for (unsigned int i = 0; checklist[i].format; ++i)
{
- unsigned int j;
- for ( j=checklist[i].num_min; j<=checklist[i].num_max; ++j )
+ for (unsigned int j = checklist[i].num_min; j <= checklist[i].num_max; ++j)
{
- sprintf(drive, checklist[i].format, j);
- if ( (is_cdrom(drive, NULL)) > 0 )
+ std::string drive = StringFromFormat(checklist[i].format, j);
+ if ( (is_cdrom(drive.c_str(), NULL)) > 0 )
{
- std::string str = drive;
- drives.push_back(str);
+ drives.push_back(std::move(drive));
}
}
}
@@ -225,14 +219,12 @@ bool cdio_is_cdrom(std::string device)
bool res = false;
for (auto& odevice : devices)
{
- if (strncmp(odevice.c_str(), device.c_str(), MAX_PATH) == 0)
+ if (odevice == device)
{
res = true;
break;
}
}
-
devices.clear();
return res;
}
-
diff --git a/Source/Core/Common/IniFile.h b/Source/Core/Common/IniFile.h
index abfb58b..005f866 100644
--- a/Source/Core/Common/IniFile.h
+++ b/Source/Core/Common/IniFile.h
@@ -140,6 +140,10 @@ public:
void SetLines(const char* sectionName, const std::vector<std::string> &lines);
bool GetLines(const char* sectionName, std::vector<std::string>& lines, const bool remove_comments = true) const;
+ inline bool DeleteKey(const char* sectionName, const std::string& key)
+ {
+ return DeleteKey(sectionName, key.c_str());
+ }
bool DeleteKey(const char* sectionName, const char* key);
bool DeleteSection(const char* sectionName);
diff --git a/Source/Core/Common/Log.h b/Source/Core/Common/Log.h
index b0f3519..8c7a1eb 100644
--- a/Source/Core/Common/Log.h
+++ b/Source/Core/Common/Log.h
@@ -77,6 +77,8 @@ enum LOG_LEVELS
LDEBUG = DEBUG_LEVEL,
};
+static const char LOG_LEVEL_TO_CHAR[7] = "-NEWID";
+
#define LOGTYPES_LEVELS LogTypes::LOG_LEVELS
#define LOGTYPES_TYPE LogTypes::LOG_TYPE
diff --git a/Source/Core/Common/LogManager.cpp b/Source/Core/Common/LogManager.cpp
index 50c6ab4..5fe218b 100644
--- a/Source/Core/Common/LogManager.cpp
+++ b/Source/Core/Common/LogManager.cpp
@@ -114,7 +114,6 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
const char *file, int line, const char *format, 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())
@@ -122,15 +121,15 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
CharArrayFromFormatV(temp, MAX_MSGLEN, format, args);
- static const char level_to_char[7] = "-NEWID";
- sprintf(msg, "%s %s:%u %c[%s]: %s\n",
- Common::Timer::GetTimeFormatted().c_str(),
- file, line, level_to_char[(int)level],
- log->GetShortName(), temp);
+ std::string msg = StringFromFormat("%s %s:%u %c[%s]: %s\n",
+ Common::Timer::GetTimeFormatted().c_str(),
+ file, line,
+ LogTypes::LOG_LEVEL_TO_CHAR[(int)level],
+ log->GetShortName(), temp);
#ifdef ANDROID
- Host_SysMessage(msg);
+ Host_SysMessage(msg.c_str());
#endif
- log->Trigger(level, msg);
+ log->Trigger(level, msg.c_str());
}
void LogManager::Init()
diff --git a/Source/Core/Common/MemArena.cpp b/Source/Core/Common/MemArena.cpp
index e7f3911..699005d 100644
--- a/Source/Core/Common/MemArena.cpp
+++ b/Source/Core/Common/MemArena.cpp
@@ -6,6 +6,7 @@
#include "MemoryUtil.h"
#include "MemArena.h"
+#include "StringUtil.h"
#ifdef _WIN32
#include <windows.h>
@@ -57,20 +58,21 @@ void MemArena::GrabLowMemSpace(size_t size)
return;
}
#else
- char fn[64];
for (int i = 0; i < 10000; i++)
{
- sprintf(fn, "dolphinmem.%d", i);
- fd = shm_open(fn, O_RDWR | O_CREAT | O_EXCL, 0600);
+ std::string file_name = StringFromFormat("dolphinmem.%d", i);
+ fd = shm_open(file_name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd != -1)
+ {
+ shm_unlink(file_name.c_str());
break;
- if (errno != EEXIST)
+ }
+ else if (errno != EEXIST)
{
ERROR_LOG(MEMMAP, "shm_open failed: %s", strerror(errno));
return;
}
}
- shm_unlink(fn);
if (ftruncate(fd, size) < 0)
ERROR_LOG(MEMMAP, "Failed to allocate low memory space");
#endif
diff --git a/Source/Core/Common/NandPaths.cpp b/Source/Core/Common/NandPaths.cpp
index 3ca5550..52e3904 100644
--- a/Source/Core/Common/NandPaths.cpp
+++ b/Source/Core/Common/NandPaths.cpp
@@ -12,20 +12,16 @@ namespace Common
std::string GetTicketFileName(u64 _titleID)
{
- char TicketFilename[1024];
- sprintf(TicketFilename, "%sticket/%08x/%08x.tik",
- File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(_titleID >> 32), (u32)_titleID);
-
- return TicketFilename;
+ return StringFromFormat("%sticket/%08x/%08x.tik",
+ File::GetUserPath(D_WIIUSER_IDX).c_str(),
+ (u32)(_titleID >> 32), (u32)_titleID);
}
std::string GetTitleDataPath(u64 _titleID)
{
- char path[1024];
- sprintf(path, "%stitle/%08x/%08x/data/",
- File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(_titleID >> 32), (u32)_titleID);
-
- return path;
+ return StringFromFormat("%stitle/%08x/%08x/data/",
+ File::GetUserPath(D_WIIUSER_IDX).c_str(),
+ (u32)(_titleID >> 32), (u32)_titleID);
}
std::string GetTMDFileName(u64 _titleID)
@@ -34,11 +30,9 @@ std::string GetTMDFileName(u64 _titleID)
}
std::string GetTitleContentPath(u64 _titleID)
{
- char ContentPath[1024];
- sprintf(ContentPath, "%stitle/%08x/%08x/content/",
- File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(_titleID >> 32), (u32)_titleID);
-
- return ContentPath;
+ return StringFromFormat("%stitle/%08x/%08x/content/",
+ File::GetUserPath(D_WIIUSER_IDX).c_str(),
+ (u32)(_titleID >> 32), (u32)_titleID);
}
bool CheckTitleTMD(u64 _titleID)
diff --git a/Source/Core/Common/SettingsHandler.h b/Source/Core/Common/SettingsHandler.h
index 232555d..3666935 100644
--- a/Source/Core/Common/SettingsHandler.h
+++ b/Source/Core/Common/SettingsHandler.h
@@ -22,6 +22,10 @@ public:
INITIAL_SEED = 0x73B5DBFA
};
+ inline void AddSetting(const char *key, const std::string& value)
+ {
+ AddSetting(key, value.c_str());
+ }
void AddSetting(const char *key, const char *value);
const u8 *GetData() const;
diff --git a/Source/Core/Common/Timer.cpp b/Source/Core/Common/Timer.cpp
index 267755f..91a2a2d 100644
--- a/Source/Core/Common/Timer.cpp
+++ b/Source/Core/Common/Timer.cpp
@@ -167,27 +167,23 @@ u64 Timer::GetLocalTimeSinceJan1970()
std::string Timer::GetTimeFormatted()
{
time_t sysTime;
- struct tm * gmTime;
- char formattedTime[13];
- char tmp[13];
-
time(&sysTime);
- gmTime = localtime(&sysTime);
+
+ struct tm * gmTime = localtime(&sysTime);
+ char tmp[13];
strftime(tmp, 6, "%M:%S", gmTime);
// Now tack on the milliseconds
#ifdef _WIN32
struct timeb tp;
(void)::ftime(&tp);
- sprintf(formattedTime, "%s:%03i", tmp, tp.millitm);
+ return StringFromFormat("%s:%03i", tmp, tp.millitm);
#else
struct timeval t;
(void)gettimeofday(&t, NULL);
- sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000));
+ return StringFromFormat("%s:%03d", tmp, (int)(t.tv_usec / 1000));
#endif
-
- return std::string(formattedTime);
}
// Returns a timestamp with decimals for precise time comparisons
diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h
index da24177..b351ce5 100644
--- a/Source/Core/Core/Boot/Boot.h
+++ b/Source/Core/Core/Boot/Boot.h
@@ -10,6 +10,17 @@
#include "../CoreParameter.h"
+#include "Volume.h"
+using DiscIO::IVolume;
+
+typedef struct CountrySetting
+{
+ const std::string area;
+ const std::string video;
+ const std::string game;
+ const std::string code;
+} CountrySetting;
+
class CBoot
{
public:
@@ -45,7 +56,7 @@ private:
static bool Load_BS2(const std::string& _rBootROMFilename);
static void Load_FST(bool _bIsWii);
- static bool SetupWiiMemory(unsigned int _CountryCode);
+ static bool SetupWiiMemory(IVolume::ECountry country);
};
#endif
diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp
index c7b8483..ef8eae7 100644
--- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp
+++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp
@@ -158,56 +158,28 @@ bool CBoot::EmulatedBS2_GC()
return true;
}
-bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
+bool CBoot::SetupWiiMemory(IVolume::ECountry country)
{
- INFO_LOG(BOOT, "Setup Wii Memory...");
-
- // Write the 256 byte setting.txt to memory.
- std::string settings_Filename(Common::GetTitleDataPath(TITLEID_SYSMENU) + WII_SETTING);
- std::string area, model, code, video, game;
-
-
- switch((DiscIO::IVolume::ECountry)_CountryCode)
- {
- case DiscIO::IVolume::COUNTRY_KOREA:
- area = "KOR";
- video = "NTSC";
- game = "KR";
- code = "LKH";
- break;
- case DiscIO::IVolume::COUNTRY_TAIWAN:
- // TODO: Determine if Taiwan have their own specific settings.
- case DiscIO::IVolume::COUNTRY_JAPAN:
- area = "JPN";
- video = "NTSC";
- game = "JP";
- code = "LJ";
- break;
- case DiscIO::IVolume::COUNTRY_USA:
- area = "USA";
- video = "NTSC";
- game = "US";
- code = "LU";
- break;
- case DiscIO::IVolume::COUNTRY_EUROPE:
- area = "EUR";
- video = "PAL";
- game = "EU";
- code = "LE";
- break;
- default:
- // PanicAlertT("SetupWiiMem: Unknown country. Wii boot process will be switched to European settings.");
- area = "EUR";
- video = "PAL";
- game = "EU";
- code = "LE";
- break;
- }
-
- model = "RVL-001(" + area + ")";
+ static const CountrySetting SETTING_EUROPE = {"EUR", "PAL", "EU", "LE"};
+ static const std::map<IVolume::ECountry, const CountrySetting&> country_settings = {
+ {IVolume::COUNTRY_EUROPE, SETTING_EUROPE},
+ {IVolume::COUNTRY_USA, {"USA", "NTSC", "US", "LU"}},
+ {IVolume::COUNTRY_JAPAN, {"JPN", "NTSC", "JP", "LJ"}},
+ {IVolume::COUNTRY_KOREA, {"KOR", "NTSC", "KR", "LKH"}},
+ //TODO: Determine if Taiwan have their own specific settings.
+ // Also determine if there are other specific settings
+ // for other countries.
+ {IVolume::COUNTRY_TAIWAN, {"JPN", "NTSC", "JP", "LJ"}}
+ };
+ auto entryPos = country_settings.find(country);
+ const CountrySetting& country_setting =
+ (entryPos != country_settings.end()) ?
+ entryPos->second :
+ SETTING_EUROPE; //Default to EUROPE
SettingsHandler gen;
- std::string serno = "";
+ std::string serno;
+ std::string settings_Filename(Common::GetTitleDataPath(TITLEID_SYSMENU) + WII_SETTING);
if (File::Exists(settings_Filename))
{
File::IOFile settingsFileHandle(settings_Filename, "rb");
@@ -230,29 +202,31 @@ bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
INFO_LOG(BOOT, "Using serial number: %s", serno.c_str());
}
- gen.AddSetting("AREA", area.c_str());
- gen.AddSetting("MODEL", model.c_str());
+ std::string model = "RVL-001(" + country_setting.area + ")";
+ gen.AddSetting("AREA", country_setting.area);
+ gen.AddSetting("MODEL", model);
gen.AddSetting("DVD", "0");
gen.AddSetting("MPCH", "0x7FFE");
- gen.AddSetting("CODE", code.c_str());
- gen.AddSetting("SERNO", serno.c_str());
- gen.AddSetting("VIDEO", video.c_str());
- gen.AddSetting("GAME", game.c_str());
-
-
+ gen.AddSetting("CODE", country_setting.code);
+ gen.AddSetting("SERNO", serno);
+ gen.AddSetting("VIDEO", country_setting.video);
+ gen.AddSetting("GAME", country_setting.game);
+
File::CreateFullPath(settings_Filename);
-
{
File::IOFile settingsFileHandle(settings_Filename, "wb");
if (!settingsFileHandle.WriteBytes(gen.GetData(), SettingsHandler::SETTINGS_SIZE))
{
- PanicAlertT("SetupWiiMem: Cant create setting file");
+ PanicAlertT("SetupWiiMemory: Cant create setting.txt file");
return false;
}
+ // Write the 256 byte setting.txt to memory.
Memory::WriteBigEData(gen.GetData(), 0x3800, SettingsHandler::SETTINGS_SIZE);
}
+ INFO_LOG(BOOT, "Setup Wii Memory...");
+
/*
Set hardcoded global variables to Wii memory. These are partly collected from
Wiibrew. These values are needed for the games to function correctly. A few
diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp
index f28dfa5..afeeaca 100644
--- a/Source/Core/Core/ConfigManager.cpp
+++ b/Source/Core/Core/ConfigManager.cpp
@@ -151,18 +151,14 @@ void SConfig::SaveSettings()
ini.Get("General", "GCMPathes", &oldPaths, 0);
for (int i = numPaths; i < oldPaths; i++)
{
- char tmp[16];
- sprintf(tmp, "GCMPath%i", i);
- ini.DeleteKey("General", tmp);
+ ini.DeleteKey("General", StringFromFormat("GCMPath%i", i));
}
- ini.Set("General", "GCMPathes", numPaths);
+ ini.Set("General", "GCMPathes", numPaths);
for (int i = 0; i < numPaths; i++)
{
- char tmp[16];
- sprintf(tmp, "GCMPath%i", i);
- ini.Set("General", tmp, m_ISOFolder[i]);
+ ini.Set("General", StringFromFormat("GCMPath%i", i).c_str(), m_ISOFolder[i]);
}
ini.Set("General", "RecursiveGCMPaths", m_RecursiveISOFolder);
@@ -249,13 +245,10 @@ void SConfig::SaveSettings()
ini.Set("Core", "SlotB", m_EXIDevice[1]);
ini.Set("Core", "SerialPort1", m_EXIDevice[2]);
ini.Set("Core", "BBA_MAC", m_bba_mac);
- char sidevicenum[16];
for (int i = 0; i < 4; ++i)
{
- sprintf(sidevicenum, "SIDevice%i", i);
- ini.Set("Core", sidevicenum, m_SIDevice[i]);
+ ini.Set("Core", StringFromFormat("SIDevice%i", i).c_str(), m_SIDevice[i]);
}
-
ini.Set("Core", "WiiSDCard", m_WiiSDCard);
ini.Set("Core", "WiiKeyboard", m_WiiKeyboard);
ini.Set("Core", "WiimoteContinuousScanning", m_WiimoteContinuousScanning);
@@ -307,11 +300,9 @@ void SConfig::LoadSettings()
{
for (int i = 0; i < numGCMPaths; i++)
{
- char tmp[16];
- sprintf(tmp, "GCMPath%i", i);
std::string tmpPath;
- ini.Get("General", tmp, &tmpPath, "");
- m_ISOFolder.push_back(tmpPath);
+ ini.Get("General", StringFromFormat("GCMPath%i", i).c_str(), &tmpPath, "");
+ m_ISOFolder.push_back(std::move(tmpPath));
}
}
@@ -410,13 +401,10 @@ void SConfig::LoadSettings()
ini.Get("Core", "BBA_MAC", &m_bba_mac);
ini.Get("Core", "TimeProfiling",&m_LocalCoreStartupParameter.bJITILTimeProfiling, false);
ini.Get("Core", "OutputIR", &m_LocalCoreStartupParameter.bJITILOutputIR, false);
- char sidevicenum[16];
for (int i = 0; i < 4; ++i)
{
- sprintf(sidevicenum, "SIDevice%i", i);
- ini.Get("Core", sidevicenum, (u32*)&m_SIDevice[i], (i == 0) ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE);
+ ini.Get("Core", StringFromFormat("SIDevice%i", i).c_str(), (u32*)&m_SIDevice[i], (i == 0) ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE);
}
-
ini.Get("Core", "WiiSDCard", &m_WiiSDCard, false);
ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false);
ini.Get("Core", "WiimoteContinuousScanning", &m_WiimoteContinuousScanning, false);
diff --git a/Source/Core/Core/DSP/DSPCodeUtil.cpp b/Source/Core/Core/DSP/DSPCodeUtil.cpp
index afaaa7d..53e47b7 100644
--- a/Source/Core/Core/DSP/DSPCodeUtil.cpp
+++ b/Source/Core/Core/DSP/DSPCodeUtil.cpp
@@ -110,8 +110,6 @@ void CodeToHeader(const std::vector<u16> &code, std::string _filename,
// Pad with nops to 32byte boundary
while (code_padded.size() & 0x7f)
code_padded.push_back(0);
-
- char buffer[1024];
header.clear();
header.reserve(code_padded.size() * 4);
header.append("#define NUM_UCODES 1\n\n");
@@ -125,8 +123,7 @@ void CodeToHeader(const std::vector<u16> &code, std::string _filename,
{
if (j && ((j & 15) == 0))
header.append("\n\t\t");
- sprintf(buffer, "0x%04x, ", code_padded[j]);
- header.append(buffer);
+ header.append(StringFromFormat("0x%04x, ", code_padded[j]));
}
header.append("\n\t},\n");
@@ -137,7 +134,6 @@ void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>
u32 numCodes, const char *name, std::string &header)
{
std::vector<std::vector<u16> > codes_padded;
- char buffer[1024];
u32 reserveSize = 0;
for(u32 i = 0; i < numCodes; i++)
{
@@ -148,20 +144,16 @@ void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>
reserveSize += (u32)codes_padded.at(i).size();
}
-
-
header.clear();
header.reserve(reserveSize * 4);
- sprintf(buffer, "#define NUM_UCODES %u\n\n", numCodes);
- header.append(buffer);
+ header.append(StringFromFormat("#define NUM_UCODES %u\n\n", numCodes));
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
for (u32 i = 0; i < numCodes; i++)
{
std::string filename;
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
filename = filenames->at(i);
- sprintf(buffer, "\t\"%s\",\n", filename.c_str());
- header.append(buffer);
+ header.append(StringFromFormat("\t\"%s\",\n", filename.c_str()));
}
header.append("};\n\n");
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
@@ -176,8 +168,7 @@ void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>
{
if (j && ((j & 15) == 0))
header.append("\n\t\t");
- sprintf(buffer, "0x%04x, ", codes_padded.at(i).at(j));
- header.append(buffer);
+ header.append(StringFromFormat("0x%04x, ", codes_padded.at(i).at(j)));
}
header.append("\n\t},\n");
}
diff --git a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp
index d4f1a40..3aa9294 100644
--- a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp
+++ b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp
@@ -151,9 +151,7 @@ void PrintDataBuffer(LogTypes::LOG_TYPE type, u8* _pData, size_t _Size, const ch
std::string Temp;
for (int i = 0; i < 16; i++)
{
- char Buffer[128];
- sprintf(Buffer, "%02x ", _pData[j++]);
- Temp.append(Buffer);
+ Temp.append(StringFromFormat("%02x ", _pData[j++]));
if (j >= _Size)
break;
diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h
index 49249a2..9838716 100644
--- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h
+++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device.h
@@ -192,9 +192,7 @@ protected:
std::string Temp;
for (u32 j = 0; j < InBufferSize; j++)
{
- char Buffer[128];
- sprintf(Buffer, "%02x ", Memory::Read_U8(InBuffer+j));
- Temp.append(Buffer);
+ Temp += StringFromFormat("%02x ", Memory::Read_U8(InBuffer+j));
}
GENERIC_LOG(LogType, LogTypes::LDEBUG, " Buffer: %s", Temp.c_str());
diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp
index 325e200..f2d9746 100644
--- a/Source/Core/DiscIO/VolumeGC.cpp
+++ b/Source/Core/DiscIO/VolumeGC.cpp
@@ -54,9 +54,7 @@ std::string CVolumeGC::GetUniqueID() const
std::string CVolumeGC::GetRevisionSpecificUniqueID() const
{
- char rev[16];
- sprintf(rev, "r%d", GetRevision());
- return GetUniqueID() + rev;
+ return GetUniqueID() + StringFromFormat("r%d", GetRevision());
}
IVolume::ECountry CVolumeGC::GetCountry() const